From 2045cf3f21f16d55fde9273d6914889b79d90b37 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 5 Jul 2024 10:46:08 +0800 Subject: [PATCH 1/7] fix: fix react component error in updateCell() #2038 --- .../scenegraph/group-creater/cell-helper.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts index 133dbec09..096646f05 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts @@ -426,10 +426,11 @@ export function updateCell(col: number, row: number, table: BaseTableAPI, addNew colForDefine = range.start.col; rowForDefine = range.start.row; } - const define = + const define: TextColumnDefine = ( cellLocation !== 'body' ? table.getHeaderDefine(colForDefine, rowForDefine) - : table.getBodyColumnDefine(colForDefine, rowForDefine); + : table.getBodyColumnDefine(colForDefine, rowForDefine) + ) as any; if (!range && (cellLocation !== 'body' || (define as TextColumnDefine)?.mergeCell)) { // 只有表头或者column配置合并单元格后再进行信息获取 @@ -449,7 +450,12 @@ export function updateCell(col: number, row: number, table: BaseTableAPI, addNew cellTheme.group.cornerRadius = getCellCornerRadius(col, row, table); // fast method for text - if (!addNew && !isMerge && canUseFastUpdate(col, row, oldCellGroup, autoWrapText, table)) { + if ( + !addNew && + !isMerge && + !(define.customLayout || define.customRender || define.headerCustomLayout || define.headerCustomRender) && + canUseFastUpdate(col, row, oldCellGroup, autoWrapText, table) + ) { // update group const cellWidth = table.getColWidth(col); const cellHeight = table.getRowHeight(row); @@ -678,8 +684,10 @@ function updateCellContent( // clear react container if (table.reactCustomLayout) { const reactGroup = oldCellGroup.getChildByName('custom-container'); - const { col, row } = reactGroup; - table.reactCustomLayout.removeCustomCell(col, row); + if (reactGroup) { + const { col, row } = reactGroup; + table.reactCustomLayout.removeCustomCell(col, row); + } } } const newCellGroup = createCell( From 1970f0bccfcb180d3b28db81baf426fb343575aa Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 5 Jul 2024 10:54:07 +0800 Subject: [PATCH 2/7] feat: add renderDefault prop in react customLayout component --- packages/react-vtable/src/components/custom/custom-layout.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/react-vtable/src/components/custom/custom-layout.tsx b/packages/react-vtable/src/components/custom/custom-layout.tsx index f6ef5838e..936c0900b 100644 --- a/packages/react-vtable/src/components/custom/custom-layout.tsx +++ b/packages/react-vtable/src/components/custom/custom-layout.tsx @@ -13,6 +13,7 @@ type CustomLayoutProps = { componentIndex?: number }; export type CustomLayoutFunctionArg = Partial & { role?: 'custom-layout' | 'header-custom-layout'; + renderDefault?: boolean; }; export const CustomLayout: React.FC = (props: PropsWithChildren, ref) => { @@ -49,7 +50,7 @@ export const CustomLayout: React.FC = (props: PropsWithChildr return { rootContainer: group, - renderDefault: false + renderDefault: !!children.props.renderDefault }; }, [children] From f9ec412975f460a177c167abe99d1b5c96e73f78 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 5 Jul 2024 17:02:29 +0800 Subject: [PATCH 3/7] feat: support multiple columns in react-vtable --- .../src/components/base-component.tsx | 132 +++++++-------- .../src/components/custom/custom-layout.tsx | 16 +- .../src/components/list/list-column.tsx | 3 +- .../components/react/react-custom-layout.ts | 154 ++++++++++++++---- 4 files changed, 196 insertions(+), 109 deletions(-) diff --git a/packages/react-vtable/src/components/base-component.tsx b/packages/react-vtable/src/components/base-component.tsx index 87cb3520d..8c84f3f0b 100644 --- a/packages/react-vtable/src/components/base-component.tsx +++ b/packages/react-vtable/src/components/base-component.tsx @@ -1,4 +1,4 @@ -import type { ReactElement } from 'react'; +import type { ReactElement, ReactNode } from 'react'; import React, { useContext, useEffect } from 'react'; import { isEqual, isNil, pickWithout } from '@visactor/vutils'; @@ -13,7 +13,7 @@ export interface BaseComponentProps { children?: React.ReactNode; } -type ComponentProps = BaseComponentProps & { updateId?: number; componentId?: number; componentIndex?: number }; +type ComponentProps = BaseComponentProps & { updateId?: number; componentId?: string; componentIndex?: number }; export const createComponent = ( componentName: string, @@ -21,7 +21,7 @@ export const createComponent = ( supportedEvents?: Record | null, isSingle?: boolean ) => { - const ignoreKeys = ['id', 'updateId', 'componentId', 'componentIndex', 'children']; + const ignoreKeys = ['id', 'updateId', 'componentIndex', 'children']; const notOptionKeys = supportedEvents ? Object.keys(supportedEvents).concat(ignoreKeys) : ignoreKeys; const Comp: React.FC = (props: T) => { @@ -65,29 +65,25 @@ export const createComponent = ( // return props.children // ? React.cloneElement(props.children as ReactElement, { componentIndex: props.componentIndex }) // : null; - if (props.children) { - return React.Children.map(props.children as ReactElement, (child: ReactElement) => { - return React.createElement(CustomLayout, { componentIndex: props.componentIndex }, child); - }); - } - return null; + // if (props.children) { + // return React.Children.map(props.children as ReactElement, (child: ReactElement) => { + // if (child.props.role === 'custom-layout' || child.props.role === 'header-custom-layout') { + // return React.createElement(CustomLayout, { componentId: props.componentId }, child); + // } + // }); + // } + return parseCustomChildren(props.children, props.componentId); }; Comp.displayName = componentName; (Comp as any).parseOption = (props: T & { updateId?: number; componentId?: string }) => { const newComponentOption: Partial = pickWithout(props, notOptionKeys); - // deal width customLayout if (props.children) { const { children } = props; - React.Children.map(children as ReactElement, (child: ReactElement) => { - if (child.props.role === 'custom-layout') { - (newComponentOption as any).customLayout = 'react-custom-layout'; - } - if (child.props.role === 'header-custom-layout') { - (newComponentOption as any).headerCustomLayout = 'react-custom-layout'; - } + React.Children.map(children as ReactElement, (child: ReactElement, index) => { + parseChild(child, props, newComponentOption, notOptionKeys, props.componentId + '-' + index); }); } // if (props.children && (props.children as React.ReactElement).props.role === 'custom-layout') { @@ -104,58 +100,50 @@ export const createComponent = ( return Comp; }; -// const updateToContext = ( -// context: TableContextType, -// id: string | number, -// optionName: string, -// isSingle: boolean, -// props: Partial -// ) => { -// if (!context.optionFromChildren) { -// return; -// } - -// if (isSingle) { -// context.optionFromChildren[optionName] = { ...props }; -// } else { -// if (!context.optionFromChildren[optionName]) { -// context.optionFromChildren[optionName] = []; -// } - -// const comps = context.optionFromChildren[optionName]; -// const index = comps.findIndex((entry: any) => entry.id === id); - -// if (index >= 0) { -// comps[index] = { -// id, -// ...props -// }; -// } else { -// context.optionFromChildren[optionName].push({ -// id, -// ...props -// }); -// } -// } -// context.isChildrenUpdated = true; -// }; - -// const deleteToContext = (context: TableContextType, id: string | number, optionName: string, isSingle: boolean) => { -// if (!context.optionFromChildren) { -// return; -// } - -// if (isSingle) { -// context.optionFromChildren[optionName] = null; -// } else { -// const comps = context.optionFromChildren[optionName] ?? []; -// const index = comps.findIndex((entry: any) => entry.id === id); - -// if (index >= 0) { -// const newComps = comps.slice(0, index - 1).concat(comps.slice(index + 1)); - -// context.optionFromChildren[optionName] = newComps; -// context.isChildrenUpdated = true; -// } -// } -// }; +function parseChild( + child: ReactElement, + componentProps: any, + newComponentOption: any, + notOptionKeys: string[], + componentId: string +) { + if (child.props.role === 'custom-layout') { + (newComponentOption as any).customLayout = 'react-custom-layout'; + (newComponentOption as any).customLayoutComponentId = componentId; + } + if (child.props.role === 'header-custom-layout') { + (newComponentOption as any).headerCustomLayout = 'react-custom-layout'; + (newComponentOption as any).headerCustomLayoutComponentId = componentId; + } + if ((child.type as any).displayName === 'ListColumn') { + if (!newComponentOption.columns) { + newComponentOption.columns = []; + } + const childOption = pickWithout(child.props, notOptionKeys); + newComponentOption.columns.push(childOption); + childOption.componentId = componentId; + if (child.props.children) { + React.Children.map(child.props.children as ReactElement, (child: ReactElement, index) => { + parseChild(child, componentProps, childOption, notOptionKeys, componentId + '-' + index); + }); + } + } +} + +function parseCustomChildren(children: ReactNode, componentId: string): ReactNode | undefined { + if (isReactElement(children) || Array.isArray(children)) { + return React.Children.map(children as ReactElement, (child: ReactElement, index) => { + if (child.props.children) { + return parseCustomChildren(child.props.children as ReactElement, componentId + '-' + index); + } else if (child.props.role === 'custom-layout' || child.props.role === 'header-custom-layout') { + return React.createElement(CustomLayout, { componentId: componentId }, child); + } + return null; + }); + } + return null; +} + +function isReactElement(obj: any) { + return obj && obj.$$typeof === Symbol.for('react.element'); +} diff --git a/packages/react-vtable/src/components/custom/custom-layout.tsx b/packages/react-vtable/src/components/custom/custom-layout.tsx index 936c0900b..199f6642c 100644 --- a/packages/react-vtable/src/components/custom/custom-layout.tsx +++ b/packages/react-vtable/src/components/custom/custom-layout.tsx @@ -1,5 +1,5 @@ /* eslint-disable react-hooks/rules-of-hooks */ -import type { PropsWithChildren } from 'react'; +import type { PropsWithChildren, ReactElement } from 'react'; import React, { isValidElement, useCallback, useContext, useLayoutEffect, useRef } from 'react'; import RootTableContext from '../../context/table'; import { VRender } from '@visactor/vtable'; @@ -9,7 +9,7 @@ import { reconcilor } from './reconciler'; import { LegacyRoot } from 'react-reconciler/constants'; const { Group } = VRender; -type CustomLayoutProps = { componentIndex?: number }; +type CustomLayoutProps = { componentId: string }; export type CustomLayoutFunctionArg = Partial & { role?: 'custom-layout' | 'header-custom-layout'; @@ -17,7 +17,7 @@ export type CustomLayoutFunctionArg = Partial & { }; export const CustomLayout: React.FC = (props: PropsWithChildren, ref) => { - const { componentIndex, children } = props; + const { componentId, children } = props; if (!isValidElement(children)) { return null; } @@ -84,15 +84,15 @@ export const CustomLayout: React.FC = (props: PropsWithChildr console.log('update props', props, table); table?.checkReactCustomLayout(); // init reactCustomLayout component - if (table && !table.reactCustomLayout?.hasReactCreateGraphic(componentIndex, isHeaderCustomLayout)) { + if (table && !table.reactCustomLayout?.hasReactCreateGraphic(componentId, isHeaderCustomLayout)) { table.reactCustomLayout?.setReactCreateGraphic( - componentIndex, + componentId, createGraphic, // container.current, isHeaderCustomLayout ); // set customLayout function - table.reactCustomLayout?.setReactRemoveGraphic(componentIndex, removeContainer, isHeaderCustomLayout); // set customLayout function - table.reactCustomLayout?.updateCustomCell(componentIndex, isHeaderCustomLayout); // update cell content + table.reactCustomLayout?.setReactRemoveGraphic(componentId, removeContainer, isHeaderCustomLayout); // set customLayout function + table.reactCustomLayout?.updateCustomCell(componentId, isHeaderCustomLayout); // update cell content } else if (table) { // update all container container.current.forEach((value, key) => { @@ -127,7 +127,7 @@ export const CustomLayout: React.FC = (props: PropsWithChildr return null; }; -function reconcilorUpdateContainer(children, currentContainer, group, args) { +function reconcilorUpdateContainer(children: ReactElement, currentContainer: any, group: typeof Group, args: any) { reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); // group = group.firstChild; // if (isReactElement(group.attribute.html?.dom)) { diff --git a/packages/react-vtable/src/components/list/list-column.tsx b/packages/react-vtable/src/components/list/list-column.tsx index 699d5b7ae..87b022b50 100644 --- a/packages/react-vtable/src/components/list/list-column.tsx +++ b/packages/react-vtable/src/components/list/list-column.tsx @@ -1,7 +1,8 @@ +import type { ReactElement, ReactNode } from 'react'; import type { BaseComponentProps } from '../base-component'; import { createComponent } from '../base-component'; import type { ColumnDefine } from '@visactor/vtable'; -export type ListColumnProps = ColumnDefine & BaseComponentProps; +export type ListColumnProps = Omit & BaseComponentProps; export const ListColumn = createComponent('ListColumn', 'columns'); diff --git a/packages/vtable/src/components/react/react-custom-layout.ts b/packages/vtable/src/components/react/react-custom-layout.ts index 4066d9092..5b1de18cf 100644 --- a/packages/vtable/src/components/react/react-custom-layout.ts +++ b/packages/vtable/src/components/react/react-custom-layout.ts @@ -12,10 +12,10 @@ export function emptyCustomLayout(args: CustomRenderFunctionArg) { export class ReactCustomLayout { table: BaseTableAPI; - customLayoutFuncCache: Map; - reactRemoveGraphicCache: Map void>; - headerCustomLayoutFuncCache: Map; - headerReactRemoveGraphicCache: Map void>; + customLayoutFuncCache: Map; + reactRemoveGraphicCache: Map void>; + headerCustomLayoutFuncCache: Map; + headerReactRemoveGraphicCache: Map void>; // reactContainerCache: Map>; constructor(table: BaseTableAPI) { this.table = table; @@ -27,49 +27,56 @@ export class ReactCustomLayout { this.headerReactRemoveGraphicCache = new Map(); } - hasReactCreateGraphic(componentIndex: number, isHeaderCustomLayout?: boolean) { + hasReactCreateGraphic(componentId: string, isHeaderCustomLayout?: boolean) { if (isHeaderCustomLayout) { - return this.headerCustomLayoutFuncCache.has(componentIndex); + return this.headerCustomLayoutFuncCache.has(componentId); } - return this.customLayoutFuncCache.has(componentIndex); + return this.customLayoutFuncCache.has(componentId); } setReactCreateGraphic( - componentIndex: number, + componentId: string, createGraphic: ICustomLayoutFuc, // containerCache: Map, isHeaderCustomLayout?: boolean ) { if (isHeaderCustomLayout) { - this.headerCustomLayoutFuncCache.set(componentIndex, createGraphic); + this.headerCustomLayoutFuncCache.set(componentId, createGraphic); } else { - this.customLayoutFuncCache.set(componentIndex, createGraphic); + this.customLayoutFuncCache.set(componentId, createGraphic); } - // this.reactContainerCache.set(componentIndex, containerCache); + // this.reactContainerCache.set(componentId, containerCache); } setReactRemoveGraphic( - componentIndex: number, + componentId: string, removeGraphic: (col: number, row: number) => void, isHeaderCustomLayout?: boolean ) { if (isHeaderCustomLayout) { - this.headerReactRemoveGraphicCache.set(componentIndex, removeGraphic); + this.headerReactRemoveGraphicCache.set(componentId, removeGraphic); } else { - this.reactRemoveGraphicCache.set(componentIndex, removeGraphic); + this.reactRemoveGraphicCache.set(componentId, removeGraphic); } } - updateCustomCell(componentIndex: number, isHeaderCustomLayout?: boolean) { + updateCustomCell(componentId: string, isHeaderCustomLayout?: boolean) { const table = this.table; - const col = componentIndex; - // to do: deal with transpose table - if (isHeaderCustomLayout) { - for (let row = 0; row < table.columnHeaderLevelCount; row++) { - table.scenegraph.updateCellContent(col, row); - } - } else { - for (let row = table.columnHeaderLevelCount; row < table.rowCount; row++) { + // const col = componentId; + // // to do: deal with transpose table + // if (isHeaderCustomLayout) { + // for (let row = 0; row < table.columnHeaderLevelCount; row++) { + // table.scenegraph.updateCellContent(col, row); + // } + // } else { + // for (let row = table.columnHeaderLevelCount; row < table.rowCount; row++) { + // table.scenegraph.updateCellContent(col, row); + // } + // } + + const range = getUpdateCustomCellRange(componentId, table, isHeaderCustomLayout); + for (let col = range.startCol; col <= range.endCol; col++) { + for (let row = range.startRow; row <= range.endRow; row++) { table.scenegraph.updateCellContent(col, row); } } @@ -78,12 +85,13 @@ export class ReactCustomLayout { } getCustomLayoutFunc(col: number, row: number) { - const { startInTotal } = this.table.getBodyColumnDefine(col, row) as any; const isHeader = this.table.isHeader(col, row); - return ( - (isHeader ? this.headerCustomLayoutFuncCache.get(startInTotal) : this.customLayoutFuncCache.get(startInTotal)) || - emptyCustomLayout - ); + if (isHeader) { + const { componentId } = this.table.getHeaderDefine(col, row) as any; + return this.headerCustomLayoutFuncCache.get(componentId) ?? emptyCustomLayout; + } + const { componentId } = this.table.getBodyColumnDefine(col, row) as any; + return this.customLayoutFuncCache.get(componentId) || emptyCustomLayout; } removeCustomCell(col: number, row: number) { @@ -97,3 +105,93 @@ export class ReactCustomLayout { } } } + +function getUpdateCustomCellRange(componentId: string, table: BaseTableAPI, isHeaderCustomLayout?: boolean) { + const rowSeriesNumber = table.internalProps.rowSeriesNumber ? 1 : 0; + if (isHeaderCustomLayout) { + const { headerObjects, _headerCellIds, transpose } = table.internalProps.layoutMap; + let headerId; + for (let i = 0; i < headerObjects.length; i++) { + const headerObject = headerObjects[i]; + if ((headerObject.define as any).componentId === componentId) { + headerId = headerObject.id; + break; + } + } + + let startCol = -1; + let endCol = -1; + let startRow = -1; + let endRow = -1; + for (let i = 0; i < _headerCellIds.length; i++) { + const row = _headerCellIds[i]; + let rowHasObject = false; + for (let j = 0; j < row.length; j++) { + if (row[j] === headerId) { + rowHasObject = true; + if (transpose) { + // return { col: i, row: j }; + startCol === -1 && (startCol = i); + startRow === -1 && (startRow = j); + } else { + // return { col: j + this.leftRowSeriesNumberColumnCount, row: i }; + startCol === -1 && (startCol = j); + startRow === -1 && (startRow = i); + } + } else { + if (transpose) { + // endCol === -1 && startCol !== -1 && (endCol = i); + endRow === -1 && startRow !== -1 && (endRow = j - 1); + } else { + endCol === -1 && startCol !== -1 && (endCol = j - 1); + // endRow === -1 && startRow !== -1 && (endRow = i); + } + } + + if (startCol !== -1 && endCol !== -1 && startRow !== -1 && endRow !== -1) { + break; + } + } + + if (!rowHasObject) { + if (transpose) { + endCol === -1 && startCol !== -1 && (endCol = i - 1); + } else { + endRow === -1 && startRow !== -1 && (endRow = i - 1); + } + } + + if (startCol !== -1 && endCol !== -1 && startRow !== -1 && endRow !== -1) { + break; + } + } + + return { + startCol: startCol + rowSeriesNumber, + endCol: endCol + rowSeriesNumber, + startRow, + endRow + }; + } + const { columnObjects } = table.internalProps.layoutMap; + for (let i = 0; i < columnObjects.length; i++) { + const columnObject = columnObjects[i]; + if ((columnObject.define as any).componentId === componentId) { + return { + startCol: rowSeriesNumber + i, + endCol: rowSeriesNumber + i, + startRow: table.columnHeaderLevelCount, + endRow: table.rowCount - 1 + }; + } + } + + // to do: pivot table + + // return { + // startCol: 0, + // endCol: table.colCount - 1, + // startRow: 0, + // endRow: table.rowCount - 1 + // }; +} From 8eb19005c872a54900f3d40bba501330670f64dd Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 5 Jul 2024 17:31:21 +0800 Subject: [PATCH 4/7] chore: add rush changes --- .../vtable/fix-react-update-cell_2024-07-05-09-29.json | 10 ++++++++++ .../vtable/fix-react-update-cell_2024-07-05-09-30.json | 10 ++++++++++ .../vtable/fix-react-update-cell_2024-07-05-09-31.json | 10 ++++++++++ 3 files changed, 30 insertions(+) create mode 100644 common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-29.json create mode 100644 common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-30.json create mode 100644 common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-31.json diff --git a/common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-29.json b/common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-29.json new file mode 100644 index 000000000..53d1ea43d --- /dev/null +++ b/common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-29.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "fix: fix react component error in updateCell() #2038", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-30.json b/common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-30.json new file mode 100644 index 000000000..179cfa49e --- /dev/null +++ b/common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-30.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "feat: add renderDefault prop in react customLayout component", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-31.json b/common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-31.json new file mode 100644 index 000000000..2ec232b13 --- /dev/null +++ b/common/changes/@visactor/vtable/fix-react-update-cell_2024-07-05-09-31.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "feat: support multiple columns tag in react-vtable", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file From 4ab42043d8d69a294cbae2542734c707ac2b1dda Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Mon, 8 Jul 2024 11:04:35 +0800 Subject: [PATCH 5/7] fix: fix type error in getUpdateCustomCellRange() --- .../src/components/react/react-custom-layout.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/vtable/src/components/react/react-custom-layout.ts b/packages/vtable/src/components/react/react-custom-layout.ts index 5b1de18cf..859a4aef2 100644 --- a/packages/vtable/src/components/react/react-custom-layout.ts +++ b/packages/vtable/src/components/react/react-custom-layout.ts @@ -109,7 +109,8 @@ export class ReactCustomLayout { function getUpdateCustomCellRange(componentId: string, table: BaseTableAPI, isHeaderCustomLayout?: boolean) { const rowSeriesNumber = table.internalProps.rowSeriesNumber ? 1 : 0; if (isHeaderCustomLayout) { - const { headerObjects, _headerCellIds, transpose } = table.internalProps.layoutMap; + const { headerObjects, _headerCellIds } = table.internalProps.layoutMap as any; + const { transpose } = table.internalProps; let headerId; for (let i = 0; i < headerObjects.length; i++) { const headerObject = headerObjects[i]; @@ -188,10 +189,10 @@ function getUpdateCustomCellRange(componentId: string, table: BaseTableAPI, isHe // to do: pivot table - // return { - // startCol: 0, - // endCol: table.colCount - 1, - // startRow: 0, - // endRow: table.rowCount - 1 - // }; + return { + startCol: 0, + endCol: table.colCount - 1, + startRow: 0, + endRow: table.rowCount - 1 + }; } From 7ab5a1d74bdf17e005ab3421a24ecdde9e2a4a87 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Mon, 8 Jul 2024 18:22:38 +0800 Subject: [PATCH 6/7] fix: fix pivot-table react component --- packages/react-vtable/README.md | 8 +- .../react-vtable/demo/data/pivot-data.json | 2252 +++++++++++++++++ packages/react-vtable/demo/src/App.tsx | 6 +- .../src/component/custom-layout-dom-site.tsx | 73 +- .../src/component/custom-layout-pivot.tsx | 219 ++ .../components/react/react-custom-layout.ts | 264 +- 6 files changed, 2736 insertions(+), 86 deletions(-) create mode 100644 packages/react-vtable/demo/data/pivot-data.json create mode 100644 packages/react-vtable/demo/src/component/custom-layout-pivot.tsx diff --git a/packages/react-vtable/README.md b/packages/react-vtable/README.md index 71ebf936d..ef2e0a987 100644 --- a/packages/react-vtable/README.md +++ b/packages/react-vtable/README.md @@ -43,19 +43,19 @@ const option = { header: [ { field: "0", - caption: "name", + title: "name", }, { field: "1", - caption: "age", + title: "age", }, { field: "2", - caption: "gender", + title: "gender", }, { field: "3", - caption: "hobby", + title: "hobby", }, ], records: new Array(1000).fill(["John", 18, "male", "🏀"]), diff --git a/packages/react-vtable/demo/data/pivot-data.json b/packages/react-vtable/demo/data/pivot-data.json new file mode 100644 index 000000000..3b448a39d --- /dev/null +++ b/packages/react-vtable/demo/data/pivot-data.json @@ -0,0 +1,2252 @@ +[ + { + "Category": "Office Supplies", + "Quantity": "3", + "City": "Aberdeen" + }, + { + "Category": "Office Supplies", + "Sales": "25.5", + "City": "Aberdeen" + }, + { + "Category": "Office Supplies", + "Profit": "6.630000114440918", + "City": "Aberdeen" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Aberdeen" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Aberdeen" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Aberdeen" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Aberdeen" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Aberdeen" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Aberdeen" + }, + { + "Category": "Office Supplies", + "Quantity": "2", + "City": "Abilene" + }, + { + "Category": "Office Supplies", + "Sales": "1.3919999599456787", + "City": "Abilene" + }, + { + "Category": "Office Supplies", + "Profit": "-3.757999897003174", + "City": "Abilene" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Abilene" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Abilene" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Abilene" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Abilene" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Abilene" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Abilene" + }, + { + "Category": "Office Supplies", + "Quantity": "45", + "City": "Akron" + }, + { + "Category": "Office Supplies", + "Sales": "1113.3880207538605", + "City": "Akron" + }, + { + "Category": "Office Supplies", + "Profit": "22.31399953365326", + "City": "Akron" + }, + { + "Category": "Technology", + "Quantity": "15", + "City": "Akron" + }, + { + "Category": "Technology", + "Sales": "1183.0019836425781", + "City": "Akron" + }, + { + "Category": "Technology", + "Profit": "-136.85100328922272", + "City": "Akron" + }, + { + "Category": "Furniture", + "Quantity": "5", + "City": "Akron" + }, + { + "Category": "Furniture", + "Sales": "433.59600830078125", + "City": "Akron" + }, + { + "Category": "Furniture", + "Profit": "-72.09900188446045", + "City": "Akron" + }, + { + "Category": "Office Supplies", + "Quantity": "41", + "City": "Albuquerque" + }, + { + "Category": "Office Supplies", + "Sales": "943.1220030784607", + "City": "Albuquerque" + }, + { + "Category": "Office Supplies", + "Profit": "384.5169929265976", + "City": "Albuquerque" + }, + { + "Category": "Technology", + "Quantity": "24", + "City": "Albuquerque" + }, + { + "Category": "Technology", + "Sales": "1277.0379962921143", + "City": "Albuquerque" + }, + { + "Category": "Technology", + "Profit": "249.57199335098267", + "City": "Albuquerque" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Albuquerque" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Albuquerque" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Albuquerque" + }, + { + "Category": "Office Supplies", + "Quantity": "48", + "City": "Alexandria" + }, + { + "Category": "Office Supplies", + "Sales": "4879.789813041687", + "City": "Alexandria" + }, + { + "Category": "Office Supplies", + "Profit": "153.12399864196777", + "City": "Alexandria" + }, + { + "Category": "Technology", + "Quantity": "16", + "City": "Alexandria" + }, + { + "Category": "Technology", + "Sales": "372.32000160217285", + "City": "Alexandria" + }, + { + "Category": "Technology", + "Profit": "61.040998458862305", + "City": "Alexandria" + }, + { + "Category": "Furniture", + "Quantity": "20", + "City": "Alexandria" + }, + { + "Category": "Furniture", + "Sales": "267.4600009918213", + "City": "Alexandria" + }, + { + "Category": "Furniture", + "Profit": "104.45199728012085", + "City": "Alexandria" + }, + { + "Category": "Office Supplies", + "Quantity": "8", + "City": "Allen" + }, + { + "Category": "Office Supplies", + "Sales": "24.72000026702881", + "City": "Allen" + }, + { + "Category": "Office Supplies", + "Profit": "-8.236999988555908", + "City": "Allen" + }, + { + "Category": "Technology", + "Quantity": "3", + "City": "Allen" + }, + { + "Category": "Technology", + "Sales": "21.479999542236328", + "City": "Allen" + }, + { + "Category": "Technology", + "Profit": "-0.26899999380111694", + "City": "Allen" + }, + { + "Category": "Furniture", + "Quantity": "2", + "City": "Allen" + }, + { + "Category": "Furniture", + "Sales": "244.00599670410156", + "City": "Allen" + }, + { + "Category": "Furniture", + "Profit": "-31.371999740600586", + "City": "Allen" + }, + { + "Category": "Office Supplies", + "Quantity": "14", + "City": "Allentown" + }, + { + "Category": "Office Supplies", + "Sales": "819.8760194778442", + "City": "Allentown" + }, + { + "Category": "Office Supplies", + "Profit": "-233.60200348496437", + "City": "Allentown" + }, + { + "Category": "Technology", + "Quantity": "4", + "City": "Allentown" + }, + { + "Category": "Technology", + "Sales": "21.72800064086914", + "City": "Allentown" + }, + { + "Category": "Technology", + "Profit": "3.802000045776367", + "City": "Allentown" + }, + { + "Category": "Furniture", + "Quantity": "2", + "City": "Allentown" + }, + { + "Category": "Furniture", + "Sales": "11.64799976348877", + "City": "Allentown" + }, + { + "Category": "Furniture", + "Profit": "3.3489999771118164", + "City": "Allentown" + }, + { + "Category": "Office Supplies", + "Quantity": "9", + "City": "Altoona" + }, + { + "Category": "Office Supplies", + "Sales": "20.45099973678589", + "City": "Altoona" + }, + { + "Category": "Office Supplies", + "Profit": "-1.184000015258789", + "City": "Altoona" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Altoona" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Altoona" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Altoona" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Altoona" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Altoona" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Altoona" + }, + { + "Category": "Office Supplies", + "Quantity": "8", + "City": "Amarillo" + }, + { + "Category": "Office Supplies", + "Sales": "73.92000007629395", + "City": "Amarillo" + }, + { + "Category": "Office Supplies", + "Profit": "25.271999835968018", + "City": "Amarillo" + }, + { + "Category": "Technology", + "Quantity": "10", + "City": "Amarillo" + }, + { + "Category": "Technology", + "Sales": "650.5600051879883", + "City": "Amarillo" + }, + { + "Category": "Technology", + "Profit": "94.46999931335449", + "City": "Amarillo" + }, + { + "Category": "Furniture", + "Quantity": "14", + "City": "Amarillo" + }, + { + "Category": "Furniture", + "Sales": "3048.5829124450684", + "City": "Amarillo" + }, + { + "Category": "Furniture", + "Profit": "-507.70899391174316", + "City": "Amarillo" + }, + { + "Category": "Office Supplies", + "Quantity": "60", + "City": "Anaheim" + }, + { + "Category": "Office Supplies", + "Sales": "3812.2500455379486", + "City": "Anaheim" + }, + { + "Category": "Office Supplies", + "Profit": "824.0999948382378", + "City": "Anaheim" + }, + { + "Category": "Technology", + "Quantity": "7", + "City": "Anaheim" + }, + { + "Category": "Technology", + "Sales": "422.3360061645508", + "City": "Anaheim" + }, + { + "Category": "Technology", + "Profit": "47.869998931884766", + "City": "Anaheim" + }, + { + "Category": "Furniture", + "Quantity": "45", + "City": "Anaheim" + }, + { + "Category": "Furniture", + "Sales": "3752.284019470215", + "City": "Anaheim" + }, + { + "Category": "Furniture", + "Profit": "362.0360040664673", + "City": "Anaheim" + }, + { + "Category": "Office Supplies", + "Quantity": "8", + "City": "Andover" + }, + { + "Category": "Office Supplies", + "Sales": "80.94999980926514", + "City": "Andover" + }, + { + "Category": "Office Supplies", + "Profit": "35.46399974822998", + "City": "Andover" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Andover" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Andover" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Andover" + }, + { + "Category": "Furniture", + "Quantity": "5", + "City": "Andover" + }, + { + "Category": "Furniture", + "Sales": "354.8999938964844", + "City": "Andover" + }, + { + "Category": "Furniture", + "Profit": "88.7249984741211", + "City": "Andover" + }, + { + "Category": "Office Supplies", + "Quantity": "15", + "City": "Ann Arbor" + }, + { + "Category": "Office Supplies", + "Sales": "240.16300201416016", + "City": "Ann Arbor" + }, + { + "Category": "Office Supplies", + "Profit": "108.8680009841919", + "City": "Ann Arbor" + }, + { + "Category": "Technology", + "Quantity": "8", + "City": "Ann Arbor" + }, + { + "Category": "Technology", + "Sales": "649.1100120544434", + "City": "Ann Arbor" + }, + { + "Category": "Technology", + "Profit": "120.04700374603271", + "City": "Ann Arbor" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Ann Arbor" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Ann Arbor" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Ann Arbor" + }, + { + "Category": "Office Supplies", + "Quantity": "3", + "City": "Antioch" + }, + { + "Category": "Office Supplies", + "Sales": "19.440000534057617", + "City": "Antioch" + }, + { + "Category": "Office Supplies", + "Profit": "9.331000328063965", + "City": "Antioch" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Antioch" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Antioch" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Antioch" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Antioch" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Antioch" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Antioch" + }, + { + "Category": "Office Supplies", + "Quantity": "25", + "City": "Apopka" + }, + { + "Category": "Office Supplies", + "Sales": "774.6660053730011", + "City": "Apopka" + }, + { + "Category": "Office Supplies", + "Profit": "41.375", + "City": "Apopka" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Apopka" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Apopka" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Apopka" + }, + { + "Category": "Furniture", + "Quantity": "6", + "City": "Apopka" + }, + { + "Category": "Furniture", + "Sales": "129.88800048828125", + "City": "Apopka" + }, + { + "Category": "Furniture", + "Profit": "12.98900032043457", + "City": "Apopka" + }, + { + "Category": "Office Supplies", + "Quantity": "19", + "City": "Apple Valley" + }, + { + "Category": "Office Supplies", + "Sales": "251.76000690460205", + "City": "Apple Valley" + }, + { + "Category": "Office Supplies", + "Profit": "59.69400119781494", + "City": "Apple Valley" + }, + { + "Category": "Technology", + "Quantity": "3", + "City": "Apple Valley" + }, + { + "Category": "Technology", + "Sales": "43.17599868774414", + "City": "Apple Valley" + }, + { + "Category": "Technology", + "Profit": "15.112000465393066", + "City": "Apple Valley" + }, + { + "Category": "Furniture", + "Quantity": "10", + "City": "Apple Valley" + }, + { + "Category": "Furniture", + "Sales": "1758.0850219726562", + "City": "Apple Valley" + }, + { + "Category": "Furniture", + "Profit": "217.78400039672852", + "City": "Apple Valley" + }, + { + "Category": "Office Supplies", + "Quantity": "7", + "City": "Appleton" + }, + { + "Category": "Office Supplies", + "Sales": "21.559999465942383", + "City": "Appleton" + }, + { + "Category": "Office Supplies", + "Profit": "10.348999977111816", + "City": "Appleton" + }, + { + "Category": "Technology", + "Quantity": "5", + "City": "Appleton" + }, + { + "Category": "Technology", + "Sales": "1649.75", + "City": "Appleton" + }, + { + "Category": "Technology", + "Profit": "544.4169921875", + "City": "Appleton" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Appleton" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Appleton" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Appleton" + }, + { + "Category": "Office Supplies", + "Quantity": "160", + "City": "Arlington" + }, + { + "Category": "Office Supplies", + "Sales": "3773.852028489113", + "City": "Arlington" + }, + { + "Category": "Office Supplies", + "Profit": "349.5840001106262", + "City": "Arlington" + }, + { + "Category": "Technology", + "Quantity": "48", + "City": "Arlington" + }, + { + "Category": "Technology", + "Sales": "12797.406238555908", + "City": "Arlington" + }, + { + "Category": "Technology", + "Profit": "3805.245924949646", + "City": "Arlington" + }, + { + "Category": "Furniture", + "Quantity": "51", + "City": "Arlington" + }, + { + "Category": "Furniture", + "Sales": "3643.2739720344543", + "City": "Arlington" + }, + { + "Category": "Furniture", + "Profit": "14.86799430847168", + "City": "Arlington" + }, + { + "Category": "Office Supplies", + "Quantity": "6", + "City": "Arlington Heights" + }, + { + "Category": "Office Supplies", + "Sales": "14.112000465393066", + "City": "Arlington Heights" + }, + { + "Category": "Office Supplies", + "Profit": "1.2350000143051147", + "City": "Arlington Heights" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Arlington Heights" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Arlington Heights" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Arlington Heights" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Arlington Heights" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Arlington Heights" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Arlington Heights" + }, + { + "Category": "Office Supplies", + "Quantity": "3", + "City": "Arvada" + }, + { + "Category": "Office Supplies", + "Sales": "6.263999938964844", + "City": "Arvada" + }, + { + "Category": "Office Supplies", + "Profit": "2.0360000133514404", + "City": "Arvada" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Arvada" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Arvada" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Arvada" + }, + { + "Category": "Furniture", + "Quantity": "7", + "City": "Arvada" + }, + { + "Category": "Furniture", + "Sales": "497.1360054016113", + "City": "Arvada" + }, + { + "Category": "Furniture", + "Profit": "57.82000160217285", + "City": "Arvada" + }, + { + "Category": "Office Supplies", + "Quantity": "23", + "City": "Asheville" + }, + { + "Category": "Office Supplies", + "Sales": "111.41599893569946", + "City": "Asheville" + }, + { + "Category": "Office Supplies", + "Profit": "-7.741000175476074", + "City": "Asheville" + }, + { + "Category": "Technology", + "Quantity": "5", + "City": "Asheville" + }, + { + "Category": "Technology", + "Sales": "1363.9599609375", + "City": "Asheville" + }, + { + "Category": "Technology", + "Profit": "85.24700164794922", + "City": "Asheville" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Asheville" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Asheville" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Asheville" + }, + { + "Category": "Office Supplies", + "Quantity": "14", + "City": "Athens" + }, + { + "Category": "Office Supplies", + "Sales": "198.24999332427979", + "City": "Athens" + }, + { + "Category": "Office Supplies", + "Profit": "59.85999774932861", + "City": "Athens" + }, + { + "Category": "Technology", + "Quantity": "13", + "City": "Athens" + }, + { + "Category": "Technology", + "Sales": "1336.0200576782227", + "City": "Athens" + }, + { + "Category": "Technology", + "Profit": "378.4230098724365", + "City": "Athens" + }, + { + "Category": "Furniture", + "Quantity": "3", + "City": "Athens" + }, + { + "Category": "Furniture", + "Sales": "186.5399932861328", + "City": "Athens" + }, + { + "Category": "Furniture", + "Profit": "41.03900146484375", + "City": "Athens" + }, + { + "Category": "Office Supplies", + "Quantity": "115", + "City": "Atlanta" + }, + { + "Category": "Office Supplies", + "Sales": "11011.940182685852", + "City": "Atlanta" + }, + { + "Category": "Office Supplies", + "Profit": "4833.85907793045", + "City": "Atlanta" + }, + { + "Category": "Technology", + "Quantity": "24", + "City": "Atlanta" + }, + { + "Category": "Technology", + "Sales": "4333.559967041016", + "City": "Atlanta" + }, + { + "Category": "Technology", + "Profit": "1744.5989561080933", + "City": "Atlanta" + }, + { + "Category": "Furniture", + "Quantity": "17", + "City": "Atlanta" + }, + { + "Category": "Furniture", + "Sales": "1852.3399353027344", + "City": "Atlanta" + }, + { + "Category": "Furniture", + "Profit": "415.2059965133667", + "City": "Atlanta" + }, + { + "Category": "Office Supplies", + "Quantity": "2", + "City": "Atlantic City" + }, + { + "Category": "Office Supplies", + "Sales": "23.360000610351562", + "City": "Atlantic City" + }, + { + "Category": "Office Supplies", + "Profit": "11.680000305175781", + "City": "Atlantic City" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Atlantic City" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Atlantic City" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Atlantic City" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Atlantic City" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Atlantic City" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Atlantic City" + }, + { + "Category": "Office Supplies", + "Quantity": "69", + "City": "Auburn" + }, + { + "Category": "Office Supplies", + "Sales": "2244.8380155563354", + "City": "Auburn" + }, + { + "Category": "Office Supplies", + "Profit": "567.2389969229698", + "City": "Auburn" + }, + { + "Category": "Technology", + "Quantity": "4", + "City": "Auburn" + }, + { + "Category": "Technology", + "Sales": "35.119998931884766", + "City": "Auburn" + }, + { + "Category": "Technology", + "Profit": "9.130999565124512", + "City": "Auburn" + }, + { + "Category": "Furniture", + "Quantity": "7", + "City": "Auburn" + }, + { + "Category": "Furniture", + "Sales": "875.2099986076355", + "City": "Auburn" + }, + { + "Category": "Furniture", + "Profit": "158.54699981212616", + "City": "Auburn" + }, + { + "Category": "Office Supplies", + "Quantity": "140", + "City": "Aurora" + }, + { + "Category": "Office Supplies", + "Sales": "3308.089991927147", + "City": "Aurora" + }, + { + "Category": "Office Supplies", + "Profit": "-392.2250031232834", + "City": "Aurora" + }, + { + "Category": "Technology", + "Quantity": "47", + "City": "Aurora" + }, + { + "Category": "Technology", + "Sales": "3108.4079661369324", + "City": "Aurora" + }, + { + "Category": "Technology", + "Profit": "291.6539967060089", + "City": "Aurora" + }, + { + "Category": "Furniture", + "Quantity": "71", + "City": "Aurora" + }, + { + "Category": "Furniture", + "Sales": "5239.980005264282", + "City": "Aurora" + }, + { + "Category": "Furniture", + "Profit": "-2591.1669788360596", + "City": "Aurora" + }, + { + "Category": "Office Supplies", + "Quantity": "93", + "City": "Austin" + }, + { + "Category": "Office Supplies", + "Sales": "2859.2999608516693", + "City": "Austin" + }, + { + "Category": "Office Supplies", + "Profit": "-61.0089918076992", + "City": "Austin" + }, + { + "Category": "Technology", + "Quantity": "29", + "City": "Austin" + }, + { + "Category": "Technology", + "Sales": "2662.998046875", + "City": "Austin" + }, + { + "Category": "Technology", + "Profit": "75.02499508857727", + "City": "Austin" + }, + { + "Category": "Furniture", + "Quantity": "9", + "City": "Austin" + }, + { + "Category": "Furniture", + "Sales": "535.6840033531189", + "City": "Austin" + }, + { + "Category": "Furniture", + "Profit": "-34.41000056266785", + "City": "Austin" + }, + { + "Category": "Office Supplies", + "Quantity": "16", + "City": "Avondale" + }, + { + "Category": "Office Supplies", + "Sales": "79.03200149536133", + "City": "Avondale" + }, + { + "Category": "Office Supplies", + "Profit": "7.819999933242798", + "City": "Avondale" + }, + { + "Category": "Technology", + "Quantity": "14", + "City": "Avondale" + }, + { + "Category": "Technology", + "Sales": "867.7759971618652", + "City": "Avondale" + }, + { + "Category": "Technology", + "Profit": "68.3490002155304", + "City": "Avondale" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Avondale" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Avondale" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Avondale" + }, + { + "Category": "Office Supplies", + "Quantity": "33", + "City": "Bakersfield" + }, + { + "Category": "Office Supplies", + "Sales": "327.737998008728", + "City": "Bakersfield" + }, + { + "Category": "Office Supplies", + "Profit": "122.97699844837189", + "City": "Bakersfield" + }, + { + "Category": "Technology", + "Quantity": "2", + "City": "Bakersfield" + }, + { + "Category": "Technology", + "Sales": "201.58399963378906", + "City": "Bakersfield" + }, + { + "Category": "Technology", + "Profit": "12.598999977111816", + "City": "Bakersfield" + }, + { + "Category": "Furniture", + "Quantity": "12", + "City": "Bakersfield" + }, + { + "Category": "Furniture", + "Sales": "847.9680099487305", + "City": "Bakersfield" + }, + { + "Category": "Furniture", + "Profit": "52.348999977111816", + "City": "Bakersfield" + }, + { + "Category": "Office Supplies", + "Quantity": "120", + "City": "Baltimore" + }, + { + "Category": "Office Supplies", + "Sales": "1637.9699934720993", + "City": "Baltimore" + }, + { + "Category": "Office Supplies", + "Profit": "617.63499802351", + "City": "Baltimore" + }, + { + "Category": "Technology", + "Quantity": "18", + "City": "Baltimore" + }, + { + "Category": "Technology", + "Sales": "503.0400085449219", + "City": "Baltimore" + }, + { + "Category": "Technology", + "Profit": "133.524995803833", + "City": "Baltimore" + }, + { + "Category": "Furniture", + "Quantity": "46", + "City": "Baltimore" + }, + { + "Category": "Furniture", + "Sales": "4015.8319511413574", + "City": "Baltimore" + }, + { + "Category": "Furniture", + "Profit": "925.0369925498962", + "City": "Baltimore" + }, + { + "Category": "Office Supplies", + "Quantity": "15", + "City": "Bangor" + }, + { + "Category": "Office Supplies", + "Sales": "361.69998931884766", + "City": "Bangor" + }, + { + "Category": "Office Supplies", + "Profit": "152.2040023803711", + "City": "Bangor" + }, + { + "Category": "Technology", + "Quantity": "12", + "City": "Bangor" + }, + { + "Category": "Technology", + "Sales": "693.2700042724609", + "City": "Bangor" + }, + { + "Category": "Technology", + "Profit": "236.07699584960938", + "City": "Bangor" + }, + { + "Category": "Furniture", + "Quantity": "2", + "City": "Bangor" + }, + { + "Category": "Furniture", + "Sales": "109.4800033569336", + "City": "Bangor" + }, + { + "Category": "Furniture", + "Profit": "33.93899917602539", + "City": "Bangor" + }, + { + "Category": "Office Supplies", + "Quantity": "8", + "City": "Bartlett" + }, + { + "Category": "Office Supplies", + "Sales": "88.95999908447266", + "City": "Bartlett" + }, + { + "Category": "Office Supplies", + "Profit": "10.008000373840332", + "City": "Bartlett" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Bartlett" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Bartlett" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Bartlett" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Bartlett" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Bartlett" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Bartlett" + }, + { + "Category": "Office Supplies", + "Quantity": "3", + "City": "Bayonne" + }, + { + "Category": "Office Supplies", + "Sales": "14.460000038146973", + "City": "Bayonne" + }, + { + "Category": "Office Supplies", + "Profit": "7.085000038146973", + "City": "Bayonne" + }, + { + "Category": "Technology", + "Quantity": "6", + "City": "Bayonne" + }, + { + "Category": "Technology", + "Sales": "168.94000244140625", + "City": "Bayonne" + }, + { + "Category": "Technology", + "Profit": "72.31800079345703", + "City": "Bayonne" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Bayonne" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Bayonne" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Bayonne" + }, + { + "Category": "Office Supplies", + "Quantity": "2", + "City": "Baytown" + }, + { + "Category": "Office Supplies", + "Sales": "10.368000030517578", + "City": "Baytown" + }, + { + "Category": "Office Supplies", + "Profit": "3.628999948501587", + "City": "Baytown" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Baytown" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Baytown" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Baytown" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Baytown" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Baytown" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Baytown" + }, + { + "Category": "Office Supplies", + "Quantity": "7", + "City": "Beaumont" + }, + { + "Category": "Office Supplies", + "Sales": "23.547999382019043", + "City": "Beaumont" + }, + { + "Category": "Office Supplies", + "Profit": "-16.289999186992645", + "City": "Beaumont" + }, + { + "Category": "Technology", + "Quantity": "7", + "City": "Beaumont" + }, + { + "Category": "Technology", + "Sales": "439.94398498535156", + "City": "Beaumont" + }, + { + "Category": "Technology", + "Profit": "77.99399757385254", + "City": "Beaumont" + }, + { + "Category": "Furniture", + "Quantity": "7", + "City": "Beaumont" + }, + { + "Category": "Furniture", + "Sales": "8.62399959564209", + "City": "Beaumont" + }, + { + "Category": "Furniture", + "Profit": "-2.5869998931884766", + "City": "Beaumont" + }, + { + "Category": "Office Supplies", + "Quantity": "23", + "City": "Bedford" + }, + { + "Category": "Office Supplies", + "Sales": "72.67199897766113", + "City": "Bedford" + }, + { + "Category": "Office Supplies", + "Profit": "-2.8179993629455566", + "City": "Bedford" + }, + { + "Category": "Technology", + "Quantity": "2", + "City": "Bedford" + }, + { + "Category": "Technology", + "Sales": "153.58399963378906", + "City": "Bedford" + }, + { + "Category": "Technology", + "Profit": "13.439000129699707", + "City": "Bedford" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Bedford" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Bedford" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Bedford" + }, + { + "Category": "Office Supplies", + "Quantity": "23", + "City": "Belleville" + }, + { + "Category": "Office Supplies", + "Sales": "1346.069978237152", + "City": "Belleville" + }, + { + "Category": "Office Supplies", + "Profit": "137.16099667549133", + "City": "Belleville" + }, + { + "Category": "Technology", + "Quantity": "3", + "City": "Belleville" + }, + { + "Category": "Technology", + "Sales": "239.97000122070312", + "City": "Belleville" + }, + { + "Category": "Technology", + "Profit": "71.99099731445312", + "City": "Belleville" + }, + { + "Category": "Furniture", + "Quantity": "6", + "City": "Belleville" + }, + { + "Category": "Furniture", + "Sales": "305.5600051879883", + "City": "Belleville" + }, + { + "Category": "Furniture", + "Profit": "74.49799728393555", + "City": "Belleville" + }, + { + "Category": "Office Supplies", + "Quantity": "17", + "City": "Bellevue" + }, + { + "Category": "Office Supplies", + "Sales": "83.38200044631958", + "City": "Bellevue" + }, + { + "Category": "Office Supplies", + "Profit": "29.16100013256073", + "City": "Bellevue" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Bellevue" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Bellevue" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Bellevue" + }, + { + "Category": "Furniture", + "Quantity": "1", + "City": "Bellevue" + }, + { + "Category": "Furniture", + "Sales": "20.239999771118164", + "City": "Bellevue" + }, + { + "Category": "Furniture", + "Profit": "7.894000053405762", + "City": "Bellevue" + }, + { + "Category": "Office Supplies", + "Quantity": "5", + "City": "Bellingham" + }, + { + "Category": "Office Supplies", + "Sales": "25.1200008392334", + "City": "Bellingham" + }, + { + "Category": "Office Supplies", + "Profit": "7.849999904632568", + "City": "Bellingham" + }, + { + "Category": "Technology", + "Quantity": "10", + "City": "Bellingham" + }, + { + "Category": "Technology", + "Sales": "1099.5", + "City": "Bellingham" + }, + { + "Category": "Technology", + "Profit": "362.8349914550781", + "City": "Bellingham" + }, + { + "Category": "Furniture", + "Quantity": "9", + "City": "Bellingham" + }, + { + "Category": "Furniture", + "Sales": "2665.6201171875", + "City": "Bellingham" + }, + { + "Category": "Furniture", + "Profit": "239.906005859375", + "City": "Bellingham" + }, + { + "Category": "Office Supplies", + "Quantity": "9", + "City": "Bethlehem" + }, + { + "Category": "Office Supplies", + "Sales": "1379.2440376281738", + "City": "Bethlehem" + }, + { + "Category": "Office Supplies", + "Profit": "-912.4650253653526", + "City": "Bethlehem" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Bethlehem" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Bethlehem" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Bethlehem" + }, + { + "Category": "Furniture", + "Quantity": "9", + "City": "Bethlehem" + }, + { + "Category": "Furniture", + "Sales": "310.38999938964844", + "City": "Bethlehem" + }, + { + "Category": "Furniture", + "Profit": "-90.63100290298462", + "City": "Bethlehem" + }, + { + "Category": "Office Supplies", + "Quantity": "15", + "City": "Beverly" + }, + { + "Category": "Office Supplies", + "Sales": "2583.1900482177734", + "City": "Beverly" + }, + { + "Category": "Office Supplies", + "Profit": "654.9190139770508", + "City": "Beverly" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Beverly" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Beverly" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Beverly" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Beverly" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Beverly" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Beverly" + }, + { + "Category": "Office Supplies", + "Quantity": "2", + "City": "Billings" + }, + { + "Category": "Office Supplies", + "Sales": "8.288000106811523", + "City": "Billings" + }, + { + "Category": "Office Supplies", + "Profit": "2.694000005722046", + "City": "Billings" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Billings" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Billings" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Billings" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Billings" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Billings" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Billings" + }, + { + "Category": "Office Supplies", + "Quantity": "41", + "City": "Bloomington" + }, + { + "Category": "Office Supplies", + "Sales": "605.8720030784607", + "City": "Bloomington" + }, + { + "Category": "Office Supplies", + "Profit": "111.08999979496002", + "City": "Bloomington" + }, + { + "Category": "Technology", + "Quantity": "6", + "City": "Bloomington" + }, + { + "Category": "Technology", + "Sales": "174.66600799560547", + "City": "Bloomington" + }, + { + "Category": "Technology", + "Profit": "45.222999572753906", + "City": "Bloomington" + }, + { + "Category": "Furniture", + "Quantity": "11", + "City": "Bloomington" + }, + { + "Category": "Furniture", + "Sales": "787.2020072937012", + "City": "Bloomington" + }, + { + "Category": "Furniture", + "Profit": "-405.66800689697266", + "City": "Bloomington" + }, + { + "Category": "Office Supplies", + "Quantity": "6", + "City": "Boca Raton" + }, + { + "Category": "Office Supplies", + "Sales": "44.54400062561035", + "City": "Boca Raton" + }, + { + "Category": "Office Supplies", + "Profit": "-24.95400059223175", + "City": "Boca Raton" + }, + { + "Category": "Technology", + "Quantity": "2", + "City": "Boca Raton" + }, + { + "Category": "Technology", + "Sales": "18.464000701904297", + "City": "Boca Raton" + }, + { + "Category": "Technology", + "Profit": "2.308000087738037", + "City": "Boca Raton" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Boca Raton" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Boca Raton" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Boca Raton" + }, + { + "Category": "Office Supplies", + "Quantity": "1", + "City": "Boise" + }, + { + "Category": "Office Supplies", + "Sales": "3.303999900817871", + "City": "Boise" + }, + { + "Category": "Office Supplies", + "Profit": "1.1150000095367432", + "City": "Boise" + }, + { + "Category": "Technology", + "Quantity": "6", + "City": "Boise" + }, + { + "Category": "Technology", + "Sales": "394.7460021972656", + "City": "Boise" + }, + { + "Category": "Technology", + "Profit": "60.64499855041504", + "City": "Boise" + }, + { + "Category": "Furniture", + "Quantity": "2", + "City": "Boise" + }, + { + "Category": "Furniture", + "Sales": "696.4199829101562", + "City": "Boise" + }, + { + "Category": "Furniture", + "Profit": "160.177001953125", + "City": "Boise" + }, + { + "Category": "Office Supplies", + "Quantity": "21", + "City": "Bolingbrook" + }, + { + "Category": "Office Supplies", + "Sales": "69.82799959182739", + "City": "Bolingbrook" + }, + { + "Category": "Office Supplies", + "Profit": "-21.364999294281006", + "City": "Bolingbrook" + }, + { + "Category": "Technology", + "Quantity": "2", + "City": "Bolingbrook" + }, + { + "Category": "Technology", + "Sales": "148.47999572753906", + "City": "Bolingbrook" + }, + { + "Category": "Technology", + "Profit": "16.70400047302246", + "City": "Bolingbrook" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Bolingbrook" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Bolingbrook" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Bolingbrook" + }, + { + "Category": "Office Supplies", + "Quantity": "14", + "City": "Bossier City" + }, + { + "Category": "Office Supplies", + "Sales": "640.5200152397156", + "City": "Bossier City" + }, + { + "Category": "Office Supplies", + "Profit": "67.8709990978241", + "City": "Bossier City" + }, + { + "Category": "Technology", + "Quantity": "6", + "City": "Bossier City" + }, + { + "Category": "Technology", + "Sales": "646.739990234375", + "City": "Bossier City" + }, + { + "Category": "Technology", + "Profit": "258.6960144042969", + "City": "Bossier City" + }, + { + "Category": "Furniture", + "Quantity": "4", + "City": "Bossier City" + }, + { + "Category": "Furniture", + "Sales": "129.9199981689453", + "City": "Bossier City" + }, + { + "Category": "Furniture", + "Profit": "10.394000053405762", + "City": "Bossier City" + }, + { + "Category": "Office Supplies", + "Quantity": "14", + "City": "Bowling Green" + }, + { + "Category": "Office Supplies", + "Sales": "798.6410026550293", + "City": "Bowling Green" + }, + { + "Category": "Office Supplies", + "Profit": "72.6489987373352", + "City": "Bowling Green" + }, + { + "Category": "Technology", + "Quantity": "15", + "City": "Bowling Green" + }, + { + "Category": "Technology", + "Sales": "1137.9240016937256", + "City": "Bowling Green" + }, + { + "Category": "Technology", + "Profit": "104.98500156402588", + "City": "Bowling Green" + }, + { + "Category": "Furniture", + "Quantity": "1", + "City": "Bowling Green" + }, + { + "Category": "Furniture", + "Sales": "140.80999755859375", + "City": "Bowling Green" + }, + { + "Category": "Furniture", + "Profit": "39.426998138427734", + "City": "Bowling Green" + }, + { + "Category": "Office Supplies", + "Quantity": "18", + "City": "Boynton Beach" + }, + { + "Category": "Office Supplies", + "Sales": "95.43299865722656", + "City": "Boynton Beach" + }, + { + "Category": "Office Supplies", + "Profit": "-10.462000489234924", + "City": "Boynton Beach" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Boynton Beach" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Boynton Beach" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Boynton Beach" + }, + { + "Category": "Furniture", + "Quantity": "10", + "City": "Boynton Beach" + }, + { + "Category": "Furniture", + "Sales": "374.1520004272461", + "City": "Boynton Beach" + }, + { + "Category": "Furniture", + "Profit": "61.12200117111206", + "City": "Boynton Beach" + }, + { + "Category": "Office Supplies", + "Quantity": "5", + "City": "Bozeman" + }, + { + "Category": "Office Supplies", + "Sales": "43.660000801086426", + "City": "Bozeman" + }, + { + "Category": "Office Supplies", + "Profit": "20.80999994277954", + "City": "Bozeman" + }, + { + "Category": "Technology", + "Quantity": null, + "City": "Bozeman" + }, + { + "Category": "Technology", + "Sales": null, + "City": "Bozeman" + }, + { + "Category": "Technology", + "Profit": null, + "City": "Bozeman" + }, + { + "Category": "Furniture", + "Quantity": null, + "City": "Bozeman" + }, + { + "Category": "Furniture", + "Sales": null, + "City": "Bozeman" + }, + { + "Category": "Furniture", + "Profit": null, + "City": "Bozeman" + }, + { + "Category": "Office Supplies", + "Quantity": "44", + "City": "Brentwood" + }, + { + "Category": "Office Supplies", + "Sales": "3772.8760557174683", + "City": "Brentwood" + }, + { + "Category": "Office Supplies", + "Profit": "1045.7260146141052", + "City": "Brentwood" + }, + { + "Category": "Technology", + "Quantity": "19", + "City": "Brentwood" + }, + { + "Category": "Technology", + "Sales": "1293.3579940795898", + "City": "Brentwood" + }, + { + "Category": "Technology", + "Profit": "160.57699871063232", + "City": "Brentwood" + }, + { + "Category": "Furniture", + "Quantity": "3", + "City": "Brentwood" + }, + { + "Category": "Furniture", + "Sales": "23.8799991607666", + "City": "Brentwood" + }, + { + "Category": "Furniture", + "Profit": "10.506999969482422", + "City": "Brentwood" + } +] \ No newline at end of file diff --git a/packages/react-vtable/demo/src/App.tsx b/packages/react-vtable/demo/src/App.tsx index bbfe21696..270912c61 100644 --- a/packages/react-vtable/demo/src/App.tsx +++ b/packages/react-vtable/demo/src/App.tsx @@ -18,6 +18,7 @@ import customLayout from './component/custom-layout'; import customLayoutDom from './component/custom-layout-dom'; import customLayoutDomSite from './component/custom-layout-dom-site'; import customLayoutDomSite1 from './component/custom-layout-dom-site-1'; +import customLayoutPivot from './component/custom-layout-pivot'; // export default listEditor; // export default listOptionRecord; @@ -34,7 +35,8 @@ import customLayoutDomSite1 from './component/custom-layout-dom-site-1'; // export default eventRebind; // export default componentContainer; -export default customLayout; +// export default customLayout; // export default customLayoutDom; -// export default customLayoutDomSite; +export default customLayoutDomSite; // export default customLayoutDomSite1; +// export default customLayoutPivot; diff --git a/packages/react-vtable/demo/src/component/custom-layout-dom-site.tsx b/packages/react-vtable/demo/src/component/custom-layout-dom-site.tsx index 7191c10e9..ff8a0ff5b 100644 --- a/packages/react-vtable/demo/src/component/custom-layout-dom-site.tsx +++ b/packages/react-vtable/demo/src/component/custom-layout-dom-site.tsx @@ -9,6 +9,58 @@ const { Meta } = Card; import '@arco-design/web-react/dist/css/arco.css'; +const HeaderCustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string }) => { + const { table, row, col, rect, text } = props; + if (!table || row === undefined || col === undefined) { + return null; + } + const { height, width } = rect || table.getCellRect(col, row); + const [hover, setHover] = useState(false); + + const groupRef = useRef(null); + + return ( + + { + // eslint-disable-next-line no-console, no-undef + console.log('groupRef-header', groupRef.current); + setHover(true); + event.currentTarget.stage.renderNextFrame(); + }} + onMouseLeave={(event: any) => { + setHover(false); + event.currentTarget.stage.renderNextFrame(); + }} + > + {/* {hover && ( + // to do: component add/remove sync + + )} */} + + ); +}; + const UserProfileComponent = (props: CustomLayoutFunctionArg) => { const { table, row, col, rect, dataValue } = props; if (!table || row === undefined || col === undefined) { @@ -35,7 +87,7 @@ const UserProfileComponent = (props: CustomLayoutFunctionArg) => { attribute={{ width: 190, height: 25, - fill: '#e6fffb', + // fill: '#e6fffb', lineWidth: 1, cornerRadius: 10, display: 'flex', @@ -209,17 +261,24 @@ function App() { // defaultRowHeight={80} onReady={table => { // eslint-disable-next-line no-undef - // (window as any).tableInstance = table; + (window as any).tableInstance = table; }} ReactDOM={ReactDOM} + rowSeriesNumber={{ title: '序号' }} + dragHeaderMode="column" > - - + + + + + + + + + + - - - ); } diff --git a/packages/react-vtable/demo/src/component/custom-layout-pivot.tsx b/packages/react-vtable/demo/src/component/custom-layout-pivot.tsx new file mode 100644 index 000000000..8c6ae7ffe --- /dev/null +++ b/packages/react-vtable/demo/src/component/custom-layout-pivot.tsx @@ -0,0 +1,219 @@ +import { useRef, useState } from 'react'; +import ReactDOM from 'react-dom/client'; +import type { CustomLayoutFunctionArg } from '../../../src'; +import { + PivotColumnDimension, + PivotRowDimension, + PivotIndicator, + PivotColumnHeaderTitle, + PivotTable, + PivotCorner, + Tooltip, + Group, + Text, + Image +} from '../../../src'; +import pivotData from '../../data/pivot-data.json'; +import { Avatar, Button, Card, Popover, Space, Typography } from '@arco-design/web-react'; +import { IconThumbUp, IconShareInternal, IconMore } from '@arco-design/web-react/icon'; +const { Meta } = Card; + +import '@arco-design/web-react/dist/css/arco.css'; + +const HeaderCustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string }) => { + const { table, row, col, rect, text, value } = props; + if (!table || row === undefined || col === undefined) { + return null; + } + const { height, width } = rect || table.getCellRect(col, row); + const [hover, setHover] = useState(false); + + const groupRef = useRef(null); + + return ( + + { + // eslint-disable-next-line no-console, no-undef + console.log('groupRef-header', groupRef.current); + setHover(true); + event.currentTarget.stage.renderNextFrame(); + }} + onMouseLeave={(event: any) => { + setHover(false); + event.currentTarget.stage.renderNextFrame(); + }} + > + {/* {hover && ( + // to do: component add/remove sync + + )} */} + + ); +}; + +const UserProfileComponent = (props: CustomLayoutFunctionArg) => { + const { table, row, col, rect, dataValue } = props; + if (!table || row === undefined || col === undefined) { + return null; + } + const { height, width } = rect || table.getCellRect(col, row); + const record = table.getRecordByCell(col, row); + + const [hover, setHover] = useState(false); + + return ( + + + } + }} + onMouseEnter={(event: any) => { + setHover(true); + event.currentTarget.stage.renderNextFrame(); // to do: auto execute in react-vtable + }} + onMouseLeave={(event: any) => { + setHover(false); + event.currentTarget.stage.renderNextFrame(); + }} + > + + + + ); +}; + +const CardInfo = (props: { record: any; hover: boolean; row?: number }) => { + // const { bloggerName, bloggerAvatar, introduction, city } = props.record; + const bloggerAvatar = 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg'; + const introduction = + 'Hi everyone, I am Xiaohua, the virtual host. I am a little fairy who likes games, animation and food.'; + const city = 'Dream City'; + const bloggerName = 'Virtual Anchor Xiaohua'; + + return props.hover ? ( + + dessert + + } + actions={[ + + + , + + + , + + + + ]} + > + + {city.slice(0, 1)} + {city} + + } + title={bloggerName} + description={introduction} + /> + + ) : null; +}; + +function App() { + return ( + { + // eslint-disable-next-line no-undef + (window as any).tableInstance = table; + }} + > + + + + + + + + + + + {/* */} + + ); +} + +export default App; diff --git a/packages/vtable/src/components/react/react-custom-layout.ts b/packages/vtable/src/components/react/react-custom-layout.ts index 859a4aef2..cf822ff75 100644 --- a/packages/vtable/src/components/react/react-custom-layout.ts +++ b/packages/vtable/src/components/react/react-custom-layout.ts @@ -1,6 +1,8 @@ import { Group } from '@src/vrender'; import type { CustomRenderFunctionArg, ICustomLayoutFuc } from '../../ts-types'; import type { BaseTableAPI } from '../../ts-types/base-table'; +import type { PivotHeaderLayoutMap } from '../../layout/pivot-header-layout'; +import type { SimpleHeaderLayoutMap } from '../../layout'; export function emptyCustomLayout(args: CustomRenderFunctionArg) { const group = new Group({}); @@ -74,10 +76,22 @@ export class ReactCustomLayout { // } // } - const range = getUpdateCustomCellRange(componentId, table, isHeaderCustomLayout); - for (let col = range.startCol; col <= range.endCol; col++) { - for (let row = range.startRow; row <= range.endRow; row++) { - table.scenegraph.updateCellContent(col, row); + if (table.isPivotTable()) { + const ranges = getUpdateCustomCellRangeInPivotTable(componentId, table, isHeaderCustomLayout); + for (let i = 0; i < ranges.length; i++) { + const range = ranges[i]; + for (let col = range.start.col; col <= range.end.col; col++) { + for (let row = range.start.row; row <= range.end.row; row++) { + table.scenegraph.updateCellContent(col, row); + } + } + } + } else { + const range = getUpdateCustomCellRangeInListTable(componentId, table, isHeaderCustomLayout); + for (let col = range.start.col; col <= range.end.col; col++) { + for (let row = range.start.row; row <= range.end.row; row++) { + table.scenegraph.updateCellContent(col, row); + } } } // table.scenegraph.updateNextFrame(); @@ -95,104 +109,208 @@ export class ReactCustomLayout { } removeCustomCell(col: number, row: number) { - const { startInTotal } = this.table.getBodyColumnDefine(col, row) as any; + // const { startInTotal } = this.table.getBodyColumnDefine(col, row) as any; const isHeader = this.table.isHeader(col, row); - const removeFun = isHeader - ? this.headerReactRemoveGraphicCache.get(startInTotal) - : this.reactRemoveGraphicCache.get(startInTotal); + let removeFun; + if (isHeader) { + const define = this.table.getHeaderDefine(col, row); + const { componentId } = define as any; + removeFun = this.headerReactRemoveGraphicCache.get(componentId); + } else { + const define = this.table.getBodyColumnDefine(col, row); + const { componentId } = define as any; + removeFun = this.reactRemoveGraphicCache.get(componentId); + } if (removeFun) { removeFun(col, row); } } } -function getUpdateCustomCellRange(componentId: string, table: BaseTableAPI, isHeaderCustomLayout?: boolean) { +function getUpdateCustomCellRangeInListTable(componentId: string, table: BaseTableAPI, isHeaderCustomLayout?: boolean) { const rowSeriesNumber = table.internalProps.rowSeriesNumber ? 1 : 0; if (isHeaderCustomLayout) { - const { headerObjects, _headerCellIds } = table.internalProps.layoutMap as any; - const { transpose } = table.internalProps; - let headerId; + const layoutMap = table.internalProps.layoutMap as SimpleHeaderLayoutMap; + const { headerObjects } = table.internalProps.layoutMap; + let headerId: number; for (let i = 0; i < headerObjects.length; i++) { const headerObject = headerObjects[i]; if ((headerObject.define as any).componentId === componentId) { - headerId = headerObject.id; + headerId = headerObject.id as number; break; } } - let startCol = -1; - let endCol = -1; - let startRow = -1; - let endRow = -1; - for (let i = 0; i < _headerCellIds.length; i++) { - const row = _headerCellIds[i]; - let rowHasObject = false; - for (let j = 0; j < row.length; j++) { - if (row[j] === headerId) { - rowHasObject = true; - if (transpose) { - // return { col: i, row: j }; - startCol === -1 && (startCol = i); - startRow === -1 && (startRow = j); - } else { - // return { col: j + this.leftRowSeriesNumberColumnCount, row: i }; - startCol === -1 && (startCol = j); - startRow === -1 && (startRow = i); - } - } else { - if (transpose) { - // endCol === -1 && startCol !== -1 && (endCol = i); - endRow === -1 && startRow !== -1 && (endRow = j - 1); - } else { - endCol === -1 && startCol !== -1 && (endCol = j - 1); - // endRow === -1 && startRow !== -1 && (endRow = i); - } - } + const startCell = layoutMap.getHeaderCellAdressById(headerId); + const range = layoutMap.getCellRange(startCell.col, startCell.row); + return range; - if (startCol !== -1 && endCol !== -1 && startRow !== -1 && endRow !== -1) { - break; - } - } + // let startCol = -1; + // let endCol = -1; + // let startRow = -1; + // let endRow = -1; + // for (let i = 0; i < _headerCellIds.length; i++) { + // const row = _headerCellIds[i]; + // let rowHasObject = false; + // for (let j = 0; j < row.length; j++) { + // if (row[j] === headerId) { + // rowHasObject = true; + // if (transpose) { + // // return { col: i, row: j }; + // startCol === -1 && (startCol = i); + // startRow === -1 && (startRow = j); + // } else { + // // return { col: j + this.leftRowSeriesNumberColumnCount, row: i }; + // startCol === -1 && (startCol = j); + // startRow === -1 && (startRow = i); + // } + // } else { + // if (transpose) { + // // endCol === -1 && startCol !== -1 && (endCol = i); + // endRow === -1 && startRow !== -1 && (endRow = j - 1); + // } else { + // endCol === -1 && startCol !== -1 && (endCol = j - 1); + // // endRow === -1 && startRow !== -1 && (endRow = i); + // } + // } - if (!rowHasObject) { - if (transpose) { - endCol === -1 && startCol !== -1 && (endCol = i - 1); - } else { - endRow === -1 && startRow !== -1 && (endRow = i - 1); - } - } + // if (startCol !== -1 && endCol !== -1 && startRow !== -1 && endRow !== -1) { + // break; + // } + // } - if (startCol !== -1 && endCol !== -1 && startRow !== -1 && endRow !== -1) { - break; - } - } + // if (!rowHasObject) { + // if (transpose) { + // endCol === -1 && startCol !== -1 && (endCol = i - 1); + // } else { + // endRow === -1 && startRow !== -1 && (endRow = i - 1); + // } + // } + + // if (startCol !== -1 && endCol !== -1 && startRow !== -1 && endRow !== -1) { + // break; + // } + // } - return { - startCol: startCol + rowSeriesNumber, - endCol: endCol + rowSeriesNumber, - startRow, - endRow - }; + // return { + // startCol: startCol + rowSeriesNumber, + // endCol: endCol + rowSeriesNumber, + // startRow, + // endRow + // }; } const { columnObjects } = table.internalProps.layoutMap; for (let i = 0; i < columnObjects.length; i++) { const columnObject = columnObjects[i]; if ((columnObject.define as any).componentId === componentId) { return { - startCol: rowSeriesNumber + i, - endCol: rowSeriesNumber + i, - startRow: table.columnHeaderLevelCount, - endRow: table.rowCount - 1 + start: { + col: rowSeriesNumber + i, + row: table.columnHeaderLevelCount + }, + end: { + col: rowSeriesNumber + i, + row: table.rowCount - 1 + } }; } } - // to do: pivot table + // return { + // start: { + // col: 0, + // row: 0 + // }, + // end: { + // col: table.colCount - 1, + // row: table.rowCount - 1 + // } + // }; +} + +function getUpdateCustomCellRangeInPivotTable( + componentId: string, + table: BaseTableAPI, + isHeaderCustomLayout?: boolean +) { + const rowSeriesNumber = table.internalProps.rowSeriesNumber ? 1 : 0; + const ranges = []; + const layoutMap = table.internalProps.layoutMap as PivotHeaderLayoutMap; + if (isHeaderCustomLayout) { + const { headerObjects } = layoutMap; + const headerIds: number[] = []; + for (let i = 0; i < headerObjects.length; i++) { + const headerObject = headerObjects[i]; + if (!headerObject) { + continue; + } + if ((headerObject.define as any).componentId === componentId) { + headerIds.push(headerObject.id as number); + } + } + + for (let i = 0; i < headerIds.length; i++) { + const headerId = headerIds[i]; + const startCell = layoutMap.getHeaderCellAdressById(headerId); + const range = layoutMap.getCellRange(startCell.col, startCell.row); + ranges.push(range); + } + } else { + let columnIndex: number; + const { columnObjects, indicatorsAsCol } = layoutMap; + for (let i = 0; i < columnObjects.length; i++) { + const columnObject = columnObjects[i]; + if ((columnObject.define as any).componentId === componentId) { + columnIndex = i; + break; + } + } + + if (indicatorsAsCol) { + for ( + let column = layoutMap.rowHeaderLevelCount + columnIndex; + column < layoutMap.colCount; + column += columnObjects.length + ) { + const range = { + start: { + col: column + rowSeriesNumber, + row: layoutMap.columnHeaderLevelCount + }, + end: { + col: column + rowSeriesNumber, + row: layoutMap.rowCount - 1 + } + }; + ranges.push(range); + } + } else { + for ( + let row = layoutMap.columnHeaderLevelCount + columnIndex; + row < layoutMap.rowCount; + row += columnObjects.length + ) { + const range = { + start: { + col: layoutMap.rowHeaderLevelCount + rowSeriesNumber, + row: row + }, + end: { + col: layoutMap.colCount - 1, + row: row + } + }; + ranges.push(range); + } + } + } + + return ranges; - return { - startCol: 0, - endCol: table.colCount - 1, - startRow: 0, - endRow: table.rowCount - 1 - }; + // return { + // startCol: 0, + // endCol: table.colCount - 1, + // startRow: 0, + // endRow: table.rowCount - 1 + // }; } From cf5cecb5d35d5c5ec1caf92031fddade0d42cc7c Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Mon, 8 Jul 2024 18:24:28 +0800 Subject: [PATCH 7/7] fix: fix react component update --- .../components/react/react-custom-layout.ts | 20 +++++++++---------- .../vtable/src/scenegraph/component/custom.ts | 3 +++ .../src/scenegraph/layout/update-height.ts | 4 ++++ .../src/scenegraph/layout/update-width.ts | 3 +++ 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/vtable/src/components/react/react-custom-layout.ts b/packages/vtable/src/components/react/react-custom-layout.ts index cf822ff75..d5067a094 100644 --- a/packages/vtable/src/components/react/react-custom-layout.ts +++ b/packages/vtable/src/components/react/react-custom-layout.ts @@ -216,16 +216,16 @@ function getUpdateCustomCellRangeInListTable(componentId: string, table: BaseTab } } - // return { - // start: { - // col: 0, - // row: 0 - // }, - // end: { - // col: table.colCount - 1, - // row: table.rowCount - 1 - // } - // }; + return { + start: { + col: 0, + row: 0 + }, + end: { + col: table.colCount - 1, + row: table.rowCount - 1 + } + }; } function getUpdateCustomCellRangeInPivotTable( diff --git a/packages/vtable/src/scenegraph/component/custom.ts b/packages/vtable/src/scenegraph/component/custom.ts index 38b484ea2..a8693912e 100644 --- a/packages/vtable/src/scenegraph/component/custom.ts +++ b/packages/vtable/src/scenegraph/component/custom.ts @@ -523,6 +523,9 @@ function onBeforeAttributeUpdate(val: Record, attribute: any) { return; } const cellGroup = getTargetCell(graphic) as Group; + if (!cellGroup || cellGroup.stage) { + return; + } const table = ((cellGroup as any).stage as any).table as BaseTableAPI; graphic.skipAttributeUpdate = true; const { mergeStartCol, mergeEndCol, mergeStartRow, mergeEndRow } = cellGroup; diff --git a/packages/vtable/src/scenegraph/layout/update-height.ts b/packages/vtable/src/scenegraph/layout/update-height.ts index ec86864ad..ace751454 100644 --- a/packages/vtable/src/scenegraph/layout/update-height.ts +++ b/packages/vtable/src/scenegraph/layout/update-height.ts @@ -187,6 +187,10 @@ export function updateCellHeight( (cell.getChildByName(CUSTOM_CONTAINER_NAME) as Group) || (cell.getChildByName(CUSTOM_MERGE_CONTAINER_NAME) as Group); if (customContainer) { + if (scene.table.reactCustomLayout) { + scene.table.reactCustomLayout.removeCustomCell(col, row); + } + let customElementsGroup; customContainer.removeAllChild(); cell.removeChild(customContainer); diff --git a/packages/vtable/src/scenegraph/layout/update-width.ts b/packages/vtable/src/scenegraph/layout/update-width.ts index cc6c521f6..c4724ec23 100644 --- a/packages/vtable/src/scenegraph/layout/update-width.ts +++ b/packages/vtable/src/scenegraph/layout/update-width.ts @@ -346,6 +346,9 @@ function updateCellWidth( (cell.getChildByName(CUSTOM_CONTAINER_NAME) as Group) || (cell.getChildByName(CUSTOM_MERGE_CONTAINER_NAME) as Group); if (customContainer) { + if (scene.table.reactCustomLayout) { + scene.table.reactCustomLayout.removeCustomCell(col, row); + } let customElementsGroup; customContainer.removeAllChild(); cell.removeChild(customContainer);