From 67cfc1167a29bab778f6d38652b77d3e80fc601a Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 30 Apr 2024 17:33:13 +0800 Subject: [PATCH 01/85] feat: add CustomComponent in react-vtable --- packages/react-vtable/demo/src/App.tsx | 6 +- .../src/component/component-container.tsx | 48 ++++++ .../src/components/custom-component.tsx | 141 ++++++++++++++++++ packages/react-vtable/src/components/index.ts | 2 + packages/vtable/src/ListTable.ts | 2 +- packages/vtable/src/core/BaseTable.ts | 2 +- 6 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 packages/react-vtable/demo/src/component/component-container.tsx create mode 100644 packages/react-vtable/src/components/custom-component.tsx diff --git a/packages/react-vtable/demo/src/App.tsx b/packages/react-vtable/demo/src/App.tsx index 6904e0e8b..a7b638e69 100644 --- a/packages/react-vtable/demo/src/App.tsx +++ b/packages/react-vtable/demo/src/App.tsx @@ -13,7 +13,9 @@ import pivotChartComponent from './pivot-chart/pivot-chart-component'; import listTableEvent from './event/list-table'; import eventRebind from './event/event-rebind'; -export default listEditor; +import componentContainer from './component/component-container'; + +// export default listEditor; // export default listOptionRecord; // export default listComponent; // export default listCustomLayout; @@ -26,3 +28,5 @@ export default listEditor; // export default listTableEvent; // export default eventRebind; + +export default componentContainer; diff --git a/packages/react-vtable/demo/src/component/component-container.tsx b/packages/react-vtable/demo/src/component/component-container.tsx new file mode 100644 index 000000000..47fa4a6ee --- /dev/null +++ b/packages/react-vtable/demo/src/component/component-container.tsx @@ -0,0 +1,48 @@ +import { useMemo, useState } from 'react'; +import { ListTable, CustomComponent } from '../../../src'; + +function AAA(props: any) { + return
123
; +} +function App() { + const [col, setCol] = useState(-1); + const [row, setRow] = useState(-1); + + const option = { + columns: [ + { + field: '0', + caption: '名称' + }, + { + field: '1', + caption: '年龄' + }, + { + field: '2', + caption: '性别' + }, + { + field: '3', + caption: '爱好' + } + ], + records: new Array(1000).fill(['张三', 18, '男', '🏀']) + }; + + const updatePos = useMemo(() => { + return (args: any) => { + setCol(args.col); + setRow(args.row); + }; + }, []); + return ( + + + + + + ); +} + +export default App; diff --git a/packages/react-vtable/src/components/custom-component.tsx b/packages/react-vtable/src/components/custom-component.tsx new file mode 100644 index 000000000..e23748bfa --- /dev/null +++ b/packages/react-vtable/src/components/custom-component.tsx @@ -0,0 +1,141 @@ +import type { ReactElement } from 'react'; +import { + type CSSProperties, + type ChangeEvent, + type ReactNode, + type HTMLAttributes, + type DetailedHTMLProps, + useContext, + useMemo, + forwardRef +} from 'react'; +import React from 'react'; +import RootTableContext from '../context/table'; +import { merge } from '@visactor/vutils'; + +export interface CustomComponentProps + extends Omit, HTMLElement>, 'className' | 'ref'> { + style?: CSSProperties; + // className?: string | string[]; + className?: string; + + // for table + displayMode: 'position' | 'cell'; + x?: number; + y?: number; + // width?: number | string; + // height?: number | string; + width?: number; + height?: number; + row?: number; + col?: number; + anchor?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; + // dx?: number | string; + // dy?: number | string; + dx?: number; + dy?: number; +} + +export const CustomComponent: React.FC = (baseProps: CustomComponentProps, ref) => { + const context = useContext(RootTableContext); + const { table } = context; + + // if (!table) { + // return null; + // } + + const props = useMergeProps(baseProps, { + style: { + left: 0, + top: 0 + }, + className: 'vtable-custom-component', + displayMode: 'position', + x: 0, + y: 0, + width: 0, + height: 0, + row: 0, + col: 0, + anchor: 'top-left', + dx: 0, + dy: 0 + }); + const { displayMode, x, y, width, height, row, col, anchor, dx, dy, className, children, style, ...rest } = props; + + let styleLeft; + let styleTop; + let styleWidth; + let styleHeight; + + if (displayMode === 'position') { + styleLeft = x + dx + 'px'; + styleTop = y + dy + 'px'; + styleWidth = width + 'px'; + styleHeight = height + 'px'; + } else if (displayMode === 'cell') { + const cellRect = + table && col >= 0 && row >= 0 ? table?.getCellRect(col, row) : { width: 0, height: 0, left: -9999, top: -9999 }; + styleWidth = width + 'px'; + styleHeight = height + 'px'; + if (anchor === 'top-left') { + styleLeft = cellRect.left + dx + 'px'; + styleTop = cellRect.top + dy + 'px'; + } else if (anchor === 'top-right') { + styleLeft = cellRect.left + dx + cellRect.width + 'px'; + styleTop = cellRect.top + dy + 'px'; + } else if (anchor === 'bottom-left') { + styleLeft = cellRect.left + dx + 'px'; + styleTop = cellRect.top + dy + cellRect.height + 'px'; + } else if (anchor === 'bottom-right') { + styleLeft = cellRect.left + dx + cellRect.width + 'px'; + styleTop = cellRect.top + dy + cellRect.height + 'px'; + } + } + + const componentStyle = merge({}, style, { + position: 'absolute', + zIndex: 1000, + width: styleWidth, + height: styleHeight, + left: styleLeft, + top: styleTop + }); + + return ( +
+ {React.Children.map(children, (child: ReactNode) => { + if (child) { + return React.cloneElement(child as ReactElement, {}); + } + return child; + })} +
+ ); +}; + +// export const CustomComponent = forwardRef(CustomComponent1); + +export default function useMergeProps( + componentProps: PropsType, + defaultProps: Partial +): PropsType { + const _defaultProps = useMemo(() => { + return { ...defaultProps }; + }, [defaultProps]); + + const props = useMemo(() => { + const mProps = merge({}, componentProps); + + // https://github.com/facebook/react/blob/cae635054e17a6f107a39d328649137b83f25972/packages/react/src/ReactElement.js#L312 + for (const propName in _defaultProps) { + if (mProps[propName] === undefined) { + mProps[propName] = _defaultProps[propName]; + } + } + + return mProps; + }, [componentProps, _defaultProps]); + + return props; +} diff --git a/packages/react-vtable/src/components/index.ts b/packages/react-vtable/src/components/index.ts index 2ca2f186a..908de112f 100644 --- a/packages/react-vtable/src/components/index.ts +++ b/packages/react-vtable/src/components/index.ts @@ -7,6 +7,8 @@ export { PivotCorner } from './pivot/pivot-corner'; export { Menu } from './component/menu'; export { Tooltip } from './component/tooltip'; +export { CustomComponent } from './custom-component'; + type Props = { updateId?: number }; export interface IMarkElement extends React.ReactElement> { diff --git a/packages/vtable/src/ListTable.ts b/packages/vtable/src/ListTable.ts index 861a565db..70fe413db 100644 --- a/packages/vtable/src/ListTable.ts +++ b/packages/vtable/src/ListTable.ts @@ -196,7 +196,7 @@ export class ListTable extends BaseTable implements ListTableAPI { return; } this.internalProps.transpose = transpose; - this.options.transpose = transpose; + // this.options.transpose = transpose; // cause extr update in react if (this.internalProps.layoutMap) { //后面如果修改是否转置 this.internalProps.layoutMap.transpose = transpose; diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 1575ec5f8..20faeb7cf 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -349,7 +349,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { if (container) { //先清空 - container.innerHTML = ''; + // container.innerHTML = ''; container.appendChild(internalProps.element); this._updateSize(); } else { From fb1a69248d813d37e90f5e9586db2db7994da158 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 30 Apr 2024 17:50:11 +0800 Subject: [PATCH 02/85] feat: add relative props in custom-component --- .../src/component/component-container.tsx | 12 +++-- .../src/components/custom-component.tsx | 54 +++++++++++-------- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/packages/react-vtable/demo/src/component/component-container.tsx b/packages/react-vtable/demo/src/component/component-container.tsx index 47fa4a6ee..b9afc34c8 100644 --- a/packages/react-vtable/demo/src/component/component-container.tsx +++ b/packages/react-vtable/demo/src/component/component-container.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from 'react'; import { ListTable, CustomComponent } from '../../../src'; function AAA(props: any) { - return
123
; + return
123
; } function App() { const [col, setCol] = useState(-1); @@ -36,9 +36,15 @@ function App() { setRow(args.row); }; }, []); + const hide = useMemo(() => { + return () => { + setCol(-1); + setRow(-1); + }; + }, []); return ( - - + + diff --git a/packages/react-vtable/src/components/custom-component.tsx b/packages/react-vtable/src/components/custom-component.tsx index e23748bfa..13b44ce63 100644 --- a/packages/react-vtable/src/components/custom-component.tsx +++ b/packages/react-vtable/src/components/custom-component.tsx @@ -11,7 +11,7 @@ import { } from 'react'; import React from 'react'; import RootTableContext from '../context/table'; -import { merge } from '@visactor/vutils'; +import { isNumber, merge } from '@visactor/vutils'; export interface CustomComponentProps extends Omit, HTMLElement>, 'className' | 'ref'> { @@ -23,17 +23,17 @@ export interface CustomComponentProps displayMode: 'position' | 'cell'; x?: number; y?: number; - // width?: number | string; - // height?: number | string; - width?: number; - height?: number; + width?: number | string; + height?: number | string; + // width?: number; + // height?: number; row?: number; col?: number; anchor?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; - // dx?: number | string; - // dy?: number | string; - dx?: number; - dy?: number; + dx?: number | string; + dy?: number | string; + // dx?: number; + // dy?: number; } export const CustomComponent: React.FC = (baseProps: CustomComponentProps, ref) => { @@ -69,27 +69,27 @@ export const CustomComponent: React.FC = (baseProps: Custo let styleHeight; if (displayMode === 'position') { - styleLeft = x + dx + 'px'; - styleTop = y + dy + 'px'; + styleLeft = x + (dx as number) + 'px'; + styleTop = y + (dy as number) + 'px'; styleWidth = width + 'px'; styleHeight = height + 'px'; } else if (displayMode === 'cell') { const cellRect = table && col >= 0 && row >= 0 ? table?.getCellRect(col, row) : { width: 0, height: 0, left: -9999, top: -9999 }; - styleWidth = width + 'px'; - styleHeight = height + 'px'; + styleWidth = dealWidthNumber(width, cellRect.width) + 'px'; + styleHeight = dealWidthNumber(height, cellRect.height) + 'px'; if (anchor === 'top-left') { - styleLeft = cellRect.left + dx + 'px'; - styleTop = cellRect.top + dy + 'px'; + styleLeft = cellRect.left + dealWidthNumber(dx, cellRect.width) + 'px'; + styleTop = cellRect.top + dealWidthNumber(dy, cellRect.height) + 'px'; } else if (anchor === 'top-right') { - styleLeft = cellRect.left + dx + cellRect.width + 'px'; - styleTop = cellRect.top + dy + 'px'; + styleLeft = cellRect.left + dealWidthNumber(dx, cellRect.width) + cellRect.width + 'px'; + styleTop = cellRect.top + dealWidthNumber(dy, cellRect.height) + 'px'; } else if (anchor === 'bottom-left') { - styleLeft = cellRect.left + dx + 'px'; - styleTop = cellRect.top + dy + cellRect.height + 'px'; + styleLeft = cellRect.left + dealWidthNumber(dx, cellRect.width) + 'px'; + styleTop = cellRect.top + dealWidthNumber(dy, cellRect.height) + cellRect.height + 'px'; } else if (anchor === 'bottom-right') { - styleLeft = cellRect.left + dx + cellRect.width + 'px'; - styleTop = cellRect.top + dy + cellRect.height + 'px'; + styleLeft = cellRect.left + dealWidthNumber(dx, cellRect.width) + cellRect.width + 'px'; + styleTop = cellRect.top + dealWidthNumber(dy, cellRect.height) + cellRect.height + 'px'; } } @@ -139,3 +139,15 @@ export default function useMergeProps( return props; } + +function dealWidthNumber(value: string | number, refenceValue: number) { + if (isNumber(value)) { + return value; + } + + if (typeof value === 'string' && value.endsWith('%')) { + return (Number(value.slice(0, -1)) / 100) * refenceValue; + } + + return 0; +} From 9efde8eabc650990df3f94de5f67ae60a650dd74 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 30 Apr 2024 18:06:38 +0800 Subject: [PATCH 03/85] fix: use getCellRelativeRect in custom-component --- packages/react-vtable/src/components/custom-component.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-vtable/src/components/custom-component.tsx b/packages/react-vtable/src/components/custom-component.tsx index 13b44ce63..da4a1102c 100644 --- a/packages/react-vtable/src/components/custom-component.tsx +++ b/packages/react-vtable/src/components/custom-component.tsx @@ -75,7 +75,9 @@ export const CustomComponent: React.FC = (baseProps: Custo styleHeight = height + 'px'; } else if (displayMode === 'cell') { const cellRect = - table && col >= 0 && row >= 0 ? table?.getCellRect(col, row) : { width: 0, height: 0, left: -9999, top: -9999 }; + table && col >= 0 && row >= 0 + ? table?.getCellRelativeRect(col, row) + : { width: 0, height: 0, left: -9999, top: -9999 }; styleWidth = dealWidthNumber(width, cellRect.width) + 'px'; styleHeight = dealWidthNumber(height, cellRect.height) + 'px'; if (anchor === 'top-left') { From a9681004d95bf7626d8a28804fcf66bfe26e6b8d Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 7 May 2024 17:32:42 +0800 Subject: [PATCH 04/85] chore: add CustomComponent demo & docs --- ...-component-container_2024-05-07-09-28.json | 10 ++ docs/assets/demo-openinula/en/event/event.md | 2 +- docs/assets/demo-openinula/en/event/ready.md | 2 +- .../demo-openinula/en/usage/option-record.md | 2 +- docs/assets/demo-openinula/en/usage/option.md | 2 +- docs/assets/demo-openinula/zh/event/event.md | 2 +- docs/assets/demo-openinula/zh/event/ready.md | 2 +- .../demo-openinula/zh/usage/option-record.md | 2 +- docs/assets/demo-openinula/zh/usage/option.md | 2 +- .../en/component/custom-component.md | 142 ++++++++++++++++++ docs/assets/demo-react/en/event/event.md | 2 +- docs/assets/demo-react/en/event/ready.md | 2 +- .../arco-select-editor.md | 2 +- .../demo-react/en/usage/option-record.md | 2 +- docs/assets/demo-react/en/usage/option.md | 2 +- docs/assets/demo-react/menu.json | 7 + .../zh/component/custom-component.md | 142 ++++++++++++++++++ docs/assets/demo-react/zh/event/event.md | 2 +- docs/assets/demo-react/zh/event/ready.md | 2 +- .../arco-select-editor.md | 2 +- .../demo-react/zh/usage/option-record.md | 2 +- docs/assets/demo-react/zh/usage/option.md | 2 +- .../guide/en/Developer_Ecology/react.md | 54 ++++++- .../guide/zh/Developer_Ecology/react.md | 54 ++++++- .../src/component/component-container.tsx | 100 +++++++++--- .../src/components/custom-component.tsx | 11 +- 26 files changed, 499 insertions(+), 57 deletions(-) create mode 100644 common/changes/@visactor/vtable/feat-react-component-container_2024-05-07-09-28.json create mode 100644 docs/assets/demo-react/en/component/custom-component.md create mode 100644 docs/assets/demo-react/zh/component/custom-component.md diff --git a/common/changes/@visactor/vtable/feat-react-component-container_2024-05-07-09-28.json b/common/changes/@visactor/vtable/feat-react-component-container_2024-05-07-09-28.json new file mode 100644 index 000000000..efabbdee6 --- /dev/null +++ b/common/changes/@visactor/vtable/feat-react-component-container_2024-05-07-09-28.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "feat: add CustomComponent in react-vtable", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/docs/assets/demo-openinula/en/event/event.md b/docs/assets/demo-openinula/en/event/event.md index e4e3f2dd4..4ba705331 100644 --- a/docs/assets/demo-openinula/en/event/event.md +++ b/docs/assets/demo-openinula/en/event/event.md @@ -17,7 +17,7 @@ The events supported by VTable can be monitored through openinula props. For det // import * as InulaVTable from '@visactor/openinula-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-openinula/en/event/ready.md b/docs/assets/demo-openinula/en/event/ready.md index 2d71ee197..210f1f128 100644 --- a/docs/assets/demo-openinula/en/event/ready.md +++ b/docs/assets/demo-openinula/en/event/ready.md @@ -17,7 +17,7 @@ The onReady callback is triggered after the table completes initialization or up // import * as InulaVTable from '@visactor/openinula-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-openinula/en/usage/option-record.md b/docs/assets/demo-openinula/en/usage/option-record.md index 01a36c65f..ef82641fa 100644 --- a/docs/assets/demo-openinula/en/usage/option-record.md +++ b/docs/assets/demo-openinula/en/usage/option-record.md @@ -15,7 +15,7 @@ Records can be separated from options and passed into the table component as a s ```javascript livedemo template=vtable-openinula // import * as InulaVTable from '@visactor/openinula-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-openinula/en/usage/option.md b/docs/assets/demo-openinula/en/usage/option.md index f04c079a3..b27a1c003 100644 --- a/docs/assets/demo-openinula/en/usage/option.md +++ b/docs/assets/demo-openinula/en/usage/option.md @@ -15,7 +15,7 @@ You can use the complete option of VTable directly and pass the option into the ```javascript livedemo template=vtable-openinula // import * as InulaVTable from '@visactor/openinula-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-openinula/zh/event/event.md b/docs/assets/demo-openinula/zh/event/event.md index 2b3534a30..66b9a9edd 100644 --- a/docs/assets/demo-openinula/zh/event/event.md +++ b/docs/assets/demo-openinula/zh/event/event.md @@ -17,7 +17,7 @@ VTable支持的事件都可以通过openinula的props传入进行监听,具体 // import * as InulaVTable from '@visactor/openinula-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-openinula/zh/event/ready.md b/docs/assets/demo-openinula/zh/event/ready.md index ee9d22e2d..697b3bc21 100644 --- a/docs/assets/demo-openinula/zh/event/ready.md +++ b/docs/assets/demo-openinula/zh/event/ready.md @@ -17,7 +17,7 @@ onReady回调再表格完成初始化或更新后触发,可以获取表格实 // import * as InulaVTable from '@visactor/openinula-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-openinula/zh/usage/option-record.md b/docs/assets/demo-openinula/zh/usage/option-record.md index 1b2d96388..e58170c22 100644 --- a/docs/assets/demo-openinula/zh/usage/option-record.md +++ b/docs/assets/demo-openinula/zh/usage/option-record.md @@ -15,7 +15,7 @@ link: '../guide/Developer_Ecology/openinula' ```javascript livedemo template=vtable-openinula // import * as InulaVTable from '@visactor/openinula-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-openinula/zh/usage/option.md b/docs/assets/demo-openinula/zh/usage/option.md index 15a53c0a7..33edc08a9 100644 --- a/docs/assets/demo-openinula/zh/usage/option.md +++ b/docs/assets/demo-openinula/zh/usage/option.md @@ -15,7 +15,7 @@ link: '../guide/Developer_Ecology/openinula' ```javascript livedemo template=vtable-openinula // import * as InulaVTable from '@visactor/openinula-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-react/en/component/custom-component.md b/docs/assets/demo-react/en/component/custom-component.md new file mode 100644 index 000000000..3eefc2dd5 --- /dev/null +++ b/docs/assets/demo-react/en/component/custom-component.md @@ -0,0 +1,142 @@ +--- +category: examples +group: component +title: Custom Component +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-component.png +order: 1-1 +link: '../guide/Developer_Ecology/react' +--- + +# Custom Component + +The `CustomComponent` component facilitates overlaying external components on React-VTable components. + +## Code Example +```javascript livedemo template=vtable-react +// import * as ReactVTable from '@visactor/react-vtable'; + +const { useCallback, useRef, useState } = React; +const { ListTable, CustomComponent } = ReactVTable; +const { Popconfirm, Message, Button } = ArcoDesign; + +function Tooltip(props) { + return ( +
+ {`${props.value}(click to show more)`} +
+ ); +} + +function App() { + const [hoverCol, setHoverCol] = useState(-1); + const [hoverRow, setHoverRow] = useState(-1); + const [clickCol, setClickCol] = useState(-1); + const [clickRow, setClickRow] = useState(-1); + const [value, setValue] = useState(''); + const visible = useRef(false); + const tableInstance = useRef(null); + + const option = { + columns: [ + { + field: '0', + caption: 'name' + }, + { + field: '1', + caption: 'age' + }, + { + field: '2', + caption: 'gender' + }, + { + field: '3', + caption: 'hobby' + } + ], + records: new Array(1000).fill(['John', 18, 'male', '🏀']) + }; + + const updateHoverPos = useCallback((args) => { + if (visible.current) { + return; + } + setHoverCol(args.col); + setHoverRow(args.row); + const cellValue = tableInstance.current.getCellValue(args.col, args.row); + setValue(cellValue); + }, []); + const hide = useCallback(() => { + setHoverCol(-1); + setHoverRow(-1); + }, []); + + const updateClickPos = useCallback((args) => { + setClickCol(args.col); + setClickRow(args.row); + }, []); + + const ready = (instance, isInitial) => { + if (isInitial) { + tableInstance.current = instance; + } + }; + + return ( + + + + + + { + Message.info({ + content: 'ok' + }); + setClickCol(-1); + setClickRow(-1); + }} + onCancel={() => { + Message.error({ + content: 'cancel' + }); + setClickCol(-1); + setClickRow(-1); + }} + onVisibleChange={(popVisible) => { + visible.current = popVisible; + }} + > + + + + + ); +} + +const root = ReactDom.createRoot(document.getElementById(CONTAINER_ID)); +root.render(); + +// release react instance, do not copy +window.customRelease = () => { + root.unmount(); +}; +``` \ No newline at end of file diff --git a/docs/assets/demo-react/en/event/event.md b/docs/assets/demo-react/en/event/event.md index e20c53a80..910e7ea08 100644 --- a/docs/assets/demo-react/en/event/event.md +++ b/docs/assets/demo-react/en/event/event.md @@ -17,7 +17,7 @@ The events supported by VTable can be monitored through react props. For details // import * as ReactVTable from '@visactor/react-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-react/en/event/ready.md b/docs/assets/demo-react/en/event/ready.md index f53a38516..7bdd91eff 100644 --- a/docs/assets/demo-react/en/event/ready.md +++ b/docs/assets/demo-react/en/event/ready.md @@ -17,7 +17,7 @@ The onReady callback is triggered after the table completes initialization or up // import * as ReactVTable from '@visactor/react-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-react/en/functional-components/arco-select-editor.md b/docs/assets/demo-react/en/functional-components/arco-select-editor.md index 60f66f8a0..6290704c7 100644 --- a/docs/assets/demo-react/en/functional-components/arco-select-editor.md +++ b/docs/assets/demo-react/en/functional-components/arco-select-editor.md @@ -107,7 +107,7 @@ const editor = new ArcoListEditor(); VTable.register.editor('list-editor', editor); const option = { defaultRowHeight: 34, - header: [ + columns: [ { field: '0', caption: 'name' diff --git a/docs/assets/demo-react/en/usage/option-record.md b/docs/assets/demo-react/en/usage/option-record.md index 8fe2763f7..2e41f1c28 100644 --- a/docs/assets/demo-react/en/usage/option-record.md +++ b/docs/assets/demo-react/en/usage/option-record.md @@ -15,7 +15,7 @@ Records can be separated from options and passed into the table component as a s ```javascript livedemo template=vtable-react // import * as ReactVTable from '@visactor/react-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-react/en/usage/option.md b/docs/assets/demo-react/en/usage/option.md index 2d05fd3ba..9b73772dd 100644 --- a/docs/assets/demo-react/en/usage/option.md +++ b/docs/assets/demo-react/en/usage/option.md @@ -15,7 +15,7 @@ You can use the complete option of VTable directly and pass the option into the ```javascript livedemo template=vtable-react // import * as ReactVTable from '@visactor/react-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-react/menu.json b/docs/assets/demo-react/menu.json index 54bce6d8d..343675dec 100644 --- a/docs/assets/demo-react/menu.json +++ b/docs/assets/demo-react/menu.json @@ -74,6 +74,13 @@ "zh": "提示信息", "en": "tooltip" } + }, + { + "path": "custom-component", + "title": { + "zh": "自定义组件", + "en": "custom component" + } } ] }, diff --git a/docs/assets/demo-react/zh/component/custom-component.md b/docs/assets/demo-react/zh/component/custom-component.md new file mode 100644 index 000000000..425d858b3 --- /dev/null +++ b/docs/assets/demo-react/zh/component/custom-component.md @@ -0,0 +1,142 @@ +--- +category: examples +group: component +title: 自定义组件 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-component.png +order: 1-1 +link: '../guide/Developer_Ecology/react' +--- + +# 自定义组件 + +自定义组件`CustomComponent`组件方便在React-VTable组件上叠加外部组件。 + +## 代码演示 +```javascript livedemo template=vtable-react +// import * as ReactVTable from '@visactor/react-vtable'; + +const { useCallback, useRef, useState } = React; +const { ListTable, CustomComponent } = ReactVTable; +const { Popconfirm, Message, Button } = ArcoDesign; + +function Tooltip(props) { + return ( +
+ {`${props.value}(click to show more)`} +
+ ); +} + +function App() { + const [hoverCol, setHoverCol] = useState(-1); + const [hoverRow, setHoverRow] = useState(-1); + const [clickCol, setClickCol] = useState(-1); + const [clickRow, setClickRow] = useState(-1); + const [value, setValue] = useState(''); + const visible = useRef(false); + const tableInstance = useRef(null); + + const option = { + columns: [ + { + field: '0', + caption: '名称' + }, + { + field: '1', + caption: '年龄' + }, + { + field: '2', + caption: '性别' + }, + { + field: '3', + caption: '爱好' + } + ], + records: new Array(1000).fill(['张三', 18, '男', '🏀']) + }; + + const updateHoverPos = useCallback((args) => { + if (visible.current) { + return; + } + setHoverCol(args.col); + setHoverRow(args.row); + const cellValue = tableInstance.current.getCellValue(args.col, args.row); + setValue(cellValue); + }, []); + const hide = useCallback(() => { + setHoverCol(-1); + setHoverRow(-1); + }, []); + + const updateClickPos = useCallback((args) => { + setClickCol(args.col); + setClickRow(args.row); + }, []); + + const ready = (instance, isInitial) => { + if (isInitial) { + tableInstance.current = instance; + } + }; + + return ( + + + + + + { + Message.info({ + content: 'ok' + }); + setClickCol(-1); + setClickRow(-1); + }} + onCancel={() => { + Message.error({ + content: 'cancel' + }); + setClickCol(-1); + setClickRow(-1); + }} + onVisibleChange={(popVisible) => { + visible.current = popVisible; + }} + > + + + + + ); +} + +const root = ReactDom.createRoot(document.getElementById(CONTAINER_ID)); +root.render(); + +// release react instance, do not copy +window.customRelease = () => { + root.unmount(); +}; +``` \ No newline at end of file diff --git a/docs/assets/demo-react/zh/event/event.md b/docs/assets/demo-react/zh/event/event.md index d12baef7c..c667e3146 100644 --- a/docs/assets/demo-react/zh/event/event.md +++ b/docs/assets/demo-react/zh/event/event.md @@ -17,7 +17,7 @@ VTable支持的事件都可以通过react的props传入进行监听,具体可 // import * as ReactVTable from '@visactor/react-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-react/zh/event/ready.md b/docs/assets/demo-react/zh/event/ready.md index e399f80d9..a0c362c23 100644 --- a/docs/assets/demo-react/zh/event/ready.md +++ b/docs/assets/demo-react/zh/event/ready.md @@ -17,7 +17,7 @@ onReady回调再表格完成初始化或更新后触发,可以获取表格实 // import * as ReactVTable from '@visactor/react-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-react/zh/functional-components/arco-select-editor.md b/docs/assets/demo-react/zh/functional-components/arco-select-editor.md index c8f0b19da..d4b4b4ae4 100644 --- a/docs/assets/demo-react/zh/functional-components/arco-select-editor.md +++ b/docs/assets/demo-react/zh/functional-components/arco-select-editor.md @@ -107,7 +107,7 @@ const editor = new ArcoListEditor(); VTable.register.editor('list-editor', editor); const option = { defaultRowHeight: 34, - header: [ + columns: [ { field: '0', caption: 'name' diff --git a/docs/assets/demo-react/zh/usage/option-record.md b/docs/assets/demo-react/zh/usage/option-record.md index 1ae5b3d43..43c8169d6 100644 --- a/docs/assets/demo-react/zh/usage/option-record.md +++ b/docs/assets/demo-react/zh/usage/option-record.md @@ -15,7 +15,7 @@ link: '../guide/Developer_Ecology/react' ```javascript livedemo template=vtable-react // import * as ReactVTable from '@visactor/react-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/demo-react/zh/usage/option.md b/docs/assets/demo-react/zh/usage/option.md index 3dd89844f..b8f749204 100644 --- a/docs/assets/demo-react/zh/usage/option.md +++ b/docs/assets/demo-react/zh/usage/option.md @@ -15,7 +15,7 @@ link: '../guide/Developer_Ecology/react' ```javascript livedemo template=vtable-react // import * as ReactVTable from '@visactor/react-vtable'; const option = { - header: [ + columns: [ { field: '0', caption: 'name', diff --git a/docs/assets/guide/en/Developer_Ecology/react.md b/docs/assets/guide/en/Developer_Ecology/react.md index a1e08adb0..c393749da 100644 --- a/docs/assets/guide/en/Developer_Ecology/react.md +++ b/docs/assets/guide/en/Developer_Ecology/react.md @@ -70,7 +70,7 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( ); ``` -Refer to [demo](https://codesandbox.io/p/sandbox/react-vtable-wjrvpq) +Refer to [demo](../../demo-react/usage/option) ## Usage @@ -78,13 +78,13 @@ React-VTable provides two styles of components for developers to use, namely uni ### Unified tags -Unified tags refer to using a Table tag to receive a complete `option` configuration. If VTable is already used in the project, this method can quickly use React-VTable. The above example is a [demo](https://codesandbox.io/p/sandbox/react-vtable-wjrvpq) using unified tags. +Unified tags refer to using a Table tag to receive a complete `option` configuration. If VTable is already used in the project, this method can quickly use React-VTable. The above example is a [demo](../../demo-react/usage/option) using unified tags. Same as VTable React-VTable provides three table types: -- ListTable: List table, used to display list data [demo](https://codesandbox.io/p/sandbox/list-table-2x3qpr) -- PivotTable: Pivot table, used to display cross-pivot data [demo](https://codesandbox.io/p/sandbox/pivot-table-jyz654) -- PivotChart: Pivot chart, used to display cross-pivot data and display it in a chart [demo](https://codesandbox.io/p/sandbox/pivot-chart-3lwn5l) +- ListTable: List table, used to display list data [demo](../../demo-react/usage/option) +- PivotTable: Pivot table, used to display cross-pivot data [demo](../../demo-react/grammatical-tag/pivot-table) +- PivotChart: Pivot chart, used to display cross-pivot data and display it in a chart [demo](../../demo-react/grammatical-tag/pivot-chart) The props of these three React components are defined as follows: @@ -131,7 +131,7 @@ function App() { } ``` -Grammatical tag demo: [demo](https://codesandbox.io/p/sandbox/list-component-2375q5) +Grammatical tag demo: [demo](../../demo-react/usage/grammatical-tag) #### PivotTable&PivotChart @@ -177,7 +177,7 @@ The props attributes accepted by PivotTable&PivotChart are the same as options. ); ``` -Grammatical label demo: [PivotTable demo](https://codesandbox.io/p/sandbox/pivot-component-c8w28h) [PivotChart demo](https://codesandbox.io/p/sandbox/pivot-chart-component-tw8x5c) +Grammatical label demo: [PivotTable demo](../../demo-react/grammatical-tag/pivot-table) [PivotChart demo](../../demo-react/grammatical-tag/pivot-chart) #### Components outside the table @@ -276,3 +276,43 @@ function App() { ``` For detailed description of the event, please refer to: [Event Introduction](../../guide/Event/event_list) + +## Custom component + +In order to facilitate the superposition of external components on the React-VTable component, React-VTable provides a `CustomComponent` tool component to quickly locate external components into the table. + +```jsx + + + + + +``` + +Among them, `CustomComponent` is used as a container for positioning in the table and automatically matching the size (based on anchored cells). There are two ways to use it: + +1. Absolute positioning + + For absolute positioning, you need to specify `displayMode` as `position`, `x` and `y` attributes, which are used to position the container to the specified pixel position in the table (based on the upper left corner), `width` and `height `property specifies the pixel dimensions of the container. + +2. Relative positioning + + For relative positioning, you need to specify `displayMode` as `cell`, the container is positioned relative to the cell, the `col` and `row` attributes are used to specify the anchored cell coordinates, and the `anchor` attribute specifies the container relative to the cell. The anchor position, `dx` and `dy` attributes specify the offset of the container relative to the anchor cell, and the `width` and `height` properties specify the size of the container, where `dx` `dy` `width` and The `height` attribute supports units of pixels or percentages. When it is a percentage, it is calculated relative to the size of the cell. + +### API + +```ts +interface CustomComponentProps { + children: React.ReactNode; + displayMode: 'position' | 'cell'; // positioning method + col?: number; // anchored column coordinates + row?: number; // anchored row coordinates + anchor?: 'top-left' | 'top-center' | 'top-right' |'middle-left' |'middle-center' |'middle-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'; // anchored position + dx?: number | string; // offset in x direction + dy?: number | string; // offset in y direction + width?: number | string; // container width + height?: number | string; // container height +} +``` + +[custom component demo](../../demo-react/component/custom-component) diff --git a/docs/assets/guide/zh/Developer_Ecology/react.md b/docs/assets/guide/zh/Developer_Ecology/react.md index 18343bf79..db0eaf63a 100644 --- a/docs/assets/guide/zh/Developer_Ecology/react.md +++ b/docs/assets/guide/zh/Developer_Ecology/react.md @@ -70,7 +70,7 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( ); ``` -参考[demo](https://codesandbox.io/p/sandbox/react-vtable-wjrvpq) +参考[demo](../../demo-react/usage/option) ## 使用方式 @@ -78,13 +78,13 @@ React-VTable提供两种风格的组件供开发者使用,分别是统一标 ### 统一标签 -统一标签是指是使用一个 Table 标签,接收一个完整的`option`配置,如果项目中已经使用了 VTable ,这种方式可以快速使用React-VTable。上面的例子就是一个使用统一标签的[demo](https://codesandbox.io/p/sandbox/react-vtable-wjrvpq)。 +统一标签是指是使用一个 Table 标签,接收一个完整的`option`配置,如果项目中已经使用了 VTable ,这种方式可以快速使用React-VTable。上面的例子就是一个使用统一标签的[demo](../../demo-react/usage/option)。 与VTable相同React-VTable提供三种表格类型: -- ListTable: 列表表格,用于展示列表数据 [demo](https://codesandbox.io/p/sandbox/list-table-2x3qpr) -- PivotTable: 透视表格,用于展示交叉透视数据 [demo](https://codesandbox.io/p/sandbox/pivot-table-jyz654) -- PivotChart: 透视图,用于展示交叉透视数据并以图表方式展示 [demo](https://codesandbox.io/p/sandbox/pivot-chart-3lwn5l) +- ListTable: 列表表格,用于展示列表数据 [demo](../../demo-react/usage/option) +- PivotTable: 透视表格,用于展示交叉透视数据 [demo](../../demo-react/grammatical-tag/pivot-table) +- PivotChart: 透视图,用于展示交叉透视数据并以图表方式展示 [demo](../../demo-react/grammatical-tag/pivot-chart) 这三种React组件,其props定义如下: @@ -131,7 +131,7 @@ function App() { } ``` -语法化标签demo:[demo](https://codesandbox.io/p/sandbox/list-component-2375q5) +语法化标签demo:[demo](../../demo-react/usage/grammatical-tag) #### PivotTable&PivotChart @@ -177,7 +177,7 @@ PivotTable&PivotChart接受的props属性与option一致,子组件如下: ); ``` -语法化标签demo:[PivotTable demo](https://codesandbox.io/p/sandbox/pivot-component-c8w28h) [PivotChart demo](https://codesandbox.io/p/sandbox/pivot-chart-component-tw8x5c) +语法化标签demo:[PivotTable demo](../../demo-react/grammatical-tag/pivot-table) [PivotChart demo](../../demo-react/grammatical-tag/pivot-chart) #### 表格外组件 @@ -276,3 +276,43 @@ function App() { ``` 事件详细描述参考:[事件介绍](../../guide/Event/event_list) + +## 自定义外部组件 + +为了方便在React-VTable组件上叠加外部组件,React-VTable提供了`CustomComponent`工具组件,方便快速将外部组件定位到表格当中。 + +```jsx + + + + + +``` + +其中,`CustomComponent`作为一个容器,用于在表格中定位,并自动匹配尺寸(基于锚定的单元格),具体有两种使用方式: + +1. 绝对定位 + + 绝对定位的方式,需要指定`displayMode`为`position`, 需要指定`x`和`y`属性,用于将容器定位到表格中的指定像素位置(基于左上角),`width`和`height`属性指定容器的像素尺寸。 + +2. 相对定位 + + 相对定位的方式,需要指定`displayMode`为`cell`,容器相对为单元格定位、`col`和`row`属性用于指定锚定的单元格坐标,`anchor`属性指定容器相对于单元格的锚定位置,`dx`和`dy`属性指定容器相对于锚定单元格的偏移量,`width`和`height`属性指定容器的尺寸,其中`dx` `dy` `width`和`height`属性的均支持单位为像素或百分比,为百分比时,相对于单元格的尺寸进行计算。 + +### API + +```ts +interface CustomComponentProps { + children: React.ReactNode; + displayMode: 'position' | 'cell'; // 定位方式 + col?: number; // 锚定的列坐标 + row?: number; // 锚定的行坐标 + anchor?: 'top-left' | 'top-center' | 'top-right' |'middle-left' |'middle-center' |'middle-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'; // 锚定的位置 + dx?: number | string; // x方向的偏移 + dy?: number | string; // y方向的偏移 + width?: number | string; // 容器的宽度 + height?: number | string; // 容器的高度 +} +``` + +自定义外部组件demo:[custom component demo](../../demo-react/component/custom-component) diff --git a/packages/react-vtable/demo/src/component/component-container.tsx b/packages/react-vtable/demo/src/component/component-container.tsx index b9afc34c8..1babdfc17 100644 --- a/packages/react-vtable/demo/src/component/component-container.tsx +++ b/packages/react-vtable/demo/src/component/component-container.tsx @@ -1,12 +1,23 @@ -import { useMemo, useState } from 'react'; +import { useCallback, useRef, useState } from 'react'; +import { Popconfirm, Message, Button } from '@arco-design/web-react'; import { ListTable, CustomComponent } from '../../../src'; +import '@arco-design/web-react/dist/css/arco.css'; -function AAA(props: any) { - return
123
; +function Tooltip(props: { value: string }) { + return ( +
+ {`${props.value}(click to show more)`} +
+ ); } function App() { - const [col, setCol] = useState(-1); - const [row, setRow] = useState(-1); + const [hoverCol, setHoverCol] = useState(-1); + const [hoverRow, setHoverRow] = useState(-1); + const [clickCol, setClickCol] = useState(-1); + const [clickRow, setClickRow] = useState(-1); + const [value, setValue] = useState(''); + const visible = useRef(false); + const tableInstance = useRef(null); const option = { columns: [ @@ -30,22 +41,75 @@ function App() { records: new Array(1000).fill(['张三', 18, '男', '🏀']) }; - const updatePos = useMemo(() => { - return (args: any) => { - setCol(args.col); - setRow(args.row); - }; + const updateHoverPos = useCallback((args: any) => { + if (visible.current) { + return; + } + setHoverCol(args.col); + setHoverRow(args.row); + const cellValue = (tableInstance.current as any)?.getCellValue(args.col, args.row); + setValue(cellValue); }, []); - const hide = useMemo(() => { - return () => { - setCol(-1); - setRow(-1); - }; + const hide = useCallback(() => { + setHoverCol(-1); + setHoverRow(-1); + }, []); + + const updateClickPos = useCallback((args: any) => { + setClickCol(args.col); + setClickRow(args.row); }, []); + + const ready = (instance: any, isInitial: boolean) => { + if (isInitial) { + tableInstance.current = instance; + } + }; + return ( - - - + + + + + + { + Message.info({ + content: 'ok' + }); + setClickCol(-1); + setClickRow(-1); + }} + onCancel={() => { + Message.error({ + content: 'cancel' + }); + setClickCol(-1); + setClickRow(-1); + }} + onVisibleChange={(popVisible: boolean) => { + visible.current = popVisible; + }} + > + + ); diff --git a/packages/react-vtable/src/components/custom-component.tsx b/packages/react-vtable/src/components/custom-component.tsx index da4a1102c..9dbba26b6 100644 --- a/packages/react-vtable/src/components/custom-component.tsx +++ b/packages/react-vtable/src/components/custom-component.tsx @@ -1,15 +1,12 @@ import type { ReactElement } from 'react'; -import { +import React, { type CSSProperties, - type ChangeEvent, type ReactNode, type HTMLAttributes, type DetailedHTMLProps, useContext, - useMemo, - forwardRef + useMemo } from 'react'; -import React from 'react'; import RootTableContext from '../context/table'; import { isNumber, merge } from '@visactor/vutils'; @@ -36,7 +33,7 @@ export interface CustomComponentProps // dy?: number; } -export const CustomComponent: React.FC = (baseProps: CustomComponentProps, ref) => { +export const CustomComponent: React.FC = (baseProps: CustomComponentProps) => { const context = useContext(RootTableContext); const { table } = context; @@ -61,7 +58,7 @@ export const CustomComponent: React.FC = (baseProps: Custo dx: 0, dy: 0 }); - const { displayMode, x, y, width, height, row, col, anchor, dx, dy, className, children, style, ...rest } = props; + const { displayMode, x, y, width, height, row, col, anchor, dx, dy, className, children, style } = props; let styleLeft; let styleTop; From a39243dc295efc0d63b06e4c6d99fb14835b4b65 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Wed, 15 May 2024 14:37:20 +0800 Subject: [PATCH 05/85] feat: add CustomLayout component in react-vtable --- ...-component-container_2024-05-15-06-22.json | 10 ++ common/config/rush/pnpm-lock.yaml | 27 +++ packages/react-vtable/demo/src/App.tsx | 4 +- .../demo/src/component/custom-layout.tsx | 100 +++++++++++ packages/react-vtable/demo/vite.config.ts | 1 + packages/react-vtable/package.json | 8 +- .../src/components/base-component.tsx | 19 ++- .../src/components/custom/custom-layout.tsx | 90 ++++++++++ .../src/components/custom/graphic.tsx | 3 + .../src/components/custom/reconciler.tsx | 155 ++++++++++++++++++ packages/react-vtable/src/components/index.ts | 2 + .../react-vtable/src/tables/base-table.tsx | 3 +- packages/vtable/src/ListTable.ts | 10 +- .../components/react/react-custom-layout.ts | 45 +++++ packages/vtable/src/core/BaseTable.ts | 9 + .../vtable/src/scenegraph/component/custom.ts | 5 + .../scenegraph/group-creater/cell-helper.ts | 2 +- .../scenegraph/layout/compute-col-width.ts | 4 +- .../scenegraph/layout/compute-row-height.ts | 4 +- packages/vtable/src/ts-types/base-table.ts | 4 + packages/vtable/src/ts-types/customLayout.ts | 2 +- 21 files changed, 486 insertions(+), 21 deletions(-) create mode 100644 common/changes/@visactor/vtable/feat-react-component-container_2024-05-15-06-22.json create mode 100644 packages/react-vtable/demo/src/component/custom-layout.tsx create mode 100644 packages/react-vtable/src/components/custom/custom-layout.tsx create mode 100644 packages/react-vtable/src/components/custom/graphic.tsx create mode 100644 packages/react-vtable/src/components/custom/reconciler.tsx create mode 100644 packages/vtable/src/components/react/react-custom-layout.ts diff --git a/common/changes/@visactor/vtable/feat-react-component-container_2024-05-15-06-22.json b/common/changes/@visactor/vtable/feat-react-component-container_2024-05-15-06-22.json new file mode 100644 index 000000000..da8e03133 --- /dev/null +++ b/common/changes/@visactor/vtable/feat-react-component-container_2024-05-15-06-22.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "feat: add CustomLayout component in react-vtable", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 8a761df7f..ced04b4a2 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -180,6 +180,7 @@ importers: '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 '@types/react-is': ^17.0.3 + '@types/react-reconciler': 0.28.8 '@visactor/vchart': 1.10.0 '@visactor/vtable': workspace:* '@visactor/vutils': ~0.18.1 @@ -201,6 +202,7 @@ importers: react: ^18.0.0 react-dom: ^18.0.0 react-is: ^18.2.0 + react-reconciler: 0.29.2 rimraf: 3.0.2 sass: 1.43.5 ts-jest: ^26.0.0 @@ -216,6 +218,7 @@ importers: '@visactor/vtable': link:../vtable '@visactor/vutils': 0.18.1 react-is: 18.2.0 + react-reconciler: 0.29.2_react@18.2.0 devDependencies: '@arco-design/web-react': 2.60.2_6qcp4jokx32fjqh56b7wyl7qsu '@babel/core': 7.20.12 @@ -232,6 +235,7 @@ importers: '@types/react': 18.2.78 '@types/react-dom': 18.2.25 '@types/react-is': 17.0.7 + '@types/react-reconciler': 0.28.8 '@visactor/vchart': 1.10.0 '@vitejs/plugin-react': 3.1.0_vite@3.2.6 axios: 1.6.8 @@ -3332,6 +3336,12 @@ packages: '@types/react': 17.0.80 dev: true + /@types/react-reconciler/0.28.8: + resolution: {integrity: sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==} + dependencies: + '@types/react': 18.2.78 + dev: true + /@types/react/17.0.80: resolution: {integrity: sha512-LrgHIu2lEtIo8M7d1FcI3BdwXWoRQwMoXOZ7+dPTW0lYREjmlHl3P0U1VD0i/9tppOuv8/sam7sOjx34TxSFbA==} dependencies: @@ -11234,6 +11244,17 @@ packages: /react-is/18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + /react-reconciler/0.29.2_react@18.2.0: + resolution: {integrity: sha512-zZQqIiYgDCTP/f1N/mAR10nJGrPD2ZR+jDSEsKWJHYC7Cm2wodlwbR3upZRdC3cjIjSlTLNVyO7Iu0Yy7t2AYg==} + engines: {node: '>=0.10.0'} + peerDependencies: + react: ^18.3.1 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.2 + dev: false + /react-refresh/0.14.0: resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} engines: {node: '>=0.10.0'} @@ -11869,6 +11890,12 @@ packages: dependencies: loose-envify: 1.4.0 + /scheduler/0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + dependencies: + loose-envify: 1.4.0 + dev: false + /scroll-into-view-if-needed/2.2.20: resolution: {integrity: sha512-P9kYMrhi9f6dvWwTGpO5I3HgjSU/8Mts7xL3lkoH5xlewK7O9Obdc5WmMCzppln7bCVGNmf3qfoZXrpCeyNJXw==} dependencies: diff --git a/packages/react-vtable/demo/src/App.tsx b/packages/react-vtable/demo/src/App.tsx index a7b638e69..cb354ef79 100644 --- a/packages/react-vtable/demo/src/App.tsx +++ b/packages/react-vtable/demo/src/App.tsx @@ -14,6 +14,7 @@ import listTableEvent from './event/list-table'; import eventRebind from './event/event-rebind'; import componentContainer from './component/component-container'; +import customLayout from './component/custom-layout'; // export default listEditor; // export default listOptionRecord; @@ -29,4 +30,5 @@ import componentContainer from './component/component-container'; // export default listTableEvent; // export default eventRebind; -export default componentContainer; +// export default componentContainer; +export default customLayout; diff --git a/packages/react-vtable/demo/src/component/custom-layout.tsx b/packages/react-vtable/demo/src/component/custom-layout.tsx new file mode 100644 index 000000000..3361a3780 --- /dev/null +++ b/packages/react-vtable/demo/src/component/custom-layout.tsx @@ -0,0 +1,100 @@ +import { useEffect, useState } from 'react'; +import type { CustomLayoutFunctionArg } from '../../../src'; +import { ListTable, ListColumn, CustomLayout, Group, Text } from '../../../src'; + +type FieldData = { value: string; label: string }; + +const CustomLayoutComponent = (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 row = 3; + // const width = 100; + // const height = 100; + const fieldData = [ + { + value: 'a', + label: 'a' + }, + { + value: 'b', + label: 'b' + } + ]; + + // useEffect(() => { + // flash(col, row, this); + // }, [hover]); + + return ( + + {fieldData.map(item => { + return ( + row !== 2 && ( + { + // if (stateName === 'hover') { + // return { + // fill: 'red' + // }; + // } + // }} + onMouseEnter={(event: any) => { + setHover(true); + event.currentTarget.stage.renderNextFrame(); + }} + onMouseLeave={(event: any) => { + setHover(false); + event.currentTarget.stage.renderNextFrame(); + }} + > + ) + ); + })} + + ); +}; + +function App() { + const records = new Array(10).fill(['John', 18, 'male', '🏀']); + const [preStr, setPreStr] = useState('vt'); + + useEffect(() => { + // eslint-disable-next-line no-undef + setTimeout(() => { + setPreStr(preStr + '1'); + }, 1000); + }, []); + + return ( + + + + + + + + + + + ); +} + +export default App; diff --git a/packages/react-vtable/demo/vite.config.ts b/packages/react-vtable/demo/vite.config.ts index 9026d0f6e..fbc8fcd80 100644 --- a/packages/react-vtable/demo/vite.config.ts +++ b/packages/react-vtable/demo/vite.config.ts @@ -25,6 +25,7 @@ export default defineConfig({ }, resolve: { alias: { + '@visactor/vtable/src/vrender': path.resolve(__dirname, '../../vtable/src/vrender.ts'), '@visactor/vtable': path.resolve(__dirname, '../../vtable/src/index.ts'), '@src': path.resolve(__dirname, '../../vtable/src/') // ...localConf.resolve?.alias diff --git a/packages/react-vtable/package.json b/packages/react-vtable/package.json index c656e28bb..1c7098dcf 100644 --- a/packages/react-vtable/package.json +++ b/packages/react-vtable/package.json @@ -51,7 +51,8 @@ "dependencies": { "@visactor/vtable": "workspace:*", "@visactor/vutils": "~0.18.1", - "react-is": "^18.2.0" + "react-is": "^18.2.0", + "react-reconciler": "0.29.2" }, "devDependencies": { "@visactor/vchart": "1.10.0", @@ -97,6 +98,7 @@ "form-data": "~4.0.0", "axios": "^1.4.0", "@types/react-is": "^17.0.3", - "@arco-design/web-react": "2.60.2" + "@arco-design/web-react": "2.60.2", + "@types/react-reconciler": "0.28.8" } -} +} \ No newline at end of file diff --git a/packages/react-vtable/src/components/base-component.tsx b/packages/react-vtable/src/components/base-component.tsx index 7d8f365d9..47b95643b 100644 --- a/packages/react-vtable/src/components/base-component.tsx +++ b/packages/react-vtable/src/components/base-component.tsx @@ -1,16 +1,19 @@ -import React, { useContext, useEffect } from 'react'; +import type { ReactElement } from 'react'; +import React, { cloneElement, useContext, useEffect } from 'react'; import { isEqual, isNil, pickWithout } from '@visactor/vutils'; import type { TableContextType } from '../context/table'; import RootTableContext from '../context/table'; import { bindEventsToTable } from '../eventsUtils'; import { uid } from '../util'; +import { CustomLayout } from './custom/custom-layout'; export interface BaseComponentProps { id?: string | number; + children?: React.ReactNode; } -type ComponentProps = BaseComponentProps & { updateId?: number; componentId?: number }; +type ComponentProps = BaseComponentProps & { updateId?: number; componentId?: number; componentIndex?: number }; export const createComponent = ( componentName: string, @@ -18,7 +21,7 @@ export const createComponent = ( supportedEvents?: Record | null, isSingle?: boolean ) => { - const ignoreKeys = ['id', 'updateId', 'componentId']; + const ignoreKeys = ['id', 'updateId', 'componentId', 'componentIndex', 'children']; const notOptionKeys = supportedEvents ? Object.keys(supportedEvents).concat(ignoreKeys) : ignoreKeys; const Comp: React.FC = (props: T) => { @@ -57,8 +60,9 @@ export const createComponent = ( // deleteToContext(context, id.current, optionName, isSingle); }; }, []); - - return null; + return props.children + ? cloneElement(props.children as ReactElement, { componentIndex: props.componentIndex }) + : null; }; Comp.displayName = componentName; @@ -66,6 +70,11 @@ export const createComponent = ( (Comp as any).parseOption = (props: T & { updateId?: number; componentId?: string }) => { const newComponentOption: Partial = pickWithout(props, notOptionKeys); + // deal width customLayout + if (props.children && (props.children as React.ReactElement).type === CustomLayout) { + (newComponentOption as any).customLayout = 'react-custom-layout'; + } + return { option: newComponentOption, optionName, diff --git a/packages/react-vtable/src/components/custom/custom-layout.tsx b/packages/react-vtable/src/components/custom/custom-layout.tsx new file mode 100644 index 000000000..df0a430f5 --- /dev/null +++ b/packages/react-vtable/src/components/custom/custom-layout.tsx @@ -0,0 +1,90 @@ +import React, { useCallback, useContext, useLayoutEffect, useRef } from 'react'; +import RootTableContext from '../../context/table'; +import { Group } from '@visactor/vtable/src/vrender'; +import type { ICustomLayoutFuc, CustomRenderFunctionArg } from '@visactor/vtable/src/ts-types'; +import type { FiberRoot } from 'react-reconciler'; +import { reconcilor } from './reconciler'; +import { LegacyRoot } from 'react-reconciler/constants'; + +type CustomLayoutProps = { componentIndex?: number; children: React.ReactElement }; + +export type CustomLayoutFunctionArg = Partial; + +export const CustomLayout: React.FC = (props: CustomLayoutProps, ref) => { + const { componentIndex, children } = props; + const context = useContext(RootTableContext); + const { table } = context; + + // react customLayout component container cache + const container = useRef>(new Map()); + + // customLayout function for vtable + const createGraphic: ICustomLayoutFuc = useCallback( + args => { + const key = `${args.col}-${args.row}`; + let group; + if (container.current.has(key)) { + const currentContainer = container.current.get(key); + reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); + group = currentContainer.containerInfo; + } else { + group = new Group({}); + const currentContainer = reconcilor.createContainer(group, LegacyRoot, null, null, null, 'custom', null, null); + container.current.set(key, currentContainer); + reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); + } + + return { + rootContainer: group, + renderDefault: false + }; + }, + [children] + ); + + useLayoutEffect(() => { + // init and release + // eslint-disable-next-line no-undef + console.log('init/release', props, table); + // table && (table._reactCreateGraphic = createGraphic); // never go to here + // table?.renderWithRecreateCells(); + }, []); + + useLayoutEffect(() => { + // update props + // eslint-disable-next-line no-undef + console.log('update props', props, table); + + table?.checkReactCustomLayout(); // init reactCustomLayout component + if (table && !table.reactCustomLayout?.hasReactCreateGraphic(componentIndex)) { + table.reactCustomLayout?.setReactCreateGraphic(componentIndex, createGraphic, container.current); // set customLayout function + table.reactCustomLayout?.updateCustomCell(componentIndex); // update cell content + } else if (table) { + container.current.forEach((value, key) => { + const [col, row] = key.split('-').map(Number); + const width = table.getColWidth(col); + const height = table.getRowHeight(row); + const currentContainer = value; + const args = { + col, + row, + dataValue: table.getCellOriginValue(col, row), + value: table.getCellValue(col, row) || '', + rect: { + left: 0, + top: 0, + right: width, + bottom: height, + width, + height + }, + table + }; + reconcilor.updateContainer(React.cloneElement(props.children, { ...args }), currentContainer, null); + table.scenegraph.updateNextFrame(); + }); + } + }); + + return null; +}; diff --git a/packages/react-vtable/src/components/custom/graphic.tsx b/packages/react-vtable/src/components/custom/graphic.tsx new file mode 100644 index 000000000..e380368e3 --- /dev/null +++ b/packages/react-vtable/src/components/custom/graphic.tsx @@ -0,0 +1,3 @@ +export const Group = 'group'; +export const Rect = 'rect'; +export const Text = 'text'; diff --git a/packages/react-vtable/src/components/custom/reconciler.tsx b/packages/react-vtable/src/components/custom/reconciler.tsx new file mode 100644 index 000000000..955887a4d --- /dev/null +++ b/packages/react-vtable/src/components/custom/reconciler.tsx @@ -0,0 +1,155 @@ +import type { Graphic } from '@visactor/vtable/src/vrender'; +import { application, createText, REACT_TO_CANOPUS_EVENTS } from '@visactor/vtable/src/vrender'; +import { isFunction } from '@visactor/vutils'; +import React from 'react'; +import ReactReconciler from 'react-reconciler'; +import { DefaultEventPriority } from 'react-reconciler/constants.js'; + +type Instance = Graphic; + +export const reconcilor = ReactReconciler({ + supportsMutation: true, + supportsPersistence: false, + + createInstance: (type: string, props: any, instance) => { + const graphic = createGraphic(type, props); + bindEventsToGraphic(graphic, props); + return graphic; + }, + + createTextInstance: (text, instance) => { + const textGraphic = createText({ text }); + return textGraphic; + }, + + appendInitialChild: (parentInstance: Instance, childInstance: Instance) => { + parentInstance.add(childInstance); + }, + + finalizeInitialChildren: () => false, + + prepareUpdate: () => true, + + shouldSetTextContent: () => false, + + getRootHostContext: () => null, + + getChildHostContext: () => null, + + getPublicInstance: (instance: Instance) => { + return instance; + }, + + prepareForCommit: () => null, + + resetAfterCommit: () => undefined, + + preparePortalMount: () => null, + + // eslint-disable-next-line no-undef + scheduleTimeout: setTimeout, + // eslint-disable-next-line no-undef + cancelTimeout: clearTimeout, + + noTimeout: -1, + isPrimaryRenderer: false, + + getCurrentEventPriority: () => DefaultEventPriority, + + getInstanceFromNode: node => null, + + beforeActiveInstanceBlur: () => undefined, + + afterActiveInstanceBlur: () => undefined, + + prepareScopeUpdate: () => undefined, + + getInstanceFromScope: () => undefined, + + detachDeletedInstance: () => undefined, + + supportsHydration: false, + + appendChild: (parentInstance: Instance, child: Instance) => { + parentInstance.add(child); + }, + appendChildToContainer: (container: Instance, child: Instance) => { + container.add(child); + }, + + insertBefore: (parentInstance: Instance, child: Instance, beforeChild: Instance) => { + parentInstance.insertBefore(child, beforeChild); + }, + + insertInContainerBefore: (parentInstance: Instance, child: Instance, beforeChild: Instance) => { + parentInstance.insertBefore(child, beforeChild); + }, + + removeChild: (parentInstance: Instance, child: Instance) => { + child.delete(); + }, + + removeChildFromContainer: (parentInstance: Instance, child: Instance) => { + child.delete(); + }, + + commitUpdate: (instance, updatePayload, type, oldProps, newProps) => { + updateGraphicProps(instance, newProps, oldProps); + }, + + hideInstance: (instance: Instance) => { + instance.setAttribute('visible', false); + }, + + unhideInstance: (instance, props) => { + instance.setAttribute('visible', true); + }, + + clearContainer: (container: Instance) => { + container.removeAllChild(); + } +}); + +reconcilor.injectIntoDevTools({ + // findFiberByHostInstance: () => {}, + // @ts-ignore + // eslint-disable-next-line no-undef + bundleType: process.env.NODE_ENV !== 'production' ? 1 : 0, + version: React.version, + rendererPackageName: 'react-vtable' +}); + +function createGraphic(type: string, props: any) { + // may have unwanted onxxx prop + const graphic = application.graphicService.creator[type]((props as any).attribute); + return graphic; +} + +function isEventProp(key: string, props: any) { + return key.startsWith('on') && isFunction(props[key]); +} + +function bindEventsToGraphic(graphic: Graphic, props: any) { + for (const key in props) { + if (isEventProp(key, props)) { + graphic.addEventListener(REACT_TO_CANOPUS_EVENTS[key], props[key]); + } + } +} + +function updateGraphicProps(graphic: Graphic, newProps: any, oldProps: any) { + // deal width event update + for (const propKey in oldProps) { + if (isEventProp(propKey, oldProps) && oldProps[propKey] !== newProps[propKey]) { + graphic.removeEventListener(REACT_TO_CANOPUS_EVENTS[propKey], oldProps[propKey]); + } + } + for (const propKey in newProps) { + if (isEventProp(propKey, newProps) && oldProps[propKey] !== newProps[propKey]) { + graphic.addEventListener(REACT_TO_CANOPUS_EVENTS[propKey], newProps[propKey]); + } + } + + // update all attribute + graphic.initAttributes(newProps.attribute); +} diff --git a/packages/react-vtable/src/components/index.ts b/packages/react-vtable/src/components/index.ts index 908de112f..2988d6055 100644 --- a/packages/react-vtable/src/components/index.ts +++ b/packages/react-vtable/src/components/index.ts @@ -8,6 +8,8 @@ export { Menu } from './component/menu'; export { Tooltip } from './component/tooltip'; export { CustomComponent } from './custom-component'; +export { CustomLayout, type CustomLayoutFunctionArg } from './custom/custom-layout'; +export * from './custom/graphic'; type Props = { updateId?: number }; diff --git a/packages/react-vtable/src/tables/base-table.tsx b/packages/react-vtable/src/tables/base-table.tsx index 0f6197809..8160fde7b 100644 --- a/packages/react-vtable/src/tables/base-table.tsx +++ b/packages/react-vtable/src/tables/base-table.tsx @@ -269,7 +269,8 @@ const BaseTable: React.FC = React.forwardRef((props, ref) => { {React.cloneElement(child as React.ReactElement>, { updateId: updateId, - componentId: childId + componentId: childId, + componentIndex: index })} ); diff --git a/packages/vtable/src/ListTable.ts b/packages/vtable/src/ListTable.ts index 70fe413db..879309fb2 100644 --- a/packages/vtable/src/ListTable.ts +++ b/packages/vtable/src/ListTable.ts @@ -69,9 +69,9 @@ export class ListTable extends BaseTable implements ListTableAPI { internalProps.sortState = options.sortState; internalProps.dataConfig = {}; //cloneDeep(options.dataConfig ?? {}); internalProps.columns = options.columns - ? cloneDeepSpec(options.columns) + ? cloneDeepSpec(options.columns, ['children']) // children for react : options.header - ? cloneDeepSpec(options.header) + ? cloneDeepSpec(options.header, ['children']) : []; options.columns?.forEach((colDefine, index) => { //如果editor 是一个IEditor的实例 需要这样重新赋值 否则clone后变质了 @@ -145,7 +145,7 @@ export class ListTable extends BaseTable implements ListTableAPI { */ updateColumns(columns: ColumnsDefine) { const oldHoverState = { col: this.stateManager.hover.cellPos.col, row: this.stateManager.hover.cellPos.row }; - this.internalProps.columns = cloneDeepSpec(columns); + this.internalProps.columns = cloneDeepSpec(columns, ['children']); columns.forEach((colDefine, index) => { if (colDefine.editor) { this.internalProps.columns[index].editor = colDefine.editor; @@ -380,9 +380,9 @@ export class ListTable extends BaseTable implements ListTableAPI { //更新protectedSpace this.showHeader = options.showHeader ?? true; internalProps.columns = options.columns - ? cloneDeepSpec(options.columns) + ? cloneDeepSpec(options.columns, ['children']) : options.header - ? cloneDeepSpec(options.header) + ? cloneDeepSpec(options.header, ['children']) : []; options.columns.forEach((colDefine, index) => { if (colDefine.editor) { diff --git a/packages/vtable/src/components/react/react-custom-layout.ts b/packages/vtable/src/components/react/react-custom-layout.ts new file mode 100644 index 000000000..75e50fdbd --- /dev/null +++ b/packages/vtable/src/components/react/react-custom-layout.ts @@ -0,0 +1,45 @@ +import { Group } from '@src/vrender'; +import type { CustomRenderFunctionArg, ICustomLayoutFuc } from '../../ts-types'; +import type { BaseTableAPI } from '../../ts-types/base-table'; + +export function emptyCustomLayout(args: CustomRenderFunctionArg) { + const group = new Group({}); + return { + rootContainer: group, + renderDefault: true + }; +} + +export class ReactCustomLayout { + table: BaseTableAPI; + customLayoutFuncCache: Map; + reactContainerCache: Map>; + constructor(table: BaseTableAPI) { + this.table = table; + this.customLayoutFuncCache = new Map(); + this.reactContainerCache = new Map(); + } + + hasReactCreateGraphic(componentIndex: number) { + return this.reactContainerCache.has(componentIndex); + } + + setReactCreateGraphic(componentIndex: number, createGraphic: ICustomLayoutFuc, containerCache: Map) { + this.customLayoutFuncCache.set(componentIndex, createGraphic); + this.reactContainerCache.set(componentIndex, containerCache); + } + + updateCustomCell(componentIndex: number) { + const table = this.table; + const col = componentIndex; + for (let row = table.columnHeaderLevelCount; row < table.rowCount; row++) { + table.scenegraph.updateCellContent(col, row); + } + table.scenegraph.updateNextFrame(); + } + + getCustomLayoutFunc(col: number, row: number) { + const { startInTotal } = this.table.getBodyColumnDefine(col, row) as any; + return this.customLayoutFuncCache.get(startInTotal) || emptyCustomLayout; + } +} diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 20faeb7cf..c1b466bb6 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -126,6 +126,7 @@ import { RowSeriesNumberHelper } from './row-series-number-helper'; import { CustomCellStylePlugin, mergeStyle } from '../plugins/custom-cell-style'; import { hideCellSelectBorder, restoreCellSelectBorder } from '../scenegraph/select/update-select-border'; import type { ITextGraphicAttribute } from '@src/vrender'; +import { ReactCustomLayout } from '../components/react/react-custom-layout'; const { toBoxArray } = utilStyle; const { isTouchEvent } = event; @@ -195,6 +196,8 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { columnWidthComputeMode?: 'normal' | 'only-header' | 'only-body'; + reactCustomLayout?: ReactCustomLayout; + constructor(container: HTMLElement, options: BaseTableConstructorOptions = {}) { super(); if (!container && options.mode !== 'node') { @@ -4254,4 +4257,10 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { // startInertia() { // startInertia(0, -1, 1, this.stateManager); // } + + checkReactCustomLayout() { + if (!this.reactCustomLayout) { + this.reactCustomLayout = new ReactCustomLayout(this); + } + } } diff --git a/packages/vtable/src/scenegraph/component/custom.ts b/packages/vtable/src/scenegraph/component/custom.ts index 61d2af606..01bafb0a7 100644 --- a/packages/vtable/src/scenegraph/component/custom.ts +++ b/packages/vtable/src/scenegraph/component/custom.ts @@ -19,6 +19,7 @@ import type { import { Icon } from '../graphic/icon'; import type { BaseTableAPI } from '../../ts-types/base-table'; import type { percentCalcObj } from '../../render/layout'; +import { emptyCustomLayout } from '../../components/react/react-custom-layout'; export function dealWithCustom( customLayout: ICustomLayout, @@ -39,6 +40,10 @@ export function dealWithCustom( let customElements; let elementsGroup: VGroup; + if (customLayout === 'react-custom-layout') { + // customLayout = table._reactCreateGraphic; + customLayout = table.reactCustomLayout?.getCustomLayoutFunc(col, row) || emptyCustomLayout; + } if (typeof customLayout === 'function') { const arg = { col, diff --git a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts index 1747ef172..94a6524ea 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts @@ -715,7 +715,7 @@ function canUseFastUpdate(col: number, row: number, oldCellGroup: Group, autoWra !autoWrapText && !autoRowHeight && !mayHaveIcon && - oldCellGroup.firstChild?.type === 'text' && + oldCellGroup.firstChild?.type === 'text' && // judgement for none text !isPromise(value) ) { return true; diff --git a/packages/vtable/src/scenegraph/layout/compute-col-width.ts b/packages/vtable/src/scenegraph/layout/compute-col-width.ts index b2b1fce4f..cfccd4e25 100644 --- a/packages/vtable/src/scenegraph/layout/compute-col-width.ts +++ b/packages/vtable/src/scenegraph/layout/compute-col-width.ts @@ -17,7 +17,7 @@ import type { PivotHeaderLayoutMap } from '../../layout/pivot-header-layout'; import { getAxisConfigInPivotChart } from '../../layout/chart-helper/get-axis-config'; import { computeAxisComponentWidth } from '../../components/axis/get-axis-component-size'; import { Group as VGroup } from '@src/vrender'; -import { isArray, isNumber, isObject, isValid } from '@visactor/vutils'; +import { isArray, isFunction, isNumber, isObject, isValid } from '@visactor/vutils'; import { decodeReactDom, dealPercentCalc } from '../component/custom'; export function computeColsWidth(table: BaseTableAPI, colStart?: number, colEnd?: number, update?: boolean): void { @@ -439,7 +439,7 @@ function computeCustomRenderWidth(col: number, row: number, table: BaseTableAPI) rect: getCellRect(col, row, table), table }; - if (customLayout) { + if (isFunction(customLayout)) { // 处理customLayout const customLayoutObj = customLayout(arg); if (customLayoutObj.rootContainer instanceof VGroup) { diff --git a/packages/vtable/src/scenegraph/layout/compute-row-height.ts b/packages/vtable/src/scenegraph/layout/compute-row-height.ts index b73171f23..6ae290509 100644 --- a/packages/vtable/src/scenegraph/layout/compute-row-height.ts +++ b/packages/vtable/src/scenegraph/layout/compute-row-height.ts @@ -10,7 +10,7 @@ import { getQuadProps } from '../utils/padding'; import { dealWithRichTextIcon } from '../utils/text-icon-layout'; import { getAxisConfigInPivotChart } from '../../layout/chart-helper/get-axis-config'; import { computeAxisComponentHeight } from '../../components/axis/get-axis-component-size'; -import { isArray, isNumber, isObject, isValid } from '@visactor/vutils'; +import { isArray, isFunction, isNumber, isObject, isValid } from '@visactor/vutils'; import { CheckBox } from '@visactor/vrender-components'; import { decodeReactDom, dealPercentCalc } from '../component/custom'; import { getCellMergeRange } from '../../tools/merge-range'; @@ -542,7 +542,7 @@ function computeCustomRenderHeight(col: number, row: number, table: BaseTableAPI rect: getCellRect(col, row, table), table }; - if (customLayout) { + if (isFunction(customLayout)) { // 处理customLayout const customLayoutObj = customLayout(arg); if (customLayoutObj.rootContainer instanceof VGroup) { diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index 7a0cf6a53..d38e8f578 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -90,6 +90,7 @@ import type { DiscreteTableLegend } from '../components/legend/discrete-legend/d import type { ContinueTableLegend } from '../components/legend/continue-legend/continue-legend'; import type { NumberRangeMap } from '../layout/row-height-map'; import type { RowSeriesNumberHelper } from '../core/row-series-number-helper'; +import type { ReactCustomLayout } from '../components/react/react-custom-layout'; export interface IBaseTableProtected { element: HTMLElement; @@ -786,6 +787,9 @@ export interface BaseTableAPI { isHasSeriesNumber: () => boolean; leftRowSeriesNumberCount: number; isAutoRowHeight: (row: number) => boolean; + + reactCustomLayout?: ReactCustomLayout; + checkReactCustomLayout: () => void; } export interface ListTableProtected extends IBaseTableProtected { /** 表格数据 */ diff --git a/packages/vtable/src/ts-types/customLayout.ts b/packages/vtable/src/ts-types/customLayout.ts index a82ab4c50..11a8d5153 100644 --- a/packages/vtable/src/ts-types/customLayout.ts +++ b/packages/vtable/src/ts-types/customLayout.ts @@ -15,4 +15,4 @@ export type ICustomLayoutObj = { export type ICustomLayoutFuc = (args: CustomRenderFunctionArg) => ICustomLayoutObj; -export type ICustomLayout = ICustomLayoutFuc; +export type ICustomLayout = ICustomLayoutFuc | 'react-custom-layout'; From 86e61a6b54028775747c0f628ba7e7cabb89e25b Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Wed, 15 May 2024 16:58:34 +0800 Subject: [PATCH 06/85] feat: add graphic component types --- .../demo/src/component/custom-layout.tsx | 7 +- .../src/components/custom/custom-layout.tsx | 6 +- .../src/components/custom/graphic.ts | 85 +++++++++++++++++++ .../src/components/custom/graphic.tsx | 3 - .../custom/{reconciler.tsx => reconciler.ts} | 0 5 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 packages/react-vtable/src/components/custom/graphic.ts delete mode 100644 packages/react-vtable/src/components/custom/graphic.tsx rename packages/react-vtable/src/components/custom/{reconciler.tsx => reconciler.ts} (100%) diff --git a/packages/react-vtable/demo/src/component/custom-layout.tsx b/packages/react-vtable/demo/src/component/custom-layout.tsx index 3361a3780..84d7a6195 100644 --- a/packages/react-vtable/demo/src/component/custom-layout.tsx +++ b/packages/react-vtable/demo/src/component/custom-layout.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import type { CustomLayoutFunctionArg } from '../../../src'; import { ListTable, ListColumn, CustomLayout, Group, Text } from '../../../src'; @@ -25,6 +25,8 @@ const CustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string } } ]; + const groupRef = useRef(null); + // useEffect(() => { // flash(col, row, this); // }, [hover]); @@ -39,6 +41,7 @@ const CustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string } alignItems: 'center', alignContent: 'center' }} + ref={groupRef} > {fieldData.map(item => { return ( @@ -57,6 +60,8 @@ const CustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string } // } // }} onMouseEnter={(event: any) => { + // eslint-disable-next-line no-console, no-undef + console.log('groupRef', groupRef.current); setHover(true); event.currentTarget.stage.renderNextFrame(); }} diff --git a/packages/react-vtable/src/components/custom/custom-layout.tsx b/packages/react-vtable/src/components/custom/custom-layout.tsx index df0a430f5..f79498e57 100644 --- a/packages/react-vtable/src/components/custom/custom-layout.tsx +++ b/packages/react-vtable/src/components/custom/custom-layout.tsx @@ -60,10 +60,11 @@ export const CustomLayout: React.FC = (props: CustomLayoutPro table.reactCustomLayout?.setReactCreateGraphic(componentIndex, createGraphic, container.current); // set customLayout function table.reactCustomLayout?.updateCustomCell(componentIndex); // update cell content } else if (table) { + // update all container container.current.forEach((value, key) => { const [col, row] = key.split('-').map(Number); - const width = table.getColWidth(col); - const height = table.getRowHeight(row); + const width = table.getColWidth(col); // to be fixed: may be merge cell + const height = table.getRowHeight(row); // to be fixed: may be merge cell const currentContainer = value; const args = { col, @@ -80,6 +81,7 @@ export const CustomLayout: React.FC = (props: CustomLayoutPro }, table }; + // update element in container reconcilor.updateContainer(React.cloneElement(props.children, { ...args }), currentContainer, null); table.scenegraph.updateNextFrame(); }); diff --git a/packages/react-vtable/src/components/custom/graphic.ts b/packages/react-vtable/src/components/custom/graphic.ts new file mode 100644 index 000000000..d053b4d74 --- /dev/null +++ b/packages/react-vtable/src/components/custom/graphic.ts @@ -0,0 +1,85 @@ +// export const Group = 'group'; +// export const Rect = 'rect'; +// export const Text = 'text'; + +import type { ReactElement, ReactNode, Ref, JSXElementConstructor } from 'react'; +import type { + IGraphic, + IGroupGraphicAttribute, + ITextGraphicAttribute, + IEventParamsType, + IArcGraphicAttribute, + ICircleGraphicAttribute, + IImageGraphicAttribute, + ILineGraphicAttribute, + IPathGraphicAttribute, + IRectGraphicAttribute, + ISymbolGraphicAttribute, + IRichTextGraphicAttribute, + IPolygonGraphicAttribute +} from '@visactor/vtable/src/vrender'; + +type GraphicProps = { + attribute: IGraphicGraphicAttribute; + ref?: Ref; + children?: ReactNode; +} & IEventParamsType; + +export const Group: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = + 'group' as any; + +export const Text: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = + 'text' as any; + +export const Arc: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = + 'arc' as any; + +export const Circle: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = + 'circle' as any; + +export const Image: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = + 'image' as any; + +export const Line: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = + 'line' as any; + +export const Path: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = + 'path' as any; + +export const Rect: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = + 'rect' as any; + +export const Symbol: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = + 'symbol' as any; + +export const RichText: ( + props: GraphicProps +) => ReactElement< + GraphicProps, + JSXElementConstructor> +> = 'richtext' as any; + +export const Polygon: ( + props: GraphicProps +) => ReactElement< + GraphicProps, + JSXElementConstructor> +> = 'polygon' as any; diff --git a/packages/react-vtable/src/components/custom/graphic.tsx b/packages/react-vtable/src/components/custom/graphic.tsx deleted file mode 100644 index e380368e3..000000000 --- a/packages/react-vtable/src/components/custom/graphic.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export const Group = 'group'; -export const Rect = 'rect'; -export const Text = 'text'; diff --git a/packages/react-vtable/src/components/custom/reconciler.tsx b/packages/react-vtable/src/components/custom/reconciler.ts similarity index 100% rename from packages/react-vtable/src/components/custom/reconciler.tsx rename to packages/react-vtable/src/components/custom/reconciler.ts From 53abc2a325d3e469bf3430f4a62786436e17e896 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Thu, 16 May 2024 11:14:47 +0800 Subject: [PATCH 07/85] feat: add react custom cell remove --- .../demo/src/component/custom-layout.tsx | 11 ++++++++++- .../src/components/custom/custom-layout.tsx | 17 ++++++++++++++++- .../src/components/react/react-custom-layout.ts | 14 ++++++++++++++ .../vtable/src/scenegraph/component/custom.ts | 2 ++ .../src/scenegraph/group-creater/cell-helper.ts | 9 +++++++++ 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/packages/react-vtable/demo/src/component/custom-layout.tsx b/packages/react-vtable/demo/src/component/custom-layout.tsx index 84d7a6195..d7b69ab37 100644 --- a/packages/react-vtable/demo/src/component/custom-layout.tsx +++ b/packages/react-vtable/demo/src/component/custom-layout.tsx @@ -73,12 +73,21 @@ const CustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string } ) ); })} + {hover && ( + + )} ); }; function App() { - const records = new Array(10).fill(['John', 18, 'male', '🏀']); + const records = new Array(1000).fill(['John', 18, 'male', '🏀']); const [preStr, setPreStr] = useState('vt'); useEffect(() => { diff --git a/packages/react-vtable/src/components/custom/custom-layout.tsx b/packages/react-vtable/src/components/custom/custom-layout.tsx index f79498e57..6a926c19c 100644 --- a/packages/react-vtable/src/components/custom/custom-layout.tsx +++ b/packages/react-vtable/src/components/custom/custom-layout.tsx @@ -42,12 +42,26 @@ export const CustomLayout: React.FC = (props: CustomLayoutPro [children] ); + const removeContainer = useCallback((col: number, row: number) => { + const key = `${col}-${row}`; + if (container.current.has(key)) { + const currentContainer = container.current.get(key); + reconcilor.updateContainer(null, currentContainer, null); + // group = currentContainer.containerInfo; + container.current.delete(key); + } + }, []); + useLayoutEffect(() => { // init and release // eslint-disable-next-line no-undef - console.log('init/release', props, table); + console.log('init', props, table); // table && (table._reactCreateGraphic = createGraphic); // never go to here // table?.renderWithRecreateCells(); + return () => { + // eslint-disable-next-line no-undef + console.log('release', props, table); + }; }, []); useLayoutEffect(() => { @@ -58,6 +72,7 @@ export const CustomLayout: React.FC = (props: CustomLayoutPro table?.checkReactCustomLayout(); // init reactCustomLayout component if (table && !table.reactCustomLayout?.hasReactCreateGraphic(componentIndex)) { table.reactCustomLayout?.setReactCreateGraphic(componentIndex, createGraphic, container.current); // set customLayout function + table.reactCustomLayout?.setReactRemoveGraphic(componentIndex, removeContainer); // set customLayout function table.reactCustomLayout?.updateCustomCell(componentIndex); // update cell content } else if (table) { // update all container diff --git a/packages/vtable/src/components/react/react-custom-layout.ts b/packages/vtable/src/components/react/react-custom-layout.ts index 75e50fdbd..50cce2d83 100644 --- a/packages/vtable/src/components/react/react-custom-layout.ts +++ b/packages/vtable/src/components/react/react-custom-layout.ts @@ -13,11 +13,13 @@ export function emptyCustomLayout(args: CustomRenderFunctionArg) { export class ReactCustomLayout { table: BaseTableAPI; customLayoutFuncCache: Map; + reactRemoveGraphicCache: Map void>; reactContainerCache: Map>; constructor(table: BaseTableAPI) { this.table = table; this.customLayoutFuncCache = new Map(); this.reactContainerCache = new Map(); + this.reactRemoveGraphicCache = new Map(); } hasReactCreateGraphic(componentIndex: number) { @@ -29,6 +31,10 @@ export class ReactCustomLayout { this.reactContainerCache.set(componentIndex, containerCache); } + setReactRemoveGraphic(componentIndex: number, removeGraphic: (col: number, row: number) => void) { + this.reactRemoveGraphicCache.set(componentIndex, removeGraphic); + } + updateCustomCell(componentIndex: number) { const table = this.table; const col = componentIndex; @@ -42,4 +48,12 @@ export class ReactCustomLayout { const { startInTotal } = this.table.getBodyColumnDefine(col, row) as any; return this.customLayoutFuncCache.get(startInTotal) || emptyCustomLayout; } + + removeCustomCell(col: number, row: number) { + const { startInTotal } = this.table.getBodyColumnDefine(col, row) as any; + const removeFun = this.reactRemoveGraphicCache.get(startInTotal); + if (removeFun) { + removeFun(col, row); + } + } } diff --git a/packages/vtable/src/scenegraph/component/custom.ts b/packages/vtable/src/scenegraph/component/custom.ts index 01bafb0a7..60581cf0b 100644 --- a/packages/vtable/src/scenegraph/component/custom.ts +++ b/packages/vtable/src/scenegraph/component/custom.ts @@ -69,6 +69,8 @@ export function dealWithCustom( if (customRenderObj.rootContainer instanceof VGroup) { elementsGroup = customRenderObj.rootContainer; elementsGroup.name = 'custom-container'; + (elementsGroup as any).col = col; + (elementsGroup as any).row = row; // } else if (customRenderObj.rootContainer) { // customElements = customRenderObj.rootContainer.getElements(undefined, false, false); } diff --git a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts index 94a6524ea..bf47e04f2 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts @@ -665,6 +665,14 @@ function updateCellContent( if (!addNew && (oldCellGroup.row !== row || oldCellGroup.col !== col)) { return null; } + if (!addNew && oldCellGroup.parent) { + // clear react container + if (table.reactCustomLayout) { + const reactGroup = oldCellGroup.getChildByName('custom-container'); + const { col, row } = reactGroup; + table.reactCustomLayout.removeCustomCell(col, row); + } + } const newCellGroup = createCell( type, value, @@ -688,6 +696,7 @@ function updateCellContent( customResult ); if (!addNew && oldCellGroup.parent) { + // update cell oldCellGroup.parent.insertAfter(newCellGroup, oldCellGroup); oldCellGroup.parent.removeChild(oldCellGroup); From b6e74e15ffcc3daa90e9625eb8329869a7036385 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Thu, 16 May 2024 15:14:40 +0800 Subject: [PATCH 08/85] feat: add react header custom cell support --- .../demo/src/component/custom-layout.tsx | 56 +++++++++++++++- .../src/components/base-component.tsx | 31 +++++++-- .../src/components/custom/custom-layout.tsx | 32 ++++++--- .../components/react/react-custom-layout.ts | 67 +++++++++++++++---- 4 files changed, 154 insertions(+), 32 deletions(-) diff --git a/packages/react-vtable/demo/src/component/custom-layout.tsx b/packages/react-vtable/demo/src/component/custom-layout.tsx index d7b69ab37..06f81ce68 100644 --- a/packages/react-vtable/demo/src/component/custom-layout.tsx +++ b/packages/react-vtable/demo/src/component/custom-layout.tsx @@ -86,6 +86,57 @@ const CustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string } ); }; +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 && ( + + )} + + ); +}; + function App() { const records = new Array(1000).fill(['John', 18, 'male', '🏀']); const [preStr, setPreStr] = useState('vt'); @@ -103,9 +154,8 @@ function App() { - - - + + ); diff --git a/packages/react-vtable/src/components/base-component.tsx b/packages/react-vtable/src/components/base-component.tsx index 47b95643b..87cb3520d 100644 --- a/packages/react-vtable/src/components/base-component.tsx +++ b/packages/react-vtable/src/components/base-component.tsx @@ -1,5 +1,5 @@ import type { ReactElement } from 'react'; -import React, { cloneElement, useContext, useEffect } from 'react'; +import React, { useContext, useEffect } from 'react'; import { isEqual, isNil, pickWithout } from '@visactor/vutils'; import type { TableContextType } from '../context/table'; @@ -60,9 +60,17 @@ export const createComponent = ( // deleteToContext(context, id.current, optionName, isSingle); }; }, []); - return props.children - ? cloneElement(props.children as ReactElement, { componentIndex: props.componentIndex }) - : null; + + // children are all custom layout temply + // 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; }; Comp.displayName = componentName; @@ -71,9 +79,20 @@ export const createComponent = ( const newComponentOption: Partial = pickWithout(props, notOptionKeys); // deal width customLayout - if (props.children && (props.children as React.ReactElement).type === CustomLayout) { - (newComponentOption as any).customLayout = 'react-custom-layout'; + 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'; + } + }); } + // if (props.children && (props.children as React.ReactElement).props.role === 'custom-layout') { + // (newComponentOption as any).customLayout = 'react-custom-layout'; + // } return { option: newComponentOption, diff --git a/packages/react-vtable/src/components/custom/custom-layout.tsx b/packages/react-vtable/src/components/custom/custom-layout.tsx index 6a926c19c..2f496f275 100644 --- a/packages/react-vtable/src/components/custom/custom-layout.tsx +++ b/packages/react-vtable/src/components/custom/custom-layout.tsx @@ -1,4 +1,6 @@ -import React, { useCallback, useContext, useLayoutEffect, useRef } from 'react'; +/* eslint-disable react-hooks/rules-of-hooks */ +import type { PropsWithChildren } from 'react'; +import React, { isValidElement, useCallback, useContext, useLayoutEffect, useRef } from 'react'; import RootTableContext from '../../context/table'; import { Group } from '@visactor/vtable/src/vrender'; import type { ICustomLayoutFuc, CustomRenderFunctionArg } from '@visactor/vtable/src/ts-types'; @@ -6,15 +8,22 @@ import type { FiberRoot } from 'react-reconciler'; import { reconcilor } from './reconciler'; import { LegacyRoot } from 'react-reconciler/constants'; -type CustomLayoutProps = { componentIndex?: number; children: React.ReactElement }; +type CustomLayoutProps = { componentIndex?: number }; -export type CustomLayoutFunctionArg = Partial; +export type CustomLayoutFunctionArg = Partial & { + role?: 'custom-layout' | 'header-custom-layout'; +}; -export const CustomLayout: React.FC = (props: CustomLayoutProps, ref) => { +export const CustomLayout: React.FC = (props: PropsWithChildren, ref) => { const { componentIndex, children } = props; + if (!isValidElement(children)) { + return null; + } const context = useContext(RootTableContext); const { table } = context; + const isHeaderCustomLayout = children.props.role === 'header-custom-layout'; + // react customLayout component container cache const container = useRef>(new Map()); @@ -70,10 +79,15 @@ export const CustomLayout: React.FC = (props: CustomLayoutPro console.log('update props', props, table); table?.checkReactCustomLayout(); // init reactCustomLayout component - if (table && !table.reactCustomLayout?.hasReactCreateGraphic(componentIndex)) { - table.reactCustomLayout?.setReactCreateGraphic(componentIndex, createGraphic, container.current); // set customLayout function - table.reactCustomLayout?.setReactRemoveGraphic(componentIndex, removeContainer); // set customLayout function - table.reactCustomLayout?.updateCustomCell(componentIndex); // update cell content + if (table && !table.reactCustomLayout?.hasReactCreateGraphic(componentIndex, isHeaderCustomLayout)) { + table.reactCustomLayout?.setReactCreateGraphic( + componentIndex, + createGraphic, + // container.current, + isHeaderCustomLayout + ); // set customLayout function + table.reactCustomLayout?.setReactRemoveGraphic(componentIndex, removeContainer, isHeaderCustomLayout); // set customLayout function + table.reactCustomLayout?.updateCustomCell(componentIndex, isHeaderCustomLayout); // update cell content } else if (table) { // update all container container.current.forEach((value, key) => { @@ -97,7 +111,7 @@ export const CustomLayout: React.FC = (props: CustomLayoutPro table }; // update element in container - reconcilor.updateContainer(React.cloneElement(props.children, { ...args }), currentContainer, null); + reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); table.scenegraph.updateNextFrame(); }); } diff --git a/packages/vtable/src/components/react/react-custom-layout.ts b/packages/vtable/src/components/react/react-custom-layout.ts index 50cce2d83..4b24efc2d 100644 --- a/packages/vtable/src/components/react/react-custom-layout.ts +++ b/packages/vtable/src/components/react/react-custom-layout.ts @@ -14,44 +14,83 @@ export class ReactCustomLayout { table: BaseTableAPI; customLayoutFuncCache: Map; reactRemoveGraphicCache: Map void>; - reactContainerCache: Map>; + headerCustomLayoutFuncCache: Map; + headerReactRemoveGraphicCache: Map void>; + // reactContainerCache: Map>; constructor(table: BaseTableAPI) { this.table = table; this.customLayoutFuncCache = new Map(); - this.reactContainerCache = new Map(); + // this.reactContainerCache = new Map(); this.reactRemoveGraphicCache = new Map(); + this.headerCustomLayoutFuncCache = new Map(); + // this.headerCeactContainerCache = new Map(); + this.headerReactRemoveGraphicCache = new Map(); } - hasReactCreateGraphic(componentIndex: number) { - return this.reactContainerCache.has(componentIndex); + hasReactCreateGraphic(componentIndex: number, isHeaderCustomLayout?: boolean) { + if (isHeaderCustomLayout) { + return this.headerCustomLayoutFuncCache.has(componentIndex); + } + return this.customLayoutFuncCache.has(componentIndex); } - setReactCreateGraphic(componentIndex: number, createGraphic: ICustomLayoutFuc, containerCache: Map) { - this.customLayoutFuncCache.set(componentIndex, createGraphic); - this.reactContainerCache.set(componentIndex, containerCache); + setReactCreateGraphic( + componentIndex: number, + createGraphic: ICustomLayoutFuc, + // containerCache: Map, + isHeaderCustomLayout?: boolean + ) { + if (isHeaderCustomLayout) { + this.headerCustomLayoutFuncCache.set(componentIndex, createGraphic); + } else { + this.customLayoutFuncCache.set(componentIndex, createGraphic); + } + // this.reactContainerCache.set(componentIndex, containerCache); } - setReactRemoveGraphic(componentIndex: number, removeGraphic: (col: number, row: number) => void) { - this.reactRemoveGraphicCache.set(componentIndex, removeGraphic); + setReactRemoveGraphic( + componentIndex: number, + removeGraphic: (col: number, row: number) => void, + isHeaderCustomLayout?: boolean + ) { + if (isHeaderCustomLayout) { + this.headerReactRemoveGraphicCache.set(componentIndex, removeGraphic); + } else { + this.reactRemoveGraphicCache.set(componentIndex, removeGraphic); + } } - updateCustomCell(componentIndex: number) { + updateCustomCell(componentIndex: number, isHeaderCustomLayout?: boolean) { const table = this.table; const col = componentIndex; - for (let row = table.columnHeaderLevelCount; row < table.rowCount; row++) { - table.scenegraph.updateCellContent(col, row); + // 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); + } } table.scenegraph.updateNextFrame(); } getCustomLayoutFunc(col: number, row: number) { const { startInTotal } = this.table.getBodyColumnDefine(col, row) as any; - return this.customLayoutFuncCache.get(startInTotal) || emptyCustomLayout; + const isHeader = this.table.isHeader(col, row); + return ( + (isHeader ? this.headerCustomLayoutFuncCache.get(startInTotal) : this.customLayoutFuncCache.get(startInTotal)) || + emptyCustomLayout + ); } removeCustomCell(col: number, row: number) { const { startInTotal } = this.table.getBodyColumnDefine(col, row) as any; - const removeFun = this.reactRemoveGraphicCache.get(startInTotal); + const isHeader = this.table.isHeader(col, row); + const removeFun = isHeader + ? this.headerReactRemoveGraphicCache.get(startInTotal) + : this.reactRemoveGraphicCache.get(startInTotal); if (removeFun) { removeFun(col, row); } From 91fe8215f7b4d1f03c675079085f86f4ba32fec4 Mon Sep 17 00:00:00 2001 From: Khalil Mejdi Date: Mon, 10 Jun 2024 16:16:56 +0100 Subject: [PATCH 09/85] fix: rename 'broswer' to 'browser' to correct a typo --- packages/vtable/src/scenegraph/graphic/chart.ts | 2 +- packages/vtable/src/ts-types/base-table.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vtable/src/scenegraph/graphic/chart.ts b/packages/vtable/src/scenegraph/graphic/chart.ts index f13d987f2..e4e221b6d 100644 --- a/packages/vtable/src/scenegraph/graphic/chart.ts +++ b/packages/vtable/src/scenegraph/graphic/chart.ts @@ -149,7 +149,7 @@ export class Chart extends Group { */ deactivate() { this.active = false; - // move active chart view box out of broswer view + // move active chart view box out of browser view // to avoid async render when chart is releasd this.activeChartInstance?.updateViewBox( { diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index f19dd9e9b..b082b6497 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -412,7 +412,7 @@ export interface BaseTableConstructorOptions { customMergeCell?: CustomMergeCell; // #region for nodejs - mode?: 'node' | 'broswer'; + mode?: 'node' | 'browser'; modeParams?: any; canvasWidth?: number; canvasHeight?: number; From 145713f7a5762e4c5a5d31d4c607b8e0dd7ce6b2 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 11 Jun 2024 11:08:59 +0800 Subject: [PATCH 10/85] feat: add basic dom component into react-vtable --- common/config/rush/pnpm-lock.yaml | 64 +++-- packages/react-vtable/demo/src/App.tsx | 4 +- .../demo/src/component/custom-layout-dom.tsx | 235 ++++++++++++++++++ .../demo/src/component/custom-layout.tsx | 2 +- .../src/components/custom/custom-layout.tsx | 28 ++- .../src/components/custom/reconciler.ts | 22 +- .../custom/vtable-react-attribute-plugin.ts | 77 ++++++ .../react-vtable/src/tables/base-table.tsx | 6 + packages/vtable/package.json | 8 +- packages/vtable/src/core/style.ts | 2 + packages/vtable/src/scenegraph/scenegraph.ts | 1 + packages/vtable/src/vrender.ts | 70 +++++- 12 files changed, 481 insertions(+), 38 deletions(-) create mode 100644 packages/react-vtable/demo/src/component/custom-layout-dom.tsx create mode 100644 packages/react-vtable/src/components/custom/vtable-react-attribute-plugin.ts diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index ced04b4a2..b82f20d71 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -284,9 +284,9 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/vchart': 1.10.0 '@visactor/vdataset': ~0.18.1 - '@visactor/vrender-components': 0.18.14-alpha.0 - '@visactor/vrender-core': 0.18.14-alpha.0 - '@visactor/vrender-kits': 0.18.14-alpha.0 + '@visactor/vrender-components': 0.19.10-beta.1 + '@visactor/vrender-core': 0.19.10-beta.1 + '@visactor/vrender-kits': 0.19.10-beta.1 '@visactor/vscale': ~0.18.1 '@visactor/vtable-editors': workspace:* '@visactor/vutils': ~0.18.1 @@ -329,9 +329,9 @@ importers: vite-plugin-markdown: ^2.1.0 dependencies: '@visactor/vdataset': 0.18.1 - '@visactor/vrender-components': 0.18.14-alpha.0 - '@visactor/vrender-core': 0.18.14-alpha.0 - '@visactor/vrender-kits': 0.18.14-alpha.0 + '@visactor/vrender-components': 0.19.10-beta.1 + '@visactor/vrender-core': 0.19.10-beta.1 + '@visactor/vrender-kits': 0.19.10-beta.1 '@visactor/vscale': 0.18.1 '@visactor/vtable-editors': link:../vtable-editors '@visactor/vutils': 0.18.1 @@ -3680,15 +3680,6 @@ packages: '@visactor/vrender-kits': 0.18.5 '@visactor/vutils': 0.18.1 - /@visactor/vrender-components/0.18.14-alpha.0: - resolution: {integrity: sha512-PKYdDdJvDmhoNl7Pnnvvy0GixD73xexWdlWNvxpkEvR6ndVhJayqYEA+0jxyyD5O/JWCpRtNQFoQj7zYRcISVg==} - dependencies: - '@visactor/vrender-core': 0.18.14-alpha.0 - '@visactor/vrender-kits': 0.18.14-alpha.0 - '@visactor/vscale': 0.17.5 - '@visactor/vutils': 0.18.1 - dev: false - /@visactor/vrender-components/0.18.5: resolution: {integrity: sha512-IJNVj/5Roji8rTNL40FuqUn/n5qWlLC5LDL+uJDi+FPmwMs8U9mbLDL8ounv8DbOzFXBGsjxw/Z9yCGuYC6TkA==} dependencies: @@ -3706,11 +3697,13 @@ packages: '@visactor/vutils': 0.18.1 dev: false - /@visactor/vrender-core/0.18.14-alpha.0: - resolution: {integrity: sha512-9Sqkg0na+W/ddEVaojA5ao6VkmdBr3kKUi3w9az0AtoWXa6RDBJePTXm3cMbH7YZt5tXXRgJGMHd/M2k8+IIgw==} + /@visactor/vrender-components/0.19.10-beta.1: + resolution: {integrity: sha512-OQaxEYOAwHIAcXqkqqtwQYejOg3mFDgH1h050VLotWyIcItTvvZxwhXPbeLcPryWzR4PaoUTGPVOM7XNoqKzEQ==} dependencies: - '@visactor/vutils': 0.18.1 - color-convert: 2.0.1 + '@visactor/vrender-core': 0.19.10-beta.1 + '@visactor/vrender-kits': 0.19.10-beta.1 + '@visactor/vscale': 0.18.9 + '@visactor/vutils': 0.18.9 dev: false /@visactor/vrender-core/0.18.5: @@ -3726,13 +3719,11 @@ packages: color-convert: 2.0.1 dev: false - /@visactor/vrender-kits/0.18.14-alpha.0: - resolution: {integrity: sha512-7fxSj3LqOnBMURqRehYWx/rBOw2udDK9EsxAYagQcrIgKADiakP5+lWNqrHGy/Qr1HKYLVz6WLZH8oJSdu/bSg==} + /@visactor/vrender-core/0.19.10-beta.1: + resolution: {integrity: sha512-vOpEtwRgb3JpXWSgHzHnartVZlw9B8y6tQ4gOs117J5jhVcSuv2KT28oLuj3wqZsSybOhr/Di7HFIibfo80dRw==} dependencies: - '@resvg/resvg-js': 2.4.1 - '@visactor/vrender-core': 0.18.14-alpha.0 - '@visactor/vutils': 0.18.1 - roughjs: 4.5.2 + '@visactor/vutils': 0.18.9 + color-convert: 2.0.1 dev: false /@visactor/vrender-kits/0.18.5: @@ -3752,6 +3743,15 @@ packages: roughjs: 4.5.2 dev: false + /@visactor/vrender-kits/0.19.10-beta.1: + resolution: {integrity: sha512-Xu8VJXscdproiMF+1AA+Te89qRPnEGoWyV9Hham97NbTg/z2AWb9NhQsNu+8O3TYugbX3tOhbKbPnIgFr+tgeQ==} + dependencies: + '@resvg/resvg-js': 2.4.1 + '@visactor/vrender-core': 0.19.10-beta.1 + '@visactor/vutils': 0.18.9 + roughjs: 4.5.2 + dev: false + /@visactor/vscale/0.17.5: resolution: {integrity: sha512-2dkS1IlAJ/IdTp8JElbctOOv6lkHKBKPDm8KvwBo0NuGWQeYAebSeyN3QCdwKbj76gMlCub4zc+xWrS5YiA2zA==} dependencies: @@ -3762,6 +3762,12 @@ packages: dependencies: '@visactor/vutils': 0.18.1 + /@visactor/vscale/0.18.9: + resolution: {integrity: sha512-rglOQQGhkamtjGtbFxY5pcfqsBXDyYU6NiQuBdVSeYRQvB9YpLLk455HpvQcEEhC+bRopNQsQgQV5276Pd0sfQ==} + dependencies: + '@visactor/vutils': 0.18.9 + dev: false + /@visactor/vutils-extension/1.10.0: resolution: {integrity: sha512-fT5SX/tfbDc2jwrn/83In38y/wdwPDftTpp9lQpS2kl7nmr43HVL3mMgZbxmOB6MG/HJUWkrUvjt5WF+RlyVEQ==} dependencies: @@ -3795,6 +3801,14 @@ packages: '@turf/invariant': 6.5.0 eventemitter3: 4.0.7 + /@visactor/vutils/0.18.9: + resolution: {integrity: sha512-+CPwBATTQUPtXQ0KVXFRz8SCwAY9m5aR9QmtsVqya+mgaay3moFaAPNTbdkLBuZM5ewRYVcv/3fsDxuH+NXfFg==} + dependencies: + '@turf/helpers': 6.5.0 + '@turf/invariant': 6.5.0 + eventemitter3: 4.0.7 + dev: false + /@vitejs/plugin-react/3.1.0_vite@3.2.6: resolution: {integrity: sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==} engines: {node: ^14.18.0 || >=16.0.0} diff --git a/packages/react-vtable/demo/src/App.tsx b/packages/react-vtable/demo/src/App.tsx index cb354ef79..6c924d6b9 100644 --- a/packages/react-vtable/demo/src/App.tsx +++ b/packages/react-vtable/demo/src/App.tsx @@ -15,6 +15,7 @@ import eventRebind from './event/event-rebind'; import componentContainer from './component/component-container'; import customLayout from './component/custom-layout'; +import customLayoutDom from './component/custom-layout-dom'; // export default listEditor; // export default listOptionRecord; @@ -31,4 +32,5 @@ import customLayout from './component/custom-layout'; // export default eventRebind; // export default componentContainer; -export default customLayout; +// export default customLayout; +export default customLayoutDom; diff --git a/packages/react-vtable/demo/src/component/custom-layout-dom.tsx b/packages/react-vtable/demo/src/component/custom-layout-dom.tsx new file mode 100644 index 000000000..ffa9f7c57 --- /dev/null +++ b/packages/react-vtable/demo/src/component/custom-layout-dom.tsx @@ -0,0 +1,235 @@ +import { useEffect, useRef, useState } from 'react'; +import type { CustomLayoutFunctionArg } from '../../../src'; +import { ListTable, ListColumn, CustomLayout, Group, Text } from '../../../src'; +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'; + +function Tooltip(props: { value: string }) { + return ( +
+ {`${props.value}(click to show more)`} +
+ ); +} + +const CustomLayoutComponent = (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 row = 3; + // const width = 100; + // const height = 100; + const fieldData = [ + { + value: 'a', + label: 'a' + }, + { + value: 'b', + label: 'b' + } + ]; + + const groupRef = useRef(null); + + // useEffect(() => { + // flash(col, row, this); + // }, [hover]); + + return ( + + // } + react: { + pointerEvents: true, + element: ( + +

Here is the text content

+

Here is the text content

+ + } + > + + {text} + +
+ ) + } + }} + ref={groupRef} + > + {fieldData.map(item => { + return ( + row !== 2 && ( + { + // if (stateName === 'hover') { + // return { + // fill: 'red' + // }; + // } + // }} + onMouseEnter={(event: any) => { + // eslint-disable-next-line no-console, no-undef + console.log('groupRef', groupRef.current); + setHover(true); + event.currentTarget.stage.renderNextFrame(); // to do: auto execute in react-vtable + }} + onMouseLeave={(event: any) => { + setHover(false); + event.currentTarget.stage.renderNextFrame(); + }} + > + ) + ); + })} + {hover && ( + + )} +
+ ); +}; + +const DomCustomLayoutComponent = (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 groupRef = useRef(null); + + return ( + + } + }} + ref={groupRef} + > + ); +}; + +const CardInfo = (props: { text: string }) => { + return ( + + dessert + + } + actions={[ + + + , + + + , + + + + ]} + > + + +

Here is the text content

+

Here is the text content

+ + } + > + A +
+ {props.text} + + } + title="Card Title" + description="This is the description" + /> +
+ ); +}; + +function App() { + const records = new Array(2000).fill(['John', 18, 'male', '🏀']); + const [preStr, setPreStr] = useState('vt'); + + useEffect(() => { + // eslint-disable-next-line no-undef + setTimeout(() => { + setPreStr(preStr + '1'); + }, 1000); + }, []); + + return ( + { + // eslint-disable-next-line no-undef + (window as any).tableInstance = table; + }} + > + + + + + {/* */} + + + + ); +} + +export default App; diff --git a/packages/react-vtable/demo/src/component/custom-layout.tsx b/packages/react-vtable/demo/src/component/custom-layout.tsx index 06f81ce68..b055434b3 100644 --- a/packages/react-vtable/demo/src/component/custom-layout.tsx +++ b/packages/react-vtable/demo/src/component/custom-layout.tsx @@ -63,7 +63,7 @@ const CustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string } // eslint-disable-next-line no-console, no-undef console.log('groupRef', groupRef.current); setHover(true); - event.currentTarget.stage.renderNextFrame(); + event.currentTarget.stage.renderNextFrame(); // to do: auto execute in react-vtable }} onMouseLeave={(event: any) => { setHover(false); diff --git a/packages/react-vtable/src/components/custom/custom-layout.tsx b/packages/react-vtable/src/components/custom/custom-layout.tsx index 2f496f275..f52fac696 100644 --- a/packages/react-vtable/src/components/custom/custom-layout.tsx +++ b/packages/react-vtable/src/components/custom/custom-layout.tsx @@ -34,13 +34,16 @@ export const CustomLayout: React.FC = (props: PropsWithChildr let group; if (container.current.has(key)) { const currentContainer = container.current.get(key); - reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); + // reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); + reconcilorUpdateContainer(children, currentContainer, group, args); group = currentContainer.containerInfo; } else { group = new Group({}); const currentContainer = reconcilor.createContainer(group, LegacyRoot, null, null, null, 'custom', null, null); container.current.set(key, currentContainer); - reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); + reconcilorUpdateContainer(children, currentContainer, group, args); + // const ele = React.cloneElement(children, { ...args }); + // reconcilor.updateContainer(ele, currentContainer, null); } return { @@ -111,7 +114,9 @@ export const CustomLayout: React.FC = (props: PropsWithChildr table }; // update element in container - reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); + const group = currentContainer.containerInfo; + reconcilorUpdateContainer(children, currentContainer, group, args); + // reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); table.scenegraph.updateNextFrame(); }); } @@ -119,3 +124,20 @@ export const CustomLayout: React.FC = (props: PropsWithChildr return null; }; + +function reconcilorUpdateContainer(children, currentContainer, group, args) { + reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); + // group = group.firstChild; + // if (isReactElement(group.attribute.html?.dom)) { + // const div = document.createElement('div'); + // const root = ReactDOM.createRoot(div as HTMLElement); + // root.render(group.attribute.html.dom); + // group.attribute.html.dom = div; + // // debugger; + // // group.html.dom = div; + // } +} + +function isReactElement(obj) { + return obj && obj.$$typeof === Symbol.for('react.element'); +} diff --git a/packages/react-vtable/src/components/custom/reconciler.ts b/packages/react-vtable/src/components/custom/reconciler.ts index 955887a4d..818ce802e 100644 --- a/packages/react-vtable/src/components/custom/reconciler.ts +++ b/packages/react-vtable/src/components/custom/reconciler.ts @@ -13,13 +13,22 @@ export const reconcilor = ReactReconciler({ createInstance: (type: string, props: any, instance) => { const graphic = createGraphic(type, props); - bindEventsToGraphic(graphic, props); + if (graphic) { + bindEventsToGraphic(graphic, props); + } else { + return undefined; + // createInstance + // graphic = createGraphic('group', {}); + } return graphic; }, createTextInstance: (text, instance) => { - const textGraphic = createText({ text }); - return textGraphic; + // const textGraphic = createText({ text }); + // return textGraphic; + // debugger; + // return document.createTextNode(text); + return undefined; }, appendInitialChild: (parentInstance: Instance, childInstance: Instance) => { @@ -107,6 +116,10 @@ export const reconcilor = ReactReconciler({ clearContainer: (container: Instance) => { container.removeAllChild(); + }, + + commitTextUpdate: (textInstance: any, oldText: string, newText: string) => { + // debugger; } }); @@ -121,6 +134,9 @@ reconcilor.injectIntoDevTools({ function createGraphic(type: string, props: any) { // may have unwanted onxxx prop + if (!application.graphicService.creator[type]) { + return; + } const graphic = application.graphicService.creator[type]((props as any).attribute); return graphic; } diff --git a/packages/react-vtable/src/components/custom/vtable-react-attribute-plugin.ts b/packages/react-vtable/src/components/custom/vtable-react-attribute-plugin.ts new file mode 100644 index 000000000..4d67f6435 --- /dev/null +++ b/packages/react-vtable/src/components/custom/vtable-react-attribute-plugin.ts @@ -0,0 +1,77 @@ +import type { CreateDOMParamsType, IGraphic, IStage } from '@visactor/vtable/src/vrender'; +import { ReactAttributePlugin, application } from '@visactor/vtable/src/vrender'; +import { isNil } from '@visactor/vutils'; + +export class VTableReactAttributePlugin extends ReactAttributePlugin { + removeElement(id: string) { + super.removeElement(id); + delete this.htmlMap[id]; + } + + renderGraphicHTML(graphic: IGraphic) { + const { react } = graphic.attribute; + if (!react) { + return; + } + const stage = graphic.stage; + if (!stage) { + return; + } + const ReactDOM = stage.params.ReactDOM; + const { element, container } = react; + if (!(element && ReactDOM && ReactDOM.createRoot)) { + return; + } + const id = isNil(react.id) ? `${graphic.id ?? graphic._uid}_react` : react.id; + + if (this.htmlMap && this.htmlMap[id] && container && container !== this.htmlMap[id].container) { + this.removeElement(id); + } + + if (!this.htmlMap || !this.htmlMap[id]) { + // createa a wrapper contianer to be the root of react element + const { wrapContainer, nativeContainer } = this.getWrapContainer(stage, container); + + if (wrapContainer) { + const root = ReactDOM.createRoot(wrapContainer); + root.render(element); + + if (!this.htmlMap) { + this.htmlMap = {}; + } + + this.htmlMap[id] = { root, wrapContainer, nativeContainer, container, renderId: this.renderId }; + } + } else { + // update react element + this.htmlMap[id].root.render(element); + } + + if (!this.htmlMap || !this.htmlMap[id]) { + return; + } + + const { wrapContainer, nativeContainer } = this.htmlMap[id]; + + this.updateStyleOfWrapContainer(graphic, stage, wrapContainer, nativeContainer, react); + this.htmlMap[id].renderId = this.renderId; + } + + getWrapContainer(stage: IStage, userContainer?: string | HTMLElement | null, domParams?: CreateDOMParamsType) { + let nativeContainer; + if (userContainer) { + if (typeof userContainer === 'string') { + nativeContainer = application.global.getElementById(userContainer); + } else { + nativeContainer = userContainer; + } + } else { + nativeContainer = stage.window.getContainer(); + } + // 创建wrapGroup + return { + wrapContainer: application.global.createDom({ tagName: 'div', parent: nativeContainer, ...domParams }), + nativeContainer + }; + } +} diff --git a/packages/react-vtable/src/tables/base-table.tsx b/packages/react-vtable/src/tables/base-table.tsx index 8160fde7b..1cd81c663 100644 --- a/packages/react-vtable/src/tables/base-table.tsx +++ b/packages/react-vtable/src/tables/base-table.tsx @@ -1,6 +1,7 @@ /* eslint-disable react/display-name */ import * as VTable from '@visactor/vtable'; import React, { useState, useEffect, useRef, useImperativeHandle, useCallback } from 'react'; +import ReactDOM from 'react-dom/client'; import type { ContainerProps } from '../containers/withContainer'; import withContainer from '../containers/withContainer'; import type { TableContextType } from '../context/table'; @@ -21,6 +22,7 @@ import type { // TableLifeCycleEventProps } from '../eventsUtils'; import { bindEventsToTable, TABLE_EVENTS_KEYS, TABLE_EVENTS } from '../eventsUtils'; +import { VTableReactAttributePlugin } from '../components/custom/vtable-react-attribute-plugin'; export type IVTable = VTable.ListTable | VTable.PivotTable | VTable.PivotChart; export type IOption = @@ -141,6 +143,10 @@ const BaseTable: React.FC = React.forwardRef((props, ref) => { } else { vtable = new VTable.ListTable(props.container, parseOption(props)); } + // vtable.scenegraph.stage.enableReactAttribute(ReactDOM); + vtable.scenegraph.stage.reactAttribute = ReactDOM; + vtable.scenegraph.stage.pluginService.register(new VTableReactAttributePlugin()); + vtable.scenegraph.stage.params.ReactDOM = ReactDOM; tableContext.current = { ...tableContext.current, table: vtable }; isUnmount.current = false; }, diff --git a/packages/vtable/package.json b/packages/vtable/package.json index 400ca6d4e..085ba02be 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -50,9 +50,9 @@ }, "dependencies": { "@visactor/vtable-editors": "workspace:*", - "@visactor/vrender-core": "0.18.14-alpha.0", - "@visactor/vrender-kits": "0.18.14-alpha.0", - "@visactor/vrender-components": "0.18.14-alpha.0", + "@visactor/vrender-core": "0.19.10-beta.1", + "@visactor/vrender-kits": "0.19.10-beta.1", + "@visactor/vrender-components": "0.19.10-beta.1", "@visactor/vutils-extension": "~1.10.4", "@visactor/vutils": "~0.18.1", "@visactor/vscale": "~0.18.1", @@ -124,4 +124,4 @@ "url": "https://github.com/VisActor/VTable.git", "directory": "packages/vtable" } -} +} \ No newline at end of file diff --git a/packages/vtable/src/core/style.ts b/packages/vtable/src/core/style.ts index ac546e901..34411e337 100644 --- a/packages/vtable/src/core/style.ts +++ b/packages/vtable/src/core/style.ts @@ -41,6 +41,8 @@ export function importStyle() { height: 100%; text-align: left; -webkit-font-smoothing:auto; + + overflow: hidden; } .vtable > canvas { position: absolute; diff --git a/packages/vtable/src/scenegraph/scenegraph.ts b/packages/vtable/src/scenegraph/scenegraph.ts index 4466732d4..eb552652e 100644 --- a/packages/vtable/src/scenegraph/scenegraph.ts +++ b/packages/vtable/src/scenegraph/scenegraph.ts @@ -148,6 +148,7 @@ export class Scenegraph { background: table.theme.underlayBackgroundColor, dpr: table.internalProps.pixelRatio, enableLayout: true, + // enableHtmlAttribute: true, // pluginList: table.isPivotChart() ? ['poptipForText'] : undefined, afterRender: () => { this.table.fireListeners('after_render', null); diff --git a/packages/vtable/src/vrender.ts b/packages/vtable/src/vrender.ts index 1827c4287..1aebb2832 100644 --- a/packages/vtable/src/vrender.ts +++ b/packages/vtable/src/vrender.ts @@ -1,6 +1,15 @@ import '@visactor/vrender-core'; -import { container, isBrowserEnv, isNodeEnv, preLoadAllModule } from '@visactor/vrender-core'; +import type { CreateDOMParamsType } from '@visactor/vrender-core'; +import { + ContainerModule, + EnvContribution, + container, + isBrowserEnv, + isNodeEnv, + preLoadAllModule +} from '@visactor/vrender-core'; import { loadBrowserEnv, loadNodeEnv } from '@visactor/vrender-kits'; +import { BrowserEnvContribution } from '@visactor/vrender-kits'; import { registerArc, registerArc3d, @@ -21,6 +30,7 @@ import { registerText, registerWrapText } from '@visactor/vrender-kits'; +import { isString } from '@visactor/vutils'; // 导出版本号 // export const version = __VERSION__; @@ -56,7 +66,65 @@ export function registerForVrender() { registerSymbol(); registerText(); registerWrapText(); + + // for react-vtable + if (isBrowserEnv()) { + // bind(BrowserEnvContribution).toSelf().inSingletonScope(); + // bind(EnvContribution).toService(BrowserEnvContribution); + container.load(reactEnvModule); + } } export * from '@visactor/vrender-core'; export * from '@visactor/vrender-kits'; + +const reactEnvModule = new ContainerModule(bind => { + bind(VTableBrowserEnvContribution).toSelf().inSingletonScope(); + bind(EnvContribution).toService(VTableBrowserEnvContribution); +}); + +class VTableBrowserEnvContribution extends BrowserEnvContribution { + updateDom(dom: HTMLElement, params: CreateDOMParamsType): boolean { + // debugger; + + const tableDiv = dom.parentElement; + if (tableDiv) { + const tableRect = tableDiv.getBoundingClientRect(); + + const top = parseInt(params.style.top, 10); + const left = parseInt(params.style.left, 10); + const domWidth = dom.offsetWidth; + const domHeight = dom.offsetHeight; + + if ( + top + domHeight < tableRect.top || + left + domWidth < tableRect.left || + top > tableRect.bottom || + left > tableRect.right + ) { + dom.style.display = 'none'; + return false; + } + } + + const { width, height, style } = params; + + if (style) { + if (isString(style)) { + dom.setAttribute('style', style); + } else { + Object.keys(style).forEach(k => { + dom.style[k] = style[k]; + }); + } + } + if (width != null) { + dom.style.width = `${width}px`; + } + if (height != null) { + dom.style.height = `${height}px`; + } + + return true; + } +} From 104705a0e9cfcc6e231fd1ee5eeae82a8ac77852 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 11 Jun 2024 19:57:24 +0800 Subject: [PATCH 11/85] feat: add header/bodyDomContainer --- .../demo/src/component/custom-layout-dom.tsx | 2 ++ .../react-vtable/src/tables/base-table.tsx | 5 +++- packages/vtable/src/core/BaseTable.ts | 25 +++++++++++++++++++ packages/vtable/src/core/style.ts | 7 ++++++ packages/vtable/src/scenegraph/scenegraph.ts | 16 ++++++++++++ packages/vtable/src/ts-types/base-table.ts | 9 +++++++ packages/vtable/src/vrender.ts | 13 +++------- 7 files changed, 67 insertions(+), 10 deletions(-) diff --git a/packages/react-vtable/demo/src/component/custom-layout-dom.tsx b/packages/react-vtable/demo/src/component/custom-layout-dom.tsx index ffa9f7c57..93d143f1a 100644 --- a/packages/react-vtable/demo/src/component/custom-layout-dom.tsx +++ b/packages/react-vtable/demo/src/component/custom-layout-dom.tsx @@ -140,6 +140,8 @@ const DomCustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: strin height, react: { pointerEvents: true, + container: table.bodyDomContainer, // table.headerDomContainer + // anchorType element: } }} diff --git a/packages/react-vtable/src/tables/base-table.tsx b/packages/react-vtable/src/tables/base-table.tsx index bb3ac0758..094838976 100644 --- a/packages/react-vtable/src/tables/base-table.tsx +++ b/packages/react-vtable/src/tables/base-table.tsx @@ -131,7 +131,10 @@ const BaseTable: React.FC = React.forwardRef((props, ref) => { records: props.records, ...prevOption.current, ...optionFromChildren.current, - clearDOM: false + clearDOM: false, + customConfig: { + createReactContainer: true + } // ...tableContext.current?.optionFromChildren } as IOption; }, diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 897501915..a55d0a19f 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -299,6 +299,15 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { internalProps.canvas = document.createElement('canvas'); internalProps.element.appendChild(internalProps.canvas); internalProps.context = internalProps.canvas.getContext('2d')!; + + if (options.customConfig?.createReactContainer) { + internalProps.bodyDomContainer = document.createElement('div'); + internalProps.bodyDomContainer.classList.add('table-component-container'); + internalProps.element.appendChild(internalProps.bodyDomContainer); + internalProps.headerDomContainer = document.createElement('div'); + internalProps.headerDomContainer.classList.add('table-component-container'); + internalProps.element.appendChild(internalProps.headerDomContainer); + } } internalProps.handler = new EventHandler(); @@ -934,6 +943,15 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { canvas.style.width = `${widthP}px`; canvas.style.height = `${heightP}px`; } + + if (this.internalProps.bodyDomContainer) { + this.internalProps.bodyDomContainer.style.width = `${widthP}px`; + this.internalProps.bodyDomContainer.style.height = `${heightP}px`; + } + if (this.internalProps.headerDomContainer) { + this.internalProps.headerDomContainer.style.width = `${widthP}px`; + this.internalProps.headerDomContainer.style.height = `${heightP}px`; + } } else if (Env.mode === 'node') { widthP = this.canvasWidth - 1; heightP = this.canvasHeight - 1; @@ -4437,4 +4455,11 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { this.reactCustomLayout = new ReactCustomLayout(this); } } + + get bodyDomContainer() { + return this.internalProps.bodyDomContainer; + } + get headerDomContainer() { + return this.internalProps.headerDomContainer; + } } diff --git a/packages/vtable/src/core/style.ts b/packages/vtable/src/core/style.ts index 34411e337..545ef0e5e 100644 --- a/packages/vtable/src/core/style.ts +++ b/packages/vtable/src/core/style.ts @@ -42,7 +42,14 @@ export function importStyle() { text-align: left; -webkit-font-smoothing:auto; + overflow: hidden; // for react-vtable dom custom element +} +.vtable .table-component-container { + pointer-events: none; overflow: hidden; + position: absolute; + top: 0px; + left: 0px; } .vtable > canvas { position: absolute; diff --git a/packages/vtable/src/scenegraph/scenegraph.ts b/packages/vtable/src/scenegraph/scenegraph.ts index f9d75d3f7..7959b2d5e 100644 --- a/packages/vtable/src/scenegraph/scenegraph.ts +++ b/packages/vtable/src/scenegraph/scenegraph.ts @@ -1532,6 +1532,8 @@ export class Scenegraph { this.updateTableSize(); this.component.updateScrollBar(); + this.updateDomContainer(); + this.updateNextFrame(); } @@ -1928,4 +1930,18 @@ export class Scenegraph { // updateCellValue(col: number, row: number) { // updateCell(col, row, this.table); // } + updateDomContainer() { + const { headerDomContainer, bodyDomContainer } = this.table.internalProps; + if (headerDomContainer) { + headerDomContainer.style.width = `${headerDomContainer.parentElement?.offsetWidth ?? 1 - 1}px`; + headerDomContainer.style.height = `${this.table.getFrozenRowsHeight()}px`; + } + if (bodyDomContainer) { + bodyDomContainer.style.width = `${bodyDomContainer.parentElement?.offsetWidth ?? 1 - 1}px`; + bodyDomContainer.style.height = `${ + bodyDomContainer.parentElement?.offsetHeight ?? 1 - 1 - this.table.getFrozenRowsHeight() + }px`; + bodyDomContainer.style.top = `${this.table.getFrozenRowsHeight()}px`; + } + } } diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index 8cdfe1885..e03e58f43 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -250,6 +250,10 @@ export interface IBaseTableProtected { * 设置为 'none' 时, 表格滚动到顶部/底部时, 不再触发父容器滚动 * */ overscrollBehavior?: 'auto' | 'none'; + + // react component container + bodyDomContainer?: HTMLElement; + headerDomContainer?: HTMLElement; } export interface BaseTableConstructorOptions { // /** 指定表格的行数 */ @@ -442,6 +446,8 @@ export interface BaseTableConstructorOptions { /** 禁用行高列宽计算取整数逻辑 对齐xTable */ _disableColumnAndRowSizeRound?: boolean; imageMargin?: number; + // 是否创建react custom container + createReactContainer?: boolean; }; // 部分特殊配置,兼容xTable等作用 animationAppear?: boolean | IAnimationAppear; @@ -822,6 +828,9 @@ export interface BaseTableAPI { exportCellRangeImg: (cellRange: CellRange) => string; exportCanvas: () => HTMLCanvasElement; setPixelRatio: (pixelRatio: number) => void; + + bodyDomContainer?: HTMLElement; + headerDomContainer?: HTMLElement; } export interface ListTableProtected extends IBaseTableProtected { /** 表格数据 */ diff --git a/packages/vtable/src/vrender.ts b/packages/vtable/src/vrender.ts index 1aebb2832..e1e647b7f 100644 --- a/packages/vtable/src/vrender.ts +++ b/packages/vtable/src/vrender.ts @@ -89,19 +89,14 @@ class VTableBrowserEnvContribution extends BrowserEnvContribution { const tableDiv = dom.parentElement; if (tableDiv) { - const tableRect = tableDiv.getBoundingClientRect(); + // const tableRect = tableDiv.getBoundingClientRect(); const top = parseInt(params.style.top, 10); const left = parseInt(params.style.left, 10); - const domWidth = dom.offsetWidth; - const domHeight = dom.offsetHeight; + const domWidth = dom.offsetWidth; // TO DO: offsetWidth is 0 when display none + const domHeight = dom.offsetHeight; // TO DO: offsetHeight is 0 when display none - if ( - top + domHeight < tableRect.top || - left + domWidth < tableRect.left || - top > tableRect.bottom || - left > tableRect.right - ) { + if (top + domHeight < 0 || left + domWidth < 0 || top > tableDiv.offsetHeight || left > tableDiv.offsetWidth) { dom.style.display = 'none'; return false; } From 0950ee3ce0c099a92778013f6ce21f00b7115efe Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 12 Jun 2024 11:24:28 +0800 Subject: [PATCH 12/85] chore: update vrender version --- common/config/rush/pnpm-lock.yaml | 1243 ++++++++++++++++------------- packages/vtable/package.json | 8 +- 2 files changed, 684 insertions(+), 567 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 50d15e5ce..596517d79 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -133,7 +133,7 @@ importers: '@types/chai': 4.2.22 '@types/jest': 26.0.24 '@types/mocha': 9.0.0 - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/offscreencanvas': 2019.6.4 '@visactor/vchart': 1.11.0 axios: 1.7.2 @@ -155,12 +155,12 @@ importers: sass: 1.43.5 ts-jest: 26.5.6_xuote2qreek47x2di7kesslrai ts-loader: 9.2.6_typescript@4.9.5 - ts-node: 10.9.0_fqbesfk7w3q7dr5vwiwy56afhe + ts-node: 10.9.0_daz7tukh2qp4t5y5hskra5bsgy tslib: 2.3.1 ttypescript: 1.5.13_fxi2xlggroal5l3a4znftvxz2m typescript: 4.9.5 typescript-transform-paths: 3.3.1_typescript@4.9.5 - vite: 3.2.6_wo5djetj4deayu5nkog2244prm + vite: 3.2.6_q2pn2u5afkvbgyxa6yhm66etea vite-plugin-markdown: 2.2.0_vite@3.2.6 ../../packages/react-vtable: @@ -227,7 +227,7 @@ importers: '@types/chai': 4.2.22 '@types/jest': 26.0.24 '@types/mocha': 9.0.0 - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/offscreencanvas': 2019.6.4 '@types/react': 18.3.3 '@types/react-dom': 18.3.0 @@ -254,12 +254,12 @@ importers: sass: 1.43.5 ts-jest: 26.5.6_xuote2qreek47x2di7kesslrai ts-loader: 9.2.6_typescript@4.9.5 - ts-node: 10.9.0_fqbesfk7w3q7dr5vwiwy56afhe + ts-node: 10.9.0_daz7tukh2qp4t5y5hskra5bsgy tslib: 2.3.1 ttypescript: 1.5.13_fxi2xlggroal5l3a4znftvxz2m typescript: 4.9.5 typescript-transform-paths: 3.3.1_typescript@4.9.5 - vite: 3.2.6_wo5djetj4deayu5nkog2244prm + vite: 3.2.6_q2pn2u5afkvbgyxa6yhm66etea vite-plugin-markdown: 2.2.0_vite@3.2.6 ../../packages/vtable: @@ -280,9 +280,9 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/vchart': 1.11.0 '@visactor/vdataset': ~0.18.1 - '@visactor/vrender-components': 0.19.10-beta.1 - '@visactor/vrender-core': 0.19.10-beta.1 - '@visactor/vrender-kits': 0.19.10-beta.1 + '@visactor/vrender-components': 0.19.9 + '@visactor/vrender-core': 0.19.9 + '@visactor/vrender-kits': 0.19.9 '@visactor/vscale': ~0.18.1 '@visactor/vtable-editors': workspace:* '@visactor/vutils': ~0.18.9 @@ -324,9 +324,9 @@ importers: vite-plugin-markdown: ^2.1.0 dependencies: '@visactor/vdataset': 0.18.9 - '@visactor/vrender-components': 0.19.10-beta.1 - '@visactor/vrender-core': 0.19.10-beta.1 - '@visactor/vrender-kits': 0.19.10-beta.1 + '@visactor/vrender-components': 0.19.9 + '@visactor/vrender-core': 0.19.9 + '@visactor/vrender-kits': 0.19.9 '@visactor/vscale': 0.18.9 '@visactor/vtable-editors': link:../vtable-editors '@visactor/vutils': 0.18.9 @@ -342,7 +342,7 @@ importers: '@types/chai': 4.2.22 '@types/jest': 26.0.24 '@types/mocha': 9.0.0 - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/offscreencanvas': 2019.6.4 '@types/react': 18.3.3 '@types/react-dom': 18.3.0 @@ -375,12 +375,12 @@ importers: sass: 1.43.5 ts-jest: 26.5.6_xuote2qreek47x2di7kesslrai ts-loader: 9.2.6_typescript@4.9.5 - ts-node: 10.9.0_fqbesfk7w3q7dr5vwiwy56afhe + ts-node: 10.9.0_daz7tukh2qp4t5y5hskra5bsgy tslib: 2.3.1 ttypescript: 1.5.13_fxi2xlggroal5l3a4znftvxz2m typescript: 4.9.5 typescript-transform-paths: 3.3.1_typescript@4.9.5 - vite: 3.2.6_wo5djetj4deayu5nkog2244prm + vite: 3.2.6_q2pn2u5afkvbgyxa6yhm66etea vite-plugin-markdown: 2.2.0_vite@3.2.6 ../../packages/vtable-editors: @@ -412,7 +412,7 @@ importers: '@internal/ts-config': link:../../share/ts-config '@rushstack/eslint-patch': 1.1.4 '@types/jest': 26.0.24 - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/offscreencanvas': 2019.6.4 eslint: 8.18.0 husky: 7.0.4 @@ -423,11 +423,11 @@ importers: react-device-detect: 2.2.3 ts-jest: 26.5.6_xuote2qreek47x2di7kesslrai ts-loader: 9.2.6_typescript@4.9.5 - ts-node: 10.9.0_fqbesfk7w3q7dr5vwiwy56afhe + ts-node: 10.9.0_daz7tukh2qp4t5y5hskra5bsgy tslib: 2.3.1 tslint: 5.12.1_typescript@4.9.5 typescript: 4.9.5 - vite: 3.2.6_@types+node@20.12.13 + vite: 3.2.6_@types+node@20.14.2 ../../packages/vtable-export: specifiers: @@ -496,7 +496,7 @@ importers: '@types/chai': 4.2.22 '@types/jest': 26.0.24 '@types/mocha': 9.0.0 - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/offscreencanvas': 2019.6.4 '@types/react': 18.3.3 '@types/react-dom': 18.3.0 @@ -524,12 +524,12 @@ importers: sass: 1.43.5 ts-jest: 26.5.6_xuote2qreek47x2di7kesslrai ts-loader: 9.2.6_typescript@4.9.5 - ts-node: 10.9.0_fqbesfk7w3q7dr5vwiwy56afhe + ts-node: 10.9.0_daz7tukh2qp4t5y5hskra5bsgy tslib: 2.3.1 ttypescript: 1.5.13_fxi2xlggroal5l3a4znftvxz2m typescript: 4.9.5 typescript-transform-paths: 3.3.1_typescript@4.9.5 - vite: 3.2.6_wo5djetj4deayu5nkog2244prm + vite: 3.2.6_q2pn2u5afkvbgyxa6yhm66etea vite-plugin-markdown: 2.2.0_vite@3.2.6 ../../packages/vtable-search: @@ -593,7 +593,7 @@ importers: '@types/chai': 4.2.22 '@types/jest': 26.0.24 '@types/mocha': 9.0.0 - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/offscreencanvas': 2019.6.4 '@types/react': 18.3.3 '@types/react-dom': 18.3.0 @@ -621,12 +621,12 @@ importers: sass: 1.43.5 ts-jest: 26.5.6_xuote2qreek47x2di7kesslrai ts-loader: 9.2.6_typescript@4.9.5 - ts-node: 10.9.0_fqbesfk7w3q7dr5vwiwy56afhe + ts-node: 10.9.0_daz7tukh2qp4t5y5hskra5bsgy tslib: 2.3.1 ttypescript: 1.5.13_fxi2xlggroal5l3a4znftvxz2m typescript: 4.9.5 typescript-transform-paths: 3.3.1_typescript@4.9.5 - vite: 3.2.6_wo5djetj4deayu5nkog2244prm + vite: 3.2.6_q2pn2u5afkvbgyxa6yhm66etea vite-plugin-markdown: 2.2.0_vite@3.2.6 ../../share/eslint-config: @@ -799,7 +799,7 @@ importers: '@types/merge2': 1.4.0 '@types/minimist': 1.2.2 '@types/ms': 0.7.31 - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/semver': 7.3.12 '@types/terser': 3.12.0 '@types/through2': 2.0.38 @@ -808,7 +808,7 @@ importers: '@types/yargs-parser': 21.0.0 eslint: 8.18.0 rimraf: 3.0.2 - ts-node: 10.9.0_fqbesfk7w3q7dr5vwiwy56afhe + ts-node: 10.9.0_daz7tukh2qp4t5y5hskra5bsgy typescript: 4.9.5 vitest: 0.30.1_less@4.1.3+terser@5.17.1 @@ -833,7 +833,7 @@ packages: react-dom: '>=16' dependencies: '@arco-design/color': 0.4.0 - '@babel/runtime': 7.24.6 + '@babel/runtime': 7.24.7 b-tween: 0.3.3 b-validate: 1.5.3 compute-scroll-into-view: 1.0.20 @@ -851,15 +851,15 @@ packages: transitivePeerDependencies: - '@types/react' - /@babel/code-frame/7.24.6: - resolution: {integrity: sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==} + /@babel/code-frame/7.24.7: + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/highlight': 7.24.6 + '@babel/highlight': 7.24.7 picocolors: 1.0.1 - /@babel/compat-data/7.24.6: - resolution: {integrity: sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==} + /@babel/compat-data/7.24.7: + resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==} engines: {node: '>=6.9.0'} /@babel/core/7.20.12: @@ -867,15 +867,15 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.6 + '@babel/code-frame': 7.24.7 '@babel/generator': 7.21.1 - '@babel/helper-compilation-targets': 7.24.6 - '@babel/helper-module-transforms': 7.24.6_@babel+core@7.20.12 - '@babel/helpers': 7.24.6 - '@babel/parser': 7.24.6 - '@babel/template': 7.24.6 - '@babel/traverse': 7.24.6 - '@babel/types': 7.24.6 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-module-transforms': 7.24.7_@babel+core@7.20.12 + '@babel/helpers': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/template': 7.24.7 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 convert-source-map: 1.9.0 debug: 4.3.4 gensync: 1.0.0-beta.2 @@ -888,67 +888,72 @@ packages: resolution: {integrity: sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.7 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 - /@babel/generator/7.24.6: - resolution: {integrity: sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==} + /@babel/generator/7.24.7: + resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.7 '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 - /@babel/helper-annotate-as-pure/7.24.6: - resolution: {integrity: sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==} + /@babel/helper-annotate-as-pure/7.24.7: + resolution: {integrity: sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.7 - /@babel/helper-builder-binary-assignment-operator-visitor/7.24.6: - resolution: {integrity: sha512-+wnfqc5uHiMYtvRX7qu80Toef8BXeh4HHR1SPeonGb1SKPniNEd4a/nlaJJMv/OIEYvIVavvo0yR7u10Gqz0Iw==} + /@babel/helper-builder-binary-assignment-operator-visitor/7.24.7: + resolution: {integrity: sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/helper-compilation-targets/7.24.6: - resolution: {integrity: sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==} + /@babel/helper-compilation-targets/7.24.7: + resolution: {integrity: sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/compat-data': 7.24.6 - '@babel/helper-validator-option': 7.24.6 - browserslist: 4.23.0 + '@babel/compat-data': 7.24.7 + '@babel/helper-validator-option': 7.24.7 + browserslist: 4.23.1 lru-cache: 5.1.1 semver: 6.3.1 - /@babel/helper-create-class-features-plugin/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA==} + /@babel/helper-create-class-features-plugin/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-function-name': 7.24.6 - '@babel/helper-member-expression-to-functions': 7.24.6 - '@babel/helper-optimise-call-expression': 7.24.6 - '@babel/helper-replace-supers': 7.24.6_@babel+core@7.20.12 - '@babel/helper-skip-transparent-expression-wrappers': 7.24.6 - '@babel/helper-split-export-declaration': 7.24.6 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-member-expression-to-functions': 7.24.7 + '@babel/helper-optimise-call-expression': 7.24.7 + '@babel/helper-replace-supers': 7.24.7_@babel+core@7.20.12 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 semver: 6.3.1 + transitivePeerDependencies: + - supports-color - /@babel/helper-create-regexp-features-plugin/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-C875lFBIWWwyv6MHZUG9HmRrlTDgOsLWZfYR0nW69gaKJNe0/Mpxx5r0EID2ZdHQkdUmQo2t0uNckTL08/1BgA==} + /@babel/helper-create-regexp-features-plugin/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.24.6 + '@babel/helper-annotate-as-pure': 7.24.7 regexpu-core: 5.3.2 semver: 6.3.1 @@ -958,8 +963,8 @@ packages: '@babel/core': ^7.4.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-compilation-targets': 7.24.6 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 debug: 4.3.4 lodash.debounce: 4.0.8 resolve: 1.22.8 @@ -967,158 +972,183 @@ packages: transitivePeerDependencies: - supports-color - /@babel/helper-environment-visitor/7.24.6: - resolution: {integrity: sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==} + /@babel/helper-environment-visitor/7.24.7: + resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.7 - /@babel/helper-function-name/7.24.6: - resolution: {integrity: sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==} + /@babel/helper-function-name/7.24.7: + resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/template': 7.24.6 - '@babel/types': 7.24.6 + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 - /@babel/helper-hoist-variables/7.24.6: - resolution: {integrity: sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==} + /@babel/helper-hoist-variables/7.24.7: + resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.7 - /@babel/helper-member-expression-to-functions/7.24.6: - resolution: {integrity: sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg==} + /@babel/helper-member-expression-to-functions/7.24.7: + resolution: {integrity: sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/helper-module-imports/7.24.6: - resolution: {integrity: sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==} + /@babel/helper-module-imports/7.24.7: + resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/helper-module-transforms/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==} + /@babel/helper-module-transforms/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-module-imports': 7.24.6 - '@babel/helper-simple-access': 7.24.6 - '@babel/helper-split-export-declaration': 7.24.6 - '@babel/helper-validator-identifier': 7.24.6 - - /@babel/helper-optimise-call-expression/7.24.6: - resolution: {integrity: sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA==} + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-simple-access': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + transitivePeerDependencies: + - supports-color + + /@babel/helper-optimise-call-expression/7.24.7: + resolution: {integrity: sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.7 - /@babel/helper-plugin-utils/7.24.6: - resolution: {integrity: sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg==} + /@babel/helper-plugin-utils/7.24.7: + resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==} engines: {node: '>=6.9.0'} - /@babel/helper-remap-async-to-generator/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-1Qursq9ArRZPAMOZf/nuzVW8HgJLkTB9y9LfP4lW2MVp4e9WkLJDovfKBxoDcCk6VuzIxyqWHyBoaCtSRP10yg==} + /@babel/helper-remap-async-to-generator/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-wrap-function': 7.24.6 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-wrap-function': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/helper-replace-supers/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ==} + /@babel/helper-replace-supers/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-member-expression-to-functions': 7.24.6 - '@babel/helper-optimise-call-expression': 7.24.6 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-member-expression-to-functions': 7.24.7 + '@babel/helper-optimise-call-expression': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/helper-simple-access/7.24.6: - resolution: {integrity: sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==} + /@babel/helper-simple-access/7.24.7: + resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/helper-skip-transparent-expression-wrappers/7.24.6: - resolution: {integrity: sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q==} + /@babel/helper-skip-transparent-expression-wrappers/7.24.7: + resolution: {integrity: sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/helper-split-export-declaration/7.24.6: - resolution: {integrity: sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==} + /@babel/helper-split-export-declaration/7.24.7: + resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.7 - /@babel/helper-string-parser/7.24.6: - resolution: {integrity: sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==} + /@babel/helper-string-parser/7.24.7: + resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier/7.24.6: - resolution: {integrity: sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==} + /@babel/helper-validator-identifier/7.24.7: + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-option/7.24.6: - resolution: {integrity: sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==} + /@babel/helper-validator-option/7.24.7: + resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==} engines: {node: '>=6.9.0'} - /@babel/helper-wrap-function/7.24.6: - resolution: {integrity: sha512-f1JLrlw/jbiNfxvdrfBgio/gRBk3yTAEJWirpAkiJG2Hb22E7cEYKHWo0dFPTv/niPovzIdPdEDetrv6tC6gPQ==} + /@babel/helper-wrap-function/7.24.7: + resolution: {integrity: sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-function-name': 7.24.6 - '@babel/template': 7.24.6 - '@babel/types': 7.24.6 + '@babel/helper-function-name': 7.24.7 + '@babel/template': 7.24.7 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/helpers/7.24.6: - resolution: {integrity: sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==} + /@babel/helpers/7.24.7: + resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/template': 7.24.6 - '@babel/types': 7.24.6 + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 - /@babel/highlight/7.24.6: - resolution: {integrity: sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==} + /@babel/highlight/7.24.7: + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.24.6 + '@babel/helper-validator-identifier': 7.24.7 chalk: 2.4.2 js-tokens: 4.0.0 picocolors: 1.0.1 - /@babel/parser/7.24.6: - resolution: {integrity: sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==} + /@babel/parser/7.24.7: + resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} engines: {node: '>=6.0.0'} hasBin: true - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-iVuhb6poq5ikqRq2XWU6OQ+R5o9wF+r/or9CeUyovgptz0UlnK4/seOQ1Istu/XybYjAhQv1FRSSfHHufIku5Q==} + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-c8TER5xMDYzzFcGqOEp9l4hvB7dcbhcGjcLVwxWfe4P5DOafdwjsBJZKsmv+o3aXh7NhopvayQIovHrh2zSRUQ==} + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.24.6 - '@babel/plugin-transform-optional-chaining': 7.24.6_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + '@babel/plugin-transform-optional-chaining': 7.24.7_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color /@babel/plugin-proposal-async-generator-functions/7.20.7_@babel+core@7.20.12: resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} @@ -1128,10 +1158,12 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-remap-async-to-generator': 7.24.6_@babel+core@7.20.12 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-remap-async-to-generator': 7.24.7_@babel+core@7.20.12 '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color /@babel/plugin-proposal-class-properties/7.18.6_@babel+core@7.20.12: resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} @@ -1141,8 +1173,10 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-create-class-features-plugin': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-create-class-features-plugin': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + transitivePeerDependencies: + - supports-color /@babel/plugin-proposal-class-static-block/7.21.0_@babel+core@7.20.12: resolution: {integrity: sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==} @@ -1152,9 +1186,11 @@ packages: '@babel/core': ^7.12.0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-create-class-features-plugin': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-create-class-features-plugin': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color /@babel/plugin-proposal-dynamic-import/7.18.6_@babel+core@7.20.12: resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} @@ -1164,7 +1200,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.20.12 /@babel/plugin-proposal-export-default-from/7.18.10_@babel+core@7.20.12: @@ -1174,8 +1210,8 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/plugin-syntax-export-default-from': 7.24.6_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-export-default-from': 7.24.7_@babel+core@7.20.12 dev: false /@babel/plugin-proposal-export-namespace-from/7.18.9_@babel+core@7.20.12: @@ -1186,7 +1222,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.20.12 /@babel/plugin-proposal-json-strings/7.18.6_@babel+core@7.20.12: @@ -1197,7 +1233,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.20.12 /@babel/plugin-proposal-logical-assignment-operators/7.20.7_@babel+core@7.20.12: @@ -1208,7 +1244,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.20.12 /@babel/plugin-proposal-nullish-coalescing-operator/7.18.6_@babel+core@7.20.12: @@ -1219,7 +1255,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.20.12 /@babel/plugin-proposal-numeric-separator/7.18.6_@babel+core@7.20.12: @@ -1230,7 +1266,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.20.12 /@babel/plugin-proposal-object-rest-spread/7.20.7_@babel+core@7.20.12: @@ -1240,12 +1276,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.24.6 + '@babel/compat-data': 7.24.7 '@babel/core': 7.20.12 - '@babel/helper-compilation-targets': 7.24.6 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-transform-parameters': 7.24.6_@babel+core@7.20.12 + '@babel/plugin-transform-parameters': 7.24.7_@babel+core@7.20.12 /@babel/plugin-proposal-optional-catch-binding/7.18.6_@babel+core@7.20.12: resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} @@ -1255,7 +1291,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.20.12 /@babel/plugin-proposal-optional-chaining/7.21.0_@babel+core@7.20.12: @@ -1266,9 +1302,11 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color /@babel/plugin-proposal-private-methods/7.18.6_@babel+core@7.20.12: resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} @@ -1278,8 +1316,10 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-create-class-features-plugin': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-create-class-features-plugin': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + transitivePeerDependencies: + - supports-color /@babel/plugin-proposal-private-property-in-object/7.21.11_@babel+core@7.20.12: resolution: {integrity: sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==} @@ -1289,10 +1329,12 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.24.6 - '@babel/helper-create-class-features-plugin': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-create-class-features-plugin': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color /@babel/plugin-proposal-unicode-property-regex/7.18.6_@babel+core@7.20.12: resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} @@ -1302,8 +1344,8 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-create-regexp-features-plugin': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.20.12: resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} @@ -1311,7 +1353,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.20.12: resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} @@ -1319,7 +1361,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 dev: true /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.20.12: @@ -1328,7 +1370,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-class-static-block/7.14.5_@babel+core@7.20.12: resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} @@ -1337,7 +1379,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-dynamic-import/7.8.3_@babel+core@7.20.12: resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} @@ -1345,16 +1387,16 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-syntax-export-default-from/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-Nzl7kZ4tjOM2LJpejBMPwZs7OJfc26++2HsMQuSrw6gxpqXGtZZ3Rj4Zt4Qm7vulMZL2gHIGGc2stnlQnHQCqA==} + /@babel/plugin-syntax-export-default-from/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-bTPz4/635WQ9WhwsyPdxUJDVpsi/X9BMmy/8Rf/UAlOO4jSql4CxUCjWI5PiM+jG+c4LVPTScoTw80geFj9+Bw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 dev: false /@babel/plugin-syntax-export-namespace-from/7.8.3_@babel+core@7.20.12: @@ -1363,16 +1405,16 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-syntax-import-assertions/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-BE6o2BogJKJImTmGpkmOic4V0hlRRxVtzqxiSPa8TIFxyhi4EFjHm08nq1M4STK4RytuLMgnSz0/wfflvGFNOg==} + /@babel/plugin-syntax-import-assertions/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.20.12: resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} @@ -1380,7 +1422,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 dev: true /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.20.12: @@ -1389,16 +1431,16 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-syntax-jsx/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw==} + /@babel/plugin-syntax-jsx/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 dev: false /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.20.12: @@ -1407,7 +1449,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.20.12: resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} @@ -1415,7 +1457,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.20.12: resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} @@ -1423,7 +1465,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.20.12: resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} @@ -1431,7 +1473,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.20.12: resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} @@ -1439,7 +1481,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.20.12: resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} @@ -1447,7 +1489,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-private-property-in-object/7.14.5_@babel+core@7.20.12: resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} @@ -1456,7 +1498,7 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.20.12: resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} @@ -1465,343 +1507,367 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-syntax-typescript/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A==} + /@babel/plugin-syntax-typescript/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 dev: false - /@babel/plugin-transform-arrow-functions/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-jSSSDt4ZidNMggcLx8SaKsbGNEfIl0PHx/4mFEulorE7bpYLbN0d3pDW3eJ7Y5Z3yPhy3L3NaPCYyTUY7TuugQ==} + /@babel/plugin-transform-arrow-functions/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-async-to-generator/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-NTBA2SioI3OsHeIn6sQmhvXleSl9T70YY/hostQLveWs0ic+qvbA3fa0kwAwQ0OA/XGaAerNZRQGJyRfhbJK4g==} + /@babel/plugin-transform-async-to-generator/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-module-imports': 7.24.6 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-remap-async-to-generator': 7.24.6_@babel+core@7.20.12 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-remap-async-to-generator': 7.24.7_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color - /@babel/plugin-transform-block-scoped-functions/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-XNW7jolYHW9CwORrZgA/97tL/k05qe/HL0z/qqJq1mdWhwwCM6D4BJBV7wAz9HgFziN5dTOG31znkVIzwxv+vw==} + /@babel/plugin-transform-block-scoped-functions/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-block-scoping/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-S/t1Xh4ehW7sGA7c1j/hiOBLnEYCp/c2sEG4ZkL8kI1xX9tW2pqJTCHKtdhe/jHKt8nG0pFCrDHUXd4DvjHS9w==} + /@babel/plugin-transform-block-scoping/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-classes/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-+fN+NO2gh8JtRmDSOB6gaCVo36ha8kfCW1nMq2Gc0DABln0VcHN4PrALDvF5/diLzIRKptC7z/d7Lp64zk92Fg==} + /@babel/plugin-transform-classes/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.24.6 - '@babel/helper-compilation-targets': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-function-name': 7.24.6 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-replace-supers': 7.24.6_@babel+core@7.20.12 - '@babel/helper-split-export-declaration': 7.24.6 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-replace-supers': 7.24.7_@babel+core@7.20.12 + '@babel/helper-split-export-declaration': 7.24.7 globals: 11.12.0 + transitivePeerDependencies: + - supports-color - /@babel/plugin-transform-computed-properties/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-cRzPobcfRP0ZtuIEkA8QzghoUpSB3X3qSH5W2+FzG+VjWbJXExtx0nbRqwumdBN1x/ot2SlTNQLfBCnPdzp6kg==} + /@babel/plugin-transform-computed-properties/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/template': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/template': 7.24.7 - /@babel/plugin-transform-destructuring/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-YLW6AE5LQpk5npNXL7i/O+U9CE4XsBCuRPgyjl1EICZYKmcitV+ayuuUGMJm2lC1WWjXYszeTnIxF/dq/GhIZQ==} + /@babel/plugin-transform-destructuring/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-dotall-regex/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-rCXPnSEKvkm/EjzOtLoGvKseK+dS4kZwx1HexO3BtRtgL0fQ34awHn34aeSHuXtZY2F8a1X8xqBBPRtOxDVmcA==} + /@babel/plugin-transform-dotall-regex/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-create-regexp-features-plugin': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-duplicate-keys/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-/8Odwp/aVkZwPFJMllSbawhDAO3UJi65foB00HYnK/uXvvCPm0TAXSByjz1mpRmp0q6oX2SIxpkUOpPFHk7FLA==} + /@babel/plugin-transform-duplicate-keys/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-exponentiation-operator/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-EemYpHtmz0lHE7hxxxYEuTYOOBZ43WkDgZ4arQ4r+VX9QHuNZC+WH3wUWmRNvR8ECpTRne29aZV6XO22qpOtdA==} + /@babel/plugin-transform-exponentiation-operator/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.24.6 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/plugin-transform-for-of/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-n3Sf72TnqK4nw/jziSqEl1qaWPbCRw2CziHH+jdRYvw4J6yeCzsj4jdw8hIntOEeDGTmHVe2w4MVL44PN0GMzg==} + /@babel/plugin-transform-for-of/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/plugin-transform-function-name/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-sOajCu6V0P1KPljWHKiDq6ymgqB+vfo3isUS4McqW1DZtvSVU2v/wuMhmRmkg3sFoq6GMaUUf8W4WtoSLkOV/Q==} + /@babel/plugin-transform-function-name/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-compilation-targets': 7.24.6 - '@babel/helper-function-name': 7.24.6 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-literals/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-f2wHfR2HF6yMj+y+/y07+SLqnOSwRp8KYLpQKOzS58XLVlULhXbiYcygfXQxJlMbhII9+yXDwOUFLf60/TL5tw==} + /@babel/plugin-transform-literals/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-member-expression-literals/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-9g8iV146szUo5GWgXpRbq/GALTnY+WnNuRTuRHWWFfWGbP9ukRL0aO/jpu9dmOPikclkxnNsjY8/gsWl6bmZJQ==} + /@babel/plugin-transform-member-expression-literals/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-modules-amd/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-eAGogjZgcwqAxhyFgqghvoHRr+EYRQPFjUXrTYKBRb5qPnAVxOOglaxc4/byHqjvq/bqO2F3/CGwTHsgKJYHhQ==} + /@babel/plugin-transform-modules-amd/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-module-transforms': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-module-transforms': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/plugin-transform-modules-commonjs/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw==} + /@babel/plugin-transform-modules-commonjs/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-module-transforms': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-simple-access': 7.24.6 + '@babel/helper-module-transforms': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-simple-access': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/plugin-transform-modules-systemjs/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-xg1Z0J5JVYxtpX954XqaaAT6NpAY6LtZXvYFCJmGFJWwtlz2EmJoR8LycFRGNE8dBKizGWkGQZGegtkV8y8s+w==} + /@babel/plugin-transform-modules-systemjs/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-hoist-variables': 7.24.6 - '@babel/helper-module-transforms': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-validator-identifier': 7.24.6 + '@babel/helper-hoist-variables': 7.24.7 + '@babel/helper-module-transforms': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/plugin-transform-modules-umd/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-esRCC/KsSEUvrSjv5rFYnjZI6qv4R1e/iHQrqwbZIoRJqk7xCvEUiN7L1XrmW5QSmQe3n1XD88wbgDTWLbVSyg==} + /@babel/plugin-transform-modules-umd/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-module-transforms': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-module-transforms': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/plugin-transform-named-capturing-groups-regex/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-6DneiCiu91wm3YiNIGDWZsl6GfTTbspuj/toTEqLh9d4cx50UIzSdg+T96p8DuT7aJOBRhFyaE9ZvTHkXrXr6Q==} + /@babel/plugin-transform-named-capturing-groups-regex/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-create-regexp-features-plugin': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-new-target/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-f8liz9JG2Va8A4J5ZBuaSdwfPqN6axfWRK+y66fjKYbwf9VBLuq4WxtinhJhvp1w6lamKUwLG0slK2RxqFgvHA==} + /@babel/plugin-transform-new-target/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-object-super/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-N/C76ihFKlZgKfdkEYKtaRUtXZAgK7sOY4h2qrbVbVTXPrKGIi8aww5WGe/+Wmg8onn8sr2ut6FXlsbu/j6JHg==} + /@babel/plugin-transform-object-super/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-replace-supers': 7.24.6_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-replace-supers': 7.24.7_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color - /@babel/plugin-transform-optional-chaining/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-cHbqF6l1QP11OkYTYQ+hhVx1E017O5ZcSPXk9oODpqhcAD1htsWG2NpHrrhthEO2qZomLK0FXS+u7NfrkF5aOQ==} + /@babel/plugin-transform-optional-chaining/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-tK+0N9yd4j+x/4hxF3F0e0fu/VdcxU18y5SevtyM/PCFlQvXbR0Zmlo2eBrKtVipGNFzpq56o8WsIIKcJFUCRQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color - /@babel/plugin-transform-parameters/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-ST7guE8vLV+vI70wmAxuZpIKzVjvFX9Qs8bl5w6tN/6gOypPWUmMQL2p7LJz5E63vEGrDhAiYetniJFyBH1RkA==} + /@babel/plugin-transform-parameters/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-property-literals/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-oARaglxhRsN18OYsnPTpb8TcKQWDYNsPNmTnx5++WOAsUJ0cSC/FZVlIJCKvPbU4yn/UXsS0551CFKJhN0CaMw==} + /@babel/plugin-transform-property-literals/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-react-display-name/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-/3iiEEHDsJuj9QU09gbyWGSUxDboFcD7Nj6dnHIlboWSodxXAoaY/zlNMHeYAC0WsERMqgO9a7UaM77CsYgWcg==} + /@babel/plugin-transform-react-display-name/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 dev: false - /@babel/plugin-transform-react-jsx-development/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-F7EsNp5StNDouSSdYyDSxh4J+xvj/JqG+Cb6s2fA+jCyHOzigG5vTwgH8tU2U8Voyiu5zCG9bAK49wTr/wPH0w==} + /@babel/plugin-transform-react-jsx-development/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/plugin-transform-react-jsx': 7.24.6_@babel+core@7.20.12 + '@babel/plugin-transform-react-jsx': 7.24.7_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color dev: false - /@babel/plugin-transform-react-jsx-self/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-FfZfHXtQ5jYPQsCRyLpOv2GeLIIJhs8aydpNh39vRDjhD411XcfWDni5i7OjP/Rs8GAtTn7sWFFELJSHqkIxYg==} + /@babel/plugin-transform-react-jsx-self/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 dev: true - /@babel/plugin-transform-react-jsx-source/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-BQTBCXmFRreU3oTUXcGKuPOfXAGb1liNY4AvvFKsOBAJ89RKcTsIrSsnMYkj59fNa66OFKnSa4AJZfy5Y4B9WA==} + /@babel/plugin-transform-react-jsx-source/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 dev: true - /@babel/plugin-transform-react-jsx/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-pCtPHhpRZHfwdA5G1Gpk5mIzMA99hv0R8S/Ket50Rw+S+8hkt3wBWqdqHaPw0CuUYxdshUgsPiLQ5fAs4ASMhw==} + /@babel/plugin-transform-react-jsx/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.24.6 - '@babel/helper-module-imports': 7.24.6 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/plugin-syntax-jsx': 7.24.6_@babel+core@7.20.12 - '@babel/types': 7.24.6 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-jsx': 7.24.7_@babel+core@7.20.12 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color dev: false - /@babel/plugin-transform-react-pure-annotations/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-0HoDQlFJJkXRyV2N+xOpUETbKHcouSwijRQbKWVtxsPoq5bbB30qZag9/pSc5xcWVYjTHlLsBsY+hZDnzQTPNw==} + /@babel/plugin-transform-react-pure-annotations/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.24.6 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 dev: false - /@babel/plugin-transform-regenerator/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-SMDxO95I8WXRtXhTAc8t/NFQUT7VYbIWwJCJgEli9ml4MhqUMh4S6hxgH6SmAC3eAQNWCDJFxcFeEt9w2sDdXg==} + /@babel/plugin-transform-regenerator/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 regenerator-transform: 0.15.2 - /@babel/plugin-transform-reserved-words/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-DcrgFXRRlK64dGE0ZFBPD5egM2uM8mgfrvTMOSB2yKzOtjpGegVYkzh3s1zZg1bBck3nkXiaOamJUqK3Syk+4A==} + /@babel/plugin-transform-reserved-words/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 /@babel/plugin-transform-runtime/7.21.0_@babel+core@7.20.12: resolution: {integrity: sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg==} @@ -1810,8 +1876,8 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-module-imports': 7.24.6 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.20.12 babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.20.12 babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.20.12 @@ -1820,83 +1886,87 @@ packages: - supports-color dev: false - /@babel/plugin-transform-shorthand-properties/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-xnEUvHSMr9eOWS5Al2YPfc32ten7CXdH7Zwyyk7IqITg4nX61oHj+GxpNvl+y5JHjfN3KXE2IV55wAWowBYMVw==} + /@babel/plugin-transform-shorthand-properties/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-spread/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-h/2j7oIUDjS+ULsIrNZ6/TKG97FgmEk1PXryk/HQq6op4XUUUwif2f69fJrzK0wza2zjCS1xhXmouACaWV5uPA==} + /@babel/plugin-transform-spread/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-skip-transparent-expression-wrappers': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + transitivePeerDependencies: + - supports-color - /@babel/plugin-transform-sticky-regex/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-fN8OcTLfGmYv7FnDrsjodYBo1DhPL3Pze/9mIIE2MGCT1KgADYIOD7rEglpLHZj8PZlC/JFX5WcD+85FLAQusw==} + /@babel/plugin-transform-sticky-regex/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-template-literals/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-BJbEqJIcKwrqUP+KfUIkxz3q8VzXe2R8Wv8TaNgO1cx+nNavxn/2+H8kp9tgFSOL6wYPPEgFvU6IKS4qoGqhmg==} + /@babel/plugin-transform-template-literals/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-typeof-symbol/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-IshCXQ+G9JIFJI7bUpxTE/oA2lgVLAIK8q1KdJNoPXOpvRaNjMySGuvLfBw/Xi2/1lLo953uE8hyYSDW3TSYig==} + /@babel/plugin-transform-typeof-symbol/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-typescript/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-H0i+hDLmaYYSt6KU9cZE0gb3Cbssa/oxWis7PX4ofQzbvsfix9Lbh8SRk7LCPDlLWJHUiFeHU0qRRpF/4Zv7mQ==} + /@babel/plugin-transform-typescript/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-iLD3UNkgx2n/HrjBesVbYX6j0yqn/sJktvbtKKgcaLIQ4bTTQ8obAypc1VpyHPD2y4Phh9zHOaAt8e/L14wCpw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-annotate-as-pure': 7.24.6 - '@babel/helper-create-class-features-plugin': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/plugin-syntax-typescript': 7.24.6_@babel+core@7.20.12 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-create-class-features-plugin': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-typescript': 7.24.7_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color dev: false - /@babel/plugin-transform-unicode-escapes/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-bKl3xxcPbkQQo5eX9LjjDpU2xYHeEeNQbOhj0iPvetSzA+Tu9q/o5lujF4Sek60CM6MgYvOS/DJuwGbiEYAnLw==} + /@babel/plugin-transform-unicode-escapes/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 - /@babel/plugin-transform-unicode-regex/7.24.6_@babel+core@7.20.12: - resolution: {integrity: sha512-pssN6ExsvxaKU638qcWb81RrvvgZom3jDgU/r5xFZ7TONkZGFf4MhI2ltMb8OcQWhHyxgIavEU+hgqtbKOmsPA==} + /@babel/plugin-transform-unicode-regex/7.24.7_@babel+core@7.20.12: + resolution: {integrity: sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-create-regexp-features-plugin': 7.24.6_@babel+core@7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-create-regexp-features-plugin': 7.24.7_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 /@babel/preset-env/7.20.2_@babel+core@7.20.12: resolution: {integrity: sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==} @@ -1904,13 +1974,13 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.24.6 + '@babel/compat-data': 7.24.7 '@babel/core': 7.20.12 - '@babel/helper-compilation-targets': 7.24.6 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-validator-option': 7.24.6 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.6_@babel+core@7.20.12 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-validator-option': 7.24.7 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.7_@babel+core@7.20.12 '@babel/plugin-proposal-async-generator-functions': 7.20.7_@babel+core@7.20.12 '@babel/plugin-proposal-class-properties': 7.18.6_@babel+core@7.20.12 '@babel/plugin-proposal-class-static-block': 7.21.0_@babel+core@7.20.12 @@ -1931,7 +2001,7 @@ packages: '@babel/plugin-syntax-class-static-block': 7.14.5_@babel+core@7.20.12 '@babel/plugin-syntax-dynamic-import': 7.8.3_@babel+core@7.20.12 '@babel/plugin-syntax-export-namespace-from': 7.8.3_@babel+core@7.20.12 - '@babel/plugin-syntax-import-assertions': 7.24.6_@babel+core@7.20.12 + '@babel/plugin-syntax-import-assertions': 7.24.7_@babel+core@7.20.12 '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.20.12 '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.20.12 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.20.12 @@ -1941,40 +2011,40 @@ packages: '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.20.12 '@babel/plugin-syntax-private-property-in-object': 7.14.5_@babel+core@7.20.12 '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.20.12 - '@babel/plugin-transform-arrow-functions': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-async-to-generator': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-block-scoped-functions': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-block-scoping': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-classes': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-computed-properties': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-destructuring': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-dotall-regex': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-duplicate-keys': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-exponentiation-operator': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-for-of': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-function-name': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-literals': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-member-expression-literals': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-modules-amd': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-modules-commonjs': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-modules-systemjs': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-modules-umd': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-named-capturing-groups-regex': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-new-target': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-object-super': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-parameters': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-property-literals': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-regenerator': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-reserved-words': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-shorthand-properties': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-spread': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-sticky-regex': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-template-literals': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-typeof-symbol': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-unicode-escapes': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-unicode-regex': 7.24.6_@babel+core@7.20.12 + '@babel/plugin-transform-arrow-functions': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-async-to-generator': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-block-scoped-functions': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-block-scoping': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-classes': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-computed-properties': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-destructuring': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-dotall-regex': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-duplicate-keys': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-exponentiation-operator': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-for-of': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-function-name': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-literals': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-member-expression-literals': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-modules-amd': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-modules-commonjs': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-modules-systemjs': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-modules-umd': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-named-capturing-groups-regex': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-new-target': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-object-super': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-parameters': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-property-literals': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-regenerator': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-reserved-words': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-shorthand-properties': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-spread': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-sticky-regex': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-template-literals': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-typeof-symbol': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-unicode-escapes': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-unicode-regex': 7.24.7_@babel+core@7.20.12 '@babel/preset-modules': 0.1.6_@babel+core@7.20.12 - '@babel/types': 7.24.6 + '@babel/types': 7.24.7 babel-plugin-polyfill-corejs2: 0.3.3_@babel+core@7.20.12 babel-plugin-polyfill-corejs3: 0.6.0_@babel+core@7.20.12 babel-plugin-polyfill-regenerator: 0.4.1_@babel+core@7.20.12 @@ -1989,10 +2059,10 @@ packages: '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-proposal-unicode-property-regex': 7.18.6_@babel+core@7.20.12 - '@babel/plugin-transform-dotall-regex': 7.24.6_@babel+core@7.20.12 - '@babel/types': 7.24.6 + '@babel/plugin-transform-dotall-regex': 7.24.7_@babel+core@7.20.12 + '@babel/types': 7.24.7 esutils: 2.0.3 /@babel/preset-react/7.18.6_@babel+core@7.20.12: @@ -2002,12 +2072,14 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-validator-option': 7.24.6 - '@babel/plugin-transform-react-display-name': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-react-jsx': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-react-jsx-development': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-react-pure-annotations': 7.24.6_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-validator-option': 7.24.7 + '@babel/plugin-transform-react-display-name': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-react-jsx': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-react-jsx-development': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-react-pure-annotations': 7.24.7_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color dev: false /@babel/preset-typescript/7.18.6_@babel+core@7.20.12: @@ -2017,51 +2089,53 @@ packages: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.20.12 - '@babel/helper-plugin-utils': 7.24.6 - '@babel/helper-validator-option': 7.24.6 - '@babel/plugin-transform-typescript': 7.24.6_@babel+core@7.20.12 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-validator-option': 7.24.7 + '@babel/plugin-transform-typescript': 7.24.7_@babel+core@7.20.12 + transitivePeerDependencies: + - supports-color dev: false /@babel/regjsgen/0.8.0: resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - /@babel/runtime/7.24.6: - resolution: {integrity: sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==} + /@babel/runtime/7.24.7: + resolution: {integrity: sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.1 - /@babel/template/7.24.6: - resolution: {integrity: sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==} + /@babel/template/7.24.7: + resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.24.6 - '@babel/parser': 7.24.6 - '@babel/types': 7.24.6 + '@babel/code-frame': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 - /@babel/traverse/7.24.6: - resolution: {integrity: sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==} + /@babel/traverse/7.24.7: + resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.24.6 - '@babel/generator': 7.24.6 - '@babel/helper-environment-visitor': 7.24.6 - '@babel/helper-function-name': 7.24.6 - '@babel/helper-hoist-variables': 7.24.6 - '@babel/helper-split-export-declaration': 7.24.6 - '@babel/parser': 7.24.6 - '@babel/types': 7.24.6 + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-hoist-variables': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: - supports-color - /@babel/types/7.24.6: - resolution: {integrity: sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==} + /@babel/types/7.24.7: + resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-string-parser': 7.24.6 - '@babel/helper-validator-identifier': 7.24.6 + '@babel/helper-string-parser': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 to-fast-properties: 2.0.0 /@bcoe/v8-coverage/0.2.3: @@ -2180,6 +2254,7 @@ packages: /@humanwhocodes/config-array/0.9.5: resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead dependencies: '@humanwhocodes/object-schema': 1.2.1 debug: 4.3.4 @@ -2189,6 +2264,7 @@ packages: /@humanwhocodes/object-schema/1.2.1: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + deprecated: Use @eslint/object-schema instead /@istanbuljs/load-nyc-config/1.1.0: resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} @@ -2220,7 +2296,7 @@ packages: engines: {node: '>= 10.14.2'} dependencies: '@jest/types': 26.6.2 - '@types/node': 20.12.13 + '@types/node': 20.14.2 chalk: 4.1.2 jest-message-util: 26.6.2 jest-util: 26.6.2 @@ -2236,7 +2312,7 @@ packages: '@jest/test-result': 26.6.2 '@jest/transform': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 20.12.13 + '@types/node': 20.14.2 ansi-escapes: 4.3.2 chalk: 4.1.2 exit: 0.1.2 @@ -2249,7 +2325,7 @@ packages: jest-resolve: 26.6.2 jest-resolve-dependencies: 26.6.3 jest-runner: 26.6.3_ts-node@10.9.0 - jest-runtime: 26.6.3_ts-node@10.9.0 + jest-runtime: 26.6.3 jest-snapshot: 26.6.2 jest-util: 26.6.2 jest-validate: 26.6.2 @@ -2285,7 +2361,7 @@ packages: dependencies: '@jest/fake-timers': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 20.12.13 + '@types/node': 20.14.2 jest-mock: 26.6.2 dev: true @@ -2304,7 +2380,7 @@ packages: dependencies: '@jest/types': 26.6.2 '@sinonjs/fake-timers': 6.0.1 - '@types/node': 20.12.13 + '@types/node': 20.14.2 jest-message-util: 26.6.2 jest-mock: 26.6.2 jest-util: 26.6.2 @@ -2410,7 +2486,7 @@ packages: graceful-fs: 4.2.11 jest-haste-map: 26.6.2 jest-runner: 26.6.3_ts-node@10.9.0 - jest-runtime: 26.6.3_ts-node@10.9.0 + jest-runtime: 26.6.3 transitivePeerDependencies: - bufferutil - canvas @@ -2481,7 +2557,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/yargs': 15.0.19 chalk: 4.1.2 dev: true @@ -2812,10 +2888,12 @@ packages: optional: true dependencies: '@babel/core': 7.20.12 - '@babel/helper-module-imports': 7.24.6 + '@babel/helper-module-imports': 7.24.7 '@rollup/pluginutils': 5.1.0_rollup@3.20.5 '@types/babel__core': 7.20.0 rollup: 3.20.5 + transitivePeerDependencies: + - supports-color dev: false /@rollup/plugin-commonjs/24.1.0_rollup@3.20.5: @@ -3071,8 +3149,8 @@ packages: /@types/babel__core/7.20.0: resolution: {integrity: sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==} dependencies: - '@babel/parser': 7.24.6 - '@babel/types': 7.24.6 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 '@types/babel__generator': 7.6.8 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.6 @@ -3080,18 +3158,18 @@ packages: /@types/babel__generator/7.6.8: resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.7 /@types/babel__template/7.4.4: resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} dependencies: - '@babel/parser': 7.24.6 - '@babel/types': 7.24.6 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 /@types/babel__traverse/7.20.6: resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.7 /@types/buble/0.20.5: resolution: {integrity: sha512-CNpql2WPrZloamMweLkyM42nPsUVa10NDurkhTB5+tGu8SstDd568dothJi7tFSAsbqJK0rSb83W9ZwGt8My/A==} @@ -3116,7 +3194,7 @@ packages: /@types/clean-css/4.2.6: resolution: {integrity: sha512-Ze1tf+LnGPmG6hBFMi0B4TEB0mhF7EiMM5oyjLDNPE9hxrPU0W+5+bHvO+eFPA+bt0iC1zkQMoU/iGdRVjcRbw==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 source-map: 0.6.1 dev: true @@ -3144,13 +3222,13 @@ packages: /@types/fs-extra/9.0.13: resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 dev: true /@types/glob-stream/8.0.2: resolution: {integrity: sha512-kyuRfGE+yiSJWzSO3t74rXxdZNdYfLcllO0IUha4eX1fl40pm9L02Q/TEc3mykTLjoWz4STBNwYnUWdFu3I0DA==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/picomatch': 2.3.3 '@types/streamx': 2.9.5 dev: true @@ -3158,19 +3236,19 @@ packages: /@types/glob-watcher/5.0.2: resolution: {integrity: sha512-MZeh2nIzibl/euv5UV0femkGzcKTSE4G2+zv48d6ymeitWwCx52+4X+FqzML9oH2mQnPs+N/JHp3CsBPj1x1Ug==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 dev: true /@types/graceful-fs/4.1.9: resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 dev: true /@types/gulp-if/0.0.34: resolution: {integrity: sha512-r2A04hHDC+ZWMRAm+3q6/UeC3ggvl+TZm9P1+2umnp4q9bOlBmUQnR178Io3c0DkZPQAwup8VNtOvmvaWCpP5w==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/vinyl': 2.0.7 dev: true @@ -3184,7 +3262,7 @@ packages: /@types/gulp-sourcemaps/0.0.35: resolution: {integrity: sha512-vUBuizwA4CAV3Mke0DJYHQxyN4YOB1aAql284qAO7Et7fe0hmnPi/R9Fhu2UhxMuSxAwFktsJUOQk5dJHOU1eA==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/vinyl': 2.0.7 dev: true @@ -3260,7 +3338,7 @@ packages: /@types/merge2/1.4.0: resolution: {integrity: sha512-MRHDvln2ldZELrUC8n1PGaQzZ33aNh8uDcsGehREW0zR1Fr818a4/JTZjO9eloHPPxnpUp8fz/YFTRc5CWm7Xw==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 dev: true /@types/minimatch/5.1.2: @@ -3287,8 +3365,8 @@ packages: resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==} dev: false - /@types/node/20.12.13: - resolution: {integrity: sha512-gBGeanV41c1L171rR7wjbMiEpEI/l5XFQdLLfhr/REwpgDy/4U8y89+i8kRiLzDyZdOkXh+cRaTetUnCYutoXA==} + /@types/node/20.14.2: + resolution: {integrity: sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==} dependencies: undici-types: 5.26.5 @@ -3340,7 +3418,7 @@ packages: /@types/resolve/0.0.8: resolution: {integrity: sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 dev: true /@types/resolve/1.20.2: @@ -3366,7 +3444,7 @@ packages: /@types/streamx/2.9.5: resolution: {integrity: sha512-IHYsa6jYrck8VEdSwpY141FTTf6D7boPeMq9jy4qazNrFMA4VbRz/sw5LSsfR7jwdDcx0QKWkUexZvsWBC2eIQ==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 dev: true /@types/terser/3.12.0: @@ -3379,7 +3457,7 @@ packages: /@types/through2/2.0.38: resolution: {integrity: sha512-YFu+nHmjxMurkH1BSzA0Z1WrKDAY8jUKPZctNQn7mc+/KKtp2XxnclHFXxdB1m7Iqnzb5aywgP8TMK283LezGQ==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 dev: true /@types/undertaker-registry/1.0.4: @@ -3389,7 +3467,7 @@ packages: /@types/undertaker/1.2.8: resolution: {integrity: sha512-gW3PRqCHYpo45XFQHJBhch7L6hytPsIe0QeLujlnFsjHPnXLhJcPdN6a9368d7aIQgH2I/dUTPFBlGeSNA3qOg==} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/undertaker-registry': 1.0.4 async-done: 1.3.2 dev: true @@ -3398,7 +3476,7 @@ packages: resolution: {integrity: sha512-ckYz9giHgV6U10RFuf9WsDQ3X86EFougapxHmmoxLK7e6ICQqO8CE+4V/3lBN148V5N1pb4nQMmMjyScleVsig==} dependencies: '@types/glob-stream': 8.0.2 - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/vinyl': 2.0.7 dev: true @@ -3406,7 +3484,7 @@ packages: resolution: {integrity: sha512-4UqPv+2567NhMQuMLdKAyK4yzrfCqwaTt6bLhHEs8PFcxbHILsrxaY63n4wgE/BRLDWDQeI+WcTmkXKExh9hQg==} dependencies: '@types/expect': 1.20.4 - '@types/node': 20.12.13 + '@types/node': 20.14.2 /@types/yargs-parser/21.0.0: resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} @@ -3679,11 +3757,11 @@ packages: '@visactor/vscale': 0.17.5 '@visactor/vutils': 0.18.9 - /@visactor/vrender-components/0.19.10-beta.1: - resolution: {integrity: sha512-OQaxEYOAwHIAcXqkqqtwQYejOg3mFDgH1h050VLotWyIcItTvvZxwhXPbeLcPryWzR4PaoUTGPVOM7XNoqKzEQ==} + /@visactor/vrender-components/0.19.9: + resolution: {integrity: sha512-IKbYMCr7KO2wE38cxS2O2FR1ufvWn2StFcWyp8mNi3ZIho9M+fjJoNDefdrOEN9o3N9b3v2AZdQzLDqs2ZMQEw==} dependencies: - '@visactor/vrender-core': 0.19.10-beta.1 - '@visactor/vrender-kits': 0.19.10-beta.1 + '@visactor/vrender-core': 0.19.9 + '@visactor/vrender-kits': 0.19.9 '@visactor/vscale': 0.18.9 '@visactor/vutils': 0.18.9 dev: false @@ -3694,8 +3772,8 @@ packages: '@visactor/vutils': 0.18.9 color-convert: 2.0.1 - /@visactor/vrender-core/0.19.10-beta.1: - resolution: {integrity: sha512-vOpEtwRgb3JpXWSgHzHnartVZlw9B8y6tQ4gOs117J5jhVcSuv2KT28oLuj3wqZsSybOhr/Di7HFIibfo80dRw==} + /@visactor/vrender-core/0.19.9: + resolution: {integrity: sha512-9Ucz93ECTbClf3zqRf348aTyr/rtAecqoQsXd69fwYgPvB2Fy6A0Ofm8O1odChxLx7oaoZPzcSeS9YGVPssn+A==} dependencies: '@visactor/vutils': 0.18.9 color-convert: 2.0.1 @@ -3709,11 +3787,11 @@ packages: '@visactor/vutils': 0.18.9 roughjs: 4.5.2 - /@visactor/vrender-kits/0.19.10-beta.1: - resolution: {integrity: sha512-Xu8VJXscdproiMF+1AA+Te89qRPnEGoWyV9Hham97NbTg/z2AWb9NhQsNu+8O3TYugbX3tOhbKbPnIgFr+tgeQ==} + /@visactor/vrender-kits/0.19.9: + resolution: {integrity: sha512-y0ncykl6i+GYK2Ih5RDt/fiLKLXVmFrDYm4zgg7O+Yaaw/iGBXOrlFVIQE6Ao0kfOwDac0xKZzaS9x7kKrULRw==} dependencies: '@resvg/resvg-js': 2.4.1 - '@visactor/vrender-core': 0.19.10-beta.1 + '@visactor/vrender-core': 0.19.9 '@visactor/vutils': 0.18.9 roughjs: 4.5.2 dev: false @@ -3761,8 +3839,8 @@ packages: vite: ^4.1.0-beta.0 dependencies: '@babel/core': 7.20.12 - '@babel/plugin-transform-react-jsx-self': 7.24.6_@babel+core@7.20.12 - '@babel/plugin-transform-react-jsx-source': 7.24.6_@babel+core@7.20.12 + '@babel/plugin-transform-react-jsx-self': 7.24.7_@babel+core@7.20.12 + '@babel/plugin-transform-react-jsx-source': 7.24.7_@babel+core@7.20.12 magic-string: 0.27.0 react-refresh: 0.14.2 vite: 3.2.6 @@ -4318,8 +4396,8 @@ packages: peerDependencies: postcss: ^8.1.0 dependencies: - browserslist: 4.23.0 - caniuse-lite: 1.0.30001625 + browserslist: 4.23.1 + caniuse-lite: 1.0.30001632 fraction.js: 4.3.7 normalize-range: 0.1.2 picocolors: 1.0.1 @@ -4404,14 +4482,16 @@ packages: /babel-plugin-import/1.13.6: resolution: {integrity: sha512-N7FYnGh0DFsvDRkAPsvFq/metVfVD7P2h1rokOPpEH4cZbdRHCW+2jbXt0nnuqowkm/xhh2ww1anIdEpfYa7ZA==} dependencies: - '@babel/helper-module-imports': 7.24.6 + '@babel/helper-module-imports': 7.24.7 + transitivePeerDependencies: + - supports-color dev: false /babel-plugin-istanbul/5.2.0: resolution: {integrity: sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==} engines: {node: '>=6'} dependencies: - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 find-up: 3.0.0 istanbul-lib-instrument: 3.3.0 test-exclude: 5.2.3 @@ -4423,7 +4503,7 @@ packages: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} dependencies: - '@babel/helper-plugin-utils': 7.24.6 + '@babel/helper-plugin-utils': 7.24.7 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 5.2.1 @@ -4443,8 +4523,8 @@ packages: resolution: {integrity: sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==} engines: {node: '>= 10.14.2'} dependencies: - '@babel/template': 7.24.6 - '@babel/types': 7.24.6 + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 '@types/babel__core': 7.20.0 '@types/babel__traverse': 7.20.6 dev: true @@ -4454,7 +4534,7 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/compat-data': 7.24.6 + '@babel/compat-data': 7.24.7 '@babel/core': 7.20.12 '@babel/helper-define-polyfill-provider': 0.3.3_@babel+core@7.20.12 semver: 6.3.1 @@ -4669,15 +4749,15 @@ packages: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} dev: true - /browserslist/4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + /browserslist/4.23.1: + resolution: {integrity: sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001625 - electron-to-chromium: 1.4.787 + caniuse-lite: 1.0.30001632 + electron-to-chromium: 1.4.799 node-releases: 2.0.14 - update-browserslist-db: 1.0.16_browserslist@4.23.0 + update-browserslist-db: 1.0.16_browserslist@4.23.1 /bs-logger/0.2.6: resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} @@ -4806,14 +4886,14 @@ packages: /caniuse-api/3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} dependencies: - browserslist: 4.23.0 - caniuse-lite: 1.0.30001625 + browserslist: 4.23.1 + caniuse-lite: 1.0.30001632 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 dev: false - /caniuse-lite/1.0.30001625: - resolution: {integrity: sha512-4KE9N2gcRH+HQhpeiRZXd+1niLB/XNLAhSy4z7fI8EzcbcPoAqjNInxVHTiTwWfTIV4w096XG8OtCOCQQKPv3w==} + /caniuse-lite/1.0.30001632: + resolution: {integrity: sha512-udx3o7yHJfUxMLkGohMlVHCvFvWmirKh9JAH/d7WOLPetlH+LTL5cocMZ0t7oZx/mdlOWXti97xLZWc8uURRHg==} /capture-exit/2.0.0: resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==} @@ -4844,7 +4924,7 @@ packages: dependencies: assertion-error: 1.1.0 check-error: 1.0.3 - deep-eql: 4.1.3 + deep-eql: 4.1.4 get-func-name: 2.0.2 loupe: 2.3.7 pathval: 1.1.1 @@ -5267,7 +5347,7 @@ packages: /core-js-compat/3.37.1: resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==} dependencies: - browserslist: 4.23.0 + browserslist: 4.23.1 /core-util-is/1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -5652,8 +5732,8 @@ packages: type-detect: 4.0.8 dev: true - /deep-eql/4.1.3: - resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + /deep-eql/4.1.4: + resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} engines: {node: '>=6'} dependencies: type-detect: 4.0.8 @@ -5789,7 +5869,7 @@ packages: /dom-helpers/5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: - '@babel/runtime': 7.24.6 + '@babel/runtime': 7.24.7 csstype: 3.1.3 /dom-serializer/1.4.1: @@ -5883,8 +5963,8 @@ packages: safer-buffer: 2.1.2 dev: true - /electron-to-chromium/1.4.787: - resolution: {integrity: sha512-d0EFmtLPjctczO3LogReyM2pbBiiZbnsKnGF+cdZhsYzHm/A0GV7W94kqzLD8SN4O3f3iHlgLUChqghgyznvCQ==} + /electron-to-chromium/1.4.799: + resolution: {integrity: sha512-3D3DwWkRTzrdEpntY0hMLYwj7SeBk1138CkPE8sBDSj3WzrzOiG2rHm3luw8jucpf+WiyLBCZyU9lMHyQI9M9Q==} /electron/11.5.0: resolution: {integrity: sha512-WjNDd6lGpxyiNjE3LhnFCAk/D9GIj1rU3GSDealVShhkkkPR3Vh4q8ErXGDl1OAO/faomVa10KoFPUN/pLbNxg==} @@ -5927,8 +6007,8 @@ packages: dependencies: once: 1.4.0 - /enhanced-resolve/5.16.1: - resolution: {integrity: sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==} + /enhanced-resolve/5.17.0: + resolution: {integrity: sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==} engines: {node: '>=10.13.0'} dependencies: graceful-fs: 4.2.11 @@ -7076,7 +7156,7 @@ packages: /generic-names/4.0.0: resolution: {integrity: sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==} dependencies: - loader-utils: 3.2.2 + loader-utils: 3.3.1 dev: false /gensync/1.0.0-beta.2: @@ -7432,7 +7512,7 @@ packages: resolution: {integrity: sha512-SVSF7ikuWKhpAW4l4wapAqPPSToJoiNKsbDoUnRrSgwZHH7lH8pbPeQj1aOVYQrbZKhfSVBxVW+Py7vtulRktw==} engines: {node: '>=10'} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@types/vinyl': 2.0.7 istextorbinary: 3.3.0 replacestream: 4.0.3 @@ -8175,10 +8255,10 @@ packages: engines: {node: '>=6'} dependencies: '@babel/generator': 7.21.1 - '@babel/parser': 7.24.6 - '@babel/template': 7.24.6 - '@babel/traverse': 7.24.6 - '@babel/types': 7.24.6 + '@babel/parser': 7.24.7 + '@babel/template': 7.24.7 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 istanbul-lib-coverage: 2.0.5 semver: 6.3.1 transitivePeerDependencies: @@ -8202,7 +8282,7 @@ packages: engines: {node: '>=8'} dependencies: '@babel/core': 7.20.12 - '@babel/parser': 7.24.6 + '@babel/parser': 7.24.7 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -8333,7 +8413,7 @@ packages: jest-validate: 26.6.2 micromatch: 4.0.7 pretty-format: 26.6.2 - ts-node: 10.9.0_fqbesfk7w3q7dr5vwiwy56afhe + ts-node: 10.9.0_daz7tukh2qp4t5y5hskra5bsgy transitivePeerDependencies: - bufferutil - canvas @@ -8438,7 +8518,7 @@ packages: '@jest/environment': 26.6.2 '@jest/fake-timers': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 20.12.13 + '@types/node': 20.14.2 jest-mock: 26.6.2 jest-util: 26.6.2 jsdom: 16.7.0 @@ -8469,7 +8549,7 @@ packages: '@jest/environment': 26.6.2 '@jest/fake-timers': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 20.12.13 + '@types/node': 20.14.2 jest-mock: 26.6.2 jest-util: 26.6.2 dev: true @@ -8509,7 +8589,7 @@ packages: dependencies: '@jest/types': 26.6.2 '@types/graceful-fs': 4.1.9 - '@types/node': 20.12.13 + '@types/node': 20.14.2 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -8528,7 +8608,7 @@ packages: resolution: {integrity: sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==} engines: {node: '>= 6'} dependencies: - '@babel/traverse': 7.24.6 + '@babel/traverse': 7.24.7 '@jest/environment': 24.9.0 '@jest/test-result': 24.9.0 '@jest/types': 24.9.0 @@ -8552,12 +8632,12 @@ packages: resolution: {integrity: sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==} engines: {node: '>= 10.14.2'} dependencies: - '@babel/traverse': 7.24.6 + '@babel/traverse': 7.24.7 '@jest/environment': 26.6.2 '@jest/source-map': 26.6.2 '@jest/test-result': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 20.12.13 + '@types/node': 20.14.2 chalk: 4.1.2 co: 4.6.0 expect: 26.6.2 @@ -8618,7 +8698,7 @@ packages: resolution: {integrity: sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==} engines: {node: '>= 6'} dependencies: - '@babel/code-frame': 7.24.6 + '@babel/code-frame': 7.24.7 '@jest/test-result': 24.9.0 '@jest/types': 24.9.0 '@types/stack-utils': 1.0.1 @@ -8632,7 +8712,7 @@ packages: resolution: {integrity: sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==} engines: {node: '>= 10.14.2'} dependencies: - '@babel/code-frame': 7.24.6 + '@babel/code-frame': 7.24.7 '@jest/types': 26.6.2 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -8655,7 +8735,7 @@ packages: engines: {node: '>= 10.14.2'} dependencies: '@jest/types': 26.6.2 - '@types/node': 20.12.13 + '@types/node': 20.14.2 dev: true /jest-pnp-resolver/1.2.3_jest-resolve@24.9.0: @@ -8761,7 +8841,7 @@ packages: '@jest/environment': 26.6.2 '@jest/test-result': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 20.12.13 + '@types/node': 20.14.2 chalk: 4.1.2 emittery: 0.7.2 exit: 0.1.2 @@ -8772,7 +8852,7 @@ packages: jest-leak-detector: 26.6.2 jest-message-util: 26.6.2 jest-resolve: 26.6.2 - jest-runtime: 26.6.3_ts-node@10.9.0 + jest-runtime: 26.6.3 jest-util: 26.6.2 jest-worker: 26.6.2 source-map-support: 0.5.21 @@ -8817,6 +8897,42 @@ packages: - supports-color dev: true + /jest-runtime/26.6.3: + resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==} + engines: {node: '>= 10.14.2'} + hasBin: true + dependencies: + '@jest/console': 26.6.2 + '@jest/environment': 26.6.2 + '@jest/fake-timers': 26.6.2 + '@jest/globals': 26.6.2 + '@jest/source-map': 26.6.2 + '@jest/test-result': 26.6.2 + '@jest/transform': 26.6.2 + '@jest/types': 26.6.2 + '@types/yargs': 15.0.19 + chalk: 4.1.2 + cjs-module-lexer: 0.6.0 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-config: 26.6.3_ts-node@10.9.0 + jest-haste-map: 26.6.2 + jest-message-util: 26.6.2 + jest-mock: 26.6.2 + jest-regex-util: 26.0.0 + jest-resolve: 26.6.2 + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + jest-validate: 26.6.2 + slash: 3.0.0 + strip-bom: 4.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - supports-color + dev: true + /jest-runtime/26.6.3_ts-node@10.9.0: resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==} engines: {node: '>= 10.14.2'} @@ -8866,7 +8982,7 @@ packages: resolution: {integrity: sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==} engines: {node: '>= 10.14.2'} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 graceful-fs: 4.2.11 dev: true @@ -8874,7 +8990,7 @@ packages: resolution: {integrity: sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==} engines: {node: '>= 6'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.7 '@jest/types': 24.9.0 chalk: 2.4.2 expect: 24.9.0 @@ -8893,7 +9009,7 @@ packages: resolution: {integrity: sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==} engines: {node: '>= 10.14.2'} dependencies: - '@babel/types': 7.24.6 + '@babel/types': 7.24.7 '@jest/types': 26.6.2 '@types/babel__traverse': 7.20.6 '@types/prettier': 2.7.3 @@ -8938,7 +9054,7 @@ packages: engines: {node: '>= 10.14.2'} dependencies: '@jest/types': 26.6.2 - '@types/node': 20.12.13 + '@types/node': 20.14.2 chalk: 4.1.2 graceful-fs: 4.2.11 is-ci: 2.0.0 @@ -8975,7 +9091,7 @@ packages: dependencies: '@jest/test-result': 26.6.2 '@jest/types': 26.6.2 - '@types/node': 20.12.13 + '@types/node': 20.14.2 ansi-escapes: 4.3.2 chalk: 4.1.2 jest-util: 26.6.2 @@ -8994,7 +9110,7 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 merge-stream: 2.0.0 supports-color: 7.2.0 dev: true @@ -9436,8 +9552,8 @@ packages: strip-bom: 3.0.0 dev: true - /loader-utils/3.2.2: - resolution: {integrity: sha512-vjJi4vQDasD8t0kMpxe+9URAcgbSuASqoj/Wuk3MawTk97LYa2KfdHreAkd1G/pmPLMvzZEw7/OsydADNemerQ==} + /loader-utils/3.3.1: + resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} engines: {node: '>= 12.13.0'} dev: false @@ -9739,7 +9855,7 @@ packages: is-promise: 2.2.2 lru-queue: 0.1.0 next-tick: 1.1.0 - timers-ext: 0.1.7 + timers-ext: 0.1.8 dev: false /merge-stream/2.0.0: @@ -9852,8 +9968,8 @@ packages: hasBin: true dev: true - /mlly/1.7.0: - resolution: {integrity: sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==} + /mlly/1.7.1: + resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} dependencies: acorn: 8.11.3 pathe: 1.1.2 @@ -10363,7 +10479,7 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.24.6 + '@babel/code-frame': 7.24.7 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -10566,7 +10682,7 @@ packages: resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==} dependencies: confbox: 0.1.7 - mlly: 1.7.0 + mlly: 1.7.1 pathe: 1.1.2 dev: true @@ -10635,7 +10751,7 @@ packages: peerDependencies: postcss: ^8.2.15 dependencies: - browserslist: 4.23.0 + browserslist: 4.23.1 caniuse-api: 3.0.0 colord: 2.9.3 postcss: 8.4.21 @@ -10648,7 +10764,7 @@ packages: peerDependencies: postcss: ^8.2.15 dependencies: - browserslist: 4.23.0 + browserslist: 4.23.1 postcss: 8.4.21 postcss-value-parser: 4.2.0 dev: false @@ -10703,7 +10819,7 @@ packages: dependencies: lilconfig: 2.1.0 postcss: 8.4.21 - ts-node: 10.9.0_fqbesfk7w3q7dr5vwiwy56afhe + ts-node: 10.9.0_daz7tukh2qp4t5y5hskra5bsgy yaml: 1.10.2 dev: false @@ -10724,7 +10840,7 @@ packages: peerDependencies: postcss: ^8.2.15 dependencies: - browserslist: 4.23.0 + browserslist: 4.23.1 caniuse-api: 3.0.0 cssnano-utils: 3.1.0_postcss@8.4.21 postcss: 8.4.21 @@ -10759,7 +10875,7 @@ packages: peerDependencies: postcss: ^8.2.15 dependencies: - browserslist: 4.23.0 + browserslist: 4.23.1 cssnano-utils: 3.1.0_postcss@8.4.21 postcss: 8.4.21 postcss-value-parser: 4.2.0 @@ -10897,7 +11013,7 @@ packages: peerDependencies: postcss: ^8.2.15 dependencies: - browserslist: 4.23.0 + browserslist: 4.23.1 postcss: 8.4.21 postcss-value-parser: 4.2.0 dev: false @@ -10940,7 +11056,7 @@ packages: peerDependencies: postcss: ^8.2.15 dependencies: - browserslist: 4.23.0 + browserslist: 4.23.1 caniuse-api: 3.0.0 postcss: 8.4.21 dev: false @@ -11160,7 +11276,7 @@ packages: peerDependencies: react: ^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 dependencies: - '@babel/runtime': 7.24.6 + '@babel/runtime': 7.24.7 react: 18.3.1 /react-device-detect/2.2.3: @@ -11190,7 +11306,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.24.6 + '@babel/runtime': 7.24.7 '@types/react': 18.3.3 focus-lock: 1.3.5 prop-types: 15.8.1 @@ -11243,7 +11359,7 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' dependencies: - '@babel/runtime': 7.24.6 + '@babel/runtime': 7.24.7 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -11394,7 +11510,7 @@ packages: /regenerator-transform/0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} dependencies: - '@babel/runtime': 7.24.6 + '@babel/runtime': 7.24.7 /regex-not/1.0.2: resolution: {integrity: sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==} @@ -12434,7 +12550,7 @@ packages: peerDependencies: postcss: ^8.2.15 dependencies: - browserslist: 4.23.0 + browserslist: 4.23.1 postcss: 8.4.21 postcss-selector-parser: 6.1.0 dev: false @@ -12644,8 +12760,9 @@ packages: engines: {node: '>=4'} dev: true - /timers-ext/0.1.7: - resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} + /timers-ext/0.1.8: + resolution: {integrity: sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==} + engines: {node: '>=0.12'} dependencies: es5-ext: 0.10.64 next-tick: 1.1.0 @@ -12807,13 +12924,13 @@ packages: webpack: ^5.0.0 dependencies: chalk: 4.1.2 - enhanced-resolve: 5.16.1 + enhanced-resolve: 5.17.0 micromatch: 4.0.7 semver: 7.3.4 typescript: 4.9.5 dev: true - /ts-node/10.9.0_fqbesfk7w3q7dr5vwiwy56afhe: + /ts-node/10.9.0_daz7tukh2qp4t5y5hskra5bsgy: resolution: {integrity: sha512-bunW18GUyaCSYRev4DPf4SQpom3pWH29wKl0sDk5zE7ze19RImEVhCW7K4v3hHKkUyfWotU08ToE2RS+Y49aug==} hasBin: true peerDependencies: @@ -12832,7 +12949,7 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.12.13 + '@types/node': 20.14.2 acorn: 8.11.3 acorn-walk: 8.3.2 arg: 4.1.3 @@ -12898,7 +13015,7 @@ packages: typescript: '>=3.2.2' dependencies: resolve: 1.22.8 - ts-node: 10.9.0_fqbesfk7w3q7dr5vwiwy56afhe + ts-node: 10.9.0_daz7tukh2qp4t5y5hskra5bsgy typescript: 4.9.5 dev: true @@ -13178,13 +13295,13 @@ packages: engines: {node: '>=4'} dev: false - /update-browserslist-db/1.0.16_browserslist@4.23.0: + /update-browserslist-db/1.0.16_browserslist@4.23.1: resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' dependencies: - browserslist: 4.23.0 + browserslist: 4.23.1 escalade: 3.1.2 picocolors: 1.0.1 @@ -13359,17 +13476,17 @@ packages: replace-ext: 1.0.1 dev: false - /vite-node/0.30.1_ziymnatjnofve2smmqi3qfq7zi: + /vite-node/0.30.1_sn22vl5x6mzjctzzzuetizlf74: resolution: {integrity: sha512-vTikpU/J7e6LU/8iM3dzBo8ZhEiKZEKRznEMm+mJh95XhWaPrJQraT/QsT2NWmuEf+zgAoMe64PKT7hfZ1Njmg==} engines: {node: '>=v14.18.0'} hasBin: true dependencies: cac: 6.7.14 debug: 4.3.4 - mlly: 1.7.0 + mlly: 1.7.1 pathe: 1.1.2 picocolors: 1.0.1 - vite: 3.2.6_ziymnatjnofve2smmqi3qfq7zi + vite: 3.2.6_sn22vl5x6mzjctzzzuetizlf74 transitivePeerDependencies: - '@types/node' - less @@ -13389,7 +13506,7 @@ packages: front-matter: 4.0.2 htmlparser2: 6.1.0 markdown-it: 12.3.2 - vite: 3.2.6_wo5djetj4deayu5nkog2244prm + vite: 3.2.6_q2pn2u5afkvbgyxa6yhm66etea dev: true /vite/3.2.6: @@ -13425,7 +13542,7 @@ packages: fsevents: 2.3.3 dev: true - /vite/3.2.6_@types+node@20.12.13: + /vite/3.2.6_@types+node@20.14.2: resolution: {integrity: sha512-nTXTxYVvaQNLoW5BQ8PNNQ3lPia57gzsQU/Khv+JvzKPku8kNZL6NMUR/qwXhMG6E+g1idqEPanomJ+VZgixEg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -13450,7 +13567,7 @@ packages: terser: optional: true dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 esbuild: 0.15.18 postcss: 8.4.21 resolve: 1.22.8 @@ -13459,7 +13576,7 @@ packages: fsevents: 2.3.3 dev: true - /vite/3.2.6_wo5djetj4deayu5nkog2244prm: + /vite/3.2.6_q2pn2u5afkvbgyxa6yhm66etea: resolution: {integrity: sha512-nTXTxYVvaQNLoW5BQ8PNNQ3lPia57gzsQU/Khv+JvzKPku8kNZL6NMUR/qwXhMG6E+g1idqEPanomJ+VZgixEg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -13484,7 +13601,7 @@ packages: terser: optional: true dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 esbuild: 0.15.18 postcss: 8.4.21 resolve: 1.22.8 @@ -13494,7 +13611,7 @@ packages: fsevents: 2.3.3 dev: true - /vite/3.2.6_ziymnatjnofve2smmqi3qfq7zi: + /vite/3.2.6_sn22vl5x6mzjctzzzuetizlf74: resolution: {integrity: sha512-nTXTxYVvaQNLoW5BQ8PNNQ3lPia57gzsQU/Khv+JvzKPku8kNZL6NMUR/qwXhMG6E+g1idqEPanomJ+VZgixEg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -13519,7 +13636,7 @@ packages: terser: optional: true dependencies: - '@types/node': 20.12.13 + '@types/node': 20.14.2 esbuild: 0.15.18 less: 4.1.3 postcss: 8.4.21 @@ -13563,7 +13680,7 @@ packages: dependencies: '@types/chai': 4.3.16 '@types/chai-subset': 1.3.5 - '@types/node': 20.12.13 + '@types/node': 20.14.2 '@vitest/expect': 0.30.1 '@vitest/runner': 0.30.1 '@vitest/snapshot': 0.30.1 @@ -13584,8 +13701,8 @@ packages: strip-literal: 1.3.0 tinybench: 2.8.0 tinypool: 0.4.0 - vite: 3.2.6_ziymnatjnofve2smmqi3qfq7zi - vite-node: 0.30.1_ziymnatjnofve2smmqi3qfq7zi + vite: 3.2.6_sn22vl5x6mzjctzzzuetizlf74 + vite-node: 0.30.1_sn22vl5x6mzjctzzzuetizlf74 why-is-node-running: 2.2.2 transitivePeerDependencies: - less diff --git a/packages/vtable/package.json b/packages/vtable/package.json index 82c321fc8..7b8292213 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -50,9 +50,9 @@ }, "dependencies": { "@visactor/vtable-editors": "workspace:*", - "@visactor/vrender-core": "0.19.10-beta.1", - "@visactor/vrender-kits": "0.19.10-beta.1", - "@visactor/vrender-components": "0.19.10-beta.1", + "@visactor/vrender-core": "0.19.9", + "@visactor/vrender-kits": "0.19.9", + "@visactor/vrender-components": "0.19.9", "@visactor/vutils": "~0.18.9", "@visactor/vscale": "~0.18.1", "@visactor/vdataset": "~0.18.1", @@ -123,4 +123,4 @@ "url": "https://github.com/VisActor/VTable.git", "directory": "packages/vtable" } -} +} \ No newline at end of file From 768b1c1b6bdfb8810b338aec92db7517d9bcdbec Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 12 Jun 2024 16:24:35 +0800 Subject: [PATCH 13/85] refactor: tooltip support scroll #1887 --- .../vtable/examples/icon/icon-register.ts | 13 ++++++++--- .../vtable/examples/interactive/tooltip.ts | 9 ++++++-- .../src/components/tooltip/TooltipHandler.ts | 2 +- .../tooltip/logic/BubbleTooltipElement.ts | 10 ++++++++- .../logic/BubbleTooltipElementStyle.ts | 22 +++++++++++++++++-- packages/vtable/src/themes/theme.ts | 6 +++++ packages/vtable/src/ts-types/icon.ts | 2 ++ packages/vtable/src/ts-types/theme.ts | 2 ++ packages/vtable/src/ts-types/tooltip.ts | 2 ++ 9 files changed, 59 insertions(+), 9 deletions(-) diff --git a/packages/vtable/examples/icon/icon-register.ts b/packages/vtable/examples/icon/icon-register.ts index 6b3b26e03..66e9344ec 100644 --- a/packages/vtable/examples/icon/icon-register.ts +++ b/packages/vtable/examples/icon/icon-register.ts @@ -88,8 +88,9 @@ export function createTable() { `, tooltip: { // 气泡框,按钮的的解释信息 - title: '更多操作', - style: { bgColor: 'black', arrowMark: true, color: 'white' }, + title: + '更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作更多操作操作 更多操作更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作更多操作', + style: { bgColor: 'black', arrowMark: true, color: 'white', maxHeight: 100, maxWidth: 100 }, disappearDelay: 100 } }); @@ -396,7 +397,8 @@ export function createTable() { return `这是第${rec.id}号`; }, title: 'ID说明', - description: '这是一个ID详细描述', + description: `这是一个ID详细描述\n这是一个ID详细描述 +这是一个ID详细描述`, sort: (v1, v2, order) => { if (order === 'desc') { return v1 === v2 ? 0 : v1 > v2 ? -1 : 1; @@ -430,6 +432,11 @@ export function createTable() { title: { text: 'title', orient: 'top' + }, + theme: { + tooltipStyle: { + maxWidth: 200 + } } }; diff --git a/packages/vtable/examples/interactive/tooltip.ts b/packages/vtable/examples/interactive/tooltip.ts index dad3b4334..5c7518d7e 100644 --- a/packages/vtable/examples/interactive/tooltip.ts +++ b/packages/vtable/examples/interactive/tooltip.ts @@ -39,7 +39,11 @@ export function createTable() { return `已完成${rec.progress}%`; }, title: 'progress', - description: '这是一个标题的详细描述', + description: `这是一个标题的详细描述,这是一个标题的详细描述, +这是一个标题的详细描述,这是一个标题的详细描述,这是一个标题的详细描述,这是一个标题的详细描述, +这是一个标题的详细描述,这是一个标题的详细描述, 这是一个标题的详细描述,这是一个标题的详细描述, +这是一个标题的详细描述,这是一个标题的详细描述,这是一个标题的详细描述,这是一个标题的详细描述, +这是一个标题的详细描述,这是一个标题的详细描述`, width: 150, showSort: true //显示VTable内置排序图标 }, @@ -86,7 +90,8 @@ export function createTable() { allowFrozenColCount: 2, tooltip: { renderMode: 'html', - isShowOverflowTextTooltip: true + isShowOverflowTextTooltip: true, + overflowTextTooltipDisappearDelay: 1000 } }; diff --git a/packages/vtable/src/components/tooltip/TooltipHandler.ts b/packages/vtable/src/components/tooltip/TooltipHandler.ts index a8fad7a12..89afbf690 100644 --- a/packages/vtable/src/components/tooltip/TooltipHandler.ts +++ b/packages/vtable/src/components/tooltip/TooltipHandler.ts @@ -196,7 +196,7 @@ export class TooltipHandler { rect }, disappearDelay: table.internalProps.tooltip.overflowTextTooltipDisappearDelay ?? 0, - style: { arrowMark: false } + style: table.theme.tooltipStyle }; } else if (table.internalProps.tooltip?.isShowOverflowTextTooltip) { const overflowText = table.getCellOverflowText(col, row); diff --git a/packages/vtable/src/components/tooltip/logic/BubbleTooltipElement.ts b/packages/vtable/src/components/tooltip/logic/BubbleTooltipElement.ts index 78347df46..bcaeff0c7 100644 --- a/packages/vtable/src/components/tooltip/logic/BubbleTooltipElement.ts +++ b/packages/vtable/src/components/tooltip/logic/BubbleTooltipElement.ts @@ -23,7 +23,7 @@ export class BubbleTooltipElement { constructor() { this._handler = new EventHandler(); const rootElement = (this._rootElement = createElement('div', [TOOLTIP_CLASS, HIDDEN_CLASS])); - const messageElement = createElement('span', [CONTENT_CLASS]); + const messageElement = createElement('div', [CONTENT_CLASS]); const triangle = createElement('span', [TRIANGLE_CLASS]); rootElement.appendChild(triangle); rootElement.appendChild(messageElement); @@ -37,6 +37,10 @@ export class BubbleTooltipElement { this._disappearDelay = undefined; this.unbindFromCell(); }); + + messageElement.addEventListener('wheel', e => { + e.stopPropagation(); + }); } bindToCell( table: BaseTableAPI, @@ -69,6 +73,10 @@ export class BubbleTooltipElement { tooltipInstanceInfo?.style?.color && (messageElement.style.color = tooltipInstanceInfo?.style?.color); tooltipInstanceInfo?.style?.padding && (messageElement.style.padding = `${tooltipInstanceInfo?.style?.padding.join('px ')}px`); + tooltipInstanceInfo?.style?.maxHeight && + (messageElement.style.maxHeight = `${tooltipInstanceInfo?.style?.maxHeight}px`); + tooltipInstanceInfo?.style?.maxWidth && + (messageElement.style.maxWidth = `${tooltipInstanceInfo?.style?.maxWidth}px`); messageElement && (messageElement.textContent = tooltipInstanceInfo?.content); const binded = this._bindToCell( table, diff --git a/packages/vtable/src/components/tooltip/logic/BubbleTooltipElementStyle.ts b/packages/vtable/src/components/tooltip/logic/BubbleTooltipElementStyle.ts index 8fcc67685..dc4f3d1a0 100644 --- a/packages/vtable/src/components/tooltip/logic/BubbleTooltipElementStyle.ts +++ b/packages/vtable/src/components/tooltip/logic/BubbleTooltipElementStyle.ts @@ -53,12 +53,30 @@ export function importStyle() { white-space: pre-wrap; margin: 0; box-sizing: border-box; - overflow: hidden; + overflow: auto; word-wrap: break-word; position: relative; background-color: #FFF; z-index: 2; - border-radius: 4px + border-radius: 4px; +} +/* WebKit Microsoft Edge(新版): */ +.vtable__bubble-tooltip-element__content::-webkit-scrollbar { + width: 0; + height: 0; + background-color: transparent; +} +/* Opera Firefox */ +.vtable__bubble-tooltip-element__content > scrollbar-track { + width: 0; + height: 0; + background-color: transparent; +} +/* Internet Explorer 11 和 Microsoft Edge(旧版) */ +.vtable__bubble-tooltip-element__content > scrollbar { + width: 0; + height: 0; + background-color: transparent; } .vtable__bubble-tooltip-element__triangle { /* font-size: .75rem; */ diff --git a/packages/vtable/src/themes/theme.ts b/packages/vtable/src/themes/theme.ts index cf9447610..3e6a3899f 100644 --- a/packages/vtable/src/themes/theme.ts +++ b/packages/vtable/src/themes/theme.ts @@ -493,6 +493,12 @@ export class TableTheme implements ITableThemeDefine { }, get color(): string | undefined { return tooltip.color ?? '#FFF'; + }, + get maxWidth(): number | undefined { + return tooltip.maxWidth; + }, + get maxHeight(): number | undefined { + return tooltip.maxHeight; } }; } diff --git a/packages/vtable/src/ts-types/icon.ts b/packages/vtable/src/ts-types/icon.ts index 7d1125225..26c289dee 100644 --- a/packages/vtable/src/ts-types/icon.ts +++ b/packages/vtable/src/ts-types/icon.ts @@ -63,6 +63,8 @@ export interface IIconBase { padding?: number[]; bgColor?: string; arrowMark?: boolean; + maxWidth?: number; + maxHeight?: number; }; disappearDelay?: number; }; diff --git a/packages/vtable/src/ts-types/theme.ts b/packages/vtable/src/ts-types/theme.ts index 069debd44..7579e0a78 100644 --- a/packages/vtable/src/ts-types/theme.ts +++ b/packages/vtable/src/ts-types/theme.ts @@ -73,6 +73,8 @@ export type TooltipStyle = { color?: string; padding?: number[]; bgColor?: string; + maxWidth?: number; + maxHeight?: number; /** !目前未实现该逻辑。触发行为:hover or click */ // trigger?: string | string[]; /**气泡框位置,可选 top left right bottom */ diff --git a/packages/vtable/src/ts-types/tooltip.ts b/packages/vtable/src/ts-types/tooltip.ts index 09382ded2..12ff04e68 100644 --- a/packages/vtable/src/ts-types/tooltip.ts +++ b/packages/vtable/src/ts-types/tooltip.ts @@ -26,6 +26,8 @@ export type TooltipOptions = { color?: string; padding?: number[]; arrowMark?: boolean; + maxWidth?: number; + maxHeight?: number; }; /** 设置tooltip的消失时间 */ disappearDelay?: number; From 40bfaed4bb385caa0f28d4dd028c7a46b08cbc39 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 12 Jun 2024 16:25:00 +0800 Subject: [PATCH 14/85] docs: update changlog of rush --- ...1887-refactor-tooltip-scroll_2024-06-12-08-25.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/1887-refactor-tooltip-scroll_2024-06-12-08-25.json diff --git a/common/changes/@visactor/vtable/1887-refactor-tooltip-scroll_2024-06-12-08-25.json b/common/changes/@visactor/vtable/1887-refactor-tooltip-scroll_2024-06-12-08-25.json new file mode 100644 index 000000000..b64c46845 --- /dev/null +++ b/common/changes/@visactor/vtable/1887-refactor-tooltip-scroll_2024-06-12-08-25.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "refactor: tooltip support scroll #1887\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From eb48b87362374fa371cc3263d25da24ed278f508 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 12 Jun 2024 17:24:34 +0800 Subject: [PATCH 15/85] docs: supplement tooltip tutorial about maxWidth maxHeight --- docs/assets/demo/en/component/tooltip.md | 72 ++++++++++++++++++---- docs/assets/demo/zh/component/tooltip.md | 70 +++++++++++++++++---- docs/assets/guide/en/components/tooltip.md | 42 +++++++++++++ docs/assets/guide/zh/components/tooltip.md | 42 +++++++++++++ docs/assets/option/en/icon/base-icon.md | 6 ++ docs/assets/option/zh/icon/base-icon.md | 6 ++ 6 files changed, 212 insertions(+), 26 deletions(-) diff --git a/docs/assets/demo/en/component/tooltip.md b/docs/assets/demo/en/component/tooltip.md index 7fae854cd..a2f5c0133 100644 --- a/docs/assets/demo/en/component/tooltip.md +++ b/docs/assets/demo/en/component/tooltip.md @@ -9,8 +9,17 @@ option: ListTable#tooltip.isShowOverflowTextTooltip # Tooltip -In this example, tooltip.isShowOverflowTextTooltip is configured to be true, and it will be prompted when the text that cannot be omitted is hover. -At the same time through monitoring`mouseenter_cell`Event, when the mouse moves into the cell that meets the prompt condition \[first column order number], the interface showTooltip is called to display the prompt information. +This example shows tooltips for four scenarios. + +1. Set `tooltip.isShowOverflowTextTooltip` to `true` to enable overflow text prompts. When hovering over the text that is too long to be displayed, the text will be displayed. In this example, the text in the cells of the `Product Name` column is omitted, and you can hover over the cell to see the prompt information. + +2. The description information of the table header is displayed by configuring `description`. + +3. This example also shows how to actively display the tooltip through the interface. By listening to the `mouseenter_cell` event, when the mouse moves into the cell of the first column of order numbers, the interface `showTooltip` is called to display the prompt information. + +4. Customize the prompt information of the icon, configure `headerIcon` in the `orderId` column to `order`, and configure `tooltip` in the configuration of the icon `order` to display the prompt information. + +The prompt information supports hovering to select and copy. When there is too much content, the maximum width and height can be configured for scrolling interaction. ## Key Configurations @@ -20,7 +29,31 @@ At the same time through monitoring`mouseenter_cell`Event, when the mouse moves ## Code demo +## 代码演示 + ```javascript livedemo template=vtable +VTable.register.icon('order', { + type: 'svg', + svg: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/order.svg', + width: 22, + height: 22, + name: 'order', + positionType: VTable.TYPES.IconPosition.right, + marginRight: 0, + hover: { + width: 22, + height: 22, + bgColor: 'rgba(101, 117, 168, 0.1)' + }, + tooltip: { + // 气泡框,按钮的的解释信息 + title: + 'Order ID is the unique identifier for each order.\n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique', + style: { bgColor: 'black', arrowMark: true, color: 'white', maxHeight: 100, maxWidth: 200 }, + disappearDelay: 100 + }, + cursor: 'pointer' +}); let tableInstance; fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_data.json') .then(res => res.json()) @@ -29,57 +62,70 @@ fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American { field: 'Order ID', title: 'Order ID', - width: 'auto' + width: 'auto', + headerIcon: 'order', + description: 'Order ID is the unique identifier for each order.\n It is a unique identifier for each order.' }, { field: 'Customer ID', title: 'Customer ID', - width: 'auto' + width: 'auto', + description: + 'Customer ID is the unique identifier for each customer.\n It is a unique identifier for each customer.' }, { field: 'Product Name', title: 'Product Name', - width: '200' + width: '200', + description: 'Product Name is the name of the product.' }, { field: 'Category', title: 'Category', - width: 'auto' + width: 'auto', + description: 'Category is the category of the product.' }, { field: 'Sub-Category', title: 'Sub-Category', - width: 'auto' + width: 'auto', + description: 'Sub-Category is the sub-category of the product.' }, { field: 'Region', title: 'Region', - width: 'auto' + width: 'auto', + description: 'Region is the region of the order produced.' }, { field: 'City', title: 'City', - width: 'auto' + width: 'auto', + description: 'City is the city of the order produced.' }, { field: 'Order Date', title: 'Order Date', - width: 'auto' + width: 'auto', + description: 'Order Date is the date of the order produced.' }, { field: 'Quantity', title: 'Quantity', - width: 'auto' + width: 'auto', + description: 'Quantity is the quantity of the order.' }, { field: 'Sales', title: 'Sales', - width: 'auto' + width: 'auto', + description: 'Sales is the sales of the order.' }, { field: 'Profit', title: 'Profit', - width: 'auto' + width: 'auto', + description: 'Profit is the profit of the order.' } ]; diff --git a/docs/assets/demo/zh/component/tooltip.md b/docs/assets/demo/zh/component/tooltip.md index fab704b21..b058a9120 100644 --- a/docs/assets/demo/zh/component/tooltip.md +++ b/docs/assets/demo/zh/component/tooltip.md @@ -9,8 +9,17 @@ option: ListTable#tooltip.isShowOverflowTextTooltip # tooltip -在该示例中,配置了 tooltip.isShowOverflowTextTooltip 为 true,超长显示不了被省略的文字被 hover 时将提示出来。 -同时通过监听`mouseenter_cell`事件,鼠标移入符合提示条件【第一列订单号】的单元格时,调用接口 showTooltip 来显示提示信息。 +在该示例中,展示了四种场景的 tooltip 提示。 + +1. 配置了 `tooltip.isShowOverflowTextTooltip` 为 `true` 开启溢出文字提示,超长显示不了被省略的文字被 hover 时将提示出来。该示例 `Product Name`列中的单元格文本有被省略,可以 hover 到单元格上出现提示信息。 + +2. 表头的描述信息,通过配置 `description` 来显示提示信息。 + +3. 在该示例也展示了通过接口主动显示 tooltip 的用法。通过监听`mouseenter_cell`事件,鼠标移入第一列订单号的单元格时,调用接口 `showTooltip` 来显示提示信息。 + +4. 自定义 icon 的提示信息,`orderId` 列配置 `headerIcon` 为`order`, 图标`order`的配置中配置了 `tooltip` 来显示提示信息。 + +提示信息支持 hover 上去进行选中复制,当内容过多时可以配置最大宽高可进行滚动交互 ## 关键配置 @@ -21,6 +30,28 @@ option: ListTable#tooltip.isShowOverflowTextTooltip ## 代码演示 ```javascript livedemo template=vtable +VTable.register.icon('order', { + type: 'svg', + svg: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/order.svg', + width: 22, + height: 22, + name: 'order', + positionType: VTable.TYPES.IconPosition.right, + marginRight: 0, + hover: { + width: 22, + height: 22, + bgColor: 'rgba(101, 117, 168, 0.1)' + }, + tooltip: { + // 气泡框,按钮的的解释信息 + title: + 'Order ID is the unique identifier for each order.\n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique identifier for each order. \n It is a unique', + style: { bgColor: 'black', arrowMark: true, color: 'white', maxHeight: 100, maxWidth: 200 }, + disappearDelay: 100 + }, + cursor: 'pointer' +}); let tableInstance; fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_data.json') .then(res => res.json()) @@ -29,57 +60,70 @@ fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American { field: 'Order ID', title: 'Order ID', - width: 'auto' + width: 'auto', + headerIcon: 'order', + description: 'Order ID is the unique identifier for each order.\n It is a unique identifier for each order.' }, { field: 'Customer ID', title: 'Customer ID', - width: 'auto' + width: 'auto', + description: + 'Customer ID is the unique identifier for each customer.\n It is a unique identifier for each customer.' }, { field: 'Product Name', title: 'Product Name', - width: '200' + width: '200', + description: 'Product Name is the name of the product.' }, { field: 'Category', title: 'Category', - width: 'auto' + width: 'auto', + description: 'Category is the category of the product.' }, { field: 'Sub-Category', title: 'Sub-Category', - width: 'auto' + width: 'auto', + description: 'Sub-Category is the sub-category of the product.' }, { field: 'Region', title: 'Region', - width: 'auto' + width: 'auto', + description: 'Region is the region of the order produced.' }, { field: 'City', title: 'City', - width: 'auto' + width: 'auto', + description: 'City is the city of the order produced.' }, { field: 'Order Date', title: 'Order Date', - width: 'auto' + width: 'auto', + description: 'Order Date is the date of the order produced.' }, { field: 'Quantity', title: 'Quantity', - width: 'auto' + width: 'auto', + description: 'Quantity is the quantity of the order.' }, { field: 'Sales', title: 'Sales', - width: 'auto' + width: 'auto', + description: 'Sales is the sales of the order.' }, { field: 'Profit', title: 'Profit', - width: 'auto' + width: 'auto', + description: 'Profit is the profit of the order.' } ]; diff --git a/docs/assets/guide/en/components/tooltip.md b/docs/assets/guide/en/components/tooltip.md index 3024a0c67..19b94f7bf 100644 --- a/docs/assets/guide/en/components/tooltip.md +++ b/docs/assets/guide/en/components/tooltip.md @@ -26,6 +26,23 @@ The configuration items are: }; } +## Tooltip prompt box style settings + +The style configuration of tooltip can be set through theme.tooltipStyle. The specific configuration is as follows: + +``` +export type TooltipStyle = { + fontFamily?: string; + fontSize?: number; + color?: string; + padding?: number[]; + bgColor?: string; + maxWidth?: number; + maxHeight?: number; +}; + +``` + ## Enable overflow content prompt By default, VTable enables the tooltip of overflow content: isShowOverflowTextTooltip defaults to true. If you need to delay disappearance so that the mouse can move to the tooltip content, you can configure overflowTextTooltipDisappearDelay. @@ -100,3 +117,28 @@ The interface showTooltip can actively display tooltip information, which is use Effect: ![image](https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/ffc3a9b5518762d274121ff05.gif) + +## Icon tooltip configuration + +When customizing the icon, you can display the prompt information by configuring the tooltip as follows: + +``` +VTable.register.icon('order', { + ... //其他配置 + tooltip: { + // 气泡框,按钮的的解释信息 + title:'Order ID is the unique identifier for each order', + style: { + fontSize: 14, + fontFamily: 'Arial', + padding: [10,10,10,10], + bgColor: 'black', + arrowMark: true, + color: 'white', + maxHeight: 100, + maxWidth: 200 + }, + disappearDelay: 1000 + } +}) +``` diff --git a/docs/assets/guide/zh/components/tooltip.md b/docs/assets/guide/zh/components/tooltip.md index 494388a24..0c5a7a881 100644 --- a/docs/assets/guide/zh/components/tooltip.md +++ b/docs/assets/guide/zh/components/tooltip.md @@ -30,6 +30,23 @@ } ``` +## tooltip 提示框的样式设置 + +tooltip 的样式配置可以通过 theme.tooltipStyle 来进行设置,具体配置如下: + +``` +export type TooltipStyle = { + fontFamily?: string; + fontSize?: number; + color?: string; + padding?: number[]; + bgColor?: string; + maxWidth?: number; + maxHeight?: number; +}; + +``` + ## 开启溢出内容提示 VTable 默认开启溢出内容的 tooltip:isShowOverflowTextTooltip 默认为 true。如果需要延迟消失以使得鼠标可以移动到 tooltip 内容上,可以配置 overflowTextTooltipDisappearDelay。 @@ -106,3 +123,28 @@ const tableInstance = new VTable.ListTable({ 效果: ![image](https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/ffc3a9b5518762d274121ff05.gif) + +## icon 的 tooltip 配置 + +当自定义 icon 时,可以通过配置 tooltip 来显示提示信息,如下使用方式: + +``` +VTable.register.icon('order', { + ... //其他配置 + tooltip: { + // 气泡框,按钮的的解释信息 + title:'Order ID is the unique identifier for each order', + style: { + fontSize: 14, + fontFamily: 'Arial', + padding: [10,10,10,10], + bgColor: 'black', + arrowMark: true, + color: 'white', + maxHeight: 100, + maxWidth: 200 + }, + disappearDelay: 1000 + } +}) +``` diff --git a/docs/assets/option/en/icon/base-icon.md b/docs/assets/option/en/icon/base-icon.md index 76745f379..264337e4e 100644 --- a/docs/assets/option/en/icon/base-icon.md +++ b/docs/assets/option/en/icon/base-icon.md @@ -133,5 +133,11 @@ Tooltip background color. ##${prefix} arrowMark (boolean) Whether the tooltip displays an arrow. +##${prefix} maxWidth (number) +The maximum width of the tooltip. + +##${prefix} maxHeight (number) +The maximum height of the tooltip. + ${prefix} interactive (boolean) Whether it is interactive, default is true. Currently known non-interactive buttons are dropdown menu states. diff --git a/docs/assets/option/zh/icon/base-icon.md b/docs/assets/option/zh/icon/base-icon.md index b01e8adc2..6087535c0 100644 --- a/docs/assets/option/zh/icon/base-icon.md +++ b/docs/assets/option/zh/icon/base-icon.md @@ -133,5 +133,11 @@ Placement 枚举类型定义: ##${prefix} arrowMark (boolean) 气泡框是否显示箭头。 +##${prefix} maxWidth (number) +tooltip 的最大宽度。 + +##${prefix} maxHeight (number) +tooltip 的最大高度。 + ${prefix} interactive (boolean) 是否可交互,默认为 true。目前已知不可交互按钮为下拉菜单状态。 From 123a2f5b07cba0dc6aaead6e41e70bab8b6236ed Mon Sep 17 00:00:00 2001 From: nikoohp Date: Thu, 13 Jun 2024 16:33:39 +0800 Subject: [PATCH 16/85] feat: add blankAreaClickDeselect/outsideClickDeselect option --- docs/assets/option/en/table/listTable.md | 8 ++++++++ docs/assets/option/zh/table/listTable.md | 8 ++++++++ packages/vtable/src/event/listener/table-group.ts | 13 ++++++++++--- packages/vtable/src/ts-types/base-table.ts | 3 +++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/docs/assets/option/en/table/listTable.md b/docs/assets/option/en/table/listTable.md index b3b330d36..79e1f2f8b 100644 --- a/docs/assets/option/en/table/listTable.md +++ b/docs/assets/option/en/table/listTable.md @@ -32,6 +32,14 @@ Whether to transpose, default is false Whether to display the table header. +## blankAreaClickDeselect(boolean) = false + +Whether to cancel the selection when clicking the blank area. + +## outsideClickDeselect(boolean) = true + +Whether to cancel the selection when clicking outside the table. + ## pagination(IPagination) Pagination configuration. diff --git a/docs/assets/option/zh/table/listTable.md b/docs/assets/option/zh/table/listTable.md index f2c1a6d81..52011c3a2 100644 --- a/docs/assets/option/zh/table/listTable.md +++ b/docs/assets/option/zh/table/listTable.md @@ -32,6 +32,14 @@ 是否显示表头。 +## blankAreaClickDeselect(boolean) = false + +点击空白区域是否取消选中。 + +## outsideClickDeselect(boolean) = true + +点击外部区域是否取消选中。 + ## pagination(IPagination) 分页配置。 diff --git a/packages/vtable/src/event/listener/table-group.ts b/packages/vtable/src/event/listener/table-group.ts index 9a99849eb..6536072d1 100644 --- a/packages/vtable/src/event/listener/table-group.ts +++ b/packages/vtable/src/event/listener/table-group.ts @@ -12,7 +12,7 @@ import type { SceneEvent } from '../util'; import { getCellEventArgsSet, regIndexReg } from '../util'; import { TABLE_EVENT_TYPE } from '../../core/TABLE_EVENT_TYPE'; import type { Group } from '../../scenegraph/graphic/group'; -import { isValid, last } from '@visactor/vutils'; +import { isValid } from '@visactor/vutils'; import { getIconAndPositionFromTarget } from '../../scenegraph/utils/icon'; import { cellInRanges } from '../../tools/helper'; import { Rect } from '../../tools/Rect'; @@ -338,7 +338,9 @@ export function bindTableGroupListener(eventManager: EventManager) { stateManager.updateInteractionState(InteractionState.default); eventManager.dealTableHover(); //点击到表格外部不需要取消选中状态 - // eventManager.dealTableSelect(); + if (table.options.outsideClickDeselect) { + eventManager.dealTableSelect(); + } }); table.scenegraph.tableGroup.addEventListener('pointerdown', (e: FederatedPointerEvent) => { @@ -729,8 +731,13 @@ export function bindTableGroupListener(eventManager: EventManager) { ) { stateManager.updateInteractionState(InteractionState.default); eventManager.dealTableHover(); - eventManager.dealTableSelect(); stateManager.endSelectCells(); + + // 点击空白区域取消选中 + if (table.options.blankAreaClickDeselect ?? true) { + eventManager.dealTableSelect(); + } + stateManager.updateCursor(); table.scenegraph.updateChartState(null); } else if (table.eventManager.isDraging && stateManager.isSelecting()) { diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index 527269e2e..4694f53a2 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -452,6 +452,9 @@ export interface BaseTableConstructorOptions { animationAppear?: boolean | IAnimationAppear; renderOption?: any; + + blankAreaClickDeselect?: boolean; //点击空白区域是否取消选中 + outsideClickDeselect?: boolean; //点击外部区域是否取消选中 } export interface BaseTableAPI { /** 数据总条目数 */ From 19483e80a46e6b25d59e670a2b2b8c4f7f2777eb Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 13 Jun 2024 18:11:02 +0800 Subject: [PATCH 17/85] refactor: when not records pivot table can show corner header #1895 --- packages/vtable/examples/menu.ts | 4 ++ .../pivot-analysis/pivot-empty-tip.ts | 56 +++++++++++++++++ packages/vtable/src/PivotTable.ts | 18 ++++++ .../src/components/empty-tip/empty-tip.ts | 20 +++--- packages/vtable/src/dataset/dataset.ts | 30 +++++++-- .../vtable/src/layout/pivot-header-layout.ts | 61 +++++++++++++++++-- 6 files changed, 169 insertions(+), 20 deletions(-) create mode 100644 packages/vtable/examples/pivot-analysis/pivot-empty-tip.ts diff --git a/packages/vtable/examples/menu.ts b/packages/vtable/examples/menu.ts index 20c1ba406..cdba02a22 100644 --- a/packages/vtable/examples/menu.ts +++ b/packages/vtable/examples/menu.ts @@ -520,6 +520,10 @@ export const menus = [ { path: 'pivot-analysis', name: 'pivot-analysis-str' + }, + { + path: 'pivot-analysis', + name: 'pivot-empty-tip' } ] }, diff --git a/packages/vtable/examples/pivot-analysis/pivot-empty-tip.ts b/packages/vtable/examples/pivot-analysis/pivot-empty-tip.ts new file mode 100644 index 000000000..947a0efcd --- /dev/null +++ b/packages/vtable/examples/pivot-analysis/pivot-empty-tip.ts @@ -0,0 +1,56 @@ +import * as VTable from '../../src'; +const PivotTable = VTable.PivotTable; +const CONTAINER_ID = 'vTable'; + +export function createTable() { + const option: VTable.PivotTableConstructorOptions = { + rows: ['province', 'city'], + columns: ['category', 'sub_category'], + indicators: ['sales', 'number'], + + indicatorTitle: '指标名称', + indicatorsAsCol: false, + corner: { titleOnDimension: 'column' }, + columnResizeType: 'all', + records: [ + { + sales: 891, + number: 7789, + province: '浙江省', + city: '杭州市', + category: '家具', + sub_category: '桌子' + } + ], + emptyTip: true, + widthMode: 'autoWidth' // 宽度模式:standard 标准模式; adaptive 自动填满容器 + }; + + const instance = new PivotTable(document.getElementById(CONTAINER_ID)!, option); + window.tableInstance = instance; + + setTimeout(() => { + instance.updateOption({ + rows: ['province', 'city'], + columns: ['category', 'sub_category'], + indicators: ['sales', 'number'], + + indicatorTitle: '指标名称', + indicatorsAsCol: false, + corner: { titleOnDimension: 'column' }, + columnResizeType: 'all', + records: [ + // { + // sales: 891, + // number: 7789, + // province: '浙江省', + // city: '杭州市', + // category: '家具', + // sub_category: '桌子' + // } + ], + emptyTip: true, + widthMode: 'autoWidth' // 宽度模式:standard 标准模式; adaptive 自动填满容器 + }); + }, 1000); +} diff --git a/packages/vtable/src/PivotTable.ts b/packages/vtable/src/PivotTable.ts index 5dd6de83a..8b763525f 100644 --- a/packages/vtable/src/PivotTable.ts +++ b/packages/vtable/src/PivotTable.ts @@ -161,6 +161,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { options.indicators ); } + if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + this.dataset.colHeaderTree = []; + } columnDimensionTree = new DimensionTree( (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId @@ -173,6 +176,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { options.indicators ); } + if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + this.dataset.rowHeaderTree = []; + } rowDimensionTree = new DimensionTree( (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId, @@ -361,6 +367,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { options.indicators ); } + if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + this.dataset.colHeaderTree = []; + } columnDimensionTree = new DimensionTree( (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId @@ -373,6 +382,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { options.indicators ); } + if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + this.dataset.rowHeaderTree = []; + } rowDimensionTree = new DimensionTree( (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId, @@ -1454,6 +1466,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (options.columnTree) { columnDimensionTree = internalProps.layoutMap.columnDimensionTree; } else { + if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + this.dataset.colHeaderTree = []; + } columnDimensionTree = new DimensionTree( (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId @@ -1462,6 +1477,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (options.rowTree) { rowDimensionTree = internalProps.layoutMap.rowDimensionTree; } else { + if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + this.dataset.rowHeaderTree = []; + } rowDimensionTree = new DimensionTree( (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId, diff --git a/packages/vtable/src/components/empty-tip/empty-tip.ts b/packages/vtable/src/components/empty-tip/empty-tip.ts index f898201b2..971b61d8a 100644 --- a/packages/vtable/src/components/empty-tip/empty-tip.ts +++ b/packages/vtable/src/components/empty-tip/empty-tip.ts @@ -62,11 +62,13 @@ export class EmptyTip { ? this.table.getFrozenRowsHeight() : 0; const width = - (this.table.columnHeaderLevelCount > 0 ? this.table.getDrawRange().width : this.table.tableNoFrameWidth) - - leftHeaderWidth; + (this.table.columnHeaderLevelCount > 0 && this.table.isListTable() + ? this.table.getDrawRange().width + : this.table.tableNoFrameWidth) - leftHeaderWidth; const height = - (this.table.rowHeaderLevelCount > 0 ? this.table.getDrawRange().height : this.table.tableNoFrameHeight) - - topHeaderHeight; + (this.table.rowHeaderLevelCount > 0 && this.table.isListTable() + ? this.table.getDrawRange().height + : this.table.tableNoFrameHeight) - topHeaderHeight; this._emptyTipComponent.setAttributes({ spaceBetweenTextAndIcon: this._emptyTipOption.spaceBetweenTextAndIcon, x: this.table.tableX + leftHeaderWidth, @@ -123,11 +125,13 @@ export class EmptyTip { ? this.table.getFrozenRowsHeight() : 0; const width = - (this.table.columnHeaderLevelCount > 0 ? this.table.getDrawRange().width : this.table.tableNoFrameWidth) - - leftHeaderWidth; + (this.table.columnHeaderLevelCount > 0 && this.table.isListTable() + ? this.table.getDrawRange().width + : this.table.tableNoFrameWidth) - leftHeaderWidth; const height = - (this.table.rowHeaderLevelCount > 0 ? this.table.getDrawRange().height : this.table.tableNoFrameHeight) - - topHeaderHeight; + (this.table.rowHeaderLevelCount > 0 && this.table.isListTable() + ? this.table.getDrawRange().height + : this.table.tableNoFrameHeight) - topHeaderHeight; return { spaceBetweenTextAndIcon: this._emptyTipOption.spaceBetweenTextAndIcon, diff --git a/packages/vtable/src/dataset/dataset.ts b/packages/vtable/src/dataset/dataset.ts index 3fe1d486b..7407f69b9 100644 --- a/packages/vtable/src/dataset/dataset.ts +++ b/packages/vtable/src/dataset/dataset.ts @@ -115,7 +115,9 @@ export class Dataset { collectedValues: Record> = {}; cacheCollectedValues: Record> = {}; rows: string[]; + rowsHasValue: boolean[]; //rows中的key是否有在records中体现 columns: string[]; + columnsHasValue: boolean[]; //columns中的key是否有在records中体现 indicatorKeys: string[]; customRowTree?: IHeaderTreeDefine[]; customColTree?: IHeaderTreeDefine[]; @@ -198,6 +200,8 @@ export class Dataset { this.rowFlatKeys = {}; this.colKeys = []; this.rowKeys = []; + this.rowsHasValue = []; + this.columnsHasValue = []; if (records) { //处理数据 this.records = records; @@ -256,7 +260,9 @@ export class Dataset { if (this.rowHierarchyType === 'tree') { this.rowHeaderTree = this.ArrToTree1( this.rowKeys, - this.rows, + this.rows.filter((key, index) => { + return this.rowsHasValue[index]; + }), this.indicatorsAsCol ? undefined : this.indicators, this.totals?.row?.showGrandTotals || (!this.indicatorsAsCol && this.columns.length === 0) || @@ -266,7 +272,9 @@ export class Dataset { } else { this.rowHeaderTree = this.ArrToTree( this.rowKeys, - this.rows, + this.rows.filter((key, index) => { + return this.rowsHasValue[index]; + }), this.indicatorsAsCol ? undefined : this.indicators, this.rowsIsTotal, this.totals?.row?.showGrandTotals || (this.indicatorsAsCol && this.rows.length === 0), @@ -285,7 +293,9 @@ export class Dataset { } else { this.colHeaderTree = this.ArrToTree( this.colKeys, - this.columns, + this.columns.filter((key, index) => { + return this.columnsHasValue[index]; + }), this.indicatorsAsCol ? this.indicators : undefined, this.colsIsTotal, this.totals?.column?.showGrandTotals || (!this.indicatorsAsCol && this.columns.length === 0), // || this.rows.length === 0,//todo 这里原有逻辑暂时注释掉 @@ -558,6 +568,7 @@ export class Dataset { for (let l = 0, len1 = this.rows.length; l < len1; l++) { const rowAttr = this.rows[l]; if (rowAttr in record) { + this.rowsHasValue[l] = true; rowKey.push(record[rowAttr]); } else if (rowAttr !== IndicatorDimensionKeyPlaceholder) { //如果数据中缺失某个维度的值 可以认为是用户传入的汇总数据 @@ -589,6 +600,7 @@ export class Dataset { for (let n = 0, len2 = this.columns.length; n < len2; n++) { const colAttr = this.columns[n]; if (colAttr in record) { + this.columnsHasValue[n] = true; colKey.push(record[colAttr]); } else if (colAttr !== IndicatorDimensionKeyPlaceholder) { //如果数据中缺失某个维度的值 可以认为是用户传入的汇总数据 @@ -767,7 +779,9 @@ export class Dataset { if (this.rowHierarchyType === 'tree') { this.rowHeaderTree = this.ArrToTree1( this.rowKeys, - this.rows, + this.rows.filter((key, index) => { + return this.rowsHasValue[index]; + }), this.indicatorsAsCol ? undefined : this.indicators, this.totals?.row?.showGrandTotals || (!this.indicatorsAsCol && this.columns.length === 0) || @@ -777,7 +791,9 @@ export class Dataset { } else { this.rowHeaderTree = this.ArrToTree( this.rowKeys, - this.rows, + this.rows.filter((key, index) => { + return this.rowsHasValue[index]; + }), this.indicatorsAsCol ? undefined : this.indicators, this.rowsIsTotal, this.totals?.row?.showGrandTotals || (this.indicatorsAsCol && this.rows.length === 0), @@ -792,7 +808,9 @@ export class Dataset { if (!this.customColTree) { this.colHeaderTree = this.ArrToTree( this.colKeys, - this.columns, + this.columns.filter((key, index) => { + return this.columnsHasValue[index]; + }), this.indicatorsAsCol ? this.indicators : undefined, this.colsIsTotal, this.totals?.column?.showGrandTotals || (!this.indicatorsAsCol && this.columns.length === 0), // || this.rows.length === 0,//todo 这里原有逻辑暂时注释掉 diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index e736a80d8..9f7c75325 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -279,7 +279,17 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.sharedVar.seqId = Math.max(this.sharedVar.seqId, this._headerObjects.length); //生成cornerHeaderObjs及_cornerHeaderCellIds if (this.cornerSetting.titleOnDimension === 'column') { - const colDimensionKeys = this.columnDimensionTree.dimensionKeysIncludeVirtual.valueArr(); + let colDimensionKeys = this.columnDimensionTree.dimensionKeysIncludeVirtual.valueArr(); + //#region 处理需求 当没有数据时仍然显示角头维度名称 + if ((this.dataset.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + colDimensionKeys = this.columnsDefine.map(define => { + if (typeof define === 'string') { + return define; + } + return define.dimensionKey; + }); + } + //#endregion this.cornerHeaderObjs = this._addCornerHeaders( this.columnHeaderTitle ? [''].concat(colDimensionKeys) : colDimensionKeys, this.columnsDefine @@ -300,7 +310,17 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.rowsDefine.concat(extensionRowDimensions) ); } else { - const rowDimensionKeys = this.rowDimensionTree.dimensionKeysIncludeVirtual.valueArr(); + //#region 处理需求 当没有数据时仍然显示角头维度名称 + let rowDimensionKeys = this.rowDimensionTree.dimensionKeysIncludeVirtual.valueArr(); + if ((this.dataset.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + rowDimensionKeys = this.rowsDefine.map(define => { + if (typeof define === 'string') { + return define; + } + return define.dimensionKey; + }); + } + //#endregion this.cornerHeaderObjs = this._addCornerHeaders( this.rowHeaderTitle ? [''].concat(rowDimensionKeys) : rowDimensionKeys, this.rowsDefine @@ -1131,6 +1151,21 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { : this.columnDimensionTree.totalLevel : this.columnDimensionTree.totalLevel : this.columnDimensionTree.totalLevel; + //#region 处理需求 当没有数据时仍然显示角头维度名称 + if (count === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + if (this.cornerSetting.titleOnDimension === 'row') { + count = 1; + } else if ((this.dataset.records?.length ?? 0) === 0 && this.cornerSetting.titleOnDimension === 'column') { + count = this.columnsDefine.length ?? 0; + } + } else if ( + (this.dataset.records?.length ?? 0) === 0 && + !this.dataset.customColTree && + !this.dataset.customRowTree + ) { + count = this.columnsDefine.length; + } + //#endregion if (this.columnHeaderTitle) { count += 1; } @@ -1178,7 +1213,21 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { ) { count = rowLevelCount - 1; } - + //#region 处理需求 当没有数据时仍然显示角头维度名称 + if (count === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + if (this.cornerSetting.titleOnDimension === 'column') { + count = 1; + } else if ((this.dataset.records?.length ?? 0) === 0 && this.cornerSetting.titleOnDimension === 'row') { + count = this.rowsDefine.length ?? 0; + } + } else if ( + (this.dataset.records?.length ?? 0) === 0 && + !this.dataset.customColTree && + !this.dataset.customRowTree + ) { + count = this.rowsDefine.length; + } + //#endregion if (this.rowHeaderTitle) { count += 1; } @@ -1321,13 +1370,13 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (this.isSeriesNumber(col, row)) { return ''; } else if (this.isCornerHeader(col, row)) { - return this._cornerHeaderCellIds[row][col - this.leftRowSeriesNumberColumnCount]; + return this._cornerHeaderCellIds[row]?.[col - this.leftRowSeriesNumberColumnCount]; } else if (this.isColumnHeader(col, row)) { - return this._columnHeaderCellIds[row][col - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount]; + return this._columnHeaderCellIds[row]?.[col - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount]; } else if (this.isRowHeader(col, row)) { return this._rowHeaderCellIds[row - this.columnHeaderLevelCount]?.[col - this.leftRowSeriesNumberColumnCount]; } else if (this.isRightFrozenColumn(col, row)) { - return this._rowHeaderCellIds[row - this.columnHeaderLevelCount][this.rowHeaderLevelCount - 1]; + return this._rowHeaderCellIds[row - this.columnHeaderLevelCount]?.[this.rowHeaderLevelCount - 1]; } else if (this.isBottomFrozenRow(col, row)) { return this._columnHeaderCellIds[this.columnHeaderLevelCount - 1]?.[ col - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount From 83b7c3726104a86db7f2d22eec6d59e0d088ae33 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 13 Jun 2024 18:12:16 +0800 Subject: [PATCH 18/85] docs: update changlog of rush --- ...e-pivotTable-corner-emptyTip_2024-06-13-10-12.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/1895-feature-pivotTable-corner-emptyTip_2024-06-13-10-12.json diff --git a/common/changes/@visactor/vtable/1895-feature-pivotTable-corner-emptyTip_2024-06-13-10-12.json b/common/changes/@visactor/vtable/1895-feature-pivotTable-corner-emptyTip_2024-06-13-10-12.json new file mode 100644 index 000000000..8c9d2bda3 --- /dev/null +++ b/common/changes/@visactor/vtable/1895-feature-pivotTable-corner-emptyTip_2024-06-13-10-12.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "refactor: when not records pivot table can show corner header #1895\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From cc93878f8c133c5d171d459acee354f913056040 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 13 Jun 2024 20:06:28 +0800 Subject: [PATCH 19/85] fix: rowHeaderLevelCount and columnHeaderLevelCount refix --- packages/vtable/src/PivotTable.ts | 18 -------- .../vtable/src/layout/pivot-header-layout.ts | 44 +++++++++++-------- 2 files changed, 25 insertions(+), 37 deletions(-) diff --git a/packages/vtable/src/PivotTable.ts b/packages/vtable/src/PivotTable.ts index 8b763525f..5dd6de83a 100644 --- a/packages/vtable/src/PivotTable.ts +++ b/packages/vtable/src/PivotTable.ts @@ -161,9 +161,6 @@ export class PivotTable extends BaseTable implements PivotTableAPI { options.indicators ); } - if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { - this.dataset.colHeaderTree = []; - } columnDimensionTree = new DimensionTree( (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId @@ -176,9 +173,6 @@ export class PivotTable extends BaseTable implements PivotTableAPI { options.indicators ); } - if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { - this.dataset.rowHeaderTree = []; - } rowDimensionTree = new DimensionTree( (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId, @@ -367,9 +361,6 @@ export class PivotTable extends BaseTable implements PivotTableAPI { options.indicators ); } - if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { - this.dataset.colHeaderTree = []; - } columnDimensionTree = new DimensionTree( (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId @@ -382,9 +373,6 @@ export class PivotTable extends BaseTable implements PivotTableAPI { options.indicators ); } - if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { - this.dataset.rowHeaderTree = []; - } rowDimensionTree = new DimensionTree( (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId, @@ -1466,9 +1454,6 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (options.columnTree) { columnDimensionTree = internalProps.layoutMap.columnDimensionTree; } else { - if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { - this.dataset.colHeaderTree = []; - } columnDimensionTree = new DimensionTree( (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId @@ -1477,9 +1462,6 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (options.rowTree) { rowDimensionTree = internalProps.layoutMap.rowDimensionTree; } else { - if ((this.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { - this.dataset.rowHeaderTree = []; - } rowDimensionTree = new DimensionTree( (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], this.layoutNodeId, diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index 9f7c75325..162818c56 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -1151,6 +1151,18 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { : this.columnDimensionTree.totalLevel : this.columnDimensionTree.totalLevel : this.columnDimensionTree.totalLevel; + + if (this.columnHeaderTitle) { + count += 1; + } + if ( + this._table.isPivotChart() && + this.indicatorsAsCol && + !this.hasTwoIndicatorAxes && + checkHasCartesianChart(this.indicatorsDefine) + ) { + count -= 1; + } //#region 处理需求 当没有数据时仍然显示角头维度名称 if (count === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { if (this.cornerSetting.titleOnDimension === 'row') { @@ -1163,20 +1175,11 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { !this.dataset.customColTree && !this.dataset.customRowTree ) { - count = this.columnsDefine.length; + if (this.cornerSetting.titleOnDimension === 'column') { + count = this.columnsDefine.length ?? 0; + } } //#endregion - if (this.columnHeaderTitle) { - count += 1; - } - if ( - this._table.isPivotChart() && - this.indicatorsAsCol && - !this.hasTwoIndicatorAxes && - checkHasCartesianChart(this.indicatorsDefine) - ) { - count -= 1; - } this.columnHeaderLevelCount = count; return; } @@ -1213,6 +1216,13 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { ) { count = rowLevelCount - 1; } + + if (this.rowHeaderTitle) { + count += 1; + } + // if (this._table.isPivotChart()&&this.indicatorsAsCol) { + // count+=1; + // } //#region 处理需求 当没有数据时仍然显示角头维度名称 if (count === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { if (this.cornerSetting.titleOnDimension === 'column') { @@ -1225,15 +1235,11 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { !this.dataset.customColTree && !this.dataset.customRowTree ) { - count = this.rowsDefine.length; + if (this.cornerSetting.titleOnDimension === 'row') { + count = this.rowsDefine.length; + } } //#endregion - if (this.rowHeaderTitle) { - count += 1; - } - // if (this._table.isPivotChart()&&this.indicatorsAsCol) { - // count+=1; - // } this.rowHeaderLevelCount = count; return; } From 0e72a89e7de0116a028b4203a083ea8ed3f49853 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 13 Jun 2024 20:24:50 +0800 Subject: [PATCH 20/85] fix: not render bugserver case --- .../vtable/src/layout/pivot-header-layout.ts | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index 162818c56..25d811cff 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -281,7 +281,12 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (this.cornerSetting.titleOnDimension === 'column') { let colDimensionKeys = this.columnDimensionTree.dimensionKeysIncludeVirtual.valueArr(); //#region 处理需求 当没有数据时仍然显示角头维度名称 - if ((this.dataset.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + if ( + this.dataset && + (this.dataset.records?.length ?? 0) === 0 && + !this.dataset.customColTree && + !this.dataset.customRowTree + ) { colDimensionKeys = this.columnsDefine.map(define => { if (typeof define === 'string') { return define; @@ -312,7 +317,12 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } else { //#region 处理需求 当没有数据时仍然显示角头维度名称 let rowDimensionKeys = this.rowDimensionTree.dimensionKeysIncludeVirtual.valueArr(); - if ((this.dataset.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + if ( + this.dataset && + (this.dataset.records?.length ?? 0) === 0 && + !this.dataset.customColTree && + !this.dataset.customRowTree + ) { rowDimensionKeys = this.rowsDefine.map(define => { if (typeof define === 'string') { return define; @@ -1164,13 +1174,14 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { count -= 1; } //#region 处理需求 当没有数据时仍然显示角头维度名称 - if (count === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + if (count === 0 && this.dataset && !this.dataset.customColTree && !this.dataset.customRowTree) { if (this.cornerSetting.titleOnDimension === 'row') { count = 1; } else if ((this.dataset.records?.length ?? 0) === 0 && this.cornerSetting.titleOnDimension === 'column') { count = this.columnsDefine.length ?? 0; } } else if ( + this.dataset && (this.dataset.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree @@ -1224,13 +1235,14 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { // count+=1; // } //#region 处理需求 当没有数据时仍然显示角头维度名称 - if (count === 0 && !this.dataset.customColTree && !this.dataset.customRowTree) { + if (count === 0 && this.dataset && !this.dataset.customColTree && !this.dataset.customRowTree) { if (this.cornerSetting.titleOnDimension === 'column') { count = 1; } else if ((this.dataset.records?.length ?? 0) === 0 && this.cornerSetting.titleOnDimension === 'row') { count = this.rowsDefine.length ?? 0; } } else if ( + this.dataset && (this.dataset.records?.length ?? 0) === 0 && !this.dataset.customColTree && !this.dataset.customRowTree From d4e1e02157aa5095ca5dd6eb45c97c5a3f0b5a27 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 14 Jun 2024 11:24:51 +0800 Subject: [PATCH 21/85] refactor: header show normal when not data --- .../vtable/src/layout/pivot-header-layout.ts | 53 +++++++++++++++---- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index 25d811cff..ce241002a 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -222,13 +222,6 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.resetRowHeaderLevelCount(); - //生成列表头单元格 - this._generateColHeaderIds(); - - this.colIndex = 0; - //生成行表头单元格 - this._generateRowHeaderIds(); - if (this._table.isPivotChart()) { this.hasTwoIndicatorAxes = this._indicators.some(indicatorObject => { if ( @@ -258,6 +251,13 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { // this.colAttrs[this.colAttrs.length-1]===this.indicatorDimensionKey&&this.colAttrs.pop(); // this.rowAttrs[this.rowAttrs.length-1]===this.indicatorDimensionKey&&this.rowAttrs.pop(); + //生成列表头单元格 + this._generateColHeaderIds(); + + this.colIndex = 0; + //生成行表头单元格 + this._generateRowHeaderIds(); + this._rowHeaderCellFullPathIds_FULL = transpose(this._rowHeaderCellFullPathIds_FULL); if ((table as PivotTable).options.rowHierarchyType === 'tree' && this.extensionRows?.length >= 1) { this.generateExtensionRowTree(); @@ -293,6 +293,9 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } return define.dimensionKey; }); + if (this.indicatorsAsCol) { + colDimensionKeys.push(this.indicatorDimensionKey); + } } //#endregion this.cornerHeaderObjs = this._addCornerHeaders( @@ -329,6 +332,9 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } return define.dimensionKey; }); + if (!this.indicatorsAsCol) { + rowDimensionKeys.push(this.indicatorDimensionKey); + } } //#endregion this.cornerHeaderObjs = this._addCornerHeaders( @@ -478,9 +484,18 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } _generateColHeaderIds() { if (this.columnDimensionTree.tree.children?.length >= 1) { + //#region 处理需求 当没有数据时仍然显示角头维度名称 + let startRow = 0; + if (this.indicatorsAsCol && this.columnDimensionTree.totalLevel < this.columnHeaderLevelCount) { + startRow = this.columnHeaderLevelCount - this.columnDimensionTree.totalLevel; + for (let i = 0; i < startRow; i++) { + this._columnHeaderCellFullPathIds.unshift([]); + } + } + //#endregion this._addHeaders( this._columnHeaderCellFullPathIds, - 0, + startRow, this.columnDimensionTree.tree.children, [], this.columnHeaderObjs @@ -530,9 +545,18 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.rowHeaderObjs ); } else { + //#region 处理需求 当没有数据时仍然显示角头维度名称 + let startRow = 0; + if (!this.indicatorsAsCol && this.rowDimensionTree.totalLevel < this.rowHeaderLevelCount) { + startRow = this.rowHeaderLevelCount - this.rowDimensionTree.totalLevel; + for (let i = 0; i < startRow; i++) { + this._rowHeaderCellFullPathIds_FULL.unshift([]); + } + } + //#endregion this._addHeaders( this._rowHeaderCellFullPathIds_FULL, - 0, + startRow, this.rowDimensionTree.tree.children, [], this.rowHeaderObjs @@ -1188,6 +1212,9 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { ) { if (this.cornerSetting.titleOnDimension === 'column') { count = this.columnsDefine.length ?? 0; + if (!this.hideIndicatorName && this.indicatorsAsCol) { + count++; + } } } //#endregion @@ -1249,6 +1276,9 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { ) { if (this.cornerSetting.titleOnDimension === 'row') { count = this.rowsDefine.length; + if (!this.hideIndicatorName && !this.indicatorsAsCol) { + count++; + } } } //#endregion @@ -3237,14 +3267,15 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.rowHierarchyType, this.rowHierarchyType === 'tree' ? this.rowExpandLevel : undefined ); + + this.resetColumnHeaderLevelCount(); + //生成列表头单元格 this._generateColHeaderIds(); this.colIndex = 0; //生成行表头单元格 this._generateRowHeaderIds(); - - this.resetColumnHeaderLevelCount(); this._rowHeaderCellFullPathIds_FULL = transpose(this._rowHeaderCellFullPathIds_FULL); this._headerObjectMap = this._headerObjects.reduce((o, e) => { From f0c140b5bb85d717f033d33e3a81940b94a220b6 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 14 Jun 2024 12:14:28 +0800 Subject: [PATCH 22/85] refactor: when rowTree children not set value can supplement indicators #1924 --- packages/vtable/src/layout/layout-helper.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/vtable/src/layout/layout-helper.ts b/packages/vtable/src/layout/layout-helper.ts index 08833bfdc..43486d117 100644 --- a/packages/vtable/src/layout/layout-helper.ts +++ b/packages/vtable/src/layout/layout-helper.ts @@ -1,4 +1,4 @@ -import { isArray, isString } from '@visactor/vutils'; +import { isArray, isString, isValid } from '@visactor/vutils'; import type { PivotTable } from '../PivotTable'; import { IndicatorDimensionKeyPlaceholder } from '../tools/global'; import { AggregationType } from '../ts-types'; @@ -303,11 +303,7 @@ export function supplementIndicatorNodesForCustomTree( ) { const checkNode = (nodes: IHeaderTreeDefine[], isHasIndicator: boolean) => { nodes.forEach((node: IHeaderTreeDefine) => { - if ( - !node.indicatorKey && - !isHasIndicator && - (!(node.children as IHeaderTreeDefine[])?.length || !node.children) - ) { + if (!node.indicatorKey && !isHasIndicator && !isValid(node.children)) { node.children = indicators?.map((indicator: IIndicator | string): { indicatorKey: string; value: string } => { if (typeof indicator === 'string') { return { indicatorKey: indicator, value: indicator }; From 7b4d43ea8cfe18220aaa13afadd7a6e5eae27f5d Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 14 Jun 2024 12:18:38 +0800 Subject: [PATCH 23/85] docs: update changlog of rush --- ...ee-not-supplement-indicators_2024-06-14-04-14.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/1924-refactor-rowtree-not-supplement-indicators_2024-06-14-04-14.json diff --git a/common/changes/@visactor/vtable/1924-refactor-rowtree-not-supplement-indicators_2024-06-14-04-14.json b/common/changes/@visactor/vtable/1924-refactor-rowtree-not-supplement-indicators_2024-06-14-04-14.json new file mode 100644 index 000000000..567afa823 --- /dev/null +++ b/common/changes/@visactor/vtable/1924-refactor-rowtree-not-supplement-indicators_2024-06-14-04-14.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "refactor: when rowTree children not set value can supplement indicators #1924\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From 55b2fc4eda8a2b05b15368810ce7283c78749a48 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 14 Jun 2024 14:04:36 +0800 Subject: [PATCH 24/85] fix: pivot chat not show axis --- packages/vtable/src/layout/pivot-header-layout.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index ce241002a..a6ae10589 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -223,7 +223,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.resetRowHeaderLevelCount(); if (this._table.isPivotChart()) { - this.hasTwoIndicatorAxes = this._indicators.some(indicatorObject => { + this.hasTwoIndicatorAxes = this.indicatorsDefine.some((indicatorObject: any) => { if ( indicatorObject.chartSpec && indicatorObject.chartSpec.series && From 3d7657cb05940a2dda9b9167dda8ea224ba58a1d Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 14 Jun 2024 14:35:27 +0800 Subject: [PATCH 25/85] docs: refix rowTree define #1924 --- docs/assets/option/en/table/pivotChart.md | 6 +++--- docs/assets/option/en/table/pivotTable.md | 6 +++--- docs/assets/option/zh/table/pivotChart.md | 4 ++-- docs/assets/option/zh/table/pivotTable.md | 6 +++--- packages/vtable/src/layout/layout-helper.ts | 6 +++++- 5 files changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/assets/option/en/table/pivotChart.md b/docs/assets/option/en/table/pivotChart.md index 162e5c344..28be1ed1a 100644 --- a/docs/assets/option/en/table/pivotChart.md +++ b/docs/assets/option/en/table/pivotChart.md @@ -51,7 +51,7 @@ The currently supported data formats are, taking the sales of large supermarkets ## columnTree(Array) -List header tree, type:`IDimensionHeaderNode|IIndicatorHeaderNode[]`. Among them, IDimensionHeaderNode refers to the dimension value node of the dimension non-indicator, and IIndicatorHeaderNode refers to the indicator name node. +List header tree, type:`(IDimensionHeaderNode|IIndicatorHeaderNode)[]`. Among them, IDimensionHeaderNode refers to the dimension value node of the dimension non-indicator, and IIndicatorHeaderNode refers to the indicator name node. ** The specific configuration items of IDimensionHeaderNode are as follows:** @@ -63,8 +63,8 @@ export interface IDimensionHeaderNode { dimensionKey: string | number; /** dimension member value */ value: string; - /** Subdimension tree structure under dimension members */ - children?: IDimensionHeaderNode|IIndicatorHeaderNode[]; + /** Subdimension tree structure under dimension members. */ + children?: (IDimensionHeaderNode|IIndicatorHeaderNode)[] ; /** The collapsed state is used with the tree structure display. Note: only valid in rowTree */ hierarchyState?: HierarchyState; } diff --git a/docs/assets/option/en/table/pivotTable.md b/docs/assets/option/en/table/pivotTable.md index 9777fed0f..ef4ce6339 100644 --- a/docs/assets/option/en/table/pivotTable.md +++ b/docs/assets/option/en/table/pivotTable.md @@ -237,7 +237,7 @@ export interface DerivedFieldRule { ## columnTree(Array) -Column header tree, type: `IDimensionHeaderNode|IIndicatorHeaderNode[]`. Among them, IDimensionHeaderNode refers to the dimension value node of non-indicator dimensions, and IIndicatorHeaderNode refers to the indicator name node. +Column header tree, type: `(IDimensionHeaderNode|IIndicatorHeaderNode)[]`. Among them, IDimensionHeaderNode refers to the dimension value node of non-indicator dimensions, and IIndicatorHeaderNode refers to the indicator name node. ** Specific configuration of IDimensionHeaderNode is as follows: ** @@ -249,8 +249,8 @@ export interface IDimensionHeaderNode { dimensionKey: string | number; /** Dimension member value */ value: string; - /** The tree structure of the sub-dimensions under the member */ - children?: IDimensionHeaderNode|IIndicatorHeaderNode[]; + /** The tree structure of the sub-dimensions under the member. true is generally used to display the fold and expand buttons and to perform lazy loading to obtain data. */ + children?: (IDimensionHeaderNode|IIndicatorHeaderNode)[] | true; /** Collapse status Used with tree structure display. Note: only valid in rowTree */ hierarchyState?: HierarchyState; /** Whether it is a virtual node. If configured to true, this dimension field will be ignored when analyzing based on records data */ diff --git a/docs/assets/option/zh/table/pivotChart.md b/docs/assets/option/zh/table/pivotChart.md index fddfbd9db..5e1461337 100644 --- a/docs/assets/option/zh/table/pivotChart.md +++ b/docs/assets/option/zh/table/pivotChart.md @@ -51,7 +51,7 @@ ## columnTree(Array) -列表头树,类型为:`IDimensionHeaderNode|IIndicatorHeaderNode[]`。其中 IDimensionHeaderNode 指的是维度非指标的维度值节点,IIndicatorHeaderNode 指的是指标名称节点。 +列表头树,类型为:`(IDimensionHeaderNode|IIndicatorHeaderNode)[]`。其中 IDimensionHeaderNode 指的是维度非指标的维度值节点,IIndicatorHeaderNode 指的是指标名称节点。 ** IDimensionHeaderNode 具体配置项如下:** @@ -64,7 +64,7 @@ export interface IDimensionHeaderNode { /** 维度成员值 */ value: string; /** 维度成员下的子维度树结构 */ - children?: IDimensionHeaderNode|IIndicatorHeaderNode[]; + children?: (IDimensionHeaderNode|IIndicatorHeaderNode)[]; /** 折叠状态 配合树形结构展示使用。注意:仅在rowTree中有效 */ hierarchyState?: HierarchyState; } diff --git a/docs/assets/option/zh/table/pivotTable.md b/docs/assets/option/zh/table/pivotTable.md index 441f85d39..8d8b64a1b 100644 --- a/docs/assets/option/zh/table/pivotTable.md +++ b/docs/assets/option/zh/table/pivotTable.md @@ -241,7 +241,7 @@ export interface DerivedFieldRule { ## columnTree(Array) -列表头树,类型为:`IDimensionHeaderNode|IIndicatorHeaderNode[]`。其中 IDimensionHeaderNode 指的是维度非指标的维度值节点,IIndicatorHeaderNode 指的是指标名称节点。 +列表头树,类型为:`(IDimensionHeaderNode|IIndicatorHeaderNode)[]`。其中 IDimensionHeaderNode 指的是维度非指标的维度值节点,IIndicatorHeaderNode 指的是指标名称节点。 ** IDimensionHeaderNode 具体配置项如下:** @@ -253,8 +253,8 @@ export interface IDimensionHeaderNode { dimensionKey: string | number; /** 维度成员值 */ value: string; - /** 维度成员下的子维度树结构 */ - children?: IDimensionHeaderNode|IIndicatorHeaderNode[]; + /** 维度成员下的子维度树结构。 true一般是用在显示折叠展开按钮,进行懒加载获取数据的场景中。 */ + children?: (IDimensionHeaderNode|IIndicatorHeaderNode)[] | true; /** 折叠状态 配合树形结构展示使用。注意:仅在rowTree中有效 */ hierarchyState?: HierarchyState; /** 是否为虚拟节点。 如果配置为true,则在基于records数据做分析时会忽略该维度字段 */ diff --git a/packages/vtable/src/layout/layout-helper.ts b/packages/vtable/src/layout/layout-helper.ts index 43486d117..ebf67678f 100644 --- a/packages/vtable/src/layout/layout-helper.ts +++ b/packages/vtable/src/layout/layout-helper.ts @@ -303,7 +303,11 @@ export function supplementIndicatorNodesForCustomTree( ) { const checkNode = (nodes: IHeaderTreeDefine[], isHasIndicator: boolean) => { nodes.forEach((node: IHeaderTreeDefine) => { - if (!node.indicatorKey && !isHasIndicator && !isValid(node.children)) { + if ( + !node.indicatorKey && + !isHasIndicator && + (!(node.children as IHeaderTreeDefine[])?.length || !node.children) + ) { node.children = indicators?.map((indicator: IIndicator | string): { indicatorKey: string; value: string } => { if (typeof indicator === 'string') { return { indicatorKey: indicator, value: indicator }; From e61d7d6b19ae1b79b39f6ca41a35ef50648abc26 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 14 Jun 2024 15:01:56 +0800 Subject: [PATCH 26/85] fix: bugserver case error --- .../vtable/src/layout/pivot-header-layout.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index a6ae10589..c2cb24623 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -486,7 +486,14 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (this.columnDimensionTree.tree.children?.length >= 1) { //#region 处理需求 当没有数据时仍然显示角头维度名称 let startRow = 0; - if (this.indicatorsAsCol && this.columnDimensionTree.totalLevel < this.columnHeaderLevelCount) { + if ( + this.dataset && + (this.dataset.records?.length ?? 0) === 0 && + !this.dataset.customColTree && + !this.dataset.customRowTree && + this.indicatorsAsCol && + this.columnDimensionTree.totalLevel < this.columnHeaderLevelCount + ) { startRow = this.columnHeaderLevelCount - this.columnDimensionTree.totalLevel; for (let i = 0; i < startRow; i++) { this._columnHeaderCellFullPathIds.unshift([]); @@ -547,7 +554,14 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } else { //#region 处理需求 当没有数据时仍然显示角头维度名称 let startRow = 0; - if (!this.indicatorsAsCol && this.rowDimensionTree.totalLevel < this.rowHeaderLevelCount) { + if ( + this.dataset && + (this.dataset.records?.length ?? 0) === 0 && + !this.dataset.customColTree && + !this.dataset.customRowTree && + !this.indicatorsAsCol && + this.rowDimensionTree.totalLevel < this.rowHeaderLevelCount + ) { startRow = this.rowHeaderLevelCount - this.rowDimensionTree.totalLevel; for (let i = 0; i < startRow; i++) { this._rowHeaderCellFullPathIds_FULL.unshift([]); From cf66f5dd792b5e85b8f62dfb92589c3502c6c350 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 14 Jun 2024 15:03:13 +0800 Subject: [PATCH 27/85] docs: refix rowTree define --- packages/vtable/src/layout/layout-helper.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/vtable/src/layout/layout-helper.ts b/packages/vtable/src/layout/layout-helper.ts index ebf67678f..8a951c456 100644 --- a/packages/vtable/src/layout/layout-helper.ts +++ b/packages/vtable/src/layout/layout-helper.ts @@ -1,6 +1,5 @@ -import { isArray, isString, isValid } from '@visactor/vutils'; +import { isArray, isString } from '@visactor/vutils'; import type { PivotTable } from '../PivotTable'; -import { IndicatorDimensionKeyPlaceholder } from '../tools/global'; import { AggregationType } from '../ts-types'; import type { BaseTableAPI } from '../ts-types/base-table'; import type { From 699a0084baf14121928588f843113cac55fbacd4 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 14 Jun 2024 16:04:31 +0800 Subject: [PATCH 28/85] feat: add react dom component demo --- packages/react-vtable/demo/src/App.tsx | 6 +- .../component/custom-layout-dom-site-1.tsx | 183 ++++++++++++++ .../src/component/custom-layout-dom-site.tsx | 225 ++++++++++++++++++ .../demo/src/component/custom-layout-dom.tsx | 85 ++++++- .../src/components/custom/component.ts | 15 ++ .../src/components/custom/custom-layout.tsx | 3 +- .../src/components/custom/graphic.ts | 30 +-- .../src/components/custom/reconciler.ts | 10 +- .../custom/vtable-browser-env-contribution.ts | 59 +++++ .../custom/vtable-react-attribute-plugin.ts | 98 +++++++- packages/react-vtable/src/components/index.ts | 1 + .../react-vtable/src/tables/base-table.tsx | 7 + .../components/react/react-custom-layout.ts | 3 +- packages/vtable/src/core/BaseTable.ts | 8 +- packages/vtable/src/index.ts | 3 + packages/vtable/src/vrender.ts | 73 +----- 16 files changed, 711 insertions(+), 98 deletions(-) create mode 100644 packages/react-vtable/demo/src/component/custom-layout-dom-site-1.tsx create mode 100644 packages/react-vtable/demo/src/component/custom-layout-dom-site.tsx create mode 100644 packages/react-vtable/src/components/custom/component.ts create mode 100644 packages/react-vtable/src/components/custom/vtable-browser-env-contribution.ts diff --git a/packages/react-vtable/demo/src/App.tsx b/packages/react-vtable/demo/src/App.tsx index 6c924d6b9..00fb52a68 100644 --- a/packages/react-vtable/demo/src/App.tsx +++ b/packages/react-vtable/demo/src/App.tsx @@ -16,6 +16,8 @@ import eventRebind from './event/event-rebind'; import componentContainer from './component/component-container'; 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'; // export default listEditor; // export default listOptionRecord; @@ -33,4 +35,6 @@ import customLayoutDom from './component/custom-layout-dom'; // export default componentContainer; // export default customLayout; -export default customLayoutDom; +// export default customLayoutDom; +// export default customLayoutDomSite; +export default customLayoutDomSite1; diff --git a/packages/react-vtable/demo/src/component/custom-layout-dom-site-1.tsx b/packages/react-vtable/demo/src/component/custom-layout-dom-site-1.tsx new file mode 100644 index 000000000..c4256eb2a --- /dev/null +++ b/packages/react-vtable/demo/src/component/custom-layout-dom-site-1.tsx @@ -0,0 +1,183 @@ +import { useEffect, useRef, useState } from 'react'; +import type { CustomLayoutFunctionArg } from '../../../src'; +import { ListTable, ListColumn, CustomLayout, Group, Text, Tag, Image } from '../../../src'; +import { + Avatar, + Comment, + Card, + Popover, + Space, + Typography, + Button, + Popconfirm, + Message, + Notification +} from '@arco-design/web-react'; +import { IconHeart, IconMessage, IconStar, IconStarFill, IconHeartFill } from '@arco-design/web-react/icon'; +const { Meta } = Card; + +import '@arco-design/web-react/dist/css/arco.css'; + +const CommentComponent = (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); + + return ( + + } + }} + > + ); +}; + +const CommentReactComponent = (props: { name: string }) => { + const { name } = props; + const [like, setLike] = useState(); + const [star, setStar] = useState(); + const actions = [ + , + , + + ]; + return ( + +

Here is the description of this user.

+ + } + > + {name.slice(0, 1)} + + } + content={
Comment body content.
} + datetime="1 hour" + style={{ marginTop: 10, marginLeft: 10 }} + /> + ); +}; + +const OperationComponent = (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); + + return ( + + } + }} + > + ); +}; + +const OperationReactComponent = () => { + return ( + + + { + Message.info({ + content: 'ok' + }); + }} + onCancel={() => { + Message.error({ + content: 'cancel' + }); + }} + > + + + + ); +}; + +function generateRandomString(length: number) { + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * characters.length)); + } + return result; +} + +function App() { + const records = []; + for (let i = 0; i < 50; i++) { + records.push({ + id: i, + name: generateRandomString(8) + }); + } + + return ( + { + // eslint-disable-next-line no-undef + // (window as any).tableInstance = table; + }} + > + + + + + + + + + ); +} + +export default App; 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 new file mode 100644 index 000000000..cfe3c1a14 --- /dev/null +++ b/packages/react-vtable/demo/src/component/custom-layout-dom-site.tsx @@ -0,0 +1,225 @@ +/* eslint-disable max-len */ +import { useEffect, useRef, useState } from 'react'; +import type { CustomLayoutFunctionArg } from '../../../src'; +import { ListTable, ListColumn, CustomLayout, Group, Text, Tag, Image } from '../../../src'; +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 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; + return props.hover ? ( + + dessert + + } + actions={[ + + + , + + + , + + + + ]} + > + + {city.slice(0, 1)} + {city} + + } + title={bloggerName} + description={introduction} + /> + + ) : null; +}; + +function App() { + const records = [ + { + bloggerId: 1, + bloggerName: 'Virtual Anchor Xiaohua', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg', + introduction: + 'Hi everyone, I am Xiaohua, the virtual host. I am a little fairy who likes games, animation and food. I hope to share happy moments with you through live broadcast.', + fansCount: 400, + worksCount: 10, + viewCount: 5, + city: 'Dream City', + tags: ['game', 'anime', 'food'] + }, + { + bloggerId: 2, + bloggerName: 'Virtual anchor little wolf', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg', + introduction: + 'Hello everyone, I am the virtual anchor Little Wolf. I like music, travel and photography, and I hope to explore the beauty of the world with you through live broadcast.', + fansCount: 800, + worksCount: 20, + viewCount: 15, + city: 'City of Music', + tags: ['music', 'travel', 'photography'] + }, + { + bloggerId: 3, + bloggerName: 'Virtual anchor bunny', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg', + introduction: + 'Hello everyone, I am the virtual anchor Xiaotu. I like painting, handicrafts and beauty makeup. I hope to share creativity and fashion with you through live broadcast.', + fansCount: 600, + worksCount: 15, + viewCount: 10, + city: 'City of Art', + tags: ['painting', 'handmade', 'beauty makeup'] + }, + { + bloggerId: 4, + bloggerName: 'Virtual anchor kitten', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg', + introduction: + 'Hello everyone, I am the virtual host Kitty. I am a lazy cat who likes dancing, fitness and cooking. I hope to live a healthy and happy life with everyone through the live broadcast.', + fansCount: 1000, + worksCount: 30, + viewCount: 20, + city: 'Health City', + tags: ['dance', 'fitness', 'cooking'] + }, + { + bloggerId: 5, + bloggerName: 'Virtual anchor Bear', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg', + introduction: + 'Hello everyone, I am the virtual host Xiaoxiong. A little wise man who likes movies, reading and philosophy, I hope to explore the meaning of life with you through live broadcast.', + fansCount: 1200, + worksCount: 25, + viewCount: 18, + city: 'City of Wisdom', + tags: ['Movie', 'Literature'] + }, + { + bloggerId: 6, + bloggerName: 'Virtual anchor bird', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg', + introduction: + 'Hello everyone, I am the virtual anchor Xiaoniao. I like singing, acting and variety shows. I hope to be happy with everyone through the live broadcast.', + fansCount: 900, + worksCount: 12, + viewCount: 8, + city: 'Happy City', + tags: ['music', 'performance', 'variety'] + } + ]; + + return ( + { + // eslint-disable-next-line no-undef + // (window as any).tableInstance = table; + }} + > + + + + + + + + + ); +} + +export default App; diff --git a/packages/react-vtable/demo/src/component/custom-layout-dom.tsx b/packages/react-vtable/demo/src/component/custom-layout-dom.tsx index 93d143f1a..eaf069bfc 100644 --- a/packages/react-vtable/demo/src/component/custom-layout-dom.tsx +++ b/packages/react-vtable/demo/src/component/custom-layout-dom.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef, useState } from 'react'; import type { CustomLayoutFunctionArg } from '../../../src'; -import { ListTable, ListColumn, CustomLayout, Group, Text } from '../../../src'; +import { ListTable, ListColumn, CustomLayout, Group, Text, Tag, Image } from '../../../src'; 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; @@ -150,8 +150,82 @@ const DomCustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: strin ); }; -const CardInfo = (props: { text: string }) => { +const UserProfileComponent = (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); + + // if (row === 2) { + // setHover(true); + // } + 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: { text: string; hover: boolean; row?: number }) => { + return props.hover ? ( { > A - {props.text} + {props.text + props.row} } title="Card Title" description="This is the description" /> - ); + ) : null; }; function App() { @@ -228,7 +302,8 @@ function App() { {/* */} - + {/* */} +
); diff --git a/packages/react-vtable/src/components/custom/component.ts b/packages/react-vtable/src/components/custom/component.ts new file mode 100644 index 000000000..ff691ad20 --- /dev/null +++ b/packages/react-vtable/src/components/custom/component.ts @@ -0,0 +1,15 @@ +import type { ReactElement, ReactNode, Ref, JSXElementConstructor } from 'react'; +import type { VRender } from '@visactor/vtable'; +type IGraphic = VRender.IGraphic; +type TagAttributes = VRender.TagAttributes; +type IEventParamsType = VRender.IEventParamsType; + +type GraphicProps = { + attribute: IGraphicGraphicAttribute; + ref?: Ref; + children?: ReactNode; +} & IEventParamsType; + +export const Tag: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = 'tag' as any; diff --git a/packages/react-vtable/src/components/custom/custom-layout.tsx b/packages/react-vtable/src/components/custom/custom-layout.tsx index f52fac696..f6ef5838e 100644 --- a/packages/react-vtable/src/components/custom/custom-layout.tsx +++ b/packages/react-vtable/src/components/custom/custom-layout.tsx @@ -2,12 +2,13 @@ import type { PropsWithChildren } from 'react'; import React, { isValidElement, useCallback, useContext, useLayoutEffect, useRef } from 'react'; import RootTableContext from '../../context/table'; -import { Group } from '@visactor/vtable/src/vrender'; +import { VRender } from '@visactor/vtable'; import type { ICustomLayoutFuc, CustomRenderFunctionArg } from '@visactor/vtable/src/ts-types'; import type { FiberRoot } from 'react-reconciler'; import { reconcilor } from './reconciler'; import { LegacyRoot } from 'react-reconciler/constants'; +const { Group } = VRender; type CustomLayoutProps = { componentIndex?: number }; export type CustomLayoutFunctionArg = Partial & { diff --git a/packages/react-vtable/src/components/custom/graphic.ts b/packages/react-vtable/src/components/custom/graphic.ts index d053b4d74..b7851f97d 100644 --- a/packages/react-vtable/src/components/custom/graphic.ts +++ b/packages/react-vtable/src/components/custom/graphic.ts @@ -3,21 +3,21 @@ // export const Text = 'text'; import type { ReactElement, ReactNode, Ref, JSXElementConstructor } from 'react'; -import type { - IGraphic, - IGroupGraphicAttribute, - ITextGraphicAttribute, - IEventParamsType, - IArcGraphicAttribute, - ICircleGraphicAttribute, - IImageGraphicAttribute, - ILineGraphicAttribute, - IPathGraphicAttribute, - IRectGraphicAttribute, - ISymbolGraphicAttribute, - IRichTextGraphicAttribute, - IPolygonGraphicAttribute -} from '@visactor/vtable/src/vrender'; +import type { VRender } from '@visactor/vtable'; + +type IGraphic = VRender.IGraphic; +type IGroupGraphicAttribute = VRender.IGroupGraphicAttribute; +type ITextGraphicAttribute = VRender.ITextGraphicAttribute; +type IEventParamsType = VRender.IEventParamsType; +type IArcGraphicAttribute = VRender.IArcGraphicAttribute; +type ICircleGraphicAttribute = VRender.ICircleGraphicAttribute; +type IImageGraphicAttribute = VRender.IImageGraphicAttribute; +type ILineGraphicAttribute = VRender.ILineGraphicAttribute; +type IPathGraphicAttribute = VRender.IPathGraphicAttribute; +type IRectGraphicAttribute = VRender.IRectGraphicAttribute; +type ISymbolGraphicAttribute = VRender.ISymbolGraphicAttribute; +type IRichTextGraphicAttribute = VRender.IRichTextGraphicAttribute; +type IPolygonGraphicAttribute = VRender.IPolygonGraphicAttribute; type GraphicProps = { attribute: IGraphicGraphicAttribute; diff --git a/packages/react-vtable/src/components/custom/reconciler.ts b/packages/react-vtable/src/components/custom/reconciler.ts index 818ce802e..8f2677c9d 100644 --- a/packages/react-vtable/src/components/custom/reconciler.ts +++ b/packages/react-vtable/src/components/custom/reconciler.ts @@ -1,10 +1,11 @@ -import type { Graphic } from '@visactor/vtable/src/vrender'; -import { application, createText, REACT_TO_CANOPUS_EVENTS } from '@visactor/vtable/src/vrender'; +import { VRender } from '@visactor/vtable'; import { isFunction } from '@visactor/vutils'; import React from 'react'; import ReactReconciler from 'react-reconciler'; import { DefaultEventPriority } from 'react-reconciler/constants.js'; +const { application, createText, REACT_TO_CANOPUS_EVENTS, Tag } = VRender; +type Graphic = VRender.Graphic; type Instance = Graphic; export const reconcilor = ReactReconciler({ @@ -134,7 +135,10 @@ reconcilor.injectIntoDevTools({ function createGraphic(type: string, props: any) { // may have unwanted onxxx prop - if (!application.graphicService.creator[type]) { + if (type === 'tag') { + const tag = new Tag(props.attribute); + return tag; + } else if (!application.graphicService.creator[type]) { return; } const graphic = application.graphicService.creator[type]((props as any).attribute); diff --git a/packages/react-vtable/src/components/custom/vtable-browser-env-contribution.ts b/packages/react-vtable/src/components/custom/vtable-browser-env-contribution.ts new file mode 100644 index 000000000..49271ece3 --- /dev/null +++ b/packages/react-vtable/src/components/custom/vtable-browser-env-contribution.ts @@ -0,0 +1,59 @@ +import { getTargetCell, VRender } from '@visactor/vtable'; +import { isString } from '@visactor/vutils'; + +const { ContainerModule, EnvContribution, BrowserEnvContribution } = VRender; +type CreateDOMParamsType = VRender.CreateDOMParamsType; + +export const reactEnvModule = new ContainerModule((bind, unbind, isBound, rebind) => { + bind(VTableBrowserEnvContribution).toSelf().inSingletonScope(); + if (isBound(EnvContribution)) { + rebind(EnvContribution).toService(VTableBrowserEnvContribution); + } else { + bind(EnvContribution).toService(VTableBrowserEnvContribution); + } +}); + +class VTableBrowserEnvContribution extends BrowserEnvContribution { + updateDom(dom: HTMLElement, params: CreateDOMParamsType): boolean { + const tableDiv = dom.parentElement; + if (tableDiv) { + const top = parseInt(params.style.top, 10); + const left = parseInt(params.style.left, 10); + + let domWidth; + let domHeight; + if ((dom.style.display = 'none')) { + const cellGroup = getTargetCell(params.graphic); + domWidth = cellGroup.attribute.width ?? 1; + domHeight = cellGroup.attribute.height ?? 1; + } else { + domWidth = dom.offsetWidth; + domHeight = dom.offsetHeight; + } + if (top + domHeight < 0 || left + domWidth < 0 || top > tableDiv.offsetHeight || left > tableDiv.offsetWidth) { + dom.style.display = 'none'; + return false; + } + } + + const { width, height, style } = params; + + if (style) { + if (isString(style)) { + dom.setAttribute('style', style); + } else { + Object.keys(style).forEach(k => { + dom.style[k] = style[k]; + }); + } + } + if (width != null) { + dom.style.width = `${width}px`; + } + if (height != null) { + dom.style.height = `${height}px`; + } + + return true; + } +} diff --git a/packages/react-vtable/src/components/custom/vtable-react-attribute-plugin.ts b/packages/react-vtable/src/components/custom/vtable-react-attribute-plugin.ts index 4d67f6435..69a573a5d 100644 --- a/packages/react-vtable/src/components/custom/vtable-react-attribute-plugin.ts +++ b/packages/react-vtable/src/components/custom/vtable-react-attribute-plugin.ts @@ -1,6 +1,13 @@ -import type { CreateDOMParamsType, IGraphic, IStage } from '@visactor/vtable/src/vrender'; -import { ReactAttributePlugin, application } from '@visactor/vtable/src/vrender'; -import { isNil } from '@visactor/vutils'; +import { VRender } from '@visactor/vtable'; +import { calculateAnchorOfBounds, isFunction, isNil, isObject, isString, styleStringToObject } from '@visactor/vutils'; + +const { ReactAttributePlugin, application } = VRender; +type CommonDomOptions = VRender.CommonDomOptions; +type CreateDOMParamsType = VRender.CreateDOMParamsType; +type IGraphic = VRender.CreateDOMParamsType; +type IStage = VRender.CreateDOMParamsType; +type IText = VRender.CreateDOMParamsType; +type SimpleDomStyleOptions = VRender.CreateDOMParamsType; export class VTableReactAttributePlugin extends ReactAttributePlugin { removeElement(id: string) { @@ -74,4 +81,89 @@ export class VTableReactAttributePlugin extends ReactAttributePlugin { nativeContainer }; } + + updateStyleOfWrapContainer( + graphic: IGraphic, + stage: IStage, + wrapContainer: HTMLElement, + nativeContainer: HTMLElement, + options: SimpleDomStyleOptions & CommonDomOptions + ) { + const { pointerEvents } = options; + let calculateStyle = this.parseDefaultStyleFromGraphic(graphic); + + calculateStyle.display = graphic.attribute.visible !== false ? 'block' : 'none'; + // 事件穿透 + calculateStyle.pointerEvents = pointerEvents === true ? 'all' : pointerEvents ? pointerEvents : 'none'; + // 定位wrapGroup + if (!wrapContainer.style.position) { + wrapContainer.style.position = 'absolute'; + nativeContainer.style.position = 'relative'; + } + let left: number = 0; + let top: number = 0; + const b = graphic.globalAABBBounds; + + let anchorType = options.anchorType; + + if (isNil(anchorType)) { + anchorType = graphic.type === 'text' ? 'position' : 'boundsLeftTop'; + } + + if (anchorType === 'boundsLeftTop') { + // 兼容老的配置,统一配置 + anchorType = 'top-left'; + } + if (anchorType === 'position' || b.empty()) { + const matrix = graphic.globalTransMatrix; + left = matrix.e; + top = matrix.f; + } else { + const anchor = calculateAnchorOfBounds(b, anchorType); + + left = anchor.x; + top = anchor.y; + } + + // 查看wrapGroup的位置 + // const wrapGroupTL = application.global.getElementTopLeft(wrapGroup, false); + const containerTL = application.global.getElementTopLeft(nativeContainer, false); + const windowTL = stage.window.getTopLeft(false); + const offsetX = left + windowTL.left - containerTL.left; + const offsetTop = top + windowTL.top - containerTL.top; + // wrapGroup.style.transform = `translate(${offsetX}px, ${offsetTop}px)`; + calculateStyle.left = `${offsetX}px`; + calculateStyle.top = `${offsetTop}px`; + + if (graphic.type === 'text' && anchorType === 'position') { + calculateStyle = { + ...calculateStyle, + ...this.getTransformOfText(graphic as IText) + }; + } + + if (isFunction(options.style)) { + const userStyle = options.style( + { top: offsetTop, left: offsetX, width: b.width(), height: b.height() }, + graphic, + wrapContainer + ); + + if (userStyle) { + calculateStyle = { ...calculateStyle, ...userStyle }; + } + } else if (isObject(options.style)) { + calculateStyle = { ...calculateStyle, ...options.style }; + } else if (isString(options.style) && options.style) { + calculateStyle = { ...calculateStyle, ...styleStringToObject(options.style as string) }; + } + + // 更新样式 + application.global.updateDom(wrapContainer, { + width: options.width, + height: options.width, + style: calculateStyle, + graphic + }); + } } diff --git a/packages/react-vtable/src/components/index.ts b/packages/react-vtable/src/components/index.ts index 2988d6055..859f59761 100644 --- a/packages/react-vtable/src/components/index.ts +++ b/packages/react-vtable/src/components/index.ts @@ -10,6 +10,7 @@ export { Tooltip } from './component/tooltip'; export { CustomComponent } from './custom-component'; export { CustomLayout, type CustomLayoutFunctionArg } from './custom/custom-layout'; export * from './custom/graphic'; +export * from './custom/component'; type Props = { updateId?: number }; diff --git a/packages/react-vtable/src/tables/base-table.tsx b/packages/react-vtable/src/tables/base-table.tsx index 094838976..e48678cbe 100644 --- a/packages/react-vtable/src/tables/base-table.tsx +++ b/packages/react-vtable/src/tables/base-table.tsx @@ -23,6 +23,8 @@ import type { } from '../eventsUtils'; import { bindEventsToTable, TABLE_EVENTS_KEYS, TABLE_EVENTS } from '../eventsUtils'; import { VTableReactAttributePlugin } from '../components/custom/vtable-react-attribute-plugin'; +import { reactEnvModule } from '../components/custom/vtable-browser-env-contribution'; +const { container, isBrowserEnv } = VTable.VRender; export type IVTable = VTable.ListTable | VTable.PivotTable | VTable.PivotChart; export type IOption = @@ -50,6 +52,11 @@ export interface BaseTableProps extends EventsProps { onError?: (err: Error) => void; } +// for react-vtable +if (isBrowserEnv()) { + container.load(reactEnvModule); +} + type Props = React.PropsWithChildren; const notOptionKeys = [ diff --git a/packages/vtable/src/components/react/react-custom-layout.ts b/packages/vtable/src/components/react/react-custom-layout.ts index 4b24efc2d..4066d9092 100644 --- a/packages/vtable/src/components/react/react-custom-layout.ts +++ b/packages/vtable/src/components/react/react-custom-layout.ts @@ -73,7 +73,8 @@ export class ReactCustomLayout { table.scenegraph.updateCellContent(col, row); } } - table.scenegraph.updateNextFrame(); + // table.scenegraph.updateNextFrame(); + table.scenegraph.renderSceneGraph(); // use sync render for faster update } getCustomLayoutFunc(col: number, row: number) { diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index a55d0a19f..66a452110 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -535,7 +535,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * 注意 这个值和options.frozenColCount 不一样!options.frozenColCount是用户实际设置的; 这里获取的值是调整过:frozen的列过宽时 frozeCount为0 */ get frozenColCount(): number { - return this.internalProps.layoutMap?.frozenColCount ?? this.internalProps.frozenColCount ?? 0; + return this.internalProps?.layoutMap?.frozenColCount ?? this.internalProps?.frozenColCount ?? 0; } /** * Set the number of frozen columns. @@ -595,7 +595,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * Get the number of frozen rows. */ get frozenRowCount(): number { - return this.internalProps.layoutMap?.frozenRowCount ?? this.internalProps.frozenRowCount ?? 0; + return this.internalProps?.layoutMap?.frozenRowCount ?? this.internalProps?.frozenRowCount ?? 0; } /** * Set the number of frozen rows. @@ -606,7 +606,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { } get rightFrozenColCount(): number { - return this.internalProps.layoutMap?.rightFrozenColCount ?? this.internalProps.rightFrozenColCount ?? 0; + return this.internalProps?.layoutMap?.rightFrozenColCount ?? this.internalProps?.rightFrozenColCount ?? 0; } set rightFrozenColCount(rightFrozenColCount: number) { @@ -614,7 +614,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { } get bottomFrozenRowCount(): number { - return this.internalProps.layoutMap?.bottomFrozenRowCount ?? this.internalProps.bottomFrozenRowCount ?? 0; + return this.internalProps?.layoutMap?.bottomFrozenRowCount ?? this.internalProps?.bottomFrozenRowCount ?? 0; } set bottomFrozenRowCount(bottomFrozenRowCount: number) { diff --git a/packages/vtable/src/index.ts b/packages/vtable/src/index.ts index 5bf04dd23..9841836a2 100644 --- a/packages/vtable/src/index.ts +++ b/packages/vtable/src/index.ts @@ -45,6 +45,9 @@ import { restoreMeasureText, setCustomAlphabetCharSet } from './scenegraph/utils export { getDataCellPath } from './tools/get-data-path'; export * from './render/jsx'; +export { getTargetCell } from './event/util'; + +export * as VRender from './vrender'; export const version = __VERSION__; /** diff --git a/packages/vtable/src/vrender.ts b/packages/vtable/src/vrender.ts index e1e647b7f..ad54c76f9 100644 --- a/packages/vtable/src/vrender.ts +++ b/packages/vtable/src/vrender.ts @@ -1,16 +1,8 @@ import '@visactor/vrender-core'; -import type { CreateDOMParamsType } from '@visactor/vrender-core'; -import { - ContainerModule, - EnvContribution, - container, - isBrowserEnv, - isNodeEnv, - preLoadAllModule -} from '@visactor/vrender-core'; -import { loadBrowserEnv, loadNodeEnv } from '@visactor/vrender-kits'; -import { BrowserEnvContribution } from '@visactor/vrender-kits'; +import { container, isBrowserEnv, isNodeEnv, preLoadAllModule } from '@visactor/vrender-core'; import { + loadBrowserEnv, + loadNodeEnv, registerArc, registerArc3d, registerArea, @@ -30,7 +22,6 @@ import { registerText, registerWrapText } from '@visactor/vrender-kits'; -import { isString } from '@visactor/vutils'; // 导出版本号 // export const version = __VERSION__; @@ -66,60 +57,12 @@ export function registerForVrender() { registerSymbol(); registerText(); registerWrapText(); - - // for react-vtable - if (isBrowserEnv()) { - // bind(BrowserEnvContribution).toSelf().inSingletonScope(); - // bind(EnvContribution).toService(BrowserEnvContribution); - container.load(reactEnvModule); - } } +export { Direction } from '@visactor/vrender-core'; +export { GroupFadeIn } from '@visactor/vrender-core'; +export { GroupFadeOut } from '@visactor/vrender-core'; + export * from '@visactor/vrender-core'; export * from '@visactor/vrender-kits'; - -const reactEnvModule = new ContainerModule(bind => { - bind(VTableBrowserEnvContribution).toSelf().inSingletonScope(); - bind(EnvContribution).toService(VTableBrowserEnvContribution); -}); - -class VTableBrowserEnvContribution extends BrowserEnvContribution { - updateDom(dom: HTMLElement, params: CreateDOMParamsType): boolean { - // debugger; - - const tableDiv = dom.parentElement; - if (tableDiv) { - // const tableRect = tableDiv.getBoundingClientRect(); - - const top = parseInt(params.style.top, 10); - const left = parseInt(params.style.left, 10); - const domWidth = dom.offsetWidth; // TO DO: offsetWidth is 0 when display none - const domHeight = dom.offsetHeight; // TO DO: offsetHeight is 0 when display none - - if (top + domHeight < 0 || left + domWidth < 0 || top > tableDiv.offsetHeight || left > tableDiv.offsetWidth) { - dom.style.display = 'none'; - return false; - } - } - - const { width, height, style } = params; - - if (style) { - if (isString(style)) { - dom.setAttribute('style', style); - } else { - Object.keys(style).forEach(k => { - dom.style[k] = style[k]; - }); - } - } - if (width != null) { - dom.style.width = `${width}px`; - } - if (height != null) { - dom.style.height = `${height}px`; - } - - return true; - } -} +export * from '@visactor/vrender-components'; From a36e7fc410f4ec8ddc814ebb2cc1776cee3361df Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 14 Jun 2024 16:12:11 +0800 Subject: [PATCH 29/85] fix: bugserver case error --- packages/vtable/src/layout/pivot-header-layout.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index c2cb24623..99f65b3f4 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -512,7 +512,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (this.columnHeaderTitle) { this.sharedVar.seqId = Math.max(this.sharedVar.seqId, this._headerObjects.length); const id = ++this.sharedVar.seqId; - const firstRowIds = Array(this.colCount - this.rowHeaderLevelCount).fill(id); + const firstRowIds = Array(this.colCount - this.rowHeaderLevelCount - this.rightFrozenColCount).fill(id); this._columnHeaderCellFullPathIds.unshift(firstRowIds); const cell: HeaderData = { id, From 19b27a19a2109128f8f0e3df8e7a500ca09e535d Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Mon, 17 Jun 2024 17:05:10 +0800 Subject: [PATCH 30/85] fix: cellIsInVisualView api error #1864 --- docs/assets/api/en/methods.md | 8 ++++++ docs/assets/api/zh/methods.md | 8 ++++++ packages/vtable/src/core/BaseTable.ts | 41 +++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/docs/assets/api/en/methods.md b/docs/assets/api/en/methods.md index 6f62321fb..9aeb62807 100644 --- a/docs/assets/api/en/methods.md +++ b/docs/assets/api/en/methods.md @@ -1157,3 +1157,11 @@ set row height. /**set row height */ setRowHeight: (row: number, height: number) ``` + +## cellIsInVisualView(Function) + +Determines whether the cell is in the visible area of the cell. If the cell is completely in the visible area, it returns true. If part or all of the cell is outside the visible area, it returns false. + +``` + cellIsInVisualView(col: number, row: number) +``` diff --git a/docs/assets/api/zh/methods.md b/docs/assets/api/zh/methods.md index 4babb23b7..1109e4fe4 100644 --- a/docs/assets/api/zh/methods.md +++ b/docs/assets/api/zh/methods.md @@ -1155,3 +1155,11 @@ interface ISortedMapItem { /**设置行高 */ setRowHeight: (row: number, height: number) ``` + +## cellIsInVisualView(Function) + +判断单元格是否在单元格可见区域,如果单元格完全都在可见区域才会返回 true,如果有部分或者完全都在可见区域外就返回 false + +``` + cellIsInVisualView(col: number, row: number) +``` diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 723f98989..55fe2af79 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -1625,6 +1625,10 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { const scrollLeft = this.scrollLeft; if (this.isLeftFrozenColumn(startCol) && this.isRightFrozenColumn(endCol)) { width = this.tableNoFrameWidth - (this.getColsWidth(startCol + 1, this.colCount - 1) ?? 0) - absoluteLeft; + // width = + // this.tableNoFrameWidth - + // (this.getColsWidth(0, startCol - 1) ?? 0) - + // (this.getColsWidth(endCol + 1, this.colCount - 1) ?? 0); } else if (this.isLeftFrozenColumn(startCol) && !this.isLeftFrozenColumn(endCol)) { width = Math.max(width - scrollLeft, this.getColsWidth(startCol, this.frozenColCount - 1)); } else if (!this.isRightFrozenColumn(startCol) && this.isRightFrozenColumn(endCol)) { @@ -1642,6 +1646,10 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { const scrollTop = this.scrollTop; if (this.isTopFrozenRow(startRow) && this.isBottomFrozenRow(endRow)) { height = this.tableNoFrameHeight - (this.getRowsHeight(startRow + 1, this.rowCount - 1) ?? 0) - absoluteTop; + // height = + // this.tableNoFrameHeight - + // (this.getRowsHeight(0, startRow - 1) ?? 0) - + // (this.getRowsHeight(endRow + 1, this.rowCount - 1) ?? 0); } else if (this.isTopFrozenRow(startRow) && !this.isTopFrozenRow(endRow)) { height = Math.max(height - scrollTop, this.getRowsHeight(startRow, this.frozenRowCount - 1)); } else if (!this.isBottomFrozenRow(startRow) && this.isBottomFrozenRow(endRow)) { @@ -4112,7 +4120,32 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { row: this.rowCount - 1 } }); - + let bottomFrozenRangeRect; + if (this.bottomFrozenRowCount >= 1) { + bottomFrozenRangeRect = this.getCellRangeRelativeRect({ + start: { + col: 0, + row: this.rowCount - this.bottomFrozenRowCount + }, + end: { + col: this.colCount - 1, + row: this.rowCount - 1 + } + }); + } + let rightFrozenRangeRect; + if (this.rightFrozenColCount >= 1) { + rightFrozenRangeRect = this.getCellRangeRelativeRect({ + start: { + col: this.colCount - this.rightFrozenColCount, + row: 0 + }, + end: { + col: this.colCount - 1, + row: this.rowCount - 1 + } + }); + } if ( rect.top >= drawRange.top && rect.bottom <= drawRange.bottom && @@ -4124,8 +4157,10 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { return true; } else if ( // body cell drawRange do not intersect colHeaderRangeRect&rowHeaderRangeRect - drawRange.top >= colHeaderRangeRect.bottom && - drawRange.left >= rowHeaderRangeRect.right + rect.top >= colHeaderRangeRect.bottom && + rect.left >= rowHeaderRangeRect.right && + rect.bottom <= (bottomFrozenRangeRect?.top ?? rect.bottom) && + rect.right <= (rightFrozenRangeRect?.left ?? rect.right) ) { return true; } From 271aa7c98de4a309cb8f7ffb80f7427d440de945 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Mon, 17 Jun 2024 17:05:30 +0800 Subject: [PATCH 31/85] docs: update changlog of rush --- ...bug-cellIsInVisualView-error_2024-06-17-09-05.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/1864-bug-cellIsInVisualView-error_2024-06-17-09-05.json diff --git a/common/changes/@visactor/vtable/1864-bug-cellIsInVisualView-error_2024-06-17-09-05.json b/common/changes/@visactor/vtable/1864-bug-cellIsInVisualView-error_2024-06-17-09-05.json new file mode 100644 index 000000000..767b24233 --- /dev/null +++ b/common/changes/@visactor/vtable/1864-bug-cellIsInVisualView-error_2024-06-17-09-05.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: cellIsInVisualView api error #1864\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From 84a421511eabff13a289f3b70bc0873d36c1b1d7 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Mon, 17 Jun 2024 17:36:37 +0800 Subject: [PATCH 32/85] fix: cellIsInVisualView api error #1864 --- .../options/listTable-api-with-frozen.test.ts | 119 ++++++++++++++++++ packages/vtable/src/core/BaseTable.ts | 53 ++++---- 2 files changed, 148 insertions(+), 24 deletions(-) create mode 100644 packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts diff --git a/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts b/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts new file mode 100644 index 000000000..b4f5d8240 --- /dev/null +++ b/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts @@ -0,0 +1,119 @@ +// @ts-nocheck +// 有问题可对照demo unitTestListTable +import records from '../data/marketsales.json'; +import { ListTable } from '../../src/ListTable'; +import { createDiv } from '../dom'; +global.__VERSION__ = 'none'; +describe('listTable init test', () => { + const containerDom: HTMLElement = createDiv(); + containerDom.style.position = 'relative'; + containerDom.style.width = '1000px'; + containerDom.style.height = '800px'; + const columns = [ + { + field: '订单 ID', + caption: '订单 ID', + sort: true, + width: 'auto', + description: '这是订单的描述信息', + style: { + fontFamily: 'Arial', + fontSize: 14 + } + }, + { + field: '订单日期', + caption: '订单日期' + }, + { + field: '发货日期', + caption: '发货日期' + }, + { + field: '客户名称', + caption: '客户名称', + style: { + padding: [10, 0, 10, 60] + } + }, + { + field: '邮寄方式', + caption: '邮寄方式' + }, + { + field: '省/自治区', + caption: '省/自治区' + }, + { + field: '产品名称', + caption: '产品名称' + }, + { + field: '类别', + caption: '类别' + }, + { + field: '子类别', + caption: '子类别' + }, + { + field: '销售额', + caption: '销售额' + }, + { + field: '数量', + caption: '数量' + }, + { + field: '折扣', + caption: '折扣' + }, + { + field: '利润', + caption: '利润' + } + ]; + const option = { + columns, + defaultColWidth: 150, + frozenColCount: 2, + rightFrozenColCount: 2, + bottomFrozenRowCount: 2 + }; + + option.container = containerDom; + option.records = records; + const listTable = new ListTable(option); + test('listTable cellIsInVisualView', () => { + expect(listTable.cellIsInVisualView(3, 0)).toBe(true); + expect(listTable.cellIsInVisualView(0, 3)).toBe(true); + expect(listTable.cellIsInVisualView(5, 3)).toBe(false); + expect(listTable.cellIsInVisualView(4, 3)).toBe(false); + expect(listTable.cellIsInVisualView(3, 3)).toBe(true); + expect(listTable.cellIsInVisualView(3, 39)).toBe(true); + expect(listTable.cellIsInVisualView(3, 38)).toBe(true); + + expect(listTable.cellIsInVisualView(12, 3)).toBe(true); + expect(listTable.cellIsInVisualView(11, 3)).toBe(true); + expect(listTable.cellIsInVisualView(10, 3)).toBe(false); + + expect(listTable.cellIsInVisualView(3, 37)).toBe(false); + }); + + test('listTable scroll cellIsInVisualView', () => { + listTable.scrollTop = 100; + listTable.scrollLeft = 100; + expect(listTable.cellIsInVisualView(3, 5)).toBe(true); + expect(listTable.cellIsInVisualView(2, 5)).toBe(false); + expect(listTable.cellIsInVisualView(5, 5)).toBe(false); + expect(listTable.cellIsInVisualView(4, 5)).toBe(true); + expect(listTable.cellIsInVisualView(12, 5)).toBe(true); + + expect(listTable.cellIsInVisualView(3, 19)).toBe(true); + expect(listTable.cellIsInVisualView(3, 20)).toBe(false); + expect(listTable.cellIsInVisualView(2, 19)).toBe(false); + + expect(listTable.cellIsInVisualView(3, 39)).toBe(true); + expect(listTable.cellIsInVisualView(3, 38)).toBe(true); + }); +}); diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 55fe2af79..8a6faa10f 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -4099,27 +4099,32 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { if (col < this.frozenColCount && row < this.frozenRowCount) { return true; } - - const colHeaderRangeRect = this.getCellRangeRelativeRect({ - start: { - col: 0, - row: 0 - }, - end: { - col: this.colCount - 1, - row: this.columnHeaderLevelCount - } - }); - const rowHeaderRangeRect = this.getCellRangeRelativeRect({ - start: { - col: 0, - row: 0 - }, - end: { - col: this.rowHeaderLevelCount, - row: this.rowCount - 1 - } - }); + let colHeaderRangeRect; + if (this.frozenRowCount >= 1) { + colHeaderRangeRect = this.getCellRangeRelativeRect({ + start: { + col: 0, + row: 0 + }, + end: { + col: this.colCount - 1, + row: this.frozenRowCount - 1 + } + }); + } + let rowHeaderRangeRect; + if (this.frozenColCount >= 1) { + rowHeaderRangeRect = this.getCellRangeRelativeRect({ + start: { + col: 0, + row: 0 + }, + end: { + col: this.frozenColCount - 1, + row: this.rowCount - 1 + } + }); + } let bottomFrozenRangeRect; if (this.bottomFrozenRowCount >= 1) { bottomFrozenRangeRect = this.getCellRangeRelativeRect({ @@ -4153,12 +4158,12 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { rect.right <= drawRange.right ) { // return true; - if (this.isHeader(col, row)) { + if (this.isFrozenCell(col, row)) { return true; } else if ( // body cell drawRange do not intersect colHeaderRangeRect&rowHeaderRangeRect - rect.top >= colHeaderRangeRect.bottom && - rect.left >= rowHeaderRangeRect.right && + rect.top >= (colHeaderRangeRect?.bottom ?? rect.top) && + rect.left >= (rowHeaderRangeRect?.right ?? rect.left) && rect.bottom <= (bottomFrozenRangeRect?.top ?? rect.bottom) && rect.right <= (rightFrozenRangeRect?.left ?? rect.right) ) { From 17c62cf3928f5f324035273ca5b008f832dee408 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Mon, 17 Jun 2024 18:19:59 +0800 Subject: [PATCH 33/85] fix: if set style autoWrapText, this config not wort when resize column width #1892 --- packages/vtable/src/scenegraph/layout/update-width.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/vtable/src/scenegraph/layout/update-width.ts b/packages/vtable/src/scenegraph/layout/update-width.ts index 23aacadaa..cb8199392 100644 --- a/packages/vtable/src/scenegraph/layout/update-width.ts +++ b/packages/vtable/src/scenegraph/layout/update-width.ts @@ -429,7 +429,10 @@ function updateCellWidth( ); isHeightChange = isHeightChange || cellChange; } - + if (!autoWrapText) { + const style = scene.table._getCellStyle(col, row); + autoWrapText = style.autoWrapText; + } return autoRowHeight && autoWrapText ? isHeightChange : false; } From 4b1cc105f0775009396fe3ba92cba1eafee17bb8 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Mon, 17 Jun 2024 18:20:17 +0800 Subject: [PATCH 34/85] docs: update changlog of rush --- ...utowraptext-computerowheight_2024-06-17-10-20.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/1892-bug-autowraptext-computerowheight_2024-06-17-10-20.json diff --git a/common/changes/@visactor/vtable/1892-bug-autowraptext-computerowheight_2024-06-17-10-20.json b/common/changes/@visactor/vtable/1892-bug-autowraptext-computerowheight_2024-06-17-10-20.json new file mode 100644 index 000000000..1ee4c9a80 --- /dev/null +++ b/common/changes/@visactor/vtable/1892-bug-autowraptext-computerowheight_2024-06-17-10-20.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: if set style autoWrapText, this config not wort when resize column width #1892\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From a4ccd7587311dfa510b79eb2c3e6be59a042ed54 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Mon, 17 Jun 2024 18:39:39 +0800 Subject: [PATCH 35/85] feat: add blankAreaClickDeselect and outsideClickDeselect config --- docs/assets/option/en/common/option-secondary.md | 8 ++++++++ docs/assets/option/en/table/listTable.md | 7 ------- docs/assets/option/zh/common/option-secondary.md | 8 ++++++++ docs/assets/option/zh/table/listTable.md | 8 -------- packages/vtable/src/event/listener/table-group.ts | 4 ++-- packages/vtable/src/ts-types/base-table.ts | 7 ++++--- 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/docs/assets/option/en/common/option-secondary.md b/docs/assets/option/en/common/option-secondary.md index c6875d736..7e73ffd4c 100644 --- a/docs/assets/option/en/common/option-secondary.md +++ b/docs/assets/option/en/common/option-secondary.md @@ -213,6 +213,14 @@ Do not respond to mouse select interaction. Separately set the header not to respond to mouse select interaction. +##${prefix} blankAreaClickDeselect(boolean) = false + +Whether to cancel the selection when clicking the blank area. + +##${prefix} outsideClickDeselect(boolean) = true + +Whether to cancel the selection when clicking outside the table. + #${prefix} theme(Object) {{ use: common-theme( diff --git a/docs/assets/option/en/table/listTable.md b/docs/assets/option/en/table/listTable.md index 79e1f2f8b..5b768db54 100644 --- a/docs/assets/option/en/table/listTable.md +++ b/docs/assets/option/en/table/listTable.md @@ -32,13 +32,6 @@ Whether to transpose, default is false Whether to display the table header. -## blankAreaClickDeselect(boolean) = false - -Whether to cancel the selection when clicking the blank area. - -## outsideClickDeselect(boolean) = true - -Whether to cancel the selection when clicking outside the table. ## pagination(IPagination) diff --git a/docs/assets/option/zh/common/option-secondary.md b/docs/assets/option/zh/common/option-secondary.md index 0d173fbfc..660fe7d7f 100644 --- a/docs/assets/option/zh/common/option-secondary.md +++ b/docs/assets/option/zh/common/option-secondary.md @@ -208,6 +208,14 @@ hover 交互响应模式:十字交叉、整列、整行或者单个单元格 单独设置表头不响应鼠标 select 交互。 +##${prefix} blankAreaClickDeselect(boolean) = false + +点击空白区域是否取消选中。 + +##${prefix} outsideClickDeselect(boolean) = true + +点击外部区域是否取消选中。 + #${prefix} theme(Object) {{ use: common-theme( diff --git a/docs/assets/option/zh/table/listTable.md b/docs/assets/option/zh/table/listTable.md index 52011c3a2..f2c1a6d81 100644 --- a/docs/assets/option/zh/table/listTable.md +++ b/docs/assets/option/zh/table/listTable.md @@ -32,14 +32,6 @@ 是否显示表头。 -## blankAreaClickDeselect(boolean) = false - -点击空白区域是否取消选中。 - -## outsideClickDeselect(boolean) = true - -点击外部区域是否取消选中。 - ## pagination(IPagination) 分页配置。 diff --git a/packages/vtable/src/event/listener/table-group.ts b/packages/vtable/src/event/listener/table-group.ts index 6536072d1..4882d89d6 100644 --- a/packages/vtable/src/event/listener/table-group.ts +++ b/packages/vtable/src/event/listener/table-group.ts @@ -338,7 +338,7 @@ export function bindTableGroupListener(eventManager: EventManager) { stateManager.updateInteractionState(InteractionState.default); eventManager.dealTableHover(); //点击到表格外部不需要取消选中状态 - if (table.options.outsideClickDeselect) { + if (table.options.select?.outsideClickDeselect) { eventManager.dealTableSelect(); } }); @@ -734,7 +734,7 @@ export function bindTableGroupListener(eventManager: EventManager) { stateManager.endSelectCells(); // 点击空白区域取消选中 - if (table.options.blankAreaClickDeselect ?? true) { + if (table.options.select?.blankAreaClickDeselect ?? true) { eventManager.dealTableSelect(); } diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index b6b2c2d32..dcb2d878a 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -338,6 +338,10 @@ export interface BaseTableConstructorOptions { disableSelect?: boolean; /** 单独设置表头不响应鼠标select交互 */ disableHeaderSelect?: boolean; + /** 点击空白区域是否取消选中 */ + blankAreaClickDeselect?: boolean; + /** 点击外部区域是否取消选中 */ + outsideClickDeselect?: boolean; // }; /** 下拉菜单的相关配置。消失时机:显示后点击菜单区域外自动消失*/ menu?: { @@ -455,9 +459,6 @@ export interface BaseTableConstructorOptions { animationAppear?: boolean | IAnimationAppear; renderOption?: any; - - blankAreaClickDeselect?: boolean; //点击空白区域是否取消选中 - outsideClickDeselect?: boolean; //点击外部区域是否取消选中 } export interface BaseTableAPI { /** 数据总条目数 */ From a16269465cbd601b2be7e8ee8b13d992bd3be3d3 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Mon, 17 Jun 2024 18:39:56 +0800 Subject: [PATCH 36/85] docs: update changlog of rush --- .../feat-add-deselect-option_2024-06-17-10-39.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/feat-add-deselect-option_2024-06-17-10-39.json diff --git a/common/changes/@visactor/vtable/feat-add-deselect-option_2024-06-17-10-39.json b/common/changes/@visactor/vtable/feat-add-deselect-option_2024-06-17-10-39.json new file mode 100644 index 000000000..37e02dfc2 --- /dev/null +++ b/common/changes/@visactor/vtable/feat-add-deselect-option_2024-06-17-10-39.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "feat: add blankAreaClickDeselect and outsideClickDeselect config\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From a7baec45fd1a7f9cc81bda5f9179c99cd6333e98 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 17 Jun 2024 11:53:31 +0000 Subject: [PATCH 37/85] build: prelease version 1.3.2 --- ...IsInVisualView-error_2024-06-17-09-05.json | 11 -------- ...actor-tooltip-scroll_2024-06-12-08-25.json | 11 -------- ...ext-computerowheight_2024-06-17-10-20.json | 11 -------- ...able-corner-emptyTip_2024-06-13-10-12.json | 11 -------- ...upplement-indicators_2024-06-14-04-14.json | 11 -------- ...-add-deselect-option_2024-06-17-10-39.json | 11 -------- common/config/rush/version-policies.json | 2 +- packages/openinula-vtable/package.json | 2 +- packages/react-vtable/package.json | 2 +- packages/vtable-editors/package.json | 2 +- packages/vtable-export/package.json | 2 +- packages/vtable-search/package.json | 2 +- packages/vtable/CHANGELOG.json | 27 +++++++++++++++++++ packages/vtable/CHANGELOG.md | 26 +++++++++++++++++- packages/vtable/package.json | 2 +- 15 files changed, 59 insertions(+), 74 deletions(-) delete mode 100644 common/changes/@visactor/vtable/1864-bug-cellIsInVisualView-error_2024-06-17-09-05.json delete mode 100644 common/changes/@visactor/vtable/1887-refactor-tooltip-scroll_2024-06-12-08-25.json delete mode 100644 common/changes/@visactor/vtable/1892-bug-autowraptext-computerowheight_2024-06-17-10-20.json delete mode 100644 common/changes/@visactor/vtable/1895-feature-pivotTable-corner-emptyTip_2024-06-13-10-12.json delete mode 100644 common/changes/@visactor/vtable/1924-refactor-rowtree-not-supplement-indicators_2024-06-14-04-14.json delete mode 100644 common/changes/@visactor/vtable/feat-add-deselect-option_2024-06-17-10-39.json diff --git a/common/changes/@visactor/vtable/1864-bug-cellIsInVisualView-error_2024-06-17-09-05.json b/common/changes/@visactor/vtable/1864-bug-cellIsInVisualView-error_2024-06-17-09-05.json deleted file mode 100644 index 767b24233..000000000 --- a/common/changes/@visactor/vtable/1864-bug-cellIsInVisualView-error_2024-06-17-09-05.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: cellIsInVisualView api error #1864\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/1887-refactor-tooltip-scroll_2024-06-12-08-25.json b/common/changes/@visactor/vtable/1887-refactor-tooltip-scroll_2024-06-12-08-25.json deleted file mode 100644 index b64c46845..000000000 --- a/common/changes/@visactor/vtable/1887-refactor-tooltip-scroll_2024-06-12-08-25.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "refactor: tooltip support scroll #1887\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/1892-bug-autowraptext-computerowheight_2024-06-17-10-20.json b/common/changes/@visactor/vtable/1892-bug-autowraptext-computerowheight_2024-06-17-10-20.json deleted file mode 100644 index 1ee4c9a80..000000000 --- a/common/changes/@visactor/vtable/1892-bug-autowraptext-computerowheight_2024-06-17-10-20.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: if set style autoWrapText, this config not wort when resize column width #1892\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/1895-feature-pivotTable-corner-emptyTip_2024-06-13-10-12.json b/common/changes/@visactor/vtable/1895-feature-pivotTable-corner-emptyTip_2024-06-13-10-12.json deleted file mode 100644 index 8c9d2bda3..000000000 --- a/common/changes/@visactor/vtable/1895-feature-pivotTable-corner-emptyTip_2024-06-13-10-12.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "refactor: when not records pivot table can show corner header #1895\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/1924-refactor-rowtree-not-supplement-indicators_2024-06-14-04-14.json b/common/changes/@visactor/vtable/1924-refactor-rowtree-not-supplement-indicators_2024-06-14-04-14.json deleted file mode 100644 index 567afa823..000000000 --- a/common/changes/@visactor/vtable/1924-refactor-rowtree-not-supplement-indicators_2024-06-14-04-14.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "refactor: when rowTree children not set value can supplement indicators #1924\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/feat-add-deselect-option_2024-06-17-10-39.json b/common/changes/@visactor/vtable/feat-add-deselect-option_2024-06-17-10-39.json deleted file mode 100644 index 37e02dfc2..000000000 --- a/common/changes/@visactor/vtable/feat-add-deselect-option_2024-06-17-10-39.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "feat: add blankAreaClickDeselect and outsideClickDeselect config\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json index 9a44c9ac4..45c56d49c 100644 --- a/common/config/rush/version-policies.json +++ b/common/config/rush/version-policies.json @@ -1 +1 @@ -[{"definitionName":"lockStepVersion","policyName":"vtableMain","version":"1.3.1","mainProject":"@visactor/vtable","nextBump":"patch"}] +[{"definitionName":"lockStepVersion","policyName":"vtableMain","version":"1.3.2","mainProject":"@visactor/vtable","nextBump":"patch"}] diff --git a/packages/openinula-vtable/package.json b/packages/openinula-vtable/package.json index 392432517..dcdc28bcf 100644 --- a/packages/openinula-vtable/package.json +++ b/packages/openinula-vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/openinula-vtable", - "version": "1.3.1", + "version": "1.3.2", "description": "The openinula version of VTable", "keywords": [ "openinula", diff --git a/packages/react-vtable/package.json b/packages/react-vtable/package.json index 7ca7478ab..a53afa788 100644 --- a/packages/react-vtable/package.json +++ b/packages/react-vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vtable", - "version": "1.3.1", + "version": "1.3.2", "description": "The react version of VTable", "keywords": [ "react", diff --git a/packages/vtable-editors/package.json b/packages/vtable-editors/package.json index 24b9475f9..b9bcf90ed 100644 --- a/packages/vtable-editors/package.json +++ b/packages/vtable-editors/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-editors", - "version": "1.3.1", + "version": "1.3.2", "description": "", "sideEffects": false, "main": "cjs/index.js", diff --git a/packages/vtable-export/package.json b/packages/vtable-export/package.json index f2f9258e8..05d524594 100644 --- a/packages/vtable-export/package.json +++ b/packages/vtable-export/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-export", - "version": "1.3.1", + "version": "1.3.2", "description": "The export util of VTable", "author": { "name": "VisActor", diff --git a/packages/vtable-search/package.json b/packages/vtable-search/package.json index 7f4b6764c..160440955 100644 --- a/packages/vtable-search/package.json +++ b/packages/vtable-search/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-search", - "version": "1.3.1", + "version": "1.3.2", "description": "The search util of VTable", "author": { "name": "VisActor", diff --git a/packages/vtable/CHANGELOG.json b/packages/vtable/CHANGELOG.json index 891471756..b81762de2 100644 --- a/packages/vtable/CHANGELOG.json +++ b/packages/vtable/CHANGELOG.json @@ -1,6 +1,33 @@ { "name": "@visactor/vtable", "entries": [ + { + "version": "1.3.2", + "tag": "@visactor/vtable_v1.3.2", + "date": "Mon, 17 Jun 2024 11:51:18 GMT", + "comments": { + "none": [ + { + "comment": "fix: cellIsInVisualView api error #1864\n\n" + }, + { + "comment": "refactor: tooltip support scroll #1887\n\n" + }, + { + "comment": "fix: if set style autoWrapText, this config not wort when resize column width #1892\n\n" + }, + { + "comment": "refactor: when not records pivot table can show corner header #1895\n\n" + }, + { + "comment": "refactor: when rowTree children not set value can supplement indicators #1924\n\n" + }, + { + "comment": "feat: add blankAreaClickDeselect and outsideClickDeselect config\n\n" + } + ] + } + }, { "version": "1.3.1", "tag": "@visactor/vtable_v1.3.1", diff --git a/packages/vtable/CHANGELOG.md b/packages/vtable/CHANGELOG.md index 5300b57a4..9cae5822a 100644 --- a/packages/vtable/CHANGELOG.md +++ b/packages/vtable/CHANGELOG.md @@ -1,6 +1,30 @@ # Change Log - @visactor/vtable -This log was last generated on Thu, 13 Jun 2024 12:35:49 GMT and should not be manually modified. +This log was last generated on Mon, 17 Jun 2024 11:51:18 GMT and should not be manually modified. + +## 1.3.2 +Mon, 17 Jun 2024 11:51:18 GMT + +### Updates + +- fix: cellIsInVisualView api error #1864 + + +- refactor: tooltip support scroll #1887 + + +- fix: if set style autoWrapText, this config not wort when resize column width #1892 + + +- refactor: when not records pivot table can show corner header #1895 + + +- refactor: when rowTree children not set value can supplement indicators #1924 + + +- feat: add blankAreaClickDeselect and outsideClickDeselect config + + ## 1.3.1 Thu, 13 Jun 2024 12:35:49 GMT diff --git a/packages/vtable/package.json b/packages/vtable/package.json index 3e8667bda..5205664b8 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable", - "version": "1.3.1", + "version": "1.3.2", "description": "canvas table width high performance", "keywords": [ "grid", From 2379b7b7946f2fc9ba6db8ef543f0e64ee269171 Mon Sep 17 00:00:00 2001 From: fangsmile Date: Mon, 17 Jun 2024 12:07:13 +0000 Subject: [PATCH 38/85] docs: generate changelog of release v1.3.2 --- docs/assets/changelog/en/release.md | 24 ++++++++++++++++++++++++ docs/assets/changelog/zh/release.md | 24 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/docs/assets/changelog/en/release.md b/docs/assets/changelog/en/release.md index 2d2ec6d11..0b0b0299b 100644 --- a/docs/assets/changelog/en/release.md +++ b/docs/assets/changelog/en/release.md @@ -1,3 +1,27 @@ +# v1.3.2 + +2024-06-17 + + +**🆕 New feature** + +- **@visactor/vtable**: add blankAreaClickDeselect and outsideClickDeselect config + +**🐛 Bug fix** + +- **@visactor/vtable**: cellIsInVisualView api error [#1864](https://github.com/VisActor/VTable/issues/1864) +- **@visactor/vtable**: if set style autoWrapText, this config not wort when resize column width [#1892](https://github.com/VisActor/VTable/issues/1892) + +**🔨 Refactor** + +- **@visactor/vtable**: tooltip support scroll [#1887](https://github.com/VisActor/VTable/issues/1887) +- **@visactor/vtable**: when not records pivot table can show corner header [#1895](https://github.com/VisActor/VTable/issues/1895) +- **@visactor/vtable**: when rowTree children not set value can supplement indicators [#1924](https://github.com/VisActor/VTable/issues/1924) + + + +[more detail about v1.3.2](https://github.com/VisActor/VTable/releases/tag/v1.3.2) + # v1.3.1 2024-06-14 diff --git a/docs/assets/changelog/zh/release.md b/docs/assets/changelog/zh/release.md index 9914c9c63..c70e7fb73 100644 --- a/docs/assets/changelog/zh/release.md +++ b/docs/assets/changelog/zh/release.md @@ -1,3 +1,27 @@ +# v1.3.2 + +2024-06-17 + + +**🆕 新增功能** + +- **@visactor/vtable**: add blankAreaClickDeselect and outsideClickDeselect config + +**🐛 功能修复** + +- **@visactor/vtable**: cellIsInVisualView api error [#1864](https://github.com/VisActor/VTable/issues/1864) +- **@visactor/vtable**: if set style autoWrapText, this config not wort when resize column width [#1892](https://github.com/VisActor/VTable/issues/1892) + +**🔨 功能重构** + +- **@visactor/vtable**: tooltip support scroll [#1887](https://github.com/VisActor/VTable/issues/1887) +- **@visactor/vtable**: when not records pivot table can show corner header [#1895](https://github.com/VisActor/VTable/issues/1895) +- **@visactor/vtable**: when rowTree children not set value can supplement indicators [#1924](https://github.com/VisActor/VTable/issues/1924) + + + +[更多详情请查看 v1.3.2](https://github.com/VisActor/VTable/releases/tag/v1.3.2) + # v1.3.1 2024-06-14 From 821dc87bf53350cce1f4a97e41d64641fe25b97d Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Mon, 17 Jun 2024 20:25:30 +0800 Subject: [PATCH 39/85] feat: update vrender to 0.19.11 --- packages/vtable/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/vtable/package.json b/packages/vtable/package.json index 8b71e0604..b26876866 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -50,9 +50,9 @@ }, "dependencies": { "@visactor/vtable-editors": "workspace:*", - "@visactor/vrender-core": "0.19.10-beta.1", - "@visactor/vrender-kits": "0.19.10-beta.1", - "@visactor/vrender-components": "0.19.10-beta.1", + "@visactor/vrender-core": "0.19.11", + "@visactor/vrender-kits": "0.19.11", + "@visactor/vrender-components": "0.19.11", "@visactor/vutils-extension": "~1.10.4", "@visactor/vutils": "~0.18.9", "@visactor/vscale": "~0.18.1", From 41b4de631609d51eba9e9011113ded3fe726517e Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Mon, 17 Jun 2024 22:10:09 +0800 Subject: [PATCH 40/85] chore: update lock file --- common/config/rush/pnpm-lock.yaml | 80 +++++++++---------------------- 1 file changed, 22 insertions(+), 58 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 6b40de576..2f4a522a7 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -284,9 +284,9 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/vchart': 1.11.0 '@visactor/vdataset': ~0.18.1 - '@visactor/vrender-components': 0.19.10-beta.1 - '@visactor/vrender-core': 0.19.10-beta.1 - '@visactor/vrender-kits': 0.19.10-beta.1 + '@visactor/vrender-components': 0.19.11 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vscale': ~0.18.1 '@visactor/vtable-editors': workspace:* '@visactor/vutils': ~0.18.9 @@ -329,13 +329,13 @@ importers: vite-plugin-markdown: ^2.1.0 dependencies: '@visactor/vdataset': 0.18.9 - '@visactor/vrender-components': 0.19.10-beta.1 - '@visactor/vrender-core': 0.19.10-beta.1 - '@visactor/vrender-kits': 0.19.10-beta.1 + '@visactor/vrender-components': 0.19.11 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vscale': 0.18.9 '@visactor/vtable-editors': link:../vtable-editors '@visactor/vutils': 0.18.9 - '@visactor/vutils-extension': 1.10.6_qgpfome4zioasfo4kveemvva7q + '@visactor/vutils-extension': 1.10.6_xvirkzyiilnqycicfhae6ydv24 cssfontparser: 1.2.1 devDependencies: '@babel/core': 7.20.12 @@ -2331,7 +2331,7 @@ packages: jest-resolve: 26.6.2 jest-resolve-dependencies: 26.6.3 jest-runner: 26.6.3_ts-node@10.9.0 - jest-runtime: 26.6.3 + jest-runtime: 26.6.3_ts-node@10.9.0 jest-snapshot: 26.6.2 jest-util: 26.6.2 jest-validate: 26.6.2 @@ -2492,7 +2492,7 @@ packages: graceful-fs: 4.2.11 jest-haste-map: 26.6.2 jest-runner: 26.6.3_ts-node@10.9.0 - jest-runtime: 26.6.3 + jest-runtime: 26.6.3_ts-node@10.9.0 transitivePeerDependencies: - bufferutil - canvas @@ -3769,11 +3769,11 @@ packages: '@visactor/vscale': 0.17.5 '@visactor/vutils': 0.18.9 - /@visactor/vrender-components/0.19.10-beta.1: - resolution: {integrity: sha512-OQaxEYOAwHIAcXqkqqtwQYejOg3mFDgH1h050VLotWyIcItTvvZxwhXPbeLcPryWzR4PaoUTGPVOM7XNoqKzEQ==} + /@visactor/vrender-components/0.19.11: + resolution: {integrity: sha512-K9967q364GojufVIlEVxr9duE/ce7tHsBTHxWHjx+uGAiJy3gmG3Vx2Ch38yoDZorR47X+YFjBSJoIqNVOwi8Q==} dependencies: - '@visactor/vrender-core': 0.19.10-beta.1 - '@visactor/vrender-kits': 0.19.10-beta.1 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vscale': 0.18.9 '@visactor/vutils': 0.18.9 dev: false @@ -3784,8 +3784,8 @@ packages: '@visactor/vutils': 0.18.9 color-convert: 2.0.1 - /@visactor/vrender-core/0.19.10-beta.1: - resolution: {integrity: sha512-vOpEtwRgb3JpXWSgHzHnartVZlw9B8y6tQ4gOs117J5jhVcSuv2KT28oLuj3wqZsSybOhr/Di7HFIibfo80dRw==} + /@visactor/vrender-core/0.19.11: + resolution: {integrity: sha512-an0zfDMJy9ygsXY1w2xSN2nWbUmy97YrBNDEvm0Nb/kS6tNpeB8G6z5t8KO2ivq5aVZihCIJv8342/yGOnDHfg==} dependencies: '@visactor/vutils': 0.18.9 color-convert: 2.0.1 @@ -3799,11 +3799,11 @@ packages: '@visactor/vutils': 0.18.9 roughjs: 4.5.2 - /@visactor/vrender-kits/0.19.10-beta.1: - resolution: {integrity: sha512-Xu8VJXscdproiMF+1AA+Te89qRPnEGoWyV9Hham97NbTg/z2AWb9NhQsNu+8O3TYugbX3tOhbKbPnIgFr+tgeQ==} + /@visactor/vrender-kits/0.19.11: + resolution: {integrity: sha512-ZzVZKVrRCuxC8+awhG3yxTwE8/qZpSTNCettTsTNs12oifeN6m+z2mvCSdHcOUn5Hw/FJyTFm2Bv2HmFNerQhw==} dependencies: '@resvg/resvg-js': 2.4.1 - '@visactor/vrender-core': 0.19.10-beta.1 + '@visactor/vrender-core': 0.19.11 '@visactor/vutils': 0.18.9 roughjs: 4.5.2 dev: false @@ -3818,15 +3818,15 @@ packages: dependencies: '@visactor/vutils': 0.18.9 - /@visactor/vutils-extension/1.10.6_qgpfome4zioasfo4kveemvva7q: + /@visactor/vutils-extension/1.10.6_xvirkzyiilnqycicfhae6ydv24: resolution: {integrity: sha512-MxB5fNb1YJ6PSJRtE+jJGYKiDVM6POxt/2zvAAW7uSj06/gDIh9/luy/MLuRMtWnY3a+s/VSnlGg5WAzkRCsZg==} peerDependencies: '@visactor/vrender-components': '>=0.18' '@visactor/vrender-core': '>=0.18' dependencies: '@visactor/vdataset': 0.18.9 - '@visactor/vrender-components': 0.19.10-beta.1 - '@visactor/vrender-core': 0.19.10-beta.1 + '@visactor/vrender-components': 0.19.11 + '@visactor/vrender-core': 0.19.11 '@visactor/vscale': 0.18.9 '@visactor/vutils': 0.18.9 dev: false @@ -8877,7 +8877,7 @@ packages: jest-leak-detector: 26.6.2 jest-message-util: 26.6.2 jest-resolve: 26.6.2 - jest-runtime: 26.6.3 + jest-runtime: 26.6.3_ts-node@10.9.0 jest-util: 26.6.2 jest-worker: 26.6.2 source-map-support: 0.5.21 @@ -8922,42 +8922,6 @@ packages: - supports-color dev: true - /jest-runtime/26.6.3: - resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==} - engines: {node: '>= 10.14.2'} - hasBin: true - dependencies: - '@jest/console': 26.6.2 - '@jest/environment': 26.6.2 - '@jest/fake-timers': 26.6.2 - '@jest/globals': 26.6.2 - '@jest/source-map': 26.6.2 - '@jest/test-result': 26.6.2 - '@jest/transform': 26.6.2 - '@jest/types': 26.6.2 - '@types/yargs': 15.0.19 - chalk: 4.1.2 - cjs-module-lexer: 0.6.0 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-config: 26.6.3_ts-node@10.9.0 - jest-haste-map: 26.6.2 - jest-message-util: 26.6.2 - jest-mock: 26.6.2 - jest-regex-util: 26.0.0 - jest-resolve: 26.6.2 - jest-snapshot: 26.6.2 - jest-util: 26.6.2 - jest-validate: 26.6.2 - slash: 3.0.0 - strip-bom: 4.0.0 - yargs: 15.4.1 - transitivePeerDependencies: - - supports-color - dev: true - /jest-runtime/26.6.3_ts-node@10.9.0: resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==} engines: {node: '>= 10.14.2'} From 53e994b1c7d831e7001078147d7a009a3383c542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E7=A5=A5=E8=BE=89?= Date: Tue, 18 Jun 2024 12:34:46 +0800 Subject: [PATCH 41/85] docs: Change the url of tooltip_custom_content demo --- ...to customize the content of a tooltip in a pop-up box.md | 6 +++--- ...to customize the content of a tooltip in a pop-up box.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/assets/faq/en/5-How to customize the content of a tooltip in a pop-up box.md b/docs/assets/faq/en/5-How to customize the content of a tooltip in a pop-up box.md index 4f67e7746..ebf1a2903 100644 --- a/docs/assets/faq/en/5-How to customize the content of a tooltip in a pop-up box.md +++ b/docs/assets/faq/en/5-How to customize the content of a tooltip in a pop-up box.md @@ -6,7 +6,7 @@ When hovering the mouse over a cell, I want to display contextual information ab ## Solution -One flexible approach is to listen to the `mouseenter_cell` and `mouseleave_cell` events of the VTable instance. Show or hide the custom DOM elements accordingly, and calculate the position to display the tooltip based on the `cellRange` parameter from the VTable event. Demo: https://visactor.io/vtable/demo/example/component/tooltip_custom_content +One flexible approach is to listen to the `mouseenter_cell` and `mouseleave_cell` events of the VTable instance. Show or hide the custom DOM elements accordingly, and calculate the position to display the tooltip based on the `cellRange` parameter from the VTable event. Demo: https://visactor.io/vtable/demo/component/tooltip_custom_content ## Code Example @@ -23,12 +23,12 @@ tableInstance.on('mouseleave_cell', args => { ## Results -[Online demo](https://visactor.io/vtable/demo/example/component/tooltip_custom_content) +[Online demo](https://visactor.io/vtable/demo/component/tooltip_custom_content) ![result](/vtable/faq/5-0.png) ## Quote -- [Table tooltip demo](https://visactor.io/vtable/demo/example/component/tooltip_custom_content) +- [Table tooltip demo](https://visactor.io/vtable/demo/component/tooltip_custom_content) - [Tooltip Tutorial](https://visactor.io/vtable/guide/components/tooltip) - [github](https://github.com/VisActor/VTable) diff --git a/docs/assets/faq/zh/5-How to customize the content of a tooltip in a pop-up box.md b/docs/assets/faq/zh/5-How to customize the content of a tooltip in a pop-up box.md index 5b70b6cac..d81fd454b 100644 --- a/docs/assets/faq/zh/5-How to customize the content of a tooltip in a pop-up box.md +++ b/docs/assets/faq/zh/5-How to customize the content of a tooltip in a pop-up box.md @@ -6,7 +6,7 @@ ## 解决方案 -提供一种比较灵活的方式:监听 VTable 实例的事件 `mouseenter_cell` 和 `mouseleave_cell` 事件,将自定义的 dom 展示和隐藏,并依据 VTable 事件参数中的 `cellRange` 计算展示 tooltip 的位置。具体可以参考 demo:https://visactor.io/vtable/demo/example/component/tooltip_custom_content +提供一种比较灵活的方式:监听 VTable 实例的事件 `mouseenter_cell` 和 `mouseleave_cell` 事件,将自定义的 dom 展示和隐藏,并依据 VTable 事件参数中的 `cellRange` 计算展示 tooltip 的位置。具体可以参考 demo:https://visactor.io/vtable/demo/component/tooltip_custom_content ## 代码示例 @@ -23,12 +23,12 @@ tableInstance.on('mouseleave_cell', args => { ## 结果展示 -[在线效果参考](https://visactor.io/vtable/demo/example/component/tooltip_custom_content) +[在线效果参考](https://visactor.io/vtable/demo/component/tooltip_custom_content) ![result](/vtable/faq/5-0.png) ## 相关文档 -- [表格 tooltip demo](https://visactor.io/vtable/demo/example/component/tooltip_custom_content) +- [表格 tooltip demo](https://visactor.io/vtable/demo/component/tooltip_custom_content) - [Tooltip 教程](https://visactor.io/vtable/guide/components/tooltip) - [github](https://github.com/VisActor/VTable) From 9d9a3634675fbbcb0dda749682239900ff027ad7 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 18 Jun 2024 12:35:08 +0800 Subject: [PATCH 42/85] fix: fix react-vtable build error --- .../demo/src/component/custom-layout-dom-site-1.tsx | 2 ++ .../demo/src/component/custom-layout-dom-site.tsx | 2 ++ .../demo/src/component/custom-layout-dom.tsx | 2 ++ packages/react-vtable/src/index.ts | 4 +--- packages/react-vtable/src/tables/base-table.tsx | 10 ++++++---- packages/react-vtable/src/vtable.ts | 3 +++ 6 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 packages/react-vtable/src/vtable.ts diff --git a/packages/react-vtable/demo/src/component/custom-layout-dom-site-1.tsx b/packages/react-vtable/demo/src/component/custom-layout-dom-site-1.tsx index c4256eb2a..01c20fbcd 100644 --- a/packages/react-vtable/demo/src/component/custom-layout-dom-site-1.tsx +++ b/packages/react-vtable/demo/src/component/custom-layout-dom-site-1.tsx @@ -1,4 +1,5 @@ import { useEffect, useRef, useState } from 'react'; +import ReactDOM from 'react-dom/client'; import type { CustomLayoutFunctionArg } from '../../../src'; import { ListTable, ListColumn, CustomLayout, Group, Text, Tag, Image } from '../../../src'; import { @@ -168,6 +169,7 @@ function App() { // eslint-disable-next-line no-undef // (window as any).tableInstance = table; }} + ReactDOM={ReactDOM} > 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 cfe3c1a14..7191c10e9 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 @@ -1,5 +1,6 @@ /* eslint-disable max-len */ import { useEffect, useRef, useState } from 'react'; +import ReactDOM from 'react-dom/client'; import type { CustomLayoutFunctionArg } from '../../../src'; import { ListTable, ListColumn, CustomLayout, Group, Text, Tag, Image } from '../../../src'; import { Avatar, Button, Card, Popover, Space, Typography } from '@arco-design/web-react'; @@ -210,6 +211,7 @@ function App() { // eslint-disable-next-line no-undef // (window as any).tableInstance = table; }} + ReactDOM={ReactDOM} > diff --git a/packages/react-vtable/demo/src/component/custom-layout-dom.tsx b/packages/react-vtable/demo/src/component/custom-layout-dom.tsx index eaf069bfc..b74f63dd7 100644 --- a/packages/react-vtable/demo/src/component/custom-layout-dom.tsx +++ b/packages/react-vtable/demo/src/component/custom-layout-dom.tsx @@ -1,4 +1,5 @@ import { useEffect, useRef, useState } from 'react'; +import ReactDOM from 'react-dom/client'; import type { CustomLayoutFunctionArg } from '../../../src'; import { ListTable, ListColumn, CustomLayout, Group, Text, Tag, Image } from '../../../src'; import { Avatar, Button, Card, Popover, Space, Typography } from '@arco-design/web-react'; @@ -296,6 +297,7 @@ function App() { // eslint-disable-next-line no-undef (window as any).tableInstance = table; }} + ReactDOM={ReactDOM} > diff --git a/packages/react-vtable/src/index.ts b/packages/react-vtable/src/index.ts index 9f2eccb9f..a8295390a 100644 --- a/packages/react-vtable/src/index.ts +++ b/packages/react-vtable/src/index.ts @@ -1,7 +1,5 @@ -import * as VTable from '@visactor/vtable'; - export * from './tables'; export * from './components'; -export { VTable }; +export * from './vtable'; export const version = __VERSION__; diff --git a/packages/react-vtable/src/tables/base-table.tsx b/packages/react-vtable/src/tables/base-table.tsx index e48678cbe..079f7c395 100644 --- a/packages/react-vtable/src/tables/base-table.tsx +++ b/packages/react-vtable/src/tables/base-table.tsx @@ -1,7 +1,7 @@ /* eslint-disable react/display-name */ -import * as VTable from '@visactor/vtable'; +// import * as VTable from '@visactor/vtable'; +import { VTable } from '../vtable'; import React, { useState, useEffect, useRef, useImperativeHandle, useCallback } from 'react'; -import ReactDOM from 'react-dom/client'; import type { ContainerProps } from '../containers/withContainer'; import withContainer from '../containers/withContainer'; import type { TableContextType } from '../context/table'; @@ -46,6 +46,8 @@ export interface BaseTableProps extends EventsProps { height?: number; skipFunctionDiff?: boolean; + ReactDOM?: any; + /** 表格渲染完成事件 */ onReady?: (instance: IVTable, isInitial: boolean) => void; /** throw error when chart run into an error */ @@ -159,9 +161,9 @@ const BaseTable: React.FC = React.forwardRef((props, ref) => { vtable = new VTable.ListTable(props.container, parseOption(props)); } // vtable.scenegraph.stage.enableReactAttribute(ReactDOM); - vtable.scenegraph.stage.reactAttribute = ReactDOM; + vtable.scenegraph.stage.reactAttribute = props.ReactDOM; vtable.scenegraph.stage.pluginService.register(new VTableReactAttributePlugin()); - vtable.scenegraph.stage.params.ReactDOM = ReactDOM; + vtable.scenegraph.stage.params.ReactDOM = props.ReactDOM; tableContext.current = { ...tableContext.current, table: vtable }; isUnmount.current = false; }, diff --git a/packages/react-vtable/src/vtable.ts b/packages/react-vtable/src/vtable.ts new file mode 100644 index 000000000..552cc5503 --- /dev/null +++ b/packages/react-vtable/src/vtable.ts @@ -0,0 +1,3 @@ +import * as VTable from '@visactor/vtable'; + +export { VTable }; From cd09dbdafd3a4d88255e3d24b7c84f8d886c4b2e Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Tue, 18 Jun 2024 20:05:06 +0800 Subject: [PATCH 43/85] feat: support calculate field for PivotTable #1941 --- packages/vtable/examples/menu.ts | 8 + .../pivot-analysis-calculatedField.ts | 169 ++++++++ .../pivot-analysis-calculatedField2.ts | 181 +++++++++ packages/vtable/src/dataset/dataset.ts | 375 ++++++++++++------ .../vtable/src/dataset/statistics-helper.ts | 255 ++++++++---- packages/vtable/src/ts-types/new-data-set.ts | 18 +- 6 files changed, 802 insertions(+), 204 deletions(-) create mode 100644 packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField.ts create mode 100644 packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField2.ts diff --git a/packages/vtable/examples/menu.ts b/packages/vtable/examples/menu.ts index cdba02a22..3d00442e0 100644 --- a/packages/vtable/examples/menu.ts +++ b/packages/vtable/examples/menu.ts @@ -524,6 +524,14 @@ export const menus = [ { path: 'pivot-analysis', name: 'pivot-empty-tip' + }, + { + path: 'pivot-analysis', + name: 'pivot-analysis-calculatedField' + }, + { + path: 'pivot-analysis', + name: 'pivot-analysis-calculatedField2' } ] }, diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField.ts new file mode 100644 index 000000000..7611d4e58 --- /dev/null +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField.ts @@ -0,0 +1,169 @@ +import * as VTable from '../../src'; +import { bindDebugTool } from '../../src/scenegraph/debug-tool'; +const PivotTable = VTable.PivotTable; +const CONTAINER_ID = 'vTable'; + +let tableInstance; +fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_data.json') + .then(res => res.json()) + .then(data => { + const option: VTable.PivotTableConstructorOptions = { + records: data, + rows: [ + { + dimensionKey: 'Category', + title: 'Category', + headerStyle: { + textStick: true + }, + width: 'auto' + }, + { + dimensionKey: 'Sub-Category', + title: 'Sub-Catogery', + headerStyle: { + textStick: true + }, + width: 'auto' + } + ], + columns: [ + { + dimensionKey: 'Year', + title: 'Year', + headerStyle: { + textStick: true + } + }, + { + dimensionKey: 'Month', + title: 'Month', + headerStyle: { + textStick: true + } + } + ], + indicators: [ + { + indicatorKey: 'Quantity', + title: 'Quantity', + width: 'auto', + showSort: false, + headerStyle: { + fontWeight: 'normal' + }, + style: { + padding: [16, 28, 16, 28], + color(args) { + if (args.dataValue >= 0) { + return 'black'; + } + return 'red'; + } + } + }, + { + indicatorKey: 'Sales', + title: 'Sales', + width: 'auto', + showSort: false, + headerStyle: { + fontWeight: 'normal' + }, + format: rec => { + return '$' + Number(rec).toFixed(2); + }, + style: { + padding: [16, 28, 16, 28], + color(args) { + if (args.dataValue >= 0) { + return 'black'; + } + return 'red'; + } + } + }, + { + indicatorKey: 'Profit', + title: 'Profit', + width: 'auto', + showSort: false, + headerStyle: { + fontWeight: 'normal' + }, + format: rec => { + return '$' + Number(rec).toFixed(2); + }, + style: { + padding: [16, 28, 16, 28], + color(args) { + if (args.dataValue >= 0) { + return 'black'; + } + return 'red'; + } + } + }, + { + indicatorKey: 'calField1', + title: 'AvgPrice', + width: 'auto', + format: rec => { + return '$' + Number(rec).toFixed(2); + }, + style: { + color: 'blue' + } + } + ], + corner: { + titleOnDimension: 'row', + headerStyle: {} + }, + dataConfig: { + derivedFieldRules: [ + { + fieldName: 'Year', + derivedFunc: VTable.DataStatistics.dateFormat('Order Date', '%y', true) + }, + { + fieldName: 'Month', + derivedFunc: VTable.DataStatistics.dateFormat('Order Date', '%n', true) + } + ], + calculatedFieldRules: [ + { + key: 'calField1', + dependIndicatorKeys: ['Quantity', 'Sales'], + calculateFun: (dependValue: any) => { + return dependValue.Sales / dependValue.Quantity; + } + } + ], + totals: { + row: { + showGrandTotals: true, + showSubTotals: true, + subTotalsDimensions: ['Category'], + grandTotalLabel: '行总计', + subTotalLabel: '小计' + }, + column: { + showGrandTotals: true, + showSubTotals: true, + subTotalsDimensions: ['Year'], + grandTotalLabel: '列总计', + subTotalLabel: '小计' + } + } + }, + widthMode: 'standard' + }; + tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); + window.tableInstance = tableInstance; + + bindDebugTool(tableInstance.scenegraph.stage, { customGrapicKeys: ['col', 'row'] }); + }) + .catch(e => { + console.error(e); + }); diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField2.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField2.ts new file mode 100644 index 000000000..fc89419f0 --- /dev/null +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField2.ts @@ -0,0 +1,181 @@ +import * as VTable from '../../src'; +import { bindDebugTool } from '../../src/scenegraph/debug-tool'; +const PivotTable = VTable.PivotTable; +const CONTAINER_ID = 'vTable'; + +let tableInstance; +fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_data.json') + .then(res => res.json()) + .then(data => { + const option: VTable.PivotTableConstructorOptions = { + records: data, + rows: [ + { + dimensionKey: 'Category', + title: 'Category', + headerStyle: { + textStick: true + }, + width: 'auto' + }, + { + dimensionKey: 'Sub-Category', + title: 'Sub-Catogery', + headerStyle: { + textStick: true + }, + width: 'auto' + } + ], + columns: [ + { + dimensionKey: 'Year', + title: 'Year', + headerStyle: { + textStick: true + } + }, + { + dimensionKey: 'Month', + title: 'Month', + headerStyle: { + textStick: true + } + } + ], + indicators: [ + // { + // indicatorKey: 'Quantity', + // title: 'Quantity', + // width: 'auto', + // showSort: false, + // headerStyle: { + // fontWeight: 'normal' + // }, + // style: { + // padding: [16, 28, 16, 28], + // color(args) { + // if (args.dataValue >= 0) { + // return 'black'; + // } + // return 'red'; + // } + // } + // }, + // { + // indicatorKey: 'Sales', + // title: 'Sales', + // width: 'auto', + // showSort: false, + // headerStyle: { + // fontWeight: 'normal' + // }, + // format: rec => { + // return '$' + Number(rec).toFixed(2); + // }, + // style: { + // padding: [16, 28, 16, 28], + // color(args) { + // if (args.dataValue >= 0) { + // return 'black'; + // } + // return 'red'; + // } + // } + // }, + { + indicatorKey: 'Profit', + title: 'Profit', + width: 'auto', + showSort: false, + headerStyle: { + fontWeight: 'normal' + }, + format: rec => { + return '$' + Number(rec).toFixed(2); + }, + style: { + padding: [16, 28, 16, 28], + color(args) { + if (args.dataValue >= 0) { + return 'black'; + } + return 'red'; + } + } + }, + { + indicatorKey: 'calField1', + title: 'AvgPrice', + width: 'auto', + format: rec => { + return '$' + Number(rec).toFixed(2); + }, + style: { + color: 'blue' + } + } + ], + corner: { + titleOnDimension: 'row', + headerStyle: {} + }, + dataConfig: { + derivedFieldRules: [ + { + fieldName: 'Year', + derivedFunc: VTable.DataStatistics.dateFormat('Order Date', '%y', true) + }, + { + fieldName: 'Month', + derivedFunc: VTable.DataStatistics.dateFormat('Order Date', '%n', true) + } + ], + aggregationRules: [ + { + indicatorKey: 'QuantitySum', + field: 'Quantity', + aggregationType: VTable.TYPES.AggregationType.SUM + }, + { + indicatorKey: 'SalesSum', + field: 'Sales', + aggregationType: VTable.TYPES.AggregationType.SUM + } + ], + calculatedFieldRules: [ + { + key: 'calField1', + dependIndicatorKeys: ['QuantitySum', 'SalesSum'], + calculateFun: (dependValue: any) => { + return dependValue.SalesSum / dependValue.QuantitySum; + } + } + ], + totals: { + row: { + showGrandTotals: true, + showSubTotals: true, + subTotalsDimensions: ['Category'], + grandTotalLabel: '行总计', + subTotalLabel: '小计' + }, + column: { + showGrandTotals: true, + showSubTotals: true, + subTotalsDimensions: ['Year'], + grandTotalLabel: '列总计', + subTotalLabel: '小计' + } + } + }, + widthMode: 'standard' + }; + tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); + window.tableInstance = tableInstance; + + bindDebugTool(tableInstance.scenegraph.stage, { customGrapicKeys: ['col', 'row'] }); + }) + .catch(e => { + console.error(e); + }); diff --git a/packages/vtable/src/dataset/dataset.ts b/packages/vtable/src/dataset/dataset.ts index 7407f69b9..ae273d9f7 100644 --- a/packages/vtable/src/dataset/dataset.ts +++ b/packages/vtable/src/dataset/dataset.ts @@ -19,7 +19,8 @@ import type { CollectValueBy, CollectedValue, IIndicator, - IPivotChartDataConfig + IPivotChartDataConfig, + CalculateddFieldRules } from '../ts-types'; import { AggregationType, SortType } from '../ts-types'; import type { Aggregator, IAggregator } from './statistics-helper'; @@ -29,6 +30,7 @@ import { MaxAggregator, MinAggregator, NoneAggregator, + RecalculateAggregator, RecordAggregator, SumAggregator, naturalSort, @@ -86,6 +88,9 @@ export class Dataset { //派生字段规则 derivedFieldRules?: DerivedFieldRules; mappingRules?: MappingRules; + calculatedFieldRules?: CalculateddFieldRules; + calculatedFiledKeys?: string[]; + calculatedFieldDependIndicatorKeys?: string[]; //汇总配置 totals?: Totals; //全局统计各指标的极值 @@ -93,12 +98,16 @@ export class Dataset { aggregators: { [key: string]: { - new ( - dimension: string | string[], - formatFun?: any, - isRecord?: boolean, - needSplitPositiveAndNegative?: boolean - ): Aggregator; + new (args: { + key: string; + dimension: string | string[]; + formatFun?: any; + isRecord?: boolean; + needSplitPositiveAndNegative?: boolean; + calculateFun?: any; + dependAggregators?: any; + dependIndicatorKeys?: string[]; + }): Aggregator; }; } = {}; @@ -119,6 +128,7 @@ export class Dataset { columns: string[]; columnsHasValue: boolean[]; //columns中的key是否有在records中体现 indicatorKeys: string[]; + indicatorKeysIncludeCalculatedFieldDependIndicatorKeys: string[]; customRowTree?: IHeaderTreeDefine[]; customColTree?: IHeaderTreeDefine[]; // // 存储行表头path 这个是全量的 对比于分页截取的rowKeysPath; @@ -152,10 +162,31 @@ export class Dataset { this.aggregationRules = this.dataConfig?.aggregationRules; this.derivedFieldRules = this.dataConfig?.derivedFieldRules; this.mappingRules = this.dataConfig?.mappingRules; + this.calculatedFieldRules = this.dataConfig?.calculatedFieldRules; + this.calculatedFiledKeys = this.calculatedFieldRules?.map(rule => rule.key); + this.calculatedFieldDependIndicatorKeys = this.calculatedFieldRules.reduce((arr: string[], rule) => { + for (let i = 0; i < rule.dependIndicatorKeys.length; i++) { + if (arr.indexOf(rule.dependIndicatorKeys[i]) === -1) { + arr.push(rule.dependIndicatorKeys[i]); + } + } + return arr; + }, []); this.totals = this.dataConfig?.totals; this.rows = rows; this.columns = columns; this.indicatorKeys = indicatorKeys; + this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys = [...indicatorKeys]; + + for (let m = 0; m < this.calculatedFieldDependIndicatorKeys.length; m++) { + if ( + this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys.indexOf( + this.calculatedFieldDependIndicatorKeys[m] + ) === -1 + ) { + this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys.push(this.calculatedFieldDependIndicatorKeys[m]); + } + } this.indicatorsAsCol = indicatorsAsCol; this.indicators = indicators; this.customColTree = customColTree; @@ -330,6 +361,7 @@ export class Dataset { this.registerAggregator(AggregationType.MIN, MinAggregator); this.registerAggregator(AggregationType.AVG, AvgAggregator); this.registerAggregator(AggregationType.NONE, NoneAggregator); + this.registerAggregator(AggregationType.RECALCULATE, RecalculateAggregator); } /**processRecord中按照collectValuesBy 收集了维度值。现在需要对有聚合需求的 处理收集维度值范围 */ private processCollectedValuesWithSumBy() { @@ -648,9 +680,11 @@ export class Dataset { if (!this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i]) { this.totalRecordsTree[flatRowKey][flatColKey][i] = new this.aggregators[ aggRule?.aggregationType ?? AggregationType.SUM - ]( - aggRule?.field ?? this.indicatorKeys[i], - aggRule?.formatFun ?? + ]({ + key: this.indicatorKeys[i], + dimension: aggRule?.field ?? this.indicatorKeys[i], + formatFun: + aggRule?.formatFun ?? ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { @@ -659,7 +693,7 @@ export class Dataset { return false; }) as IIndicator )?.format - ); + }); } //push融合了计算过程 @@ -687,20 +721,42 @@ export class Dataset { } //组织树结构: 行-列-单元格 行key为flatRowKey如’山东青岛‘ 列key为flatColKey如’家具椅子‘ - // TODO 原先pivotTable是必须有行或列维度的 pivotChart这里强制进入 - if (true || colKey.length !== 0 || rowKey.length !== 0) { - if (!this.tree[flatRowKey]) { - this.tree[flatRowKey] = {}; - } - //这里改成数组 因为可能是多个指标值 遍历indicators 生成对应类型的聚合对象 - if (!this.tree[flatRowKey]?.[flatColKey]) { - this.tree[flatRowKey][flatColKey] = []; - } - for (let i = 0; i < this.indicatorKeys.length; i++) { - const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); + if (!this.tree[flatRowKey]) { + this.tree[flatRowKey] = {}; + } + //这里改成数组 因为可能是多个指标值 遍历indicators 生成对应类型的聚合对象 + if (!this.tree[flatRowKey]?.[flatColKey]) { + this.tree[flatRowKey][flatColKey] = []; + } + + const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; + for (let i = 0; i < toComputeIndicatorKeys.length; i++) { + if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { + const calculatedFieldRule = this.calculatedFieldRules?.find(rule => rule.key === toComputeIndicatorKeys[i]); + if (!this.tree[flatRowKey]?.[flatColKey]?.[i]) { + this.tree[flatRowKey][flatColKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ + key: toComputeIndicatorKeys[i], + dimension: toComputeIndicatorKeys[i], + isRecord: true, + formatFun: ( + this.indicators?.find((indicator: string | IIndicator) => { + if (typeof indicator !== 'string') { + return indicator.indicatorKey === toComputeIndicatorKeys[i]; + } + return false; + }) as IIndicator + )?.format, + calculateFun: calculatedFieldRule?.calculateFun, + dependAggregators: this.tree[flatRowKey][flatColKey], + dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys + }); + } + this.tree[flatRowKey]?.[flatColKey]?.[i].push(record); + } else { + const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); let needAddToAggregator = false; if (assignedIndicatorKey) { - this.indicatorKeys[i] === assignedIndicatorKey && (needAddToAggregator = true); + toComputeIndicatorKeys[i] === assignedIndicatorKey && (needAddToAggregator = true); } //加入聚合结果 考虑field为数组的情况 else if (aggRule?.field) { @@ -714,21 +770,23 @@ export class Dataset { } } else { //push融合了计算过程 - this.indicatorKeys[i] in record && (needAddToAggregator = true); + toComputeIndicatorKeys[i] in record && (needAddToAggregator = true); } if (!this.tree[flatRowKey]?.[flatColKey]?.[i] && needAddToAggregator) { - this.tree[flatRowKey][flatColKey][i] = new this.aggregators[aggRule?.aggregationType ?? AggregationType.SUM]( - aggRule?.field ?? this.indicatorKeys[i], - aggRule?.formatFun ?? + this.tree[flatRowKey][flatColKey][i] = new this.aggregators[aggRule?.aggregationType ?? AggregationType.SUM]({ + key: toComputeIndicatorKeys[i], + dimension: aggRule?.field ?? toComputeIndicatorKeys[i], + formatFun: + aggRule?.formatFun ?? ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { - return indicator.indicatorKey === this.indicatorKeys[i]; + return indicator.indicatorKey === toComputeIndicatorKeys[i]; } return false; }) as IIndicator )?.format - ); + }); } if (needAddToAggregator) { @@ -736,17 +794,26 @@ export class Dataset { } } } + //统计整体的最大最小值和总计值 共mapping使用 if (this.mappingRules) { for (let i = 0; i < this.indicatorKeys.length; i++) { if (!this.indicatorStatistics[i]) { const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); this.indicatorStatistics[i] = { - max: new this.aggregators[AggregationType.MAX](this.indicatorKeys[i]), - min: new this.aggregators[AggregationType.MIN](this.indicatorKeys[i]), - total: new this.aggregators[aggRule?.aggregationType ?? AggregationType.SUM]( - aggRule?.field ?? this.indicatorKeys[i], - aggRule?.formatFun ?? + max: new this.aggregators[AggregationType.MAX]({ + key: this.indicatorKeys[i], + dimension: this.indicatorKeys[i] + }), + min: new this.aggregators[AggregationType.MIN]({ + key: this.indicatorKeys[i], + dimension: this.indicatorKeys[i] + }), + total: new this.aggregators[aggRule?.aggregationType ?? AggregationType.SUM]({ + key: this.indicatorKeys[i], + dimension: aggRule?.field ?? this.indicatorKeys[i], + formatFun: + aggRule?.formatFun ?? ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { @@ -755,7 +822,7 @@ export class Dataset { return false; }) as IIndicator )?.format - ) + }) }; } //push融合了计算过程 @@ -1191,7 +1258,6 @@ export class Dataset { * @param flatColKey */ const colCompute = (flatRowKey: string, flatColKey: string) => { - console.log('totalStatistics', flatRowKey); if (this.totalRecordsTree?.[flatRowKey]?.[flatColKey]) { // 利用汇总数据替换 this.tree[flatRowKey][flatColKey] = this.totalRecordsTree?.[flatRowKey]?.[flatColKey]; @@ -1216,25 +1282,54 @@ export class Dataset { if (!this.tree[flatRowKey][flatColTotalKey]) { this.tree[flatRowKey][flatColTotalKey] = []; } - for (let i = 0; i < this.indicatorKeys.length; i++) { - if (!this.tree[flatRowKey][flatColTotalKey][i]) { - const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); - this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[ - aggRule?.aggregationType ?? AggregationType.SUM - ]( - aggRule?.field ?? this.indicatorKeys[i], - aggRule?.formatFun ?? - ( + const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; + + for (let i = 0; i < toComputeIndicatorKeys.length; i++) { + if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { + const calculatedFieldRule = this.calculatedFieldRules?.find( + rule => rule.key === toComputeIndicatorKeys[i] + ); + if (!this.tree[flatRowKey]?.[flatColTotalKey]?.[i]) { + this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ + key: toComputeIndicatorKeys[i], + dimension: toComputeIndicatorKeys[i], + isRecord: true, + formatFun: ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { - return indicator.indicatorKey === this.indicatorKeys[i]; + return indicator.indicatorKey === toComputeIndicatorKeys[i]; } return false; }) as IIndicator - )?.format - ); + )?.format, + calculateFun: calculatedFieldRule?.calculateFun, + dependAggregators: this.tree[flatRowKey][flatColTotalKey], + dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys + }); + } + this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); + } else { + if (!this.tree[flatRowKey][flatColTotalKey][i]) { + const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); + this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[ + aggRule?.aggregationType ?? AggregationType.SUM + ]({ + key: toComputeIndicatorKeys[i], + dimension: aggRule?.field ?? toComputeIndicatorKeys[i], + formatFun: + aggRule?.formatFun ?? + ( + this.indicators?.find((indicator: string | IIndicator) => { + if (typeof indicator !== 'string') { + return indicator.indicatorKey === toComputeIndicatorKeys[i]; + } + return false; + }) as IIndicator + )?.format + }); + } + this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); } - this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); } } } @@ -1249,25 +1344,53 @@ export class Dataset { if (!this.tree[flatRowKey][flatColTotalKey]) { this.tree[flatRowKey][flatColTotalKey] = []; } - for (let i = 0; i < this.indicatorKeys.length; i++) { - if (!this.tree[flatRowKey][flatColTotalKey][i]) { - const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); - this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[ - aggRule?.aggregationType ?? AggregationType.SUM - ]( - aggRule?.field ?? this.indicatorKeys[i], - aggRule?.formatFun ?? - ( + const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; + for (let i = 0; i < toComputeIndicatorKeys.length; i++) { + if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { + const calculatedFieldRule = this.calculatedFieldRules?.find( + rule => rule.key === toComputeIndicatorKeys[i] + ); + if (!this.tree[flatRowKey]?.[flatColTotalKey]?.[i]) { + this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ + key: toComputeIndicatorKeys[i], + dimension: toComputeIndicatorKeys[i], + isRecord: true, + formatFun: ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { - return indicator.indicatorKey === this.indicatorKeys[i]; + return indicator.indicatorKey === toComputeIndicatorKeys[i]; } return false; }) as IIndicator - )?.format - ); + )?.format, + calculateFun: calculatedFieldRule?.calculateFun, + dependAggregators: this.tree[flatRowKey][flatColTotalKey], + dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys + }); + } + this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); + } else { + if (!this.tree[flatRowKey][flatColTotalKey][i]) { + const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); + this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[ + aggRule?.aggregationType ?? AggregationType.SUM + ]({ + key: toComputeIndicatorKeys[i], + dimension: aggRule?.field ?? toComputeIndicatorKeys[i], + formatFun: + aggRule?.formatFun ?? + ( + this.indicators?.find((indicator: string | IIndicator) => { + if (typeof indicator !== 'string') { + return indicator.indicatorKey === toComputeIndicatorKeys[i]; + } + return false; + }) as IIndicator + )?.format + }); + } + this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); } - this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); } } }; @@ -1292,23 +1415,48 @@ export class Dataset { if (!this.tree[flatRowTotalKey][flatColKey]) { this.tree[flatRowTotalKey][flatColKey] = []; } - for (let i = 0; i < this.indicatorKeys.length; i++) { + const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; + for (let i = 0; i < toComputeIndicatorKeys.length; i++) { if (!this.tree[flatRowTotalKey][flatColKey][i]) { - const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); - this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[ - aggRule?.aggregationType ?? AggregationType.SUM - ]( - aggRule?.field ?? this.indicatorKeys[i], - aggRule?.formatFun ?? - ( + if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { + const calculatedFieldRule = this.calculatedFieldRules?.find( + rule => rule.key === toComputeIndicatorKeys[i] + ); + this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ + key: toComputeIndicatorKeys[i], + dimension: toComputeIndicatorKeys[i], + isRecord: true, + formatFun: ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { - return indicator.indicatorKey === this.indicatorKeys[i]; + return indicator.indicatorKey === toComputeIndicatorKeys[i]; } return false; }) as IIndicator - )?.format - ); + )?.format, + calculateFun: calculatedFieldRule?.calculateFun, + dependAggregators: this.tree[flatRowTotalKey][flatColKey], + dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys + }); + } else { + const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); + this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[ + aggRule?.aggregationType ?? AggregationType.SUM + ]({ + key: toComputeIndicatorKeys[i], + dimension: aggRule?.field ?? toComputeIndicatorKeys[i], + formatFun: + aggRule?.formatFun ?? + ( + this.indicators?.find((indicator: string | IIndicator) => { + if (typeof indicator !== 'string') { + return indicator.indicatorKey === toComputeIndicatorKeys[i]; + } + return false; + }) as IIndicator + )?.format + }); + } } this.tree[flatRowTotalKey][flatColKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); } @@ -1325,23 +1473,48 @@ export class Dataset { if (!this.tree[flatRowTotalKey][flatColKey]) { this.tree[flatRowTotalKey][flatColKey] = []; } - for (let i = 0; i < this.indicatorKeys.length; i++) { + const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; + for (let i = 0; i < toComputeIndicatorKeys.length; i++) { if (!this.tree[flatRowTotalKey][flatColKey][i]) { - const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); - this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[ - aggRule?.aggregationType ?? AggregationType.SUM - ]( - aggRule?.field ?? this.indicatorKeys[i], - aggRule?.formatFun ?? - ( + if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { + const calculatedFieldRule = this.calculatedFieldRules?.find( + rule => rule.key === toComputeIndicatorKeys[i] + ); + this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ + key: toComputeIndicatorKeys[i], + dimension: toComputeIndicatorKeys[i], + isRecord: true, + formatFun: ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { - return indicator.indicatorKey === this.indicatorKeys[i]; + return indicator.indicatorKey === toComputeIndicatorKeys[i]; } return false; }) as IIndicator - )?.format - ); + )?.format, + calculateFun: calculatedFieldRule?.calculateFun, + dependAggregators: this.tree[flatRowTotalKey][flatColKey], + dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys + }); + } else { + const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); + this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[ + aggRule?.aggregationType ?? AggregationType.SUM + ]({ + key: toComputeIndicatorKeys[i], + dimension: aggRule?.field ?? toComputeIndicatorKeys[i], + formatFun: + aggRule?.formatFun ?? + ( + this.indicators?.find((indicator: string | IIndicator) => { + if (typeof indicator !== 'string') { + return indicator.indicatorKey === toComputeIndicatorKeys[i]; + } + return false; + }) as IIndicator + )?.format + }); + } } this.tree[flatRowTotalKey][flatColKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); } @@ -1600,40 +1773,6 @@ export class Dataset { } } - // private _adjustCustomTree(customTree: IHeaderTreeDefine[]) { - // const checkNode = (nodes: IHeaderTreeDefine[], isHasIndicator: boolean) => { - // nodes.forEach((node: IHeaderTreeDefine) => { - // if ( - // !node.indicatorKey && - // !isHasIndicator && - // (!(node.children as IHeaderTreeDefine[])?.length || !node.children) - // ) { - // node.children = this.indicators?.map( - // (indicator: IIndicator | string): { indicatorKey: string; value: string } => { - // if (typeof indicator === 'string') { - // return { indicatorKey: indicator, value: indicator }; - // } - // return { indicatorKey: indicator.indicatorKey, value: indicator.title ?? indicator.indicatorKey }; - // } - // ); - // } else if (node.children && Array.isArray(node.children)) { - // checkNode(node.children, isHasIndicator || !!node.indicatorKey); - // } - // }); - // }; - // if (customTree?.length) { - // checkNode(customTree, false); - // } else { - // customTree = this.indicators?.map((indicator: IIndicator | string): { indicatorKey: string; value: string } => { - // if (typeof indicator === 'string') { - // return { indicatorKey: indicator, value: indicator }; - // } - // return { indicatorKey: indicator.indicatorKey, value: indicator.title ?? indicator.indicatorKey }; - // }); - // } - // return customTree; - // } - changeTreeNodeValue( rowKey: string[] | string = [], colKey: string[] | string = [], diff --git a/packages/vtable/src/dataset/statistics-helper.ts b/packages/vtable/src/dataset/statistics-helper.ts index 5f48797f1..0c94f2c81 100644 --- a/packages/vtable/src/dataset/statistics-helper.ts +++ b/packages/vtable/src/dataset/statistics-helper.ts @@ -18,11 +18,13 @@ export abstract class Aggregator implements IAggregator { isRecord?: boolean = true; //是否需要维护records 将数据源都记录下来 records?: any[] = []; type?: string; + key: string; field?: string | string[]; formatFun?: any; _formatedValue?: any; - constructor(dimension: string, formatFun?: any, isRecord?: boolean) { + constructor(key: string, dimension: string, formatFun?: any, isRecord?: boolean) { + this.key = key; this.field = dimension; this.formatFun = formatFun; this.isRecord = isRecord ?? this.isRecord; @@ -51,7 +53,7 @@ export class RecordAggregator extends Aggregator { type: string = AggregationType.RECORD; isRecord?: boolean = true; push(record: any): void { - if (this.isRecord && this.records) { + if (record && this.isRecord && this.records) { if (record.className === 'Aggregator') { this.records.push(...record.records); } else { @@ -76,11 +78,13 @@ export class NoneAggregator extends Aggregator { declare field?: string; fieldValue?: any; push(record: any): void { - if (this.isRecord) { - this.records = [record]; - } - if (this.field) { - this.fieldValue = record[this.field]; + if (record) { + if (this.isRecord) { + this.records = [record]; + } + if (this.field) { + this.fieldValue = record[this.field]; + } } } value() { @@ -101,25 +105,79 @@ export class CustomAggregator extends Aggregator { aggregationFun?: Function; values: (string | number)[] = []; fieldValue?: any; - constructor(dimension: string, formatFun?: any, isRecord?: boolean, aggregationFun?: Function) { - super(dimension, formatFun, isRecord); - this.aggregationFun = aggregationFun; + constructor(config: { + key: string; + dimension: string; + formatFun?: any; + isRecord?: boolean; + aggregationFun?: Function; + }) { + super(config.key, config.dimension, config.formatFun, config.isRecord); + this.aggregationFun = config.aggregationFun; + } + push(record: any): void { + if (record) { + if (this.isRecord && this.records) { + if (record.className === 'Aggregator') { + this.records.push(...record.records); + } else { + this.records.push(record); + } + } + if (this.field) { + this.values.push(record[this.field]); + } + } + } + value() { + if (!this.fieldValue) { + this.fieldValue = this.aggregationFun?.(this.values, this.records, this.field); + } + return this.fieldValue; + } + reset() { + this.records = []; + this.fieldValue = undefined; + } + recalculate() { + // do nothing + } +} +export class RecalculateAggregator extends Aggregator { + type: string = AggregationType.RECALCULATE; //仅获取其中一条数据 不做聚合 其fieldValue可以是number或者string类型 + isRecord?: boolean = true; + declare field?: string; + calculateFun: Function; + fieldValue?: any; + dependAggregators: Aggregator[]; + dependIndicatorKeys: string[]; + constructor(config: { + key: string; + dimension: string; + formatFun: any; + isRecord: boolean; + calculateFun: Function; + dependAggregators: Aggregator[]; + dependIndicatorKeys: string[]; + }) { + super(config.key, config.dimension, config.formatFun, config.isRecord); + this.calculateFun = config.calculateFun; + this.dependAggregators = config.dependAggregators; + this.dependIndicatorKeys = config.dependIndicatorKeys; } push(record: any): void { - if (this.isRecord && this.records) { + if (record && this.isRecord && this.records) { if (record.className === 'Aggregator') { this.records.push(...record.records); } else { this.records.push(record); } } - if (this.field) { - this.values.push(record[this.field]); - } } value() { if (!this.fieldValue) { - this.fieldValue = this.aggregationFun?.(this.values, this.records, this.field); + const aggregatorValue = _getDependAggregatorValues(this.dependAggregators, this.dependIndicatorKeys); + this.fieldValue = this.calculateFun?.(aggregatorValue, this.records, this.field); } return this.fieldValue; } @@ -138,36 +196,44 @@ export class SumAggregator extends Aggregator { nagetiveSum = 0; declare field?: string; needSplitPositiveAndNegativeForSum?: boolean = false; - constructor(dimension: string, formatFun?: any, isRecord?: boolean, needSplitPositiveAndNegative?: boolean) { - super(dimension, formatFun, isRecord); - this.needSplitPositiveAndNegativeForSum = needSplitPositiveAndNegative ?? false; + constructor(config: { + key: string; + dimension: string; + formatFun?: any; + isRecord?: boolean; + needSplitPositiveAndNegative?: boolean; + }) { + super(config.key, config.dimension, config.formatFun, config.isRecord); + this.needSplitPositiveAndNegativeForSum = config.needSplitPositiveAndNegative ?? false; } push(record: any): void { - if (this.isRecord && this.records) { - if (record.className === 'Aggregator') { - this.records.push(...record.records); - } else { - this.records.push(record); - } - } - if (record.className === 'Aggregator') { - const value = record.value(); - this.sum += value; - if (this.needSplitPositiveAndNegativeForSum) { - if (value > 0) { - this.positiveSum += value; - } else if (value < 0) { - this.nagetiveSum += value; + if (record) { + if (this.isRecord && this.records) { + if (record.className === 'Aggregator') { + this.records.push(...record.records); + } else { + this.records.push(record); } } - } else if (this.field && !isNaN(parseFloat(record[this.field]))) { - const value = parseFloat(record[this.field]); - this.sum += value; - if (this.needSplitPositiveAndNegativeForSum) { - if (value > 0) { - this.positiveSum += value; - } else if (value < 0) { - this.nagetiveSum += value; + if (record.className === 'Aggregator') { + const value = record.value(); + this.sum += value; + if (this.needSplitPositiveAndNegativeForSum) { + if (value > 0) { + this.positiveSum += value; + } else if (value < 0) { + this.nagetiveSum += value; + } + } + } else if (this.field && !isNaN(parseFloat(record[this.field]))) { + const value = parseFloat(record[this.field]); + this.sum += value; + if (this.needSplitPositiveAndNegativeForSum) { + if (value > 0) { + this.positiveSum += value; + } else if (value < 0) { + this.nagetiveSum += value; + } } } } @@ -222,18 +288,20 @@ export class CountAggregator extends Aggregator { count = 0; declare field?: string; push(record: any): void { - if (this.isRecord && this.records) { + if (record) { + if (this.isRecord && this.records) { + if (record.className === 'Aggregator') { + this.records.push(...record.records); + } else { + this.records.push(record); + } + } if (record.className === 'Aggregator') { - this.records.push(...record.records); + this.count += record.value(); } else { - this.records.push(record); + this.count++; } } - if (record.className === 'Aggregator') { - this.count += record.value(); - } else { - this.count++; - } } value() { return this.count; @@ -263,19 +331,21 @@ export class AvgAggregator extends Aggregator { count = 0; declare field?: string; push(record: any): void { - if (this.isRecord && this.records) { - if (record.className === 'Aggregator') { - this.records.push(...record.records); - } else { - this.records.push(record); + if (record) { + if (this.isRecord && this.records) { + if (record.className === 'Aggregator') { + this.records.push(...record.records); + } else { + this.records.push(record); + } + } + if (record.className === 'Aggregator' && record.type === AggregationType.AVG) { + this.sum += record.sum; + this.count += record.count; + } else if (this.field && !isNaN(parseFloat(record[this.field]))) { + this.sum += parseFloat(record[this.field]); + this.count++; } - } - if (record.className === 'Aggregator' && record.type === AggregationType.AVG) { - this.sum += record.sum; - this.count += record.count; - } else if (this.field && !isNaN(parseFloat(record[this.field]))) { - this.sum += parseFloat(record[this.field]); - this.count++; } } value() { @@ -309,22 +379,24 @@ export class MaxAggregator extends Aggregator { max: number = Number.MIN_SAFE_INTEGER; declare field?: string; push(record: any): void { - if (this.isRecord && this.records) { + if (record) { + if (this.isRecord && this.records) { + if (record.className === 'Aggregator') { + this.records.push(...record.records); + } else { + this.records.push(record); + } + } if (record.className === 'Aggregator') { - this.records.push(...record.records); - } else { - this.records.push(record); + this.max = record.max > this.max ? record.max : this.max; + } else if (typeof record === 'number') { + this.max = record > this.max ? record : this.max; + } else if (this.field && typeof record[this.field] === 'number') { + this.max = record[this.field] > this.max ? record[this.field] : this.max; + } else if (this.field && !isNaN(record[this.field])) { + this.max = parseFloat(record[this.field]) > this.max ? parseFloat(record[this.field]) : this.max; } } - if (record.className === 'Aggregator') { - this.max = record.max > this.max ? record.max : this.max; - } else if (typeof record === 'number') { - this.max = record > this.max ? record : this.max; - } else if (this.field && typeof record[this.field] === 'number') { - this.max = record[this.field] > this.max ? record[this.field] : this.max; - } else if (this.field && !isNaN(record[this.field])) { - this.max = parseFloat(record[this.field]) > this.max ? parseFloat(record[this.field]) : this.max; - } } value() { return this.max; @@ -357,20 +429,22 @@ export class MinAggregator extends Aggregator { min: number = Number.MAX_SAFE_INTEGER; declare field?: string; push(record: any): void { - if (this.isRecord && this.records) { + if (record) { + if (this.isRecord && this.records) { + if (record.className === 'Aggregator') { + this.records.push(...record.records); + } else { + this.records.push(record); + } + } if (record.className === 'Aggregator') { - this.records.push(...record.records); - } else { - this.records.push(record); + this.min = record.min < this.min ? record.min : this.min; + } else if (typeof record === 'number') { + this.min = record < this.min ? record : this.min; + } else if (this.field && typeof record[this.field] === 'number') { + this.min = record[this.field] < this.min ? record[this.field] : this.min; } } - if (record.className === 'Aggregator') { - this.min = record.min < this.min ? record.min : this.min; - } else if (typeof record === 'number') { - this.min = record < this.min ? record : this.min; - } else if (this.field && typeof record[this.field] === 'number') { - this.min = record[this.field] < this.min ? record[this.field] : this.min; - } } value() { return this.min; @@ -525,3 +599,14 @@ export function sortBy(order: string[]) { return naturalSort(a, b); }; } + +function _getDependAggregatorValues(aggregators: Aggregator[], dependIndicatorKeys: string[]) { + const dependAggregatorValues: any = {}; + for (let m = 0; m < dependIndicatorKeys?.length; m++) { + const aggrator = aggregators.find(aggrator => aggrator.key === dependIndicatorKeys[m]); + if (aggrator) { + dependAggregatorValues[aggrator.key] = aggrator?.value(); + } + } + return dependAggregatorValues; +} diff --git a/packages/vtable/src/ts-types/new-data-set.ts b/packages/vtable/src/ts-types/new-data-set.ts index 89cdb0404..83e3ae858 100644 --- a/packages/vtable/src/ts-types/new-data-set.ts +++ b/packages/vtable/src/ts-types/new-data-set.ts @@ -18,7 +18,8 @@ export enum AggregationType { MAX = 'MAX', AVG = 'AVG', COUNT = 'COUNT', - CUSTOM = 'CUSTOM' + CUSTOM = 'CUSTOM', + RECALCULATE = 'RECALCULATE' } export enum SortType { ASC = 'ASC', @@ -168,11 +169,25 @@ export type MappingFuncRule = { }; //#endregion 映射规则 + +//#region 派生字段规则 export interface DerivedFieldRule { fieldName?: string; derivedFunc?: (record: Record) => any; } export type DerivedFieldRules = DerivedFieldRule[]; +//#endregion 派生字段规则 + +//#region 计算字段规则 +export interface CalculateddFieldRule { + key: string; + dependIndicatorKeys: string[]; + calculateFun?: (dependFieldsValue: any) => any; +} + +export type CalculateddFieldRules = CalculateddFieldRule[]; +//#endregion 计算字段规则 + /** * 基本表数据处理配置 */ @@ -196,6 +211,7 @@ export interface IPivotTableDataConfig { */ mappingRules?: MappingRules; derivedFieldRules?: DerivedFieldRules; + calculatedFieldRules?: CalculateddFieldRules; } /** From c10e0bc1574c0f41e31f96ad3f2befccf9ea17ef Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Tue, 18 Jun 2024 20:05:27 +0800 Subject: [PATCH 44/85] docs: update changlog of rush --- ...ture-support-calculate-field_2024-06-18-12-05.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json diff --git a/common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json b/common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json new file mode 100644 index 000000000..a2461926d --- /dev/null +++ b/common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "feat: support calculate field for PivotTable #1941\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From 00b2cb57f6f517b5db6b201678402551d4f55d0a Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Tue, 18 Jun 2024 20:07:05 +0800 Subject: [PATCH 45/85] feat: support calculate field for PivotTable #1941 --- packages/vtable/src/dataset/dataset.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/vtable/src/dataset/dataset.ts b/packages/vtable/src/dataset/dataset.ts index ae273d9f7..dfb7b7596 100644 --- a/packages/vtable/src/dataset/dataset.ts +++ b/packages/vtable/src/dataset/dataset.ts @@ -563,12 +563,11 @@ export class Dataset { .sumBy!.map(byField => record[byField]) .join(this.stringJoinChar); if (!this.collectedValues[field][collectKeys][sumByKeys]) { - this.collectedValues[field][collectKeys][sumByKeys] = new this.aggregators[AggregationType.SUM]( - field, - undefined, - undefined, - this.needSplitPositiveAndNegative - ); + this.collectedValues[field][collectKeys][sumByKeys] = new this.aggregators[AggregationType.SUM]({ + key: field, + dimension: undefined, + needSplitPositiveAndNegative: this.needSplitPositiveAndNegative + }); } this.collectedValues[field][collectKeys][sumByKeys].push(record); } else if (this.collectValuesBy[field].range) { From 254f66e1e9fe6974d6d54934677f72e5a3239480 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Tue, 18 Jun 2024 20:14:03 +0800 Subject: [PATCH 46/85] feat: support calculate field for PivotTable #1941 --- packages/vtable/src/dataset/dataset.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vtable/src/dataset/dataset.ts b/packages/vtable/src/dataset/dataset.ts index dfb7b7596..bb24dde63 100644 --- a/packages/vtable/src/dataset/dataset.ts +++ b/packages/vtable/src/dataset/dataset.ts @@ -164,7 +164,7 @@ export class Dataset { this.mappingRules = this.dataConfig?.mappingRules; this.calculatedFieldRules = this.dataConfig?.calculatedFieldRules; this.calculatedFiledKeys = this.calculatedFieldRules?.map(rule => rule.key); - this.calculatedFieldDependIndicatorKeys = this.calculatedFieldRules.reduce((arr: string[], rule) => { + this.calculatedFieldDependIndicatorKeys = this.calculatedFieldRules?.reduce((arr: string[], rule) => { for (let i = 0; i < rule.dependIndicatorKeys.length; i++) { if (arr.indexOf(rule.dependIndicatorKeys[i]) === -1) { arr.push(rule.dependIndicatorKeys[i]); From 3e5bd3d7268a86cf75d65945d409d03e579dc222 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Tue, 18 Jun 2024 20:15:48 +0800 Subject: [PATCH 47/85] feat: support calculate field for PivotTable #1941 --- packages/vtable/src/dataset/dataset.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/vtable/src/dataset/dataset.ts b/packages/vtable/src/dataset/dataset.ts index bb24dde63..07d9db708 100644 --- a/packages/vtable/src/dataset/dataset.ts +++ b/packages/vtable/src/dataset/dataset.ts @@ -163,15 +163,16 @@ export class Dataset { this.derivedFieldRules = this.dataConfig?.derivedFieldRules; this.mappingRules = this.dataConfig?.mappingRules; this.calculatedFieldRules = this.dataConfig?.calculatedFieldRules; - this.calculatedFiledKeys = this.calculatedFieldRules?.map(rule => rule.key); - this.calculatedFieldDependIndicatorKeys = this.calculatedFieldRules?.reduce((arr: string[], rule) => { - for (let i = 0; i < rule.dependIndicatorKeys.length; i++) { - if (arr.indexOf(rule.dependIndicatorKeys[i]) === -1) { - arr.push(rule.dependIndicatorKeys[i]); + this.calculatedFiledKeys = this.calculatedFieldRules?.map(rule => rule.key) ?? []; + this.calculatedFieldDependIndicatorKeys = + this.calculatedFieldRules?.reduce((arr: string[], rule) => { + for (let i = 0; i < rule.dependIndicatorKeys.length; i++) { + if (arr.indexOf(rule.dependIndicatorKeys[i]) === -1) { + arr.push(rule.dependIndicatorKeys[i]); + } } - } - return arr; - }, []); + return arr; + }, []) ?? []; this.totals = this.dataConfig?.totals; this.rows = rows; this.columns = columns; From ad917be6828967c412ed108712b12cef92b026cb Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Tue, 18 Jun 2024 20:26:24 +0800 Subject: [PATCH 48/85] feat: support calculate field for PivotTable #1941 --- packages/vtable/src/dataset/dataset.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/vtable/src/dataset/dataset.ts b/packages/vtable/src/dataset/dataset.ts index 07d9db708..967bd3de0 100644 --- a/packages/vtable/src/dataset/dataset.ts +++ b/packages/vtable/src/dataset/dataset.ts @@ -103,7 +103,7 @@ export class Dataset { dimension: string | string[]; formatFun?: any; isRecord?: boolean; - needSplitPositiveAndNegative?: boolean; + needSplitPositiveAndNegativeForSum?: boolean; calculateFun?: any; dependAggregators?: any; dependIndicatorKeys?: string[]; @@ -566,8 +566,9 @@ export class Dataset { if (!this.collectedValues[field][collectKeys][sumByKeys]) { this.collectedValues[field][collectKeys][sumByKeys] = new this.aggregators[AggregationType.SUM]({ key: field, - dimension: undefined, - needSplitPositiveAndNegative: this.needSplitPositiveAndNegative + dimension: field, + isRecord: undefined, + needSplitPositiveAndNegativeForSum: this.needSplitPositiveAndNegative }); } this.collectedValues[field][collectKeys][sumByKeys].push(record); From 1df75f441ca8ee578339f6a16fe4b20a7ae1fa1e Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Tue, 18 Jun 2024 20:28:36 +0800 Subject: [PATCH 49/85] feat: support calculate field for PivotTable #1941 --- packages/vtable/src/dataset/dataset.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vtable/src/dataset/dataset.ts b/packages/vtable/src/dataset/dataset.ts index 967bd3de0..0b930da61 100644 --- a/packages/vtable/src/dataset/dataset.ts +++ b/packages/vtable/src/dataset/dataset.ts @@ -103,7 +103,7 @@ export class Dataset { dimension: string | string[]; formatFun?: any; isRecord?: boolean; - needSplitPositiveAndNegativeForSum?: boolean; + needSplitPositiveAndNegative?: boolean; calculateFun?: any; dependAggregators?: any; dependIndicatorKeys?: string[]; @@ -568,7 +568,7 @@ export class Dataset { key: field, dimension: field, isRecord: undefined, - needSplitPositiveAndNegativeForSum: this.needSplitPositiveAndNegative + needSplitPositiveAndNegative: this.needSplitPositiveAndNegative }); } this.collectedValues[field][collectKeys][sumByKeys].push(record); From 6defe8ae295623a633f9da1202f30890b2367874 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 18 Jun 2024 21:34:52 +0800 Subject: [PATCH 50/85] fix: add image reload function in reconcilor --- packages/react-vtable/src/components/custom/reconciler.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-vtable/src/components/custom/reconciler.ts b/packages/react-vtable/src/components/custom/reconciler.ts index 8f2677c9d..51d2833e9 100644 --- a/packages/react-vtable/src/components/custom/reconciler.ts +++ b/packages/react-vtable/src/components/custom/reconciler.ts @@ -172,4 +172,7 @@ function updateGraphicProps(graphic: Graphic, newProps: any, oldProps: any) { // update all attribute graphic.initAttributes(newProps.attribute); + if (graphic.type === 'image') { + graphic.loadImage(newProps.attribute.image); + } } From cab5b8ed659ff11270128d2ac8449c384173bb41 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 18 Jun 2024 21:35:30 +0800 Subject: [PATCH 51/85] docs: add react-custom-layout-dom demos --- docs/assets/demo-react/menu.json | 14 + .../zh/custom-layout/custom-layout-all-dom.md | 204 +++++++++++++++ .../zh/custom-layout/custom-layout-dom.md | 247 ++++++++++++++++++ docs/src/main.tsx | 2 + 4 files changed, 467 insertions(+) create mode 100644 docs/assets/demo-react/zh/custom-layout/custom-layout-all-dom.md create mode 100644 docs/assets/demo-react/zh/custom-layout/custom-layout-dom.md diff --git a/docs/assets/demo-react/menu.json b/docs/assets/demo-react/menu.json index 343675dec..a8b80653c 100644 --- a/docs/assets/demo-react/menu.json +++ b/docs/assets/demo-react/menu.json @@ -120,6 +120,20 @@ "zh": "自定义布局", "en": "custom layout" } + }, + { + "path": "custom-layout-dom", + "title": { + "zh": "自定义布局dom", + "en": "custom layout dom" + } + }, + { + "path": "custom-layout-all-dom", + "title": { + "zh": "自定义布局all dom", + "en": "custom layout all dom" + } } ] }, diff --git a/docs/assets/demo-react/zh/custom-layout/custom-layout-all-dom.md b/docs/assets/demo-react/zh/custom-layout/custom-layout-all-dom.md new file mode 100644 index 000000000..0b96f90ce --- /dev/null +++ b/docs/assets/demo-react/zh/custom-layout/custom-layout-all-dom.md @@ -0,0 +1,204 @@ +--- +category: examples +group: component +title: 自定义组件 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-component.png +order: 1-1 +link: '../guide/Developer_Ecology/react' +--- + +# 自定义组件 + +自定义组件`CustomComponent`组件方便在 React-VTable 组件上叠加外部组件。 + +## 代码演示 + +```javascript livedemo template=vtable-react +// import * as ReactVTable from '@visactor/react-vtable'; + +const { useCallback, useRef, useState } = React; +const { ListTable, ListColumn, Group } = ReactVTable; +const { + Avatar, + Comment, + Card, + Popover, + Space, + Button, + Popconfirm, + Message, + Notification + } = ArcoDesign; +const { IconHeart, IconMessage, IconStar, IconStarFill, IconHeartFill } = ArcoDesignIcon; + +const CommentComponent = (props) => { + 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); + + return ( + + } + }} + > + ); +}; + +const CommentReactComponent = (props) => { + const { name } = props; + const [like, setLike] = useState(); + const [star, setStar] = useState(); + const actions = [ + , + , + + ]; + return ( + +

Here is the description of this user.

+ + } + > + {name.slice(0, 1)} + + } + content={
Comment body content.
} + datetime="1 hour" + style={{ marginTop: 10, marginLeft: 10 }} + /> + ); +}; + +const OperationComponent = (props) => { + 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); + + return ( + + } + }} + > + ); +}; + +const OperationReactComponent = () => { + return ( + + + { + Message.info({ + content: 'ok' + }); + }} + onCancel={() => { + Message.error({ + content: 'cancel' + }); + }} + > + + + + ); +}; + +function generateRandomString(length) { + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * characters.length)); + } + return result; +} + +function App() { + const records = []; + for (let i = 0; i < 50; i++) { + records.push({ + id: i, + name: generateRandomString(8) + }); + } + + return ( + { + // eslint-disable-next-line no-undef + // (window as any).tableInstance = table; + }} + ReactDOM={ReactDom} + > + + + + + + + + + ); +} + +const root = ReactDom.createRoot(document.getElementById(CONTAINER_ID)); +root.render(); + +// release react instance, do not copy +window.customRelease = () => { + root.unmount(); +}; +``` diff --git a/docs/assets/demo-react/zh/custom-layout/custom-layout-dom.md b/docs/assets/demo-react/zh/custom-layout/custom-layout-dom.md new file mode 100644 index 000000000..6150e8f91 --- /dev/null +++ b/docs/assets/demo-react/zh/custom-layout/custom-layout-dom.md @@ -0,0 +1,247 @@ +--- +category: examples +group: component +title: 自定义组件 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-component.png +order: 1-1 +link: '../guide/Developer_Ecology/react' +--- + +# 自定义组件 + +自定义组件`CustomComponent`组件方便在 React-VTable 组件上叠加外部组件。 + +## 代码演示 + +```javascript livedemo template=vtable-react +// import * as ReactVTable from '@visactor/react-vtable'; + +const { useCallback, useRef, useState } = React; +const { ListTable, ListColumn, Group, Text, Image } = ReactVTable; +const { Avatar, Card, Space, Typography } = ArcoDesign; +const { IconThumbUp, IconShareInternal, IconMore } = ArcoDesignIcon; +const { Meta } = Card; + +const UserProfileComponent = (props) => { + 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) => { + setHover(true); + event.currentTarget.stage.renderNextFrame(); // to do: auto execute in react-vtable + }} + onMouseLeave={(event) => { + setHover(false); + event.currentTarget.stage.renderNextFrame(); + }} + > + + + + + ); +}; + +const CardInfo = (props) => { + const { bloggerName, bloggerAvatar, introduction, city } = props.record; + return props.hover ? ( + + dessert + + } + // actions={[ + // + // + // , + // + // + // , + // + // + // + // ]} + > + + {city.slice(0, 1)} + {city} + + } + title={bloggerName} + description={introduction} + /> + + ) : <>; +}; + +function App() { + const records = [ + { + bloggerId: 1, + bloggerName: 'Virtual Anchor Xiaohua', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg', + introduction: + 'Hi everyone, I am Xiaohua, the virtual host. I am a little fairy who likes games, animation and food. I hope to share happy moments with you through live broadcast.', + fansCount: 400, + worksCount: 10, + viewCount: 5, + city: 'Dream City', + tags: ['game', 'anime', 'food'] + }, + { + bloggerId: 2, + bloggerName: 'Virtual anchor little wolf', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg', + introduction: + 'Hello everyone, I am the virtual anchor Little Wolf. I like music, travel and photography, and I hope to explore the beauty of the world with you through live broadcast.', + fansCount: 800, + worksCount: 20, + viewCount: 15, + city: 'City of Music', + tags: ['music', 'travel', 'photography'] + }, + { + bloggerId: 3, + bloggerName: 'Virtual anchor bunny', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg', + introduction: + 'Hello everyone, I am the virtual anchor Xiaotu. I like painting, handicrafts and beauty makeup. I hope to share creativity and fashion with you through live broadcast.', + fansCount: 600, + worksCount: 15, + viewCount: 10, + city: 'City of Art', + tags: ['painting', 'handmade', 'beauty makeup'] + }, + { + bloggerId: 4, + bloggerName: 'Virtual anchor kitten', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg', + introduction: + 'Hello everyone, I am the virtual host Kitty. I am a lazy cat who likes dancing, fitness and cooking. I hope to live a healthy and happy life with everyone through the live broadcast.', + fansCount: 1000, + worksCount: 30, + viewCount: 20, + city: 'Health City', + tags: ['dance', 'fitness', 'cooking'] + }, + { + bloggerId: 5, + bloggerName: 'Virtual anchor Bear', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg', + introduction: + 'Hello everyone, I am the virtual host Xiaoxiong. A little wise man who likes movies, reading and philosophy, I hope to explore the meaning of life with you through live broadcast.', + fansCount: 1200, + worksCount: 25, + viewCount: 18, + city: 'City of Wisdom', + tags: ['Movie', 'Literature'] + }, + { + bloggerId: 6, + bloggerName: 'Virtual anchor bird', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg', + introduction: + 'Hello everyone, I am the virtual anchor Xiaoniao. I like singing, acting and variety shows. I hope to be happy with everyone through the live broadcast.', + fansCount: 900, + worksCount: 12, + viewCount: 8, + city: 'Happy City', + tags: ['music', 'performance', 'variety'] + } + ]; + + return ( + { + // eslint-disable-next-line no-undef + // (window as any).tableInstance = table; + }} + ReactDOM={ReactDom} + > + + + + + + + + + ); +} + +const root = ReactDom.createRoot(document.getElementById(CONTAINER_ID)); +root.render(); + +// release react instance, do not copy +window.customRelease = () => { + root.unmount(); +}; +``` diff --git a/docs/src/main.tsx b/docs/src/main.tsx index f97df93ed..a0b70518e 100644 --- a/docs/src/main.tsx +++ b/docs/src/main.tsx @@ -10,9 +10,11 @@ import * as ReactVTable from '@visactor/react-vtable'; import * as InulaVTable from '@visactor/openinula-vtable'; import { App } from './app'; import * as ArcoDesign from '@arco-design/web-react'; +import * as ArcoDesignIcon from '@arco-design/web-react/icon'; import '@arco-design/web-react/dist/css/arco.css'; (window as any).ArcoDesign = ArcoDesign; +(window as any).ArcoDesignIcon = ArcoDesignIcon; (window as any).VTable = VTable; (window as any).VTable_editors = VTableEditors; (window as any).VChart = VChart.VChart; From 326e2150120f034c6ee8723fd1f119a398a8b338 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 19 Jun 2024 11:12:23 +0800 Subject: [PATCH 52/85] feat: support calculate field for PivotTable #1941 --- packages/vtable/src/dataset/statistics-helper.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/vtable/src/dataset/statistics-helper.ts b/packages/vtable/src/dataset/statistics-helper.ts index 0c94f2c81..72e5d4f42 100644 --- a/packages/vtable/src/dataset/statistics-helper.ts +++ b/packages/vtable/src/dataset/statistics-helper.ts @@ -23,11 +23,11 @@ export abstract class Aggregator implements IAggregator { formatFun?: any; _formatedValue?: any; - constructor(key: string, dimension: string, formatFun?: any, isRecord?: boolean) { - this.key = key; - this.field = dimension; - this.formatFun = formatFun; - this.isRecord = isRecord ?? this.isRecord; + constructor(config: { key: string; dimension: string; formatFun?: any; isRecord?: boolean }) { + this.key = config.key; + this.field = config.dimension; + this.formatFun = config.formatFun; + this.isRecord = config.isRecord ?? this.isRecord; } abstract push(record: any): void; abstract value(): any; @@ -112,7 +112,7 @@ export class CustomAggregator extends Aggregator { isRecord?: boolean; aggregationFun?: Function; }) { - super(config.key, config.dimension, config.formatFun, config.isRecord); + super(config); this.aggregationFun = config.aggregationFun; } push(record: any): void { @@ -160,7 +160,7 @@ export class RecalculateAggregator extends Aggregator { dependAggregators: Aggregator[]; dependIndicatorKeys: string[]; }) { - super(config.key, config.dimension, config.formatFun, config.isRecord); + super(config); this.calculateFun = config.calculateFun; this.dependAggregators = config.dependAggregators; this.dependIndicatorKeys = config.dependIndicatorKeys; @@ -203,7 +203,7 @@ export class SumAggregator extends Aggregator { isRecord?: boolean; needSplitPositiveAndNegative?: boolean; }) { - super(config.key, config.dimension, config.formatFun, config.isRecord); + super(config); this.needSplitPositiveAndNegativeForSum = config.needSplitPositiveAndNegative ?? false; } push(record: any): void { From 9dcefea1c23f9f87c2bd206a9ef0c66ed6e66adc Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 19 Jun 2024 11:47:24 +0800 Subject: [PATCH 53/85] chore: update vrender version --- packages/openinula-vtable/package.json | 4 ++-- packages/react-vtable/package.json | 4 ++-- packages/vtable-export/package.json | 4 ++-- packages/vtable-search/package.json | 4 ++-- packages/vtable/package.json | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/openinula-vtable/package.json b/packages/openinula-vtable/package.json index dcdc28bcf..36652fccd 100644 --- a/packages/openinula-vtable/package.json +++ b/packages/openinula-vtable/package.json @@ -51,7 +51,7 @@ "@visactor/vutils": "~0.18.9" }, "devDependencies": { - "@visactor/vchart": "1.11.0", + "@visactor/vchart": "1.11.4", "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", @@ -93,4 +93,4 @@ "peerDependencies": { "openinula": "~0.1.2-SNAPSHOT" } -} +} \ No newline at end of file diff --git a/packages/react-vtable/package.json b/packages/react-vtable/package.json index a53afa788..34e99f622 100644 --- a/packages/react-vtable/package.json +++ b/packages/react-vtable/package.json @@ -54,7 +54,7 @@ "react-is": "^18.2.0" }, "devDependencies": { - "@visactor/vchart": "1.11.0", + "@visactor/vchart": "1.11.4", "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", @@ -99,4 +99,4 @@ "@types/react-is": "^17.0.3", "@arco-design/web-react": "2.60.2" } -} +} \ No newline at end of file diff --git a/packages/vtable-export/package.json b/packages/vtable-export/package.json index 05d524594..8d9b4b581 100644 --- a/packages/vtable-export/package.json +++ b/packages/vtable-export/package.json @@ -42,7 +42,7 @@ "exceljs": "4.4.0" }, "devDependencies": { - "@visactor/vchart": "1.11.0", + "@visactor/vchart": "1.11.4", "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", @@ -87,4 +87,4 @@ "@types/react-is": "^17.0.3", "rollup-plugin-node-resolve": "5.2.0" } -} +} \ No newline at end of file diff --git a/packages/vtable-search/package.json b/packages/vtable-search/package.json index 160440955..e77b3808a 100644 --- a/packages/vtable-search/package.json +++ b/packages/vtable-search/package.json @@ -38,7 +38,7 @@ "@visactor/vutils": "~0.18.9" }, "devDependencies": { - "@visactor/vchart": "1.11.0", + "@visactor/vchart": "1.11.4", "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", @@ -83,4 +83,4 @@ "@types/react-is": "^17.0.3", "rollup-plugin-node-resolve": "5.2.0" } -} +} \ No newline at end of file diff --git a/packages/vtable/package.json b/packages/vtable/package.json index 30000491f..a8cf1c548 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -50,9 +50,9 @@ }, "dependencies": { "@visactor/vtable-editors": "workspace:*", - "@visactor/vrender-core": "0.19.9", - "@visactor/vrender-kits": "0.19.9", - "@visactor/vrender-components": "0.19.9", + "@visactor/vrender-core": "0.19.11", + "@visactor/vrender-kits": "0.19.11", + "@visactor/vrender-components": "0.19.11", "@visactor/vutils": "~0.18.9", "@visactor/vscale": "~0.18.1", "@visactor/vdataset": "~0.18.1", From d5f9668b7263dc42bd38152d9ff76a0bc268ba54 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 19 Jun 2024 11:51:39 +0800 Subject: [PATCH 54/85] chore: update vrender version --- common/config/rush/pnpm-lock.yaml | 263 +++++++++++------------------- docs/package.json | 2 +- packages/vtable/package.json | 2 +- 3 files changed, 94 insertions(+), 173 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 596517d79..984321b4e 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -17,7 +17,7 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/openinula-vtable': workspace:* '@visactor/react-vtable': workspace:* - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 '@visactor/vtable': workspace:* '@visactor/vtable-editors': workspace:* '@visactor/vtable-export': workspace:* @@ -45,7 +45,7 @@ importers: '@arco-design/web-react': 2.60.2_psuonouaqi5wuc37nxyknoubym '@visactor/openinula-vtable': link:../packages/openinula-vtable '@visactor/react-vtable': link:../packages/react-vtable - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 '@visactor/vtable': link:../packages/vtable '@visactor/vtable-editors': link:../packages/vtable-editors '@visactor/vtable-export': link:../packages/vtable-export @@ -91,7 +91,7 @@ importers: '@types/mocha': 9.0.0 '@types/node': '*' '@types/offscreencanvas': 2019.6.4 - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 '@visactor/vtable': workspace:* '@visactor/vutils': ~0.18.9 axios: ^1.4.0 @@ -135,7 +135,7 @@ importers: '@types/mocha': 9.0.0 '@types/node': 20.14.2 '@types/offscreencanvas': 2019.6.4 - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 axios: 1.7.2 chai: 4.3.4 eslint: 8.18.0 @@ -180,7 +180,7 @@ importers: '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 '@types/react-is': ^17.0.3 - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 '@visactor/vtable': workspace:* '@visactor/vutils': ~0.18.9 '@vitejs/plugin-react': 3.1.0 @@ -232,7 +232,7 @@ importers: '@types/react': 18.3.3 '@types/react-dom': 18.3.0 '@types/react-is': 17.0.7 - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 '@vitejs/plugin-react': 3.1.0_vite@3.2.6 axios: 1.7.2 chai: 4.3.4 @@ -278,11 +278,11 @@ importers: '@types/offscreencanvas': 2019.6.4 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 '@visactor/vdataset': ~0.18.1 - '@visactor/vrender-components': 0.19.9 - '@visactor/vrender-core': 0.19.9 - '@visactor/vrender-kits': 0.19.9 + '@visactor/vrender-components': 0.19.11 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vscale': ~0.18.1 '@visactor/vtable-editors': workspace:* '@visactor/vutils': ~0.18.9 @@ -324,9 +324,9 @@ importers: vite-plugin-markdown: ^2.1.0 dependencies: '@visactor/vdataset': 0.18.9 - '@visactor/vrender-components': 0.19.9 - '@visactor/vrender-core': 0.19.9 - '@visactor/vrender-kits': 0.19.9 + '@visactor/vrender-components': 0.19.11 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vscale': 0.18.9 '@visactor/vtable-editors': link:../vtable-editors '@visactor/vutils': 0.18.9 @@ -346,7 +346,7 @@ importers: '@types/offscreencanvas': 2019.6.4 '@types/react': 18.3.3 '@types/react-dom': 18.3.0 - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 '@vitejs/plugin-react': 3.1.0_vite@3.2.6 axios: 1.7.2 chai: 4.3.4 @@ -446,7 +446,7 @@ importers: '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 '@types/react-is': ^17.0.3 - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 '@visactor/vtable': workspace:* '@visactor/vutils': ~0.18.9 '@vitejs/plugin-react': 3.1.0 @@ -501,7 +501,7 @@ importers: '@types/react': 18.3.3 '@types/react-dom': 18.3.0 '@types/react-is': 17.0.7 - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 '@vitejs/plugin-react': 3.1.0_vite@3.2.6 axios: 1.7.2 chai: 4.3.4 @@ -548,7 +548,7 @@ importers: '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 '@types/react-is': ^17.0.3 - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 '@visactor/vtable': workspace:* '@visactor/vutils': ~0.18.9 '@vitejs/plugin-react': 3.1.0 @@ -598,7 +598,7 @@ importers: '@types/react': 18.3.3 '@types/react-dom': 18.3.0 '@types/react-is': 17.0.7 - '@visactor/vchart': 1.11.0 + '@visactor/vchart': 1.11.4 '@vitejs/plugin-react': 3.1.0_vite@3.2.6 axios: 1.7.2 chai: 4.3.4 @@ -2325,7 +2325,7 @@ packages: jest-resolve: 26.6.2 jest-resolve-dependencies: 26.6.3 jest-runner: 26.6.3_ts-node@10.9.0 - jest-runtime: 26.6.3 + jest-runtime: 26.6.3_ts-node@10.9.0 jest-snapshot: 26.6.2 jest-util: 26.6.2 jest-validate: 26.6.2 @@ -2486,7 +2486,7 @@ packages: graceful-fs: 4.2.11 jest-haste-map: 26.6.2 jest-runner: 26.6.3_ts-node@10.9.0 - jest-runtime: 26.6.3 + jest-runtime: 26.6.3_ts-node@10.9.0 transitivePeerDependencies: - bufferutil - canvas @@ -3632,24 +3632,24 @@ packages: resolution: {integrity: sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==} dev: true - /@visactor/vchart/1.11.0: - resolution: {integrity: sha512-omEwPwLzi9PioVmiP/9L8IJoJnqRs/LsGPEkFhQYCBdSSuyh+OApWXo/a7jL/t7PsRSZVIeogmXh6YUY72XuLw==} + /@visactor/vchart/1.11.4: + resolution: {integrity: sha512-PwqvMIwBAN3I5TvL91ug9vRbdI9chMKw/LzjXKTgXMq4PQt2XJ0VY+eovpCFgE/Tb6JQFBrwzxxnxhUzrX4ypg==} dependencies: '@visactor/vdataset': 0.18.9 - '@visactor/vgrammar-core': 0.13.2 - '@visactor/vgrammar-hierarchy': 0.13.2 - '@visactor/vgrammar-projection': 0.13.2 - '@visactor/vgrammar-sankey': 0.13.2 - '@visactor/vgrammar-util': 0.13.2 - '@visactor/vgrammar-venn': 0.13.2 - '@visactor/vgrammar-wordcloud': 0.13.2 - '@visactor/vgrammar-wordcloud-shape': 0.13.2 - '@visactor/vrender-components': 0.19.0 - '@visactor/vrender-core': 0.19.0 - '@visactor/vrender-kits': 0.19.0 + '@visactor/vgrammar-core': 0.13.10 + '@visactor/vgrammar-hierarchy': 0.13.10 + '@visactor/vgrammar-projection': 0.13.10 + '@visactor/vgrammar-sankey': 0.13.10 + '@visactor/vgrammar-util': 0.13.10 + '@visactor/vgrammar-venn': 0.13.10 + '@visactor/vgrammar-wordcloud': 0.13.10 + '@visactor/vgrammar-wordcloud-shape': 0.13.10 + '@visactor/vrender-components': 0.19.11 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vscale': 0.18.9 '@visactor/vutils': 0.18.9 - '@visactor/vutils-extension': 1.11.0_7qcgcpuz2j5tzhxzhxchuz72qy + '@visactor/vutils-extension': 1.11.4 /@visactor/vdataset/0.18.9: resolution: {integrity: sha512-qQBOGKbB4W1+0aUQ95y9q4Nu56VAiC01Pijhkje0EUHpO8EIy17tUc0xtjpHE4iO8ym/02c4cGv4FKtuiewIrA==} @@ -3672,159 +3672,116 @@ packages: simplify-geojson: 1.0.5 topojson-client: 3.1.0 - /@visactor/vgrammar-coordinate/0.13.2: - resolution: {integrity: sha512-mvIJa8V7zVnfOrKDc6v4XLXo5h0vJoPG/US4nakSX+EK4cODbiQg0TCOsJQDHntPRdXx20A5EGp3mRoIOHM6sw==} + /@visactor/vgrammar-coordinate/0.13.10: + resolution: {integrity: sha512-DxVGoAXkSr/tSDSQcfY14kGdeX87wczpefBdkb/qiZESjzfDixnAL9nNaBppoV+wtzP6YxOBLZ7qNlmo8oyvtA==} dependencies: - '@visactor/vgrammar-util': 0.13.2 + '@visactor/vgrammar-util': 0.13.10 '@visactor/vutils': 0.18.9 - /@visactor/vgrammar-core/0.13.2: - resolution: {integrity: sha512-uBmGP4Cj1yEc+iR31dKCM4J0ISs5Qy9cbtouCJfuMx2lGzlJQR7ThVS5sFKlPbLtRDp8YPz+TmNcACHGXWZLUg==} + /@visactor/vgrammar-core/0.13.10: + resolution: {integrity: sha512-sJajDZ51tB61ho/YI0WxeUx10pZ3GyVBCxzPIKGZaQWuopnt/gpPwy/Y0bSqbI5V/qXAcCbDKJuvNWMJsEFgEQ==} dependencies: '@visactor/vdataset': 0.18.9 - '@visactor/vgrammar-coordinate': 0.13.2 - '@visactor/vgrammar-util': 0.13.2 - '@visactor/vrender-components': 0.19.0 - '@visactor/vrender-core': 0.19.0 - '@visactor/vrender-kits': 0.19.0 + '@visactor/vgrammar-coordinate': 0.13.10 + '@visactor/vgrammar-util': 0.13.10 + '@visactor/vrender-components': 0.19.11 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vscale': 0.18.9 '@visactor/vutils': 0.18.9 - /@visactor/vgrammar-hierarchy/0.13.2: - resolution: {integrity: sha512-31pDnI4/+DPHme1isFNTvAoU8BAJCdmNM734hQ0gBgq7wyjKyybkxdIFNm7oh2ow+Q3wpVSUHNoyAR7l/uJGPg==} + /@visactor/vgrammar-hierarchy/0.13.10: + resolution: {integrity: sha512-JoGjcW1FsdUVpYJXZng3Up00Ipirffne2hp08HD4yjVSzi5jwMTJ2qazkQaIkG8vdeOErCqyLiKdfnnHfBMybg==} dependencies: - '@visactor/vgrammar-core': 0.13.2 - '@visactor/vgrammar-util': 0.13.2 - '@visactor/vrender-core': 0.19.0 - '@visactor/vrender-kits': 0.19.0 + '@visactor/vgrammar-core': 0.13.10 + '@visactor/vgrammar-util': 0.13.10 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vutils': 0.18.9 - /@visactor/vgrammar-projection/0.13.2: - resolution: {integrity: sha512-+3xObQkYSWYZPuWiml82Gp3mSuUa7/QRoKmicv9sEFjC++HmTllD729/CofPXEodYhK5Ju4q5TO0qRhV5/DOOA==} + /@visactor/vgrammar-projection/0.13.10: + resolution: {integrity: sha512-RTxfI9u2pdZOjYiDTQa9b9bPQgEMOn0r0Yp2Am4HhYzCpPiE0NrXNFPz1Ot1vnFIsGLaLRn+DwQVryVSVC7myw==} dependencies: - '@visactor/vgrammar-core': 0.13.2 - '@visactor/vgrammar-util': 0.13.2 + '@visactor/vgrammar-core': 0.13.10 + '@visactor/vgrammar-util': 0.13.10 '@visactor/vutils': 0.18.9 d3-geo: 1.12.1 - /@visactor/vgrammar-sankey/0.13.2: - resolution: {integrity: sha512-jjX6BGLTbTivAVRjS5KIMK7GLJ2QlosYzzUXl6/4xP8fmiUJgoLLQpDUIucKTE3QcA1tUDWn6tXrzgTB4fyD5A==} + /@visactor/vgrammar-sankey/0.13.10: + resolution: {integrity: sha512-G0zS998eHMoO5VCLu0pd/Mi6JKaLKNafsRU8O2uGVgk2WweyaG5SRDgvZv5/YlaMSBwrtG/2iOYIvpEWOKvd5g==} dependencies: - '@visactor/vgrammar-core': 0.13.2 - '@visactor/vgrammar-util': 0.13.2 - '@visactor/vrender-core': 0.19.0 - '@visactor/vrender-kits': 0.19.0 + '@visactor/vgrammar-core': 0.13.10 + '@visactor/vgrammar-util': 0.13.10 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vutils': 0.18.9 - /@visactor/vgrammar-util/0.13.2: - resolution: {integrity: sha512-UIGLsoFP0q9NcLSfDiSGLIZ6QzB5kOyP8AHqqktZs08bPgqisbobyVtl6zuGVuwsQZBKf1i50knLX1Lnb+sOcw==} + /@visactor/vgrammar-util/0.13.10: + resolution: {integrity: sha512-N+HLotFXlCAnYkrHQ7YDkVatTCirlOGCL/26+2VZtB69aiIV9qTQm/Cor7LOTAR7Xb7uF8QgyndDwHe3+ojw9Q==} dependencies: '@visactor/vutils': 0.18.9 - /@visactor/vgrammar-venn/0.13.2: - resolution: {integrity: sha512-ppMHjZeOiMbmNTiyeWYqVkZdEUn/ny1v6pPGUh1f3/JKUYy80fM6PG6yKcwbEPg5Rc68Hjz5T9IFO4f0mWloNQ==} + /@visactor/vgrammar-venn/0.13.10: + resolution: {integrity: sha512-dClkh269VSy5wVR4sC2l2ZoUo2lbQj0RvhJrZp8WoGK4wXHuoGlMlxb+qQc4TRw/lD8G6YJltcg8rtRPZ8+dog==} dependencies: - '@visactor/vgrammar-core': 0.13.2 - '@visactor/vgrammar-util': 0.13.2 - '@visactor/vrender-core': 0.19.0 - '@visactor/vrender-kits': 0.19.0 + '@visactor/vgrammar-core': 0.13.10 + '@visactor/vgrammar-util': 0.13.10 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vutils': 0.18.9 - /@visactor/vgrammar-wordcloud-shape/0.13.2: - resolution: {integrity: sha512-RxpakDTusIYSy3G2SNmB1nYtXKBs4nYcONc/Njrfk21/+P73pVoZ/DXGI8SB4YxSjp1MPRf9bpPWOWNTw5u8og==} + /@visactor/vgrammar-wordcloud-shape/0.13.10: + resolution: {integrity: sha512-AYLrgiYDf6OIn3jNZwzO5CPIhCaECr2SO++hrlQJMCy/3ZuER1cSj8VIIwH3/CDzIE+h086ENSXrou1jIBLxFw==} dependencies: - '@visactor/vgrammar-core': 0.13.2 - '@visactor/vgrammar-util': 0.13.2 - '@visactor/vrender-core': 0.19.0 - '@visactor/vrender-kits': 0.19.0 + '@visactor/vgrammar-core': 0.13.10 + '@visactor/vgrammar-util': 0.13.10 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vscale': 0.18.9 '@visactor/vutils': 0.18.9 - /@visactor/vgrammar-wordcloud/0.13.2: - resolution: {integrity: sha512-VSho3WsH1AQt95qZytrlZDyEUNVXnuO+4hPAyXWVtT2DrGFkF6MHXqx/pPQRfHW3AkrQByCuK4KAirMPNPi8Kw==} - dependencies: - '@visactor/vgrammar-core': 0.13.2 - '@visactor/vgrammar-util': 0.13.2 - '@visactor/vrender-core': 0.19.0 - '@visactor/vrender-kits': 0.19.0 - '@visactor/vutils': 0.18.9 - - /@visactor/vrender-components/0.19.0: - resolution: {integrity: sha512-J+Dtw727xVKg+7tTAbFkaM6AzNVdx0ZEXaGH4JYbhGTC6S6gO7rn8X+vGO2l/vilt4MfEWYAhRuGwZkJToiAxA==} + /@visactor/vgrammar-wordcloud/0.13.10: + resolution: {integrity: sha512-AojmYCqtNnSzkIl21WWCIa8ZQT5sI6i9tFbcbjzostJ7xSqN9c5eKkbnQoybKHRzq7dcQ3oEu0pu2/XJtpoNiA==} dependencies: - '@visactor/vrender-core': 0.19.0 - '@visactor/vrender-kits': 0.19.0 - '@visactor/vscale': 0.17.5 + '@visactor/vgrammar-core': 0.13.10 + '@visactor/vgrammar-util': 0.13.10 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vutils': 0.18.9 - /@visactor/vrender-components/0.19.9: - resolution: {integrity: sha512-IKbYMCr7KO2wE38cxS2O2FR1ufvWn2StFcWyp8mNi3ZIho9M+fjJoNDefdrOEN9o3N9b3v2AZdQzLDqs2ZMQEw==} + /@visactor/vrender-components/0.19.11: + resolution: {integrity: sha512-K9967q364GojufVIlEVxr9duE/ce7tHsBTHxWHjx+uGAiJy3gmG3Vx2Ch38yoDZorR47X+YFjBSJoIqNVOwi8Q==} dependencies: - '@visactor/vrender-core': 0.19.9 - '@visactor/vrender-kits': 0.19.9 + '@visactor/vrender-core': 0.19.11 + '@visactor/vrender-kits': 0.19.11 '@visactor/vscale': 0.18.9 '@visactor/vutils': 0.18.9 - dev: false - - /@visactor/vrender-core/0.19.0: - resolution: {integrity: sha512-LOMg4bySvVXrCcyd8dqsQRvrPcdozOi1trIddslJuiES7bzldniTH0yWaqdysdhIK9dPCryDjOtU0i9nc0bz2w==} - dependencies: - '@visactor/vutils': 0.18.9 - color-convert: 2.0.1 - /@visactor/vrender-core/0.19.9: - resolution: {integrity: sha512-9Ucz93ECTbClf3zqRf348aTyr/rtAecqoQsXd69fwYgPvB2Fy6A0Ofm8O1odChxLx7oaoZPzcSeS9YGVPssn+A==} + /@visactor/vrender-core/0.19.11: + resolution: {integrity: sha512-an0zfDMJy9ygsXY1w2xSN2nWbUmy97YrBNDEvm0Nb/kS6tNpeB8G6z5t8KO2ivq5aVZihCIJv8342/yGOnDHfg==} dependencies: '@visactor/vutils': 0.18.9 color-convert: 2.0.1 - dev: false - /@visactor/vrender-kits/0.19.0: - resolution: {integrity: sha512-aTB2CYYpNHWusVTO3bjH/wMYkhaKvO+sD6TA9A0tB5T4+jh0cfxKT+K3UE3sYDXhCjcuQNr9ZLbyz51IdxE4Gg==} + /@visactor/vrender-kits/0.19.11: + resolution: {integrity: sha512-ZzVZKVrRCuxC8+awhG3yxTwE8/qZpSTNCettTsTNs12oifeN6m+z2mvCSdHcOUn5Hw/FJyTFm2Bv2HmFNerQhw==} dependencies: '@resvg/resvg-js': 2.4.1 - '@visactor/vrender-core': 0.19.0 + '@visactor/vrender-core': 0.19.11 '@visactor/vutils': 0.18.9 roughjs: 4.5.2 - /@visactor/vrender-kits/0.19.9: - resolution: {integrity: sha512-y0ncykl6i+GYK2Ih5RDt/fiLKLXVmFrDYm4zgg7O+Yaaw/iGBXOrlFVIQE6Ao0kfOwDac0xKZzaS9x7kKrULRw==} - dependencies: - '@resvg/resvg-js': 2.4.1 - '@visactor/vrender-core': 0.19.9 - '@visactor/vutils': 0.18.9 - roughjs: 4.5.2 - dev: false - - /@visactor/vscale/0.17.5: - resolution: {integrity: sha512-2dkS1IlAJ/IdTp8JElbctOOv6lkHKBKPDm8KvwBo0NuGWQeYAebSeyN3QCdwKbj76gMlCub4zc+xWrS5YiA2zA==} - dependencies: - '@visactor/vutils': 0.17.5 - /@visactor/vscale/0.18.9: resolution: {integrity: sha512-rglOQQGhkamtjGtbFxY5pcfqsBXDyYU6NiQuBdVSeYRQvB9YpLLk455HpvQcEEhC+bRopNQsQgQV5276Pd0sfQ==} dependencies: '@visactor/vutils': 0.18.9 - /@visactor/vutils-extension/1.11.0_7qcgcpuz2j5tzhxzhxchuz72qy: - resolution: {integrity: sha512-fRxv1VkoDgDVaTCeBoc9u6d343vd/lZGR8N2f/c6Hn8woToJB1lHrGg1MBEgxNKOaeLZN3dc5EcMn9LhxOpM4g==} - peerDependencies: - '@visactor/vrender-components': '>=0.18' - '@visactor/vrender-core': '>=0.18' + /@visactor/vutils-extension/1.11.4: + resolution: {integrity: sha512-7803joLO5XYpbUyJZDU3dAygLtpjvCcj1k4+RY6Co3+xH+aJ85qfqU8iKuKCKzjo0j0ls8MUNGJUTVW2nySwTw==} dependencies: '@visactor/vdataset': 0.18.9 - '@visactor/vrender-components': 0.19.0 - '@visactor/vrender-core': 0.19.0 - '@visactor/vscale': 0.18.9 '@visactor/vutils': 0.18.9 - /@visactor/vutils/0.17.5: - resolution: {integrity: sha512-HFN6Pk1Wc1RK842g02MeKOlvdri5L7/nqxMVTqxIvi0XMhHXpmoqN4+/9H+h8LmJpVohyrI/MT85TRBV/rManw==} - dependencies: - '@turf/helpers': 6.5.0 - '@turf/invariant': 6.5.0 - eventemitter3: 4.0.7 - /@visactor/vutils/0.18.9: resolution: {integrity: sha512-+CPwBATTQUPtXQ0KVXFRz8SCwAY9m5aR9QmtsVqya+mgaay3moFaAPNTbdkLBuZM5ewRYVcv/3fsDxuH+NXfFg==} dependencies: @@ -8852,7 +8809,7 @@ packages: jest-leak-detector: 26.6.2 jest-message-util: 26.6.2 jest-resolve: 26.6.2 - jest-runtime: 26.6.3 + jest-runtime: 26.6.3_ts-node@10.9.0 jest-util: 26.6.2 jest-worker: 26.6.2 source-map-support: 0.5.21 @@ -8897,42 +8854,6 @@ packages: - supports-color dev: true - /jest-runtime/26.6.3: - resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==} - engines: {node: '>= 10.14.2'} - hasBin: true - dependencies: - '@jest/console': 26.6.2 - '@jest/environment': 26.6.2 - '@jest/fake-timers': 26.6.2 - '@jest/globals': 26.6.2 - '@jest/source-map': 26.6.2 - '@jest/test-result': 26.6.2 - '@jest/transform': 26.6.2 - '@jest/types': 26.6.2 - '@types/yargs': 15.0.19 - chalk: 4.1.2 - cjs-module-lexer: 0.6.0 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-config: 26.6.3_ts-node@10.9.0 - jest-haste-map: 26.6.2 - jest-message-util: 26.6.2 - jest-mock: 26.6.2 - jest-regex-util: 26.0.0 - jest-resolve: 26.6.2 - jest-snapshot: 26.6.2 - jest-util: 26.6.2 - jest-validate: 26.6.2 - slash: 3.0.0 - strip-bom: 4.0.0 - yargs: 15.4.1 - transitivePeerDependencies: - - supports-color - dev: true - /jest-runtime/26.6.3_ts-node@10.9.0: resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==} engines: {node: '>= 10.14.2'} diff --git a/docs/package.json b/docs/package.json index 05b054ad0..3dcb57689 100644 --- a/docs/package.json +++ b/docs/package.json @@ -17,7 +17,7 @@ "@visactor/vtable-export": "workspace:*", "@visactor/vtable-search": "workspace:*", "buble": "^0.20.0", - "@visactor/vchart": "1.11.0", + "@visactor/vchart": "1.11.4", "markdown-it": "^13.0.0", "highlight.js": "^11.8.0", "axios": "^1.4.0", diff --git a/packages/vtable/package.json b/packages/vtable/package.json index a8cf1c548..39bc80f36 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -60,7 +60,7 @@ }, "devDependencies": { "luxon": "*", - "@visactor/vchart": "1.11.0", + "@visactor/vchart": "1.11.4", "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", From 8dc02e6185c58a35510cc34a9065f6b5a876bbb6 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 19 Jun 2024 14:11:26 +0800 Subject: [PATCH 55/85] feat: support calculate field for PivotTable #1941 --- packages/vtable/src/data/DataSource.ts | 31 +++++++++++++++----------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/packages/vtable/src/data/DataSource.ts b/packages/vtable/src/data/DataSource.ts index 57320431d..b8170a57e 100644 --- a/packages/vtable/src/data/DataSource.ts +++ b/packages/vtable/src/data/DataSource.ts @@ -178,7 +178,12 @@ export class DataSource extends EventTarget implements DataSourceAPI { // 注册聚合类型 registedAggregators: { [key: string]: { - new (dimension: string | string[], formatFun?: any, isRecord?: boolean, aggregationFun?: Function): Aggregator; + new (config: { + dimension: string | string[]; + formatFun?: any; + isRecord?: boolean; + aggregationFun?: Function; + }): Aggregator; }; } = {}; rowHierarchyType: 'grid' | 'tree'; @@ -279,12 +284,12 @@ export class DataSource extends EventTarget implements DataSourceAPI { if (Array.isArray(aggragation)) { for (let j = 0; j < aggragation.length; j++) { const item = aggragation[j]; - const aggregator = new this.registedAggregators[item.aggregationType]( - field as string, - item.formatFun, - true, - (item as CustomAggregation).aggregationFun - ); + const aggregator = new this.registedAggregators[item.aggregationType]({ + dimension: field as string, + formatFun: item.formatFun, + isRecord: true, + aggregationFun: (item as CustomAggregation).aggregationFun + }); this.fieldAggregators.push(aggregator); if (!columnObjs[i].aggregator) { columnObjs[i].aggregator = []; @@ -292,12 +297,12 @@ export class DataSource extends EventTarget implements DataSourceAPI { columnObjs[i].aggregator.push(aggregator); } } else { - const aggregator = new this.registedAggregators[aggragation.aggregationType]( - field as string, - aggragation.formatFun, - true, - (aggragation as CustomAggregation).aggregationFun - ); + const aggregator = new this.registedAggregators[aggragation.aggregationType]({ + dimension: field as string, + formatFun: aggragation.formatFun, + isRecord: true, + aggregationFun: (aggragation as CustomAggregation).aggregationFun + }); this.fieldAggregators.push(aggregator); columnObjs[i].aggregator = aggregator; } From 7c98e6b875d79442a25b0e4317abeed7a73f4e32 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 19 Jun 2024 14:19:42 +0800 Subject: [PATCH 56/85] docs: update changlog of rush --- .../vtable/chore-updateVrender_2024-06-19-06-19.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/chore-updateVrender_2024-06-19-06-19.json diff --git a/common/changes/@visactor/vtable/chore-updateVrender_2024-06-19-06-19.json b/common/changes/@visactor/vtable/chore-updateVrender_2024-06-19-06-19.json new file mode 100644 index 000000000..cfce0c96a --- /dev/null +++ b/common/changes/@visactor/vtable/chore-updateVrender_2024-06-19-06-19.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "chore: update vrender version\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From a9ecc90ed3fadb209e5586fa92692f1f830c44af Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 19 Jun 2024 16:28:18 +0800 Subject: [PATCH 57/85] docs: add demo for calculated field --- .../pivot-analysis-aggregation.md | 2 +- .../pivot-analysis-calculatedField.md | 194 ++++++++++++++++++ .../pivot-analysis-custom-total.md | 2 +- .../pivot-analysis-derivedField.md | 2 +- .../en/data-analysis/pivot-analysis-filter.md | 2 +- .../pivot-analysis-sort-dimension.md | 2 +- .../data-analysis/pivot-analysis-sort-func.md | 2 +- .../pivot-analysis-sort-indicator.md | 2 +- .../pivot-analysis-table-drill.md | 2 +- .../en/data-analysis/pivot-analysis-total.md | 2 +- .../pivot-analysis-table-indicator-row.md | 2 +- .../table-type/pivot-analysis-table-tree.md | 2 +- .../en/table-type/pivot-analysis-table.md | 2 +- docs/assets/demo/menu.json | 7 + .../pivot-analysis-aggregation.md | 2 +- .../pivot-analysis-calculatedField.md | 194 ++++++++++++++++++ .../pivot-analysis-custom-total.md | 2 +- .../pivot-analysis-derivedField.md | 2 +- .../zh/data-analysis/pivot-analysis-filter.md | 2 +- .../pivot-analysis-sort-dimension.md | 2 +- .../data-analysis/pivot-analysis-sort-func.md | 2 +- .../pivot-analysis-sort-indicator.md | 2 +- .../pivot-analysis-table-drill.md | 2 +- .../zh/data-analysis/pivot-analysis-total.md | 2 +- .../pivot-analysis-table-indicator-row.md | 2 +- .../table-type/pivot-analysis-table-tree.md | 2 +- .../zh/table-type/pivot-analysis-table.md | 2 +- 27 files changed, 419 insertions(+), 24 deletions(-) create mode 100644 docs/assets/demo/en/data-analysis/pivot-analysis-calculatedField.md create mode 100644 docs/assets/demo/zh/data-analysis/pivot-analysis-calculatedField.md diff --git a/docs/assets/demo/en/data-analysis/pivot-analysis-aggregation.md b/docs/assets/demo/en/data-analysis/pivot-analysis-aggregation.md index 50af8c199..de4039e81 100644 --- a/docs/assets/demo/en/data-analysis/pivot-analysis-aggregation.md +++ b/docs/assets/demo/en/data-analysis/pivot-analysis-aggregation.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: Indicator Aggregation Type cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-aggregation.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.aggregationRules --- diff --git a/docs/assets/demo/en/data-analysis/pivot-analysis-calculatedField.md b/docs/assets/demo/en/data-analysis/pivot-analysis-calculatedField.md new file mode 100644 index 000000000..3250d23d6 --- /dev/null +++ b/docs/assets/demo/en/data-analysis/pivot-analysis-calculatedField.md @@ -0,0 +1,194 @@ +--- +category: examples +group: data-analysis +title: Pivot Table - Calculated Field +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/calculatedField.jpeg +link: '../guide/data_analysis/pivot_table_dataAnalysis' +option: PivotTable#dataConfig.totals +--- + +# Pivot Table - Calculated Field + +The pivot table configures the calculated fields through the calculatedFieldRules in the dataConfig. + +## Key Configurations + +- `PivotTable` +- `columns` +- `rows` +- `indicators` +- `dataConfig.calculatedFieldRules` + +## Code demo + +```javascript livedemo template=vtable +let tableInstance; +fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') + .then(res => res.json()) + .then(data => { + const option = { + records: data, + rows: [ + { + dimensionKey: 'Category', + title: 'Category', + headerStyle: { + textStick: true, + bgColor(arg) { + if (arg.dataValue === 'Row Totals') { + return '#ff9900'; + } + return '#ECF1F5'; + } + }, + width: 'auto' + }, + { + dimensionKey: 'Sub-Category', + title: 'Sub-Catogery', + headerStyle: { + textStick: true, + bgColor(arg) { + if (arg.dataValue === 'Sub Totals') { + return '#ba54ba'; + } + return '#ECF1F5'; + } + }, + width: 'auto' + } + ], + columns: [ + { + dimensionKey: 'Region', + title: 'Region', + headerStyle: { + textStick: true + }, + width: 'auto' + }, + { + dimensionKey: 'Segment', + title: 'Segment', + headerStyle: { + textStick: true + }, + width: 'auto' + } + ], + indicators: [ + { + indicatorKey: 'Quantity', + title: 'Quantity', + width: 'auto', + showSort: false, + headerStyle: { + fontWeight: 'normal' + }, + style: { + padding: [16, 28, 16, 28], + color(args) { + if (args.dataValue >= 0) return 'black'; + return 'red'; + }, + bgColor(arg) { + const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; + if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { + return '#ba54ba'; + } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { + return '#ff9900'; + } + return undefined; + } + } + }, + { + indicatorKey: 'Sales', + title: 'Sales', + width: 'auto', + showSort: false, + headerStyle: { + fontWeight: 'normal' + }, + format: rec => { + return '$' + Number(rec).toFixed(2); + }, + style: { + padding: [16, 28, 16, 28], + color(args) { + if (args.dataValue >= 0) return 'black'; + return 'red'; + }, + bgColor(arg) { + const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; + if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { + return '#ba54ba'; + } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { + return '#ff9900'; + } + return undefined; + } + } + }, + { + indicatorKey: 'AvgPrice', + title: 'AvgPrice', + width: 'auto', + format: rec => { + return '$' + Number(rec).toFixed(2); + }, + headerStyle: { + color: 'blue' + }, + style: { + bgColor(arg) { + const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; + if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { + return '#ba54ba'; + } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { + return '#ff9900'; + } + return undefined; + } + } + } + ], + corner: { + titleOnDimension: 'row', + headerStyle: { + textStick: true + } + }, + dataConfig: { + calculatedFieldRules: [ + { + key: 'AvgPrice', + dependIndicatorKeys: ['Quantity', 'Sales'], + calculateFun: dependValue => { + return dependValue.Sales / dependValue.Quantity; + } + } + ], + totals: { + row: { + showGrandTotals: true, + showSubTotals: true, + subTotalsDimensions: ['Category'], + grandTotalLabel: 'Row Totals', + subTotalLabel: 'Sub Totals' + }, + column: { + showGrandTotals: true, + showSubTotals: true, + subTotalsDimensions: ['Region'], + grandTotalLabel: 'Column Totals', + subTotalLabel: 'Sub Totals' + } + } + }, + widthMode: 'standard' + }; + tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); + window['tableInstance'] = tableInstance; + }); +``` diff --git a/docs/assets/demo/en/data-analysis/pivot-analysis-custom-total.md b/docs/assets/demo/en/data-analysis/pivot-analysis-custom-total.md index f8189e5b1..11160a82a 100644 --- a/docs/assets/demo/en/data-analysis/pivot-analysis-custom-total.md +++ b/docs/assets/demo/en/data-analysis/pivot-analysis-custom-total.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: Custom Total cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-custom-total.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.totals --- diff --git a/docs/assets/demo/en/data-analysis/pivot-analysis-derivedField.md b/docs/assets/demo/en/data-analysis/pivot-analysis-derivedField.md index 544f93d0d..46621e84e 100644 --- a/docs/assets/demo/en/data-analysis/pivot-analysis-derivedField.md +++ b/docs/assets/demo/en/data-analysis/pivot-analysis-derivedField.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: Derived Field cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-derivedField.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.derivedFieldRules --- diff --git a/docs/assets/demo/en/data-analysis/pivot-analysis-filter.md b/docs/assets/demo/en/data-analysis/pivot-analysis-filter.md index 04ceea88b..eff4134b2 100644 --- a/docs/assets/demo/en/data-analysis/pivot-analysis-filter.md +++ b/docs/assets/demo/en/data-analysis/pivot-analysis-filter.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: Data Filter cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-filter.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.filterRules --- diff --git a/docs/assets/demo/en/data-analysis/pivot-analysis-sort-dimension.md b/docs/assets/demo/en/data-analysis/pivot-analysis-sort-dimension.md index 652047a15..49bed67cf 100644 --- a/docs/assets/demo/en/data-analysis/pivot-analysis-sort-dimension.md +++ b/docs/assets/demo/en/data-analysis/pivot-analysis-sort-dimension.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: Sort Dimension cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-sort-dimension.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.sortRules --- diff --git a/docs/assets/demo/en/data-analysis/pivot-analysis-sort-func.md b/docs/assets/demo/en/data-analysis/pivot-analysis-sort-func.md index 307936e35..4079ac1b8 100644 --- a/docs/assets/demo/en/data-analysis/pivot-analysis-sort-func.md +++ b/docs/assets/demo/en/data-analysis/pivot-analysis-sort-func.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: Sort Function cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-sort-func.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.sortRules --- diff --git a/docs/assets/demo/en/data-analysis/pivot-analysis-sort-indicator.md b/docs/assets/demo/en/data-analysis/pivot-analysis-sort-indicator.md index d2fcffd52..71c09232e 100644 --- a/docs/assets/demo/en/data-analysis/pivot-analysis-sort-indicator.md +++ b/docs/assets/demo/en/data-analysis/pivot-analysis-sort-indicator.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: Sort Indicator cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-sort-indicator.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.sortRules --- diff --git a/docs/assets/demo/en/data-analysis/pivot-analysis-table-drill.md b/docs/assets/demo/en/data-analysis/pivot-analysis-table-drill.md index 3c1c25d6a..5382a61ac 100644 --- a/docs/assets/demo/en/data-analysis/pivot-analysis-table-drill.md +++ b/docs/assets/demo/en/data-analysis/pivot-analysis-table-drill.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: Pivot analysis table drill down and drill up cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-table-drill.gif -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable-columns-text#drillDown --- diff --git a/docs/assets/demo/en/data-analysis/pivot-analysis-total.md b/docs/assets/demo/en/data-analysis/pivot-analysis-total.md index 71fcf6795..a3f4941cd 100644 --- a/docs/assets/demo/en/data-analysis/pivot-analysis-total.md +++ b/docs/assets/demo/en/data-analysis/pivot-analysis-total.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: Pivot Analysis Total cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-total.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.totals --- diff --git a/docs/assets/demo/en/table-type/pivot-analysis-table-indicator-row.md b/docs/assets/demo/en/table-type/pivot-analysis-table-indicator-row.md index 4eec6dc1e..938da88fe 100644 --- a/docs/assets/demo/en/table-type/pivot-analysis-table-indicator-row.md +++ b/docs/assets/demo/en/table-type/pivot-analysis-table-indicator-row.md @@ -3,7 +3,7 @@ category: examples group: table-type title: Pivot analysis table (indicators are displayed in rows) cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-table-indicator-row.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#indicatorsAsCol --- diff --git a/docs/assets/demo/en/table-type/pivot-analysis-table-tree.md b/docs/assets/demo/en/table-type/pivot-analysis-table-tree.md index ab3285b08..4aa2b0fd9 100644 --- a/docs/assets/demo/en/table-type/pivot-analysis-table-tree.md +++ b/docs/assets/demo/en/table-type/pivot-analysis-table-tree.md @@ -3,7 +3,7 @@ category: examples group: table-type title: Pivot analysis tree table cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-table-tree.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#rowHierarchyType('grid'%20%7C%20'tree') --- diff --git a/docs/assets/demo/en/table-type/pivot-analysis-table.md b/docs/assets/demo/en/table-type/pivot-analysis-table.md index 051db4cb9..aed3b346c 100644 --- a/docs/assets/demo/en/table-type/pivot-analysis-table.md +++ b/docs/assets/demo/en/table-type/pivot-analysis-table.md @@ -3,7 +3,7 @@ category: examples group: table-type title: Pivot analysis table cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-table.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig --- diff --git a/docs/assets/demo/menu.json b/docs/assets/demo/menu.json index 3e858ac01..4238264d4 100644 --- a/docs/assets/demo/menu.json +++ b/docs/assets/demo/menu.json @@ -1039,6 +1039,13 @@ "en": "Indicator Aggregation Type" } }, + { + "path": "pivot-analysis-calculatedField", + "title": { + "zh": "计算字段", + "en": "Calculate Field" + } + }, { "path": "pivot-analysis-table-drill", "title": { diff --git a/docs/assets/demo/zh/data-analysis/pivot-analysis-aggregation.md b/docs/assets/demo/zh/data-analysis/pivot-analysis-aggregation.md index c25d02020..3a3581a90 100644 --- a/docs/assets/demo/zh/data-analysis/pivot-analysis-aggregation.md +++ b/docs/assets/demo/zh/data-analysis/pivot-analysis-aggregation.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: 指标聚合方式 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-aggregation.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.aggregationRules --- diff --git a/docs/assets/demo/zh/data-analysis/pivot-analysis-calculatedField.md b/docs/assets/demo/zh/data-analysis/pivot-analysis-calculatedField.md new file mode 100644 index 000000000..c7d50cb67 --- /dev/null +++ b/docs/assets/demo/zh/data-analysis/pivot-analysis-calculatedField.md @@ -0,0 +1,194 @@ +--- +category: examples +group: data-analysis +title: 透视表计算字段 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/calculatedField.jpeg +link: '../guide/data_analysis/pivot_table_dataAnalysis' +option: PivotTable#dataConfig.totals +--- + +# 透视分析——计算字段 + +透视分析表通过 dataConfig 中的 calculatedFieldRules 来配置计算字段。 + +## 关键配置 + +- `PivotTable` +- `columns` +- `rows` +- `indicators` +- `dataConfig.calculatedFieldRules` 配置计算字段 + +## 代码演示 + +```javascript livedemo template=vtable +let tableInstance; +fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') + .then(res => res.json()) + .then(data => { + const option = { + records: data, + rows: [ + { + dimensionKey: 'Category', + title: 'Category', + headerStyle: { + textStick: true, + bgColor(arg) { + if (arg.dataValue === 'Row Totals') { + return '#ff9900'; + } + return '#ECF1F5'; + } + }, + width: 'auto' + }, + { + dimensionKey: 'Sub-Category', + title: 'Sub-Catogery', + headerStyle: { + textStick: true, + bgColor(arg) { + if (arg.dataValue === 'Sub Totals') { + return '#ba54ba'; + } + return '#ECF1F5'; + } + }, + width: 'auto' + } + ], + columns: [ + { + dimensionKey: 'Region', + title: 'Region', + headerStyle: { + textStick: true + }, + width: 'auto' + }, + { + dimensionKey: 'Segment', + title: 'Segment', + headerStyle: { + textStick: true + }, + width: 'auto' + } + ], + indicators: [ + { + indicatorKey: 'Quantity', + title: 'Quantity', + width: 'auto', + showSort: false, + headerStyle: { + fontWeight: 'normal' + }, + style: { + padding: [16, 28, 16, 28], + color(args) { + if (args.dataValue >= 0) return 'black'; + return 'red'; + }, + bgColor(arg) { + const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; + if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { + return '#ba54ba'; + } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { + return '#ff9900'; + } + return undefined; + } + } + }, + { + indicatorKey: 'Sales', + title: 'Sales', + width: 'auto', + showSort: false, + headerStyle: { + fontWeight: 'normal' + }, + format: rec => { + return '$' + Number(rec).toFixed(2); + }, + style: { + padding: [16, 28, 16, 28], + color(args) { + if (args.dataValue >= 0) return 'black'; + return 'red'; + }, + bgColor(arg) { + const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; + if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { + return '#ba54ba'; + } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { + return '#ff9900'; + } + return undefined; + } + } + }, + { + indicatorKey: 'AvgPrice', + title: 'AvgPrice', + width: 'auto', + format: rec => { + return '$' + Number(rec).toFixed(2); + }, + headerStyle: { + color: 'blue' + }, + style: { + bgColor(arg) { + const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; + if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { + return '#ba54ba'; + } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { + return '#ff9900'; + } + return undefined; + } + } + } + ], + corner: { + titleOnDimension: 'row', + headerStyle: { + textStick: true + } + }, + dataConfig: { + calculatedFieldRules: [ + { + key: 'AvgPrice', + dependIndicatorKeys: ['Quantity', 'Sales'], + calculateFun: dependValue => { + return dependValue.Sales / dependValue.Quantity; + } + } + ], + totals: { + row: { + showGrandTotals: true, + showSubTotals: true, + subTotalsDimensions: ['Category'], + grandTotalLabel: 'Row Totals', + subTotalLabel: 'Sub Totals' + }, + column: { + showGrandTotals: true, + showSubTotals: true, + subTotalsDimensions: ['Region'], + grandTotalLabel: 'Column Totals', + subTotalLabel: 'Sub Totals' + } + } + }, + widthMode: 'standard' + }; + tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); + window['tableInstance'] = tableInstance; + }); +``` diff --git a/docs/assets/demo/zh/data-analysis/pivot-analysis-custom-total.md b/docs/assets/demo/zh/data-analysis/pivot-analysis-custom-total.md index a5877b937..4295ac736 100644 --- a/docs/assets/demo/zh/data-analysis/pivot-analysis-custom-total.md +++ b/docs/assets/demo/zh/data-analysis/pivot-analysis-custom-total.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: 自定义小计总计 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-custom-total.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.totals --- diff --git a/docs/assets/demo/zh/data-analysis/pivot-analysis-derivedField.md b/docs/assets/demo/zh/data-analysis/pivot-analysis-derivedField.md index 44aa76ae7..4e7a7e910 100644 --- a/docs/assets/demo/zh/data-analysis/pivot-analysis-derivedField.md +++ b/docs/assets/demo/zh/data-analysis/pivot-analysis-derivedField.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: 派生字段 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-derivedField.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.derivedFieldRules --- diff --git a/docs/assets/demo/zh/data-analysis/pivot-analysis-filter.md b/docs/assets/demo/zh/data-analysis/pivot-analysis-filter.md index 421302bb3..e4e212b13 100644 --- a/docs/assets/demo/zh/data-analysis/pivot-analysis-filter.md +++ b/docs/assets/demo/zh/data-analysis/pivot-analysis-filter.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: 数据过滤 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-filter.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.filterRules --- diff --git a/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-dimension.md b/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-dimension.md index b6e45f970..01228f0d0 100644 --- a/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-dimension.md +++ b/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-dimension.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: 维度值排序 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-sort-dimension.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.sortRules --- diff --git a/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-func.md b/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-func.md index 42a159b70..cb6529f36 100644 --- a/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-func.md +++ b/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-func.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: 自定义排序 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-sort-func.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.sortRules --- diff --git a/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-indicator.md b/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-indicator.md index a487e9640..a541386a3 100644 --- a/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-indicator.md +++ b/docs/assets/demo/zh/data-analysis/pivot-analysis-sort-indicator.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: 指标值排序 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-sort-indicator.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.sortRules --- diff --git a/docs/assets/demo/zh/data-analysis/pivot-analysis-table-drill.md b/docs/assets/demo/zh/data-analysis/pivot-analysis-table-drill.md index d14c4235b..78724ac32 100644 --- a/docs/assets/demo/zh/data-analysis/pivot-analysis-table-drill.md +++ b/docs/assets/demo/zh/data-analysis/pivot-analysis-table-drill.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: 透视分析表格下钻上钻 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-table-drill.gif -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable-columns-text#drillDown --- diff --git a/docs/assets/demo/zh/data-analysis/pivot-analysis-total.md b/docs/assets/demo/zh/data-analysis/pivot-analysis-total.md index 1fe2a5e5b..4bcfab205 100644 --- a/docs/assets/demo/zh/data-analysis/pivot-analysis-total.md +++ b/docs/assets/demo/zh/data-analysis/pivot-analysis-total.md @@ -3,7 +3,7 @@ category: examples group: data-analysis title: 透视维度小计总计 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-total.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig.totals --- diff --git a/docs/assets/demo/zh/table-type/pivot-analysis-table-indicator-row.md b/docs/assets/demo/zh/table-type/pivot-analysis-table-indicator-row.md index 87df03628..43d9ae665 100644 --- a/docs/assets/demo/zh/table-type/pivot-analysis-table-indicator-row.md +++ b/docs/assets/demo/zh/table-type/pivot-analysis-table-indicator-row.md @@ -3,7 +3,7 @@ category: examples group: table-type title: 透视分析表格(指标以行展示) cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-table-indicator-row.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#indicatorsAsCol --- diff --git a/docs/assets/demo/zh/table-type/pivot-analysis-table-tree.md b/docs/assets/demo/zh/table-type/pivot-analysis-table-tree.md index db6ed21e4..ed9c337fb 100644 --- a/docs/assets/demo/zh/table-type/pivot-analysis-table-tree.md +++ b/docs/assets/demo/zh/table-type/pivot-analysis-table-tree.md @@ -3,7 +3,7 @@ category: examples group: table-type title: 透视分析表格 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-analysis-table-tree.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#rowHierarchyType('grid'%20%7C%20'tree') --- diff --git a/docs/assets/demo/zh/table-type/pivot-analysis-table.md b/docs/assets/demo/zh/table-type/pivot-analysis-table.md index 6b6dc4a99..9a8555359 100644 --- a/docs/assets/demo/zh/table-type/pivot-analysis-table.md +++ b/docs/assets/demo/zh/table-type/pivot-analysis-table.md @@ -3,7 +3,7 @@ category: examples group: table-type title: 透视分析表格 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/pivot-table.png -link: '../guide/table_type/Pivot_table/pivot_table_dataAnalysis' +link: '../guide/data_analysis/pivot_table_dataAnalysis' option: PivotTable#dataConfig --- From b44d8fcbba7a0bea6dd3061796c7815d8fe7dfab Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 19 Jun 2024 17:18:25 +0800 Subject: [PATCH 58/85] docs: add tutorial for calculatedField --- .../data_analysis/pivot_table_dataAnalysis.md | 45 +++++++++++++++++++ .../data_analysis/pivot_table_dataAnalysis.md | 45 +++++++++++++++++++ docs/assets/option/en/table/pivotTable.md | 22 ++++++++- docs/assets/option/zh/table/pivotTable.md | 22 ++++++++- packages/vtable/src/ts-types/new-data-set.ts | 4 ++ 5 files changed, 136 insertions(+), 2 deletions(-) diff --git a/docs/assets/guide/en/data_analysis/pivot_table_dataAnalysis.md b/docs/assets/guide/en/data_analysis/pivot_table_dataAnalysis.md index 2e830f8ed..2b07f0aef 100644 --- a/docs/assets/guide/en/data_analysis/pivot_table_dataAnalysis.md +++ b/docs/assets/guide/en/data_analysis/pivot_table_dataAnalysis.md @@ -68,7 +68,10 @@ dataConfig application example: ### 1. Totals +#### VTable to calculate subtotals configuration: + [option description](../../option/PivotTable#dataConfig.totals) + Configuration example: ``` @@ -95,6 +98,17 @@ dataConfig: { Online demo:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-total +#### Custom summary data + +If you need to customize summary data, you do not want VTable to calculate the subtotals. In addition to the above configuration, you also need to include the corresponding summary data in the data passed to VTable. In this way, VTable will analyze it internally and display it as summary data instead of using VTable's summary value. + +
+ +

Custom subtotal total sample code

+
+ +Specific example: https://visactor.io/vtable/demo/data-analysis/pivot-analysis-custom-total + ### 2. Sorting rules VTable's pivot table supports four sorting methods: natural sorting of dimension values, specified dimension value order, indicator value sorting, and custom sorting. @@ -124,6 +138,7 @@ Online demo:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-sort- ### 3. Filter rules [option description](../../option/PivotTable#dataConfig.filterRules) + Configuration example: ``` @@ -141,6 +156,7 @@ Online demo:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-filte ### 4. Aggregation method [option description](../../option/PivotTable#dataConfig.aggregationRules) + Configuration example: ``` @@ -206,6 +222,7 @@ The sales indicator in this record is a non-numeric value, and it is required to ### 5. Derive Field [option description](../../option/PivotTable#dataConfig.derivedFieldRules) + Configuration example: ``` @@ -223,6 +240,34 @@ Configuration example: Online demo:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-derivedField +### 6. Pivot table calculated fields + +[option description](../../option/PivotTable#dataConfig.calculatedFieldRules) + +Configuration example: + +``` +dataConfig: { + calculatedFieldRules:[ + { + key: 'AvgPrice', + dependIndicatorKeys: ['Quantity', 'Sales'], + calculateFun: dependValue => { + return dependValue.Sales / dependValue.Quantity; + } + } + ], +} +``` + +Configuration explanation: + +- key: The key unique identifier of the calculated field, which can be used as a new indicator and configured in indicators for display in the pivot table. +- dependIndicatorKeys: The indicators that the calculated field depends on, which can be the corresponding indicator fields in records. If the dependent indicator is not in records, it needs to be configured in aggregationRules, specifying the aggregation rules and indicatorKey to be used in dependIndicatorKeys. +- calculateFun: the calculation function of the calculated field, the function parameter is the value of the dependent indicator. + +Specific example: https://visactor.io/vtable/demo/data-analysis/pivot-analysis-calculatedField + ## Data analysis process Dependent configuration: dimensions, indicators and dataConfig. diff --git a/docs/assets/guide/zh/data_analysis/pivot_table_dataAnalysis.md b/docs/assets/guide/zh/data_analysis/pivot_table_dataAnalysis.md index e0cb369dd..ba23260e6 100644 --- a/docs/assets/guide/zh/data_analysis/pivot_table_dataAnalysis.md +++ b/docs/assets/guide/zh/data_analysis/pivot_table_dataAnalysis.md @@ -68,7 +68,10 @@ dataConfig 应用举例: ### 1. 数据汇总规则 +#### VTable 来计算小计总计配置: + [option 说明](../../option/PivotTable#dataConfig.totals) + 配置示例: ``` @@ -95,6 +98,17 @@ dataConfig: { 具体示例:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-total +#### 自定义汇总数据 + +如果需要自定义汇总数据,不期望 VTable 来计算小计总计值。除了需要配置上述配置外,还需要传入 VTable 的数据中需要包含对应的汇总数据。这样 VTable 内部会分析将其作为汇总数据而不使用 VTable 的汇总值来展示 + +
+ +

自定义小计总计示例代码

+
+ +具体示例:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-custom-total + ### 2. 排序规则 VTable 的透视表支持四种排序方式:维度值自然排序、指定维度值顺序,指标值排序、自定义排序。 @@ -124,6 +138,7 @@ VTable 的透视表支持四种排序方式:维度值自然排序、指定维 ### 3. 过滤规则 [option 说明](../../option/PivotTable#dataConfig.filterRules) + 配置示例: ``` @@ -141,6 +156,7 @@ filterRules: [ ### 4. 聚合方式 [option 说明](../../option/PivotTable#dataConfig.aggregationRules) + 配置示例: ``` @@ -207,6 +223,7 @@ dataConfig:{ ### 5. 派生字段 [option 说明](../../option/PivotTable#dataConfig.derivedFieldRules) + 配置示例: ``` @@ -224,6 +241,34 @@ dataConfig:{ 具体示例:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-derivedField +### 6. 透视表计算字段 + +[option 说明](../../option/PivotTable#dataConfig.calculatedFieldRules) + +配置示例: + +``` + dataConfig: { + calculatedFieldRules: [ + { + key: 'AvgPrice', + dependIndicatorKeys: ['Quantity', 'Sales'], + calculateFun: dependValue => { + return dependValue.Sales / dependValue.Quantity; + } + } + ], + } +``` + +配置解释说明: + +- key: 计算字段的 key 唯一标识,可以当做新指标,用于配置在 indicators 中在透视表中展示。 +- dependIndicatorKeys:计算字段依赖的指标,可以是在 records 中具体对应的指标字段。如果依赖的指标不在 records 中,则需要在 aggregationRules 中配置,具体指明聚合规则和 indicatorKey 以在 dependIndicatorKeys 所使用。 +- calculateFun:计算字段的计算函数,依赖的指标值作为参数传入,返回值作为计算字段的值。 + +具体示例:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-calculatedField + ## 数据分析过程 依赖配置:维度,指标及 dataConfig。 diff --git a/docs/assets/option/en/table/pivotTable.md b/docs/assets/option/en/table/pivotTable.md index ef4ce6339..fed69ddfe 100644 --- a/docs/assets/option/en/table/pivotTable.md +++ b/docs/assets/option/en/table/pivotTable.md @@ -220,7 +220,7 @@ export interface Total { ### derivedFieldRules(DerivedFieldRules) -Add derived fields +Add a derived field. The vtable will generate a new field based on the rules defined by the derived field and add the new field to the data. The new field can be used as a dimension item or an indicator item. ``` export type DerivedFieldRules = DerivedFieldRule[]; @@ -235,6 +235,26 @@ export interface DerivedFieldRule { } ``` +### calculatedFieldRules (CalculatedFieldRules) + +Calculated fields are similar to the calculated fields in Excel pivot tables. New indicator values can be calculated through calculated fields, and they are all recalculated based on the summary results. Note: Different from derived fields. + +``` +export type CalculateddFieldRules = CalculateddFieldRule[]; +``` + +``` +export interface CalculatedFieldRule { + /** Unique identifier, which can be used as the key of a new indicator and used to configure indicators to be displayed in a pivot table. */ + key: string; + /** The indicator that the calculated field depends on, which can be the corresponding indicator field in records or not the field in data records + * If the dependent indicator is not in records, it needs to be explicitly configured in aggregationRules, specifying the aggregation rule and indicatorKey to be used in dependIndicatorKeys. */ + dependIndicatorKeys: string[]; + /** The calculation function of the calculated field. The dependent indicator value is passed in as a parameter, and the return value is used as the value of the calculated field. */ + calculateFun?: (dependFieldsValue: any) => any; +} +``` + ## columnTree(Array) Column header tree, type: `(IDimensionHeaderNode|IIndicatorHeaderNode)[]`. Among them, IDimensionHeaderNode refers to the dimension value node of non-indicator dimensions, and IIndicatorHeaderNode refers to the indicator name node. diff --git a/docs/assets/option/zh/table/pivotTable.md b/docs/assets/option/zh/table/pivotTable.md index 8d8b64a1b..f72456cdc 100644 --- a/docs/assets/option/zh/table/pivotTable.md +++ b/docs/assets/option/zh/table/pivotTable.md @@ -224,7 +224,7 @@ export interface Total { ### derivedFieldRules(DerivedFieldRules) -增加派生字段 +增加派生字段,vtable 会基于派生字段定义的规则来生成新的字段,并将新字段加入到数据中。该新的字段可以作为维度项或者指标项。 ``` export type DerivedFieldRules = DerivedFieldRule[]; @@ -239,6 +239,26 @@ export interface DerivedFieldRule { } ``` +### calculatedFieldRules (CalculateddFieldRules) + +计算字段,类 Excel 透视表中的计算字段,可以通过计算字段来计算新的指标值,且都是在汇总结果基础上进行的再计算。注意:不同于派生字段。 + +``` +export type CalculateddFieldRules = CalculateddFieldRule[]; +``` + +``` +export interface CalculateddFieldRule { + /** 唯一标识,可以当做新指标的key,用于配置在 indicators 中在透视表中展示。 */ + key: string; + /** 计算字段依赖的指标,可以是在 records 中具体对应的指标字段 or 不是数据records 中的字段 + * 如果依赖的指标不在 records 中,则需要在 aggregationRules 中明确配置,具体指明聚合规则和 indicatorKey 以在 dependIndicatorKeys 所使用。 */ + dependIndicatorKeys: string[]; + /** 计算字段的计算函数,依赖的指标值作为参数传入,返回值作为计算字段的值。 */ + calculateFun?: (dependFieldsValue: any) => any; +} +``` + ## columnTree(Array) 列表头树,类型为:`(IDimensionHeaderNode|IIndicatorHeaderNode)[]`。其中 IDimensionHeaderNode 指的是维度非指标的维度值节点,IIndicatorHeaderNode 指的是指标名称节点。 diff --git a/packages/vtable/src/ts-types/new-data-set.ts b/packages/vtable/src/ts-types/new-data-set.ts index 83e3ae858..fc22e6614 100644 --- a/packages/vtable/src/ts-types/new-data-set.ts +++ b/packages/vtable/src/ts-types/new-data-set.ts @@ -180,8 +180,12 @@ export type DerivedFieldRules = DerivedFieldRule[]; //#region 计算字段规则 export interface CalculateddFieldRule { + /** 唯一标识,可以当做新指标的key,用于配置在 indicators 中在透视表中展示。 */ key: string; + /** 计算字段依赖的指标,可以是在 records 中具体对应的指标字段 or 不是数据records 中的字段 + * 如果依赖的指标不在 records 中,则需要在 aggregationRules 中明确配置,具体指明聚合规则和 indicatorKey 以在 dependIndicatorKeys 所使用。 */ dependIndicatorKeys: string[]; + /** 计算字段的计算函数,依赖的指标值作为参数传入,返回值作为计算字段的值。 */ calculateFun?: (dependFieldsValue: any) => any; } From 654bffe986c5e864a67a2afeff6da73207bf7670 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 19 Jun 2024 17:47:58 +0800 Subject: [PATCH 59/85] fix: handle with calculatedField when use custom total data --- packages/vtable/src/dataset/dataset.ts | 71 ++++++++++++++++++-------- 1 file changed, 51 insertions(+), 20 deletions(-) diff --git a/packages/vtable/src/dataset/dataset.ts b/packages/vtable/src/dataset/dataset.ts index 0b930da61..af0981291 100644 --- a/packages/vtable/src/dataset/dataset.ts +++ b/packages/vtable/src/dataset/dataset.ts @@ -675,30 +675,53 @@ export class Dataset { if (!this.totalRecordsTree[flatRowKey][flatColKey]) { this.totalRecordsTree[flatRowKey][flatColKey] = []; } - - for (let i = 0; i < this.indicatorKeys.length; i++) { - const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); - if (!this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i]) { - this.totalRecordsTree[flatRowKey][flatColKey][i] = new this.aggregators[ - aggRule?.aggregationType ?? AggregationType.SUM - ]({ - key: this.indicatorKeys[i], - dimension: aggRule?.field ?? this.indicatorKeys[i], - formatFun: - aggRule?.formatFun ?? - ( + const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; + for (let i = 0; i < toComputeIndicatorKeys.length; i++) { + if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { + const calculatedFieldRule = this.calculatedFieldRules?.find(rule => rule.key === toComputeIndicatorKeys[i]); + if (!this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i]) { + this.totalRecordsTree[flatRowKey][flatColKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ + key: toComputeIndicatorKeys[i], + dimension: toComputeIndicatorKeys[i], + isRecord: true, + formatFun: ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { - return indicator.indicatorKey === this.indicatorKeys[i]; + return indicator.indicatorKey === toComputeIndicatorKeys[i]; } return false; }) as IIndicator - )?.format - }); - } + )?.format, + calculateFun: calculatedFieldRule?.calculateFun, + dependAggregators: this.totalRecordsTree[flatRowKey][flatColKey], + dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys + }); + } + toComputeIndicatorKeys[i] in record && this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i].push(record); + } else { + const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); + if (!this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i]) { + this.totalRecordsTree[flatRowKey][flatColKey][i] = new this.aggregators[ + aggRule?.aggregationType ?? AggregationType.SUM + ]({ + key: toComputeIndicatorKeys[i], + dimension: aggRule?.field ?? toComputeIndicatorKeys[i], + formatFun: + aggRule?.formatFun ?? + ( + this.indicators?.find((indicator: string | IIndicator) => { + if (typeof indicator !== 'string') { + return indicator.indicatorKey === toComputeIndicatorKeys[i]; + } + return false; + }) as IIndicator + )?.format + }); + } - //push融合了计算过程 - this.indicatorKeys[i] in record && this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i].push(record); + //push融合了计算过程 + toComputeIndicatorKeys[i] in record && this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i].push(record); + } } return; } @@ -1265,7 +1288,11 @@ export class Dataset { return; } const colKey = flatColKey.split(this.stringJoinChar); - if (that.totals?.column?.subTotalsDimensions) { + if ( + that.totals?.column?.subTotalsDimensions && + that.totals?.column?.subTotalsDimensions?.length > 0 && + that.totals.column.showSubTotals !== false + ) { for (let i = 0, len = that.totals?.column?.subTotalsDimensions?.length; i < len; i++) { const dimension = that.totals.column.subTotalsDimensions[i]; const dimensionIndex = that.columns.indexOf(dimension); @@ -1398,7 +1425,11 @@ export class Dataset { Object.keys(that.tree).forEach(flatRowKey => { const rowKey = flatRowKey.split(this.stringJoinChar); Object.keys(that.tree[flatRowKey]).forEach(flatColKey => { - if (that.totals?.row?.subTotalsDimensions) { + if ( + that.totals?.row?.subTotalsDimensions && + that.totals?.row?.subTotalsDimensions?.length > 0 && + that.totals.row.showSubTotals !== false + ) { for (let i = 0, len = that.totals?.row?.subTotalsDimensions?.length; i < len; i++) { const dimension = that.totals.row.subTotalsDimensions[i]; const dimensionIndex = that.rows.indexOf(dimension); From b004819a5ba680ae2943451e88e04c60c6118e1e Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 19 Jun 2024 19:15:28 +0800 Subject: [PATCH 60/85] fix: when setRecords should update emptyTip #1953 --- packages/vtable/src/PivotTable.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/vtable/src/PivotTable.ts b/packages/vtable/src/PivotTable.ts index b368a734b..e50bd7760 100644 --- a/packages/vtable/src/PivotTable.ts +++ b/packages/vtable/src/PivotTable.ts @@ -1497,6 +1497,14 @@ export class PivotTable extends BaseTable implements PivotTableAPI { this.scenegraph.resize(); } this.eventManager.updateEventBinder(); + if (this.options.emptyTip) { + if (this.internalProps.emptyTip) { + this.internalProps.emptyTip.resetVisible(); + } else { + this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); + this.internalProps.emptyTip.resetVisible(); + } + } } /** 开启单元格编辑 */ startEditCell(col?: number, row?: number) { From 5f8131fd40838009214fb8ddfbafcfe2ae836164 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Wed, 19 Jun 2024 19:17:35 +0800 Subject: [PATCH 61/85] docs: update changlog of rush --- ...votTable-setRecords-emptytip_2024-06-19-11-17.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/1953-feature-pivotTable-setRecords-emptytip_2024-06-19-11-17.json diff --git a/common/changes/@visactor/vtable/1953-feature-pivotTable-setRecords-emptytip_2024-06-19-11-17.json b/common/changes/@visactor/vtable/1953-feature-pivotTable-setRecords-emptytip_2024-06-19-11-17.json new file mode 100644 index 000000000..f598c24f9 --- /dev/null +++ b/common/changes/@visactor/vtable/1953-feature-pivotTable-setRecords-emptytip_2024-06-19-11-17.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: when setRecords should update emptyTip #1953\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From e1262b5adeeca304a9826f64f8236ac1be4c6b66 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Wed, 19 Jun 2024 21:37:24 +0800 Subject: [PATCH 62/85] docs: add react-custom-layout-dom docs --- .../en/custom-layout/cell-custom-component.md | 301 ++++++++++++++++++ .../en/custom-layout/cell-custom-dom.md | 204 ++++++++++++ .../custom-layout/cell-custom-layout-dom.md | 249 +++++++++++++++ .../en/custom-layout/custom-layout.md | 297 ----------------- docs/assets/demo-react/menu.json | 18 +- .../zh/custom-layout/cell-custom-component.md | 301 ++++++++++++++++++ ...m-layout-all-dom.md => cell-custom-dom.md} | 8 +- ...ayout-dom.md => cell-custom-layout-dom.md} | 14 +- .../zh/custom-layout/custom-layout.md | 297 ----------------- .../react-custom-component.md | 235 ++++++++++++++ .../guide/en/Developer_Ecology/react.md | 49 --- docs/assets/guide/menu.json | 7 + .../react-custom-component.md | 235 ++++++++++++++ .../guide/zh/Developer_Ecology/react.md | 49 --- packages/react-vtable/demo/src/App.tsx | 4 +- .../src/components/custom/component.ts | 11 + 16 files changed, 1566 insertions(+), 713 deletions(-) create mode 100644 docs/assets/demo-react/en/custom-layout/cell-custom-component.md create mode 100644 docs/assets/demo-react/en/custom-layout/cell-custom-dom.md create mode 100644 docs/assets/demo-react/en/custom-layout/cell-custom-layout-dom.md delete mode 100644 docs/assets/demo-react/en/custom-layout/custom-layout.md create mode 100644 docs/assets/demo-react/zh/custom-layout/cell-custom-component.md rename docs/assets/demo-react/zh/custom-layout/{custom-layout-all-dom.md => cell-custom-dom.md} (95%) rename docs/assets/demo-react/zh/custom-layout/{custom-layout-dom.md => cell-custom-layout-dom.md} (95%) delete mode 100644 docs/assets/demo-react/zh/custom-layout/custom-layout.md create mode 100644 docs/assets/guide/en/Developer_Ecology/react-custom-component.md create mode 100644 docs/assets/guide/zh/Developer_Ecology/react-custom-component.md diff --git a/docs/assets/demo-react/en/custom-layout/cell-custom-component.md b/docs/assets/demo-react/en/custom-layout/cell-custom-component.md new file mode 100644 index 000000000..69744bbf5 --- /dev/null +++ b/docs/assets/demo-react/en/custom-layout/cell-custom-component.md @@ -0,0 +1,301 @@ +--- +category: examples +group: component +title: cell custom component +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-cell-layout-jsx.png +order: 1-1 +link: '../guide/Developer_Ecology/react' +--- + +# cell custom component + +Like customLayout, you can use react components to customize layout. For details, please refer to [Custom Components](../guide/Developer_Ecology/react-custom-component) + +## code demo + +```javascript livedemo template=vtable-react +// import * as ReactVTable from '@visactor/react-vtable'; + +const VGroup = ReactVTable.Group; +const VText = ReactVTable.Text; +const VImage = ReactVTable.Image; +const VTag = ReactVTable.Tag; + +const records = [ + { + bloggerId: 1, + bloggerName: 'Virtual Anchor Xiaohua', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg', + introduction: + 'Hi everyone, I am Xiaohua, the virtual host. I am a little fairy who likes games, animation and food. I hope to share happy moments with you through live broadcast.', + fansCount: 400, + worksCount: 10, + viewCount: 5, + city: 'Dream City', + tags: ['game', 'anime', 'food'] + }, + { + bloggerId: 2, + bloggerName: 'Virtual anchor little wolf', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg', + introduction: + 'Hello everyone, I am the virtual anchor Little Wolf. I like music, travel and photography, and I hope to explore the beauty of the world with you through live broadcast.', + fansCount: 800, + worksCount: 20, + viewCount: 15, + city: 'City of Music', + tags: ['music', 'travel', 'photography'] + }, + { + bloggerId: 3, + bloggerName: 'Virtual anchor bunny', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg', + introduction: + 'Hello everyone, I am the virtual anchor Xiaotu. I like painting, handicrafts and beauty makeup. I hope to share creativity and fashion with you through live broadcast.', + fansCount: 600, + worksCount: 15, + viewCount: 10, + city: 'City of Art', + tags: ['painting', 'handmade', 'beauty makeup'] + }, + { + bloggerId: 4, + bloggerName: 'Virtual anchor kitten', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg', + introduction: + 'Hello everyone, I am the virtual host Kitty. I am a lazy cat who likes dancing, fitness and cooking. I hope to live a healthy and happy life with everyone through the live broadcast.', + fansCount: 1000, + worksCount: 30, + viewCount: 20, + city: 'Health City', + tags: ['dance', 'fitness', 'cooking'] + }, + { + bloggerId: 5, + bloggerName: 'Virtual anchor Bear', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg', + introduction: + 'Hello everyone, I am the virtual host Xiaoxiong. A little wise man who likes movies, reading and philosophy, I hope to explore the meaning of life with you through live broadcast.', + fansCount: 1200, + worksCount: 25, + viewCount: 18, + city: 'City of Wisdom', + tags: ['Movie', 'Literature'] + }, + { + bloggerId: 6, + bloggerName: 'Virtual anchor bird', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg', + introduction: + 'Hello everyone, I am the virtual anchor Xiaoniao. I like singing, acting and variety shows. I hope to be happy with everyone through the live broadcast.', + fansCount: 900, + worksCount: 12, + viewCount: 8, + city: 'Happy City', + tags: ['music', 'performance', 'variety'] + } +]; + +const CustomLayoutComponent = (props) => { + const { table, row, col, rect, text } = props; + if (!table || row === undefined || col === undefined) { + return null; + } + const { height, width } = rect || table.getCellRect(col, row); + const record = table.getRecordByRowCol(col, row); + + const [hoverTitle, setHoverTitle] = React.useState(false); + const [hoverIcon, setHoverIcon] = React.useState(false); + const groupRef = React.useRef(null); + + return ( + + + + + + + { + setHoverTitle(true); + event.currentTarget.stage.renderNextFrame(); + }} + onMouseLeave={(event) => { + setHoverTitle(false); + event.currentTarget.stage.renderNextFrame(); + }} + > + ', + boundsPadding: [0, 0, 0, 10], + cursor: 'pointer', + background: hoverIcon ? { + fill: '#ccc', + cornerRadius: 5, + expandX: 1, + expandY: 1 + } : undefined + }} + + onMouseEnter={event => { + setHoverIcon(true); + event.currentTarget.stage.renderNextFrame(); + }} + onMouseLeave={event => { + setHoverIcon(false); + event.currentTarget.stage.renderNextFrame(); + }} + > + + + + {record.tags.length + ? record.tags.map((str, i) => ( + // + + )) + : null} + + + + ); +} + +const root = ReactDom.createRoot(document.getElementById(CONTAINER_ID)); +root.render( + + + + + + + + + +); + +// release openinula instance, do not copy +window.customRelease = () => { + root.unmount(); +}; +``` diff --git a/docs/assets/demo-react/en/custom-layout/cell-custom-dom.md b/docs/assets/demo-react/en/custom-layout/cell-custom-dom.md new file mode 100644 index 000000000..4745ab3d4 --- /dev/null +++ b/docs/assets/demo-react/en/custom-layout/cell-custom-dom.md @@ -0,0 +1,204 @@ +--- +category: examples +group: component +title: cell custom dom component +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/react-vtable-cell-dom-component.jpeg +order: 1-1 +link: '../guide/Developer_Ecology/react' +--- + +# cell custom dom component + +Use ArcoDesign in cells. For details, please refer to [Custom Components](../guide/Developer_Ecology/react-custom-component) + +## code demo + +```javascript livedemo template=vtable-react +// import * as ReactVTable from '@visactor/react-vtable'; + +const { useCallback, useRef, useState } = React; +const { ListTable, ListColumn, Group } = ReactVTable; +const { + Avatar, + Comment, + Card, + Popover, + Space, + Button, + Popconfirm, + Message, + Notification + } = ArcoDesign; +const { IconHeart, IconMessage, IconStar, IconStarFill, IconHeartFill } = ArcoDesignIcon; + +const CommentComponent = (props) => { + 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); + + return ( + + } + }} + > + ); +}; + +const CommentReactComponent = (props) => { + const { name } = props; + const [like, setLike] = useState(); + const [star, setStar] = useState(); + const actions = [ + , + , + + ]; + return ( + +

Here is the description of this user.

+ + } + > + {name.slice(0, 1)} + + } + content={
Comment body content.
} + datetime="1 hour" + style={{ marginTop: 10, marginLeft: 10 }} + /> + ); +}; + +const OperationComponent = (props) => { + 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); + + return ( + + } + }} + > + ); +}; + +const OperationReactComponent = () => { + return ( + + + { + Message.info({ + content: 'ok' + }); + }} + onCancel={() => { + Message.error({ + content: 'cancel' + }); + }} + > + + + + ); +}; + +function generateRandomString(length) { + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * characters.length)); + } + return result; +} + +function App() { + const records = []; + for (let i = 0; i < 50; i++) { + records.push({ + id: i, + name: generateRandomString(8) + }); + } + + return ( + { + // eslint-disable-next-line no-undef + // (window as any).tableInstance = table; + }} + ReactDOM={ReactDom} + > + + + + + + + + + ); +} + +const root = ReactDom.createRoot(document.getElementById(CONTAINER_ID)); +root.render(); + +// release react instance, do not copy +window.customRelease = () => { + root.unmount(); +}; +``` diff --git a/docs/assets/demo-react/en/custom-layout/cell-custom-layout-dom.md b/docs/assets/demo-react/en/custom-layout/cell-custom-layout-dom.md new file mode 100644 index 000000000..706bed9f8 --- /dev/null +++ b/docs/assets/demo-react/en/custom-layout/cell-custom-layout-dom.md @@ -0,0 +1,249 @@ +--- +category: examples +group: component +title: cell custom component + dom component +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/react-vtable-dom-component.gif +order: 1-1 +link: '../guide/Developer_Ecology/react' +--- + +# cell custom component + dom component + +Use ArcoDesign in the cell pop-up window. For details, please refer to [Custom Components](../guide/Developer_Ecology/react-custom-component) + +## code demo + +```javascript livedemo template=vtable-react +// import * as ReactVTable from '@visactor/react-vtable'; + +const { useCallback, useRef, useState } = React; +const { ListTable, ListColumn, Group, Text, Image } = ReactVTable; +const { Avatar, Card, Space, Typography } = ArcoDesign; +const { IconThumbUp, IconShareInternal, IconMore } = ArcoDesignIcon; +const { Meta } = Card; + +const UserProfileComponent = (props) => { + 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) => { + setHover(true); + event.currentTarget.stage.renderNextFrame(); // to do: auto execute in react-vtable + }} + onMouseLeave={(event) => { + setHover(false); + event.currentTarget.stage.renderNextFrame(); + }} + > + + + + + ); +}; + +const CardInfo = (props) => { + const { bloggerName, bloggerAvatar, introduction, city } = props.record; + return props.hover ? ( + + dessert + + } + // actions={[ + // + // + // , + // + // + // , + // + // + // + // ]} + > + + {city.slice(0, 1)} + {city} + + } + title={bloggerName} + description={introduction} + /> + + ) : <>; +}; + +function App() { + const records = [ + { + bloggerId: 1, + bloggerName: 'Virtual Anchor Xiaohua', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg', + introduction: + 'Hi everyone, I am Xiaohua, the virtual host. I am a little fairy who likes games, animation and food. I hope to share happy moments with you through live broadcast.', + fansCount: 400, + worksCount: 10, + viewCount: 5, + city: 'Dream City', + tags: ['game', 'anime', 'food'] + }, + { + bloggerId: 2, + bloggerName: 'Virtual anchor little wolf', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg', + introduction: + 'Hello everyone, I am the virtual anchor Little Wolf. I like music, travel and photography, and I hope to explore the beauty of the world with you through live broadcast.', + fansCount: 800, + worksCount: 20, + viewCount: 15, + city: 'City of Music', + tags: ['music', 'travel', 'photography'] + }, + { + bloggerId: 3, + bloggerName: 'Virtual anchor bunny', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg', + introduction: + 'Hello everyone, I am the virtual anchor Xiaotu. I like painting, handicrafts and beauty makeup. I hope to share creativity and fashion with you through live broadcast.', + fansCount: 600, + worksCount: 15, + viewCount: 10, + city: 'City of Art', + tags: ['painting', 'handmade', 'beauty makeup'] + }, + { + bloggerId: 4, + bloggerName: 'Virtual anchor kitten', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg', + introduction: + 'Hello everyone, I am the virtual host Kitty. I am a lazy cat who likes dancing, fitness and cooking. I hope to live a healthy and happy life with everyone through the live broadcast.', + fansCount: 1000, + worksCount: 30, + viewCount: 20, + city: 'Health City', + tags: ['dance', 'fitness', 'cooking'] + }, + { + bloggerId: 5, + bloggerName: 'Virtual anchor Bear', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg', + introduction: + 'Hello everyone, I am the virtual host Xiaoxiong. A little wise man who likes movies, reading and philosophy, I hope to explore the meaning of life with you through live broadcast.', + fansCount: 1200, + worksCount: 25, + viewCount: 18, + city: 'City of Wisdom', + tags: ['Movie', 'Literature'] + }, + { + bloggerId: 6, + bloggerName: 'Virtual anchor bird', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg', + introduction: + 'Hello everyone, I am the virtual anchor Xiaoniao. I like singing, acting and variety shows. I hope to be happy with everyone through the live broadcast.', + fansCount: 900, + worksCount: 12, + viewCount: 8, + city: 'Happy City', + tags: ['music', 'performance', 'variety'] + } + ]; + + return ( + { + // eslint-disable-next-line no-undef + // (window as any).tableInstance = table; + }} + ReactDOM={ReactDom} + > + + + + + + + + + ); +} + +const root = ReactDom.createRoot(document.getElementById(CONTAINER_ID)); +root.render(); + +// release react instance, do not copy +window.customRelease = () => { + root.unmount(); +}; +``` diff --git a/docs/assets/demo-react/en/custom-layout/custom-layout.md b/docs/assets/demo-react/en/custom-layout/custom-layout.md deleted file mode 100644 index 706e3749f..000000000 --- a/docs/assets/demo-react/en/custom-layout/custom-layout.md +++ /dev/null @@ -1,297 +0,0 @@ ---- -category: examples -group: component -title: custom layout -cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-cell-layout-jsx.png -order: 1-1 -link: '../guide/custom_define/custom_layout' -option: ListTable-columns-text#customLayout ---- - -# custom layout - -You can use jsx in customLayout to customize the layout. For details, please refer to [Custom Layout](../guide/custom_define/custom_layout) - -## code demo - -```javascript livedemo template=vtable-react -// import * as ReactVTable from '@visactor/react-vtable'; - -const VGroup = ReactVTable.VTable.VGroup; -const VText = ReactVTable.VTable.VText; -const VImage = ReactVTable.VTable.VImage; -const VTag = ReactVTable.VTable.VTag; - -const records = [ - { - bloggerId: 1, - bloggerName: 'Virtual Anchor Xiaohua', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg', - introduction: - 'Hi everyone, I am Xiaohua, the virtual host. I am a little fairy who likes games, animation and food. I hope to share happy moments with you through live broadcast.', - fansCount: 400, - worksCount: 10, - viewCount: 5, - city: 'Dream City', - tags: ['game', 'anime', 'food'] - }, - { - bloggerId: 2, - bloggerName: 'Virtual anchor little wolf', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg', - introduction: - 'Hello everyone, I am the virtual anchor Little Wolf. I like music, travel and photography, and I hope to explore the beauty of the world with you through live broadcast.', - fansCount: 800, - worksCount: 20, - viewCount: 15, - city: 'City of Music', - tags: ['music', 'travel', 'photography'] - }, - { - bloggerId: 3, - bloggerName: 'Virtual anchor bunny', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg', - introduction: - 'Hello everyone, I am the virtual anchor Xiaotu. I like painting, handicrafts and beauty makeup. I hope to share creativity and fashion with you through live broadcast.', - fansCount: 600, - worksCount: 15, - viewCount: 10, - city: 'City of Art', - tags: ['painting', 'handmade', 'beauty makeup'] - }, - { - bloggerId: 4, - bloggerName: 'Virtual anchor kitten', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg', - introduction: - 'Hello everyone, I am the virtual host Kitty. I am a lazy cat who likes dancing, fitness and cooking. I hope to live a healthy and happy life with everyone through the live broadcast.', - fansCount: 1000, - worksCount: 30, - viewCount: 20, - city: 'Health City', - tags: ['dance', 'fitness', 'cooking'] - }, - { - bloggerId: 5, - bloggerName: 'Virtual anchor Bear', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg', - introduction: - 'Hello everyone, I am the virtual host Xiaoxiong. A little wise man who likes movies, reading and philosophy, I hope to explore the meaning of life with you through live broadcast.', - fansCount: 1200, - worksCount: 25, - viewCount: 18, - city: 'City of Wisdom', - tags: ['Movie', 'Literature'] - }, - { - bloggerId: 6, - bloggerName: 'Virtual anchor bird', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg', - introduction: - 'Hello everyone, I am the virtual anchor Xiaoniao. I like singing, acting and variety shows. I hope to be happy with everyone through the live broadcast.', - fansCount: 900, - worksCount: 12, - viewCount: 8, - city: 'Happy City', - tags: ['music', 'performance', 'variety'] - } -]; - -const root = ReactDom.createRoot(document.getElementById(CONTAINER_ID)); -root.render( - - - { - const { table, row, col, rect } = args; - const { height, width } = rect || table.getCellRect(col, row); - const record = table.getRecordByRowCol(col, row); - // const jsx = jsx; - const container = ( - - - - - - - - ', - boundsPadding: [0, 0, 0, 10], - cursor: 'pointer' - }} - stateProxy={stateName => { - if (stateName === 'hover') { - return { - background: { - fill: '#ccc', - cornerRadius: 5, - expandX: 1, - expandY: 1 - } - }; - } - }} - onMouseEnter={event => { - event.currentTarget.addState('hover', true, false); - event.currentTarget.stage.renderNextFrame(); - }} - onMouseLeave={event => { - event.currentTarget.removeState('hover', false); - event.currentTarget.stage.renderNextFrame(); - }} - > - - - - {record.tags.length - ? record.tags.map((str, i) => ( - // - - )) - : null} - - - - ); - - // decode(container) - return { - rootContainer: container, - renderDefault: false - }; - }} - /> - - - - -); - -// release openinula instance, do not copy -window.customRelease = () => { - root.unmount(); -}; -``` diff --git a/docs/assets/demo-react/menu.json b/docs/assets/demo-react/menu.json index a8b80653c..7509032f0 100644 --- a/docs/assets/demo-react/menu.json +++ b/docs/assets/demo-react/menu.json @@ -115,24 +115,24 @@ }, "children": [ { - "path": "custom-layout", + "path": "cell-custom-component", "title": { - "zh": "自定义布局", - "en": "custom layout" + "zh": "单元格自定义组件", + "en": "cell custom component" } }, { - "path": "custom-layout-dom", + "path": "cell-custom-layout-dom", "title": { - "zh": "自定义布局dom", - "en": "custom layout dom" + "zh": "单元格自定义组件+dom组件", + "en": "cell custom component + dom component" } }, { - "path": "custom-layout-all-dom", + "path": "cell-custom-dom", "title": { - "zh": "自定义布局all dom", - "en": "custom layout all dom" + "zh": "单元格内dom组件", + "en": "cell custom dom component" } } ] diff --git a/docs/assets/demo-react/zh/custom-layout/cell-custom-component.md b/docs/assets/demo-react/zh/custom-layout/cell-custom-component.md new file mode 100644 index 000000000..f475938f7 --- /dev/null +++ b/docs/assets/demo-react/zh/custom-layout/cell-custom-component.md @@ -0,0 +1,301 @@ +--- +category: examples +group: component +title: 单元格自定义组件 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-cell-layout-jsx.png +order: 1-1 +link: '../guide/Developer_Ecology/react' +--- + +# 单元格自定义组件 + +同customLayout一样,可以使用react组件进行自定义布局,具体可以参考[自定义组件](../guide/Developer_Ecology/react-custom-component) + +## 代码演示 + +```javascript livedemo template=vtable-react +// import * as ReactVTable from '@visactor/react-vtable'; + +const VGroup = ReactVTable.Group; +const VText = ReactVTable.Text; +const VImage = ReactVTable.Image; +const VTag = ReactVTable.Tag; + +const records = [ + { + bloggerId: 1, + bloggerName: 'Virtual Anchor Xiaohua', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg', + introduction: + 'Hi everyone, I am Xiaohua, the virtual host. I am a little fairy who likes games, animation and food. I hope to share happy moments with you through live broadcast.', + fansCount: 400, + worksCount: 10, + viewCount: 5, + city: 'Dream City', + tags: ['game', 'anime', 'food'] + }, + { + bloggerId: 2, + bloggerName: 'Virtual anchor little wolf', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg', + introduction: + 'Hello everyone, I am the virtual anchor Little Wolf. I like music, travel and photography, and I hope to explore the beauty of the world with you through live broadcast.', + fansCount: 800, + worksCount: 20, + viewCount: 15, + city: 'City of Music', + tags: ['music', 'travel', 'photography'] + }, + { + bloggerId: 3, + bloggerName: 'Virtual anchor bunny', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg', + introduction: + 'Hello everyone, I am the virtual anchor Xiaotu. I like painting, handicrafts and beauty makeup. I hope to share creativity and fashion with you through live broadcast.', + fansCount: 600, + worksCount: 15, + viewCount: 10, + city: 'City of Art', + tags: ['painting', 'handmade', 'beauty makeup'] + }, + { + bloggerId: 4, + bloggerName: 'Virtual anchor kitten', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg', + introduction: + 'Hello everyone, I am the virtual host Kitty. I am a lazy cat who likes dancing, fitness and cooking. I hope to live a healthy and happy life with everyone through the live broadcast.', + fansCount: 1000, + worksCount: 30, + viewCount: 20, + city: 'Health City', + tags: ['dance', 'fitness', 'cooking'] + }, + { + bloggerId: 5, + bloggerName: 'Virtual anchor Bear', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg', + introduction: + 'Hello everyone, I am the virtual host Xiaoxiong. A little wise man who likes movies, reading and philosophy, I hope to explore the meaning of life with you through live broadcast.', + fansCount: 1200, + worksCount: 25, + viewCount: 18, + city: 'City of Wisdom', + tags: ['Movie', 'Literature'] + }, + { + bloggerId: 6, + bloggerName: 'Virtual anchor bird', + bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg', + introduction: + 'Hello everyone, I am the virtual anchor Xiaoniao. I like singing, acting and variety shows. I hope to be happy with everyone through the live broadcast.', + fansCount: 900, + worksCount: 12, + viewCount: 8, + city: 'Happy City', + tags: ['music', 'performance', 'variety'] + } +]; + +const CustomLayoutComponent = (props) => { + const { table, row, col, rect, text } = props; + if (!table || row === undefined || col === undefined) { + return null; + } + const { height, width } = rect || table.getCellRect(col, row); + const record = table.getRecordByRowCol(col, row); + + const [hoverTitle, setHoverTitle] = React.useState(false); + const [hoverIcon, setHoverIcon] = React.useState(false); + const groupRef = React.useRef(null); + + return ( + + + + + + + { + setHoverTitle(true); + event.currentTarget.stage.renderNextFrame(); + }} + onMouseLeave={(event) => { + setHoverTitle(false); + event.currentTarget.stage.renderNextFrame(); + }} + > + ', + boundsPadding: [0, 0, 0, 10], + cursor: 'pointer', + background: hoverIcon ? { + fill: '#ccc', + cornerRadius: 5, + expandX: 1, + expandY: 1 + } : undefined + }} + + onMouseEnter={event => { + setHoverIcon(true); + event.currentTarget.stage.renderNextFrame(); + }} + onMouseLeave={event => { + setHoverIcon(false); + event.currentTarget.stage.renderNextFrame(); + }} + > + + + + {record.tags.length + ? record.tags.map((str, i) => ( + // + + )) + : null} + + + + ); +} + +const root = ReactDom.createRoot(document.getElementById(CONTAINER_ID)); +root.render( + + + + + + + + + +); + +// release openinula instance, do not copy +window.customRelease = () => { + root.unmount(); +}; +``` diff --git a/docs/assets/demo-react/zh/custom-layout/custom-layout-all-dom.md b/docs/assets/demo-react/zh/custom-layout/cell-custom-dom.md similarity index 95% rename from docs/assets/demo-react/zh/custom-layout/custom-layout-all-dom.md rename to docs/assets/demo-react/zh/custom-layout/cell-custom-dom.md index 0b96f90ce..b08666947 100644 --- a/docs/assets/demo-react/zh/custom-layout/custom-layout-all-dom.md +++ b/docs/assets/demo-react/zh/custom-layout/cell-custom-dom.md @@ -1,15 +1,15 @@ --- category: examples group: component -title: 自定义组件 -cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-component.png +title: 单元格内dom组件 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/react-vtable-cell-dom-component.jpeg order: 1-1 link: '../guide/Developer_Ecology/react' --- -# 自定义组件 +# 单元格内dom组件 -自定义组件`CustomComponent`组件方便在 React-VTable 组件上叠加外部组件。 +在单元格内使用ArcoDesign,具体可以参考[自定义组件](../guide/Developer_Ecology/react-custom-component) ## 代码演示 diff --git a/docs/assets/demo-react/zh/custom-layout/custom-layout-dom.md b/docs/assets/demo-react/zh/custom-layout/cell-custom-layout-dom.md similarity index 95% rename from docs/assets/demo-react/zh/custom-layout/custom-layout-dom.md rename to docs/assets/demo-react/zh/custom-layout/cell-custom-layout-dom.md index 6150e8f91..8c451c2c9 100644 --- a/docs/assets/demo-react/zh/custom-layout/custom-layout-dom.md +++ b/docs/assets/demo-react/zh/custom-layout/cell-custom-layout-dom.md @@ -1,15 +1,15 @@ --- category: examples group: component -title: 自定义组件 -cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-component.png +title: 单元格自定义组件+dom组件 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/react-vtable-dom-component.gif order: 1-1 link: '../guide/Developer_Ecology/react' --- -# 自定义组件 +# 单元格自定义组件+dom组件 -自定义组件`CustomComponent`组件方便在 React-VTable 组件上叠加外部组件。 +在单元格弹窗使用ArcoDesign,具体可以参考[自定义组件](../guide/Developer_Ecology/react-custom-component) ## 代码演示 @@ -80,7 +80,8 @@ const UserProfileComponent = (props) => { height: 20, image: record.bloggerAvatar, cornerRadius: 10, - boundsPadding: [0, 0, 0, 10] + boundsPadding: [0, 0, 0, 10], + cursor: 'pointer', }} /> { fontSize: 14, fontFamily: 'sans-serif', fill: 'rgb(51, 101, 238)', - boundsPadding: [0, 0, 0, 10] + boundsPadding: [0, 0, 0, 10], + cursor: 'pointer', }} /> diff --git a/docs/assets/demo-react/zh/custom-layout/custom-layout.md b/docs/assets/demo-react/zh/custom-layout/custom-layout.md deleted file mode 100644 index 3f44dc1d8..000000000 --- a/docs/assets/demo-react/zh/custom-layout/custom-layout.md +++ /dev/null @@ -1,297 +0,0 @@ ---- -category: examples -group: component -title: custom layout -cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/preview/custom-cell-layout-jsx.png -order: 1-1 -link: '../guide/custom_define/custom_layout' -option: ListTable-columns-text#customLayout ---- - -# custom layout - -可以在 customLayout 中使用 jsx 进行自定义布局,具体可以参考[自定义布局](../guide/custom_define/custom_layout) - -## 代码演示 - -```javascript livedemo template=vtable-react -// import * as ReactVTable from '@visactor/react-vtable'; - -const VGroup = ReactVTable.VTable.VGroup; -const VText = ReactVTable.VTable.VText; -const VImage = ReactVTable.VTable.VImage; -const VTag = ReactVTable.VTable.VTag; - -const records = [ - { - bloggerId: 1, - bloggerName: 'Virtual Anchor Xiaohua', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg', - introduction: - 'Hi everyone, I am Xiaohua, the virtual host. I am a little fairy who likes games, animation and food. I hope to share happy moments with you through live broadcast.', - fansCount: 400, - worksCount: 10, - viewCount: 5, - city: 'Dream City', - tags: ['game', 'anime', 'food'] - }, - { - bloggerId: 2, - bloggerName: 'Virtual anchor little wolf', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg', - introduction: - 'Hello everyone, I am the virtual anchor Little Wolf. I like music, travel and photography, and I hope to explore the beauty of the world with you through live broadcast.', - fansCount: 800, - worksCount: 20, - viewCount: 15, - city: 'City of Music', - tags: ['music', 'travel', 'photography'] - }, - { - bloggerId: 3, - bloggerName: 'Virtual anchor bunny', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg', - introduction: - 'Hello everyone, I am the virtual anchor Xiaotu. I like painting, handicrafts and beauty makeup. I hope to share creativity and fashion with you through live broadcast.', - fansCount: 600, - worksCount: 15, - viewCount: 10, - city: 'City of Art', - tags: ['painting', 'handmade', 'beauty makeup'] - }, - { - bloggerId: 4, - bloggerName: 'Virtual anchor kitten', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg', - introduction: - 'Hello everyone, I am the virtual host Kitty. I am a lazy cat who likes dancing, fitness and cooking. I hope to live a healthy and happy life with everyone through the live broadcast.', - fansCount: 1000, - worksCount: 30, - viewCount: 20, - city: 'Health City', - tags: ['dance', 'fitness', 'cooking'] - }, - { - bloggerId: 5, - bloggerName: 'Virtual anchor Bear', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg', - introduction: - 'Hello everyone, I am the virtual host Xiaoxiong. A little wise man who likes movies, reading and philosophy, I hope to explore the meaning of life with you through live broadcast.', - fansCount: 1200, - worksCount: 25, - viewCount: 18, - city: 'City of Wisdom', - tags: ['Movie', 'Literature'] - }, - { - bloggerId: 6, - bloggerName: 'Virtual anchor bird', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg', - introduction: - 'Hello everyone, I am the virtual anchor Xiaoniao. I like singing, acting and variety shows. I hope to be happy with everyone through the live broadcast.', - fansCount: 900, - worksCount: 12, - viewCount: 8, - city: 'Happy City', - tags: ['music', 'performance', 'variety'] - } -]; - -const root = ReactDom.createRoot(document.getElementById(CONTAINER_ID)); -root.render( - - - { - const { table, row, col, rect } = args; - const { height, width } = rect || table.getCellRect(col, row); - const record = table.getRecordByRowCol(col, row); - // const jsx = jsx; - const container = ( - - - - - - - - ', - boundsPadding: [0, 0, 0, 10], - cursor: 'pointer' - }} - stateProxy={stateName => { - if (stateName === 'hover') { - return { - background: { - fill: '#ccc', - cornerRadius: 5, - expandX: 1, - expandY: 1 - } - }; - } - }} - onMouseEnter={event => { - event.currentTarget.addState('hover', true, false); - event.currentTarget.stage.renderNextFrame(); - }} - onMouseLeave={event => { - event.currentTarget.removeState('hover', false); - event.currentTarget.stage.renderNextFrame(); - }} - > - - - - {record.tags.length - ? record.tags.map((str, i) => ( - // - - )) - : null} - - - - ); - - // decode(container) - return { - rootContainer: container, - renderDefault: false - }; - }} - /> - - - - -); - -// release openinula instance, do not copy -window.customRelease = () => { - root.unmount(); -}; -``` diff --git a/docs/assets/guide/en/Developer_Ecology/react-custom-component.md b/docs/assets/guide/en/Developer_Ecology/react-custom-component.md new file mode 100644 index 000000000..45487648f --- /dev/null +++ b/docs/assets/guide/en/Developer_Ecology/react-custom-component.md @@ -0,0 +1,235 @@ +# React-VTable custom components + +## Custom cell components + +To help react developers quickly implement custom cell content, React-VTable provides the ability to encapsulate components and use them in cells. + +### Component usage + +Custom cell components are encapsulated based on [custom layout](../custom_define/custom_layout), and their usage is similar to custom layout. To use components in `ListColumn`, custom components need to pass in the `role` attribute to identify the component as a custom cell component; the `custom-layout` component will take effect in the table content part, and the `header-custom-layout` component will take effect in the table header part. There can be at most one `custom-layout` component in each column, and at most one `header-custom-layout` component. + +```tsx + + + + + + // ...... + +``` + +### Component encapsulation + +#### Default properties + +In the component, in addition to user-defined properties, like custom layouts, react-vtable also provides some default properties for components to use + +```tsx +interface CustomLayoutProps { + table: ListTable; // 表格实例 + row: number; // 行号 + col: number; // 列号 + value: FieldData; // 单元格展示数据 + dataValue: FieldData; // 单元格原始数据 + rect?: RectProps; // 单元格布局信息 +} +const CustomLayoutComponent = (props: CustomLayoutProps & UserProps) => { + const { table, row, col, rect, text } = props; + // ...... +} +``` + +#### Label + +The label returned by the component must be based on the element label provided by react-vtable (HTML tags or DOM react components cannot be used directly. If you need to use them, please refer to the next section) + +```tsx +import { Group, Text } from '@visactor/react-vtable'; + +const CustomLayoutComponent = (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 fieldData = [ + { + value: 'a', + label: 'a' + }, + { + value: 'b', + label: 'b' + } + ]; + + const groupRef = useRef(null); + + return ( + + {fieldData.map(item => { + return ( + { + // eslint-disable-next-line no-console, no-undef + console.log('groupRef', groupRef.current); + setHover(true); + event.currentTarget.stage.renderNextFrame(); + }} + onMouseLeave={(event: any) => { + setHover(false); + event.currentTarget.stage.renderNextFrame(); + }} + /> + ); + })} + {hover && ( + + )} + + ); +}; +``` + +Basic primitives: + +* Text +* Rect +* Image +* Line +* ​​Arc +* Circle +* Group + +Basic components: + +* Tag +* Radio +* Checkbox Checkbox + +For specific configuration properties, please refer to [`VRender element configuration`](https://visactor.io/vrender/option/Group), and for specific usage and layout, please refer to [custom layout](../custom_define/custom_layout), [reference example](../../demo-react/component/custom-layout). + +
+ +
+ +#### Use DOM react components + +If you need to use DOM react components in components, you can specify the `react` attribute in the `attribute` property of the element component and pass the react component as the `element` property: + +```tsx + + } + }} + onMouseEnter={(event) => { + setHover(true); + event.currentTarget.stage.renderNextFrame(); + }} + onMouseLeave={(event) => { + setHover(false); + event.currentTarget.stage.renderNextFrame(); + }} +> +// ... + +``` + +
+ +
+ +The following properties are also supported in react: +* `pointerEvents` whether to respond to mouse events +* `container` Container, used to limit the component display area in the table when scrolling. If you need to limit the component display in the table content area, you need to specify it as `table.bodyDomContainer`; if you need to limit the component display in the table header area, you need to specify it as `table.headerDomContainer`; if it is a pop-up window or menu component, you do not need to configure this property +* `anchorType` Anchor type, used to specify the anchor position of the upper left corner of the component relative to the cell + * 'top' + * 'bottom' + * 'left' + * 'right' + * 'top-right' + * 'top-left' + * 'bottom-right' + * 'bottom-left' + * 'center' + +We recommend that users use the meta tags provided by react-vtable for the content displayed in the cell. For pop-ups, menus and other components triggered in the cell, you can use DOM react components. This is the best performance solution. [Reference example](../../demo-react/component/custom-layout). + +If you need to display content in a cell, use DOM react components. You need to specify `react.container` according to the restrictions on components displayed in the table content area. It should be noted that this method requires frequent updates of component-related DOM, which will have a certain impact on performance. You can refer to [custom layout](../custom_define/custom_layout). We strongly recommend that the content components in the cell use the meta tags provided by react-vtable, which is the best solution for performance. + +## Custom external components + +In order to facilitate the overlay of external components on the React-VTable component, React-VTable provides the `CustomComponent` tool component, which allows you to quickly locate external components in the table, and can be used to quickly implement functional components such as pop-ups and menus. + +```jsx + + + + + +``` + +Among them, `CustomComponent` is used as a container to position in the table and automatically match the size (based on the anchored cell). There are two specific ways to use it: + +1. Absolute positioning + +For absolute positioning, you need to specify `displayMode` as `position`, and you need to specify `x` and `y` attributes to position the container to the specified pixel position in the table (based on the upper left corner). The `width` and `height` attributes specify the pixel size of the container. + +2. Relative positioning + +For relative positioning, you need to specify `displayMode` as `cell`, the container is positioned relative to the cell, the `col` and `row` attributes are used to specify the anchored cell coordinates, the `anchor` attribute specifies the anchor position of the container relative to the cell, the `dx` and `dy` attributes specify the offset of the container relative to the anchored cell, and the `width` and `height` attributes specify the size of the container. The `dx` `dy` `width` and `height` attributes all support units of pixels or percentages. When the percentage is calculated relative to the size of the cell. + +### API + +```ts +interface CustomComponentProps { + children: React.ReactNode; + displayMode: 'position' | 'cell'; // Positioning mode + col?: number; // Anchored column coordinates + row?: number; // Anchored row coordinates + anchor?: + | 'top-left' + | 'top-center' + | 'top-right' + | 'middle-left' + | 'middle-center' + | 'middle-right' + | 'bottom-left' + | 'bottom-center' + | 'bottom-right'; // Anchored position + dx?: number | string; // x-direction offset + dy?: number | string; // y-direction offset + width?: number | string; // container width + height?: number | string; // container height +} +``` + +Custom external component demo: [custom component demo](../../demo-react/component/custom-component) \ No newline at end of file diff --git a/docs/assets/guide/en/Developer_Ecology/react.md b/docs/assets/guide/en/Developer_Ecology/react.md index 3857dd05d..23c855849 100644 --- a/docs/assets/guide/en/Developer_Ecology/react.md +++ b/docs/assets/guide/en/Developer_Ecology/react.md @@ -278,52 +278,3 @@ function App() { ``` For detailed description of the event, please refer to: [Event Introduction](../../guide/Event/event_list) - -## Custom component - -In order to facilitate the superposition of external components on the React-VTable component, React-VTable provides a `CustomComponent` tool component to quickly locate external components into the table. - -```jsx - - - - - -``` - -Among them, `CustomComponent` is used as a container for positioning in the table and automatically matching the size (based on anchored cells). There are two ways to use it: - -1. Absolute positioning - - For absolute positioning, you need to specify `displayMode` as `position`, `x` and `y` attributes, which are used to position the container to the specified pixel position in the table (based on the upper left corner), `width` and `height `property specifies the pixel dimensions of the container. - -2. Relative positioning - - For relative positioning, you need to specify `displayMode` as `cell`, the container is positioned relative to the cell, the `col` and `row` attributes are used to specify the anchored cell coordinates, and the `anchor` attribute specifies the container relative to the cell. The anchor position, `dx` and `dy` attributes specify the offset of the container relative to the anchor cell, and the `width` and `height` properties specify the size of the container, where `dx` `dy` `width` and The `height` attribute supports units of pixels or percentages. When it is a percentage, it is calculated relative to the size of the cell. - -### API - -```ts -interface CustomComponentProps { - children: React.ReactNode; - displayMode: 'position' | 'cell'; // positioning method - col?: number; // anchored column coordinates - row?: number; // anchored row coordinates - anchor?: - | 'top-left' - | 'top-center' - | 'top-right' - | 'middle-left' - | 'middle-center' - | 'middle-right' - | 'bottom-left' - | 'bottom-center' - | 'bottom-right'; // anchored position - dx?: number | string; // offset in x direction - dy?: number | string; // offset in y direction - width?: number | string; // container width - height?: number | string; // container height -} -``` - -[custom component demo](../../demo-react/component/custom-component) diff --git a/docs/assets/guide/menu.json b/docs/assets/guide/menu.json index c8b44d150..09a36a953 100644 --- a/docs/assets/guide/menu.json +++ b/docs/assets/guide/menu.json @@ -595,6 +595,13 @@ "en": "React-VTable" } }, + { + "path": "react-custom-component", + "title": { + "zh": "React自定义组件", + "en": "React Custom Component" + } + }, { "path": "openinula", "title": { diff --git a/docs/assets/guide/zh/Developer_Ecology/react-custom-component.md b/docs/assets/guide/zh/Developer_Ecology/react-custom-component.md new file mode 100644 index 000000000..b9fae0166 --- /dev/null +++ b/docs/assets/guide/zh/Developer_Ecology/react-custom-component.md @@ -0,0 +1,235 @@ +# React-VTable自定义组件 + +## 自定义单元格组件 + +为了方便react开发者快速实现自定义单元格内容,React-VTable 提供了封装组件并在单元格中使用的能力。 + +### 组件用法 + +自定义单元格组件在[自定义布局](../custom_define/custom_layout)的基础上封装而成,用法类似于自定义布局。在`ListColumn`中使用组件,自定义组件需要传入`role`属性,用于标识该组件为自定义单元格组件;其中`custom-layout`组件会在表格内容部分生效,`header-custom-layout`组件会在表格表头部分生效。每列中最多只能有一个`custom-layout`组件,最多只能有一个`header-custom-layout`组件。 + +```tsx + + + + + + // ...... + +``` + +### 组件封装 + +#### 默认属性 + +在组件中,除了用户定义的属性外,与自定义布局一样,react-vtable还提供了一些默认属性供组件使用 + +```tsx +interface CustomLayoutProps { + table: ListTable; // 表格实例 + row: number; // 行号 + col: number; // 列号 + value: FieldData; // 单元格展示数据 + dataValue: FieldData; // 单元格原始数据 + rect?: RectProps; // 单元格布局信息 +} +const CustomLayoutComponent = (props: CustomLayoutProps & UserProps) => { + const { table, row, col, rect, text } = props; + // ...... +} +``` + +#### 标签 + +组件返回的标签,必须是基于react-vtable提供的图元标签(不可以直接使用HTML标签或DOM react组件,如果需要使用,请参考下一节) + +```tsx +import { Group, Text } from '@visactor/react-vtable'; + +const CustomLayoutComponent = (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 fieldData = [ + { + value: 'a', + label: 'a' + }, + { + value: 'b', + label: 'b' + } + ]; + + const groupRef = useRef(null); + + return ( + + {fieldData.map(item => { + return ( + { + // eslint-disable-next-line no-console, no-undef + console.log('groupRef', groupRef.current); + setHover(true); + event.currentTarget.stage.renderNextFrame(); + }} + onMouseLeave={(event: any) => { + setHover(false); + event.currentTarget.stage.renderNextFrame(); + }} + /> + ); + })} + {hover && ( + + )} + + ); +}; +``` + +基础图元: + +* Text 文字 +* Rect 矩形 +* Image 图片 +* Line 线 +* Arc 弧形 +* Circle 圆 +* Group 图元组 + +基础组件: + +* Tag 文本标签 +* Radio 单选框 +* Checkbox 复选框 + +具体配置属性可以参考[`VRender图元配置`](https://visactor.io/vrender/option/Group),具体使用和布局可以参考[自定义布局](../custom_define/custom_layout),[参考示例](../../demo-react/component/custom-layout)。 + +
+ +
+ +#### 使用DOM react组件 + +如果需要在组件中使用DOM react组件,可以在图元组件的`attribute`属性中,指定`react`属性,并将react组件作为`element`属性传入: + +```tsx + + } + }} + onMouseEnter={(event) => { + setHover(true); + event.currentTarget.stage.renderNextFrame(); + }} + onMouseLeave={(event) => { + setHover(false); + event.currentTarget.stage.renderNextFrame(); + }} +> +// ... + +``` + +
+ +
+ +react中还支持配置以下属性: +* `pointerEvents` 是否响应鼠标事件 +* `container` 容器,用于限制滚动时组件显示区域在表格中,如果需要限制组件显示在表格内容区域,需要指定为`table.bodyDomContainer`;如果需要限制组件显示在表格表头区域,需要指定为`table.headerDomContainer`;如果是弹窗或菜单类组件,不需要配置该属性 +* `anchorType` 锚定类型,用于指定组件左上角相对于单元格的锚定位置 + * 'top' + * 'bottom' + * 'left' + * 'right' + * 'top-right' + * 'top-left' + * 'bottom-right' + * 'bottom-left' + * 'center' + +我们推荐用户在单元格内展示的内容,使用react-vtable提供的图元标签,单元格内触发的弹窗、菜单等组件,可以使用DOM react组件,这样是性能最优的方案。[参考示例](../../demo-react/component/custom-layout)。 + +如果需要在单元格内展示的内容,使用DOM react组件,需要按照限制组件显示在表格内容区域,指定`react.container`。需要注意,这样的方式需要频繁更新组件相关DOM,会对性能有一定影响,可以参考[自定义布局](../custom_define/custom_layout)。我们强烈推荐将单元格内的内容组件使用react-vtable提供的图元标签,这样是性能最优的方案。 + +## 自定义外部组件 + +为了方便在 React-VTable 组件上叠加外部组件,React-VTable 提供了`CustomComponent`工具组件,方便快速将外部组件定位到表格当中,可以用来快速实现弹窗、菜单等功能组件。 + +```jsx + + + + + +``` + +其中,`CustomComponent`作为一个容器,用于在表格中定位,并自动匹配尺寸(基于锚定的单元格),具体有两种使用方式: + +1. 绝对定位 + + 绝对定位的方式,需要指定`displayMode`为`position`, 需要指定`x`和`y`属性,用于将容器定位到表格中的指定像素位置(基于左上角),`width`和`height`属性指定容器的像素尺寸。 + +2. 相对定位 + + 相对定位的方式,需要指定`displayMode`为`cell`,容器相对为单元格定位、`col`和`row`属性用于指定锚定的单元格坐标,`anchor`属性指定容器相对于单元格的锚定位置,`dx`和`dy`属性指定容器相对于锚定单元格的偏移量,`width`和`height`属性指定容器的尺寸,其中`dx` `dy` `width`和`height`属性的均支持单位为像素或百分比,为百分比时,相对于单元格的尺寸进行计算。 + +### API + +```ts +interface CustomComponentProps { + children: React.ReactNode; + displayMode: 'position' | 'cell'; // 定位方式 + col?: number; // 锚定的列坐标 + row?: number; // 锚定的行坐标 + anchor?: + | 'top-left' + | 'top-center' + | 'top-right' + | 'middle-left' + | 'middle-center' + | 'middle-right' + | 'bottom-left' + | 'bottom-center' + | 'bottom-right'; // 锚定的位置 + dx?: number | string; // x方向的偏移 + dy?: number | string; // y方向的偏移 + width?: number | string; // 容器的宽度 + height?: number | string; // 容器的高度 +} +``` + +自定义外部组件 demo:[custom component demo](../../demo-react/component/custom-component) \ No newline at end of file diff --git a/docs/assets/guide/zh/Developer_Ecology/react.md b/docs/assets/guide/zh/Developer_Ecology/react.md index bfe90fcd8..be0ab61bf 100644 --- a/docs/assets/guide/zh/Developer_Ecology/react.md +++ b/docs/assets/guide/zh/Developer_Ecology/react.md @@ -280,52 +280,3 @@ function App() { ``` 事件详细描述参考:[事件介绍](../../guide/Event/event_list) - -## 自定义外部组件 - -为了方便在 React-VTable 组件上叠加外部组件,React-VTable 提供了`CustomComponent`工具组件,方便快速将外部组件定位到表格当中。 - -```jsx - - - - - -``` - -其中,`CustomComponent`作为一个容器,用于在表格中定位,并自动匹配尺寸(基于锚定的单元格),具体有两种使用方式: - -1. 绝对定位 - - 绝对定位的方式,需要指定`displayMode`为`position`, 需要指定`x`和`y`属性,用于将容器定位到表格中的指定像素位置(基于左上角),`width`和`height`属性指定容器的像素尺寸。 - -2. 相对定位 - - 相对定位的方式,需要指定`displayMode`为`cell`,容器相对为单元格定位、`col`和`row`属性用于指定锚定的单元格坐标,`anchor`属性指定容器相对于单元格的锚定位置,`dx`和`dy`属性指定容器相对于锚定单元格的偏移量,`width`和`height`属性指定容器的尺寸,其中`dx` `dy` `width`和`height`属性的均支持单位为像素或百分比,为百分比时,相对于单元格的尺寸进行计算。 - -### API - -```ts -interface CustomComponentProps { - children: React.ReactNode; - displayMode: 'position' | 'cell'; // 定位方式 - col?: number; // 锚定的列坐标 - row?: number; // 锚定的行坐标 - anchor?: - | 'top-left' - | 'top-center' - | 'top-right' - | 'middle-left' - | 'middle-center' - | 'middle-right' - | 'bottom-left' - | 'bottom-center' - | 'bottom-right'; // 锚定的位置 - dx?: number | string; // x方向的偏移 - dy?: number | string; // y方向的偏移 - width?: number | string; // 容器的宽度 - height?: number | string; // 容器的高度 -} -``` - -自定义外部组件 demo:[custom component demo](../../demo-react/component/custom-component) diff --git a/packages/react-vtable/demo/src/App.tsx b/packages/react-vtable/demo/src/App.tsx index 00fb52a68..bbfe21696 100644 --- a/packages/react-vtable/demo/src/App.tsx +++ b/packages/react-vtable/demo/src/App.tsx @@ -34,7 +34,7 @@ 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 customLayoutDomSite1; +// export default customLayoutDomSite1; diff --git a/packages/react-vtable/src/components/custom/component.ts b/packages/react-vtable/src/components/custom/component.ts index ff691ad20..9496f6152 100644 --- a/packages/react-vtable/src/components/custom/component.ts +++ b/packages/react-vtable/src/components/custom/component.ts @@ -2,6 +2,8 @@ import type { ReactElement, ReactNode, Ref, JSXElementConstructor } from 'react' import type { VRender } from '@visactor/vtable'; type IGraphic = VRender.IGraphic; type TagAttributes = VRender.TagAttributes; +type RadioAttributes = VRender.RadioAttributes; +type CheckboxAttributes = VRender.CheckboxAttributes; type IEventParamsType = VRender.IEventParamsType; type GraphicProps = { @@ -13,3 +15,12 @@ type GraphicProps = { export const Tag: ( props: GraphicProps ) => ReactElement, JSXElementConstructor>> = 'tag' as any; + +export const Radio: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = 'radio' as any; + +export const Checkbox: ( + props: GraphicProps +) => ReactElement, JSXElementConstructor>> = + 'checkbox' as any; From 89f9d4a7ab782aadba80a6cf91cb79a80427695b Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 20 Jun 2024 11:03:26 +0800 Subject: [PATCH 63/85] feat: support corner header cell edit value #1945 --- packages/vtable/examples/editor/pivot-editor.ts | 5 +++-- packages/vtable/src/PivotTable.ts | 9 +++++++-- packages/vtable/src/layout/pivot-header-layout.ts | 8 +++++++- packages/vtable/src/ts-types/pivot-table/corner.ts | 6 ++++++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/vtable/examples/editor/pivot-editor.ts b/packages/vtable/examples/editor/pivot-editor.ts index 941166222..3b53fd9cc 100644 --- a/packages/vtable/examples/editor/pivot-editor.ts +++ b/packages/vtable/examples/editor/pivot-editor.ts @@ -433,14 +433,15 @@ export function createTable() { } ], corner: { + // headerEditor: 'input', titleOnDimension: 'row', headerStyle: { bgColor: '#356b9c', color: '#00ffff' } - } + }, // widthMode: 'adaptive', - // headerEditor: 'input' + headerEditor: 'input' }; const tableInstance = new VTable.PivotTable(option); // 只为了方便控制太调试用,不要拷贝 diff --git a/packages/vtable/src/PivotTable.ts b/packages/vtable/src/PivotTable.ts index b368a734b..712b0512e 100644 --- a/packages/vtable/src/PivotTable.ts +++ b/packages/vtable/src/PivotTable.ts @@ -1517,7 +1517,10 @@ export class PivotTable extends BaseTable implements PivotTableAPI { /** 获取单元格对应的编辑器 */ getEditor(col: number, row: number) { let editorDefine; - if (this.isHeader(col, row) && !this.isCornerHeader(col, row)) { + if (this.isCornerHeader(col, row)) { + const define = this.getHeaderDefine(col, row); + editorDefine = (define as ColumnDefine)?.headerEditor ?? this.options.headerEditor; + } else if (this.isHeader(col, row)) { const define = this.getHeaderDefine(col, row); editorDefine = (define as ColumnDefine)?.headerEditor ?? this.options.headerEditor; } else { @@ -1708,7 +1711,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { this.records[rowIndex][colIndex] = newValue; } else if (this.dataset) { const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - if (this.isHeader(col, row)) { + if (this.isCornerHeader(col, row)) { + this.internalProps.layoutMap.changeCornerTitle(col, row, newValue as string); + } else if (this.isHeader(col, row)) { this.internalProps.layoutMap.changeTreeNodeTitle(col, row, newValue as string); !this.isCornerHeader(col, row) && diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index 8fe03ac33..553fdbb34 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -704,6 +704,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { dimensionKey: dimensionKey, // '维度名称', id, value: dimensionKey, + headerEditor: this.cornerSetting.headerEditor, disableHeaderHover: !!this.cornerSetting.disableHeaderHover, disableHeaderSelect: !!this.cornerSetting.disableHeaderSelect }, @@ -3395,7 +3396,12 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { const id = this.getCellId(col, row); this._headerObjectMap[id as number].title = value; } - + changeCornerTitle(col: number, row: number, value: string) { + if (this.isCornerHeader(col, row)) { + const id = this.getCellId(col, row); + this._headerObjectMap[id as number].title = value; + } + } generateCellIdsConsiderHideHeader() { // deal with hide header // 创建原数组的副本 diff --git a/packages/vtable/src/ts-types/pivot-table/corner.ts b/packages/vtable/src/ts-types/pivot-table/corner.ts index 45c87a86c..9427ea95a 100644 --- a/packages/vtable/src/ts-types/pivot-table/corner.ts +++ b/packages/vtable/src/ts-types/pivot-table/corner.ts @@ -1,5 +1,8 @@ +import type { IEditor } from '@visactor/vtable-editors'; import type { IImageStyleOption, ITextStyleOption, IStyleOption } from '../column'; import type { ShowColumnRowType } from '../table-engine'; +import type { BaseCellInfo } from '../common'; +import type { BaseTableAPI } from '../base-table'; interface IBasicCornerDefine { titleOnDimension?: ShowColumnRowType; //角头标题是否显示列维度名称 否则显示行维度名称 @@ -15,16 +18,19 @@ interface IBasicCornerDefine { interface ITextCornerDefine extends IBasicCornerDefine { headerType?: 'text'; headerStyle?: Omit; + headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); } interface IImageCornerDefine extends IBasicCornerDefine { headerType: 'image'; headerStyle?: Omit; + headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); } interface ILinkCornerDefine extends IBasicCornerDefine { headerType: 'link'; headerStyle?: Omit; + headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); } export type ICornerDefine = IImageCornerDefine | ILinkCornerDefine | ITextCornerDefine; From 4940c7d4069c223b9837b2a5ff7dc4346d8710da Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 20 Jun 2024 11:03:47 +0800 Subject: [PATCH 64/85] docs: update changlog of rush --- ...r-when-editing-corner-header_2024-06-20-03-03.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-03-03.json diff --git a/common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-03-03.json b/common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-03-03.json new file mode 100644 index 000000000..795d0bf33 --- /dev/null +++ b/common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-03-03.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "feat: support corner header cell edit value #1945\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From 33f0839f8f038614e06d7e36b63d28f82e10f58b Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 20 Jun 2024 11:06:53 +0800 Subject: [PATCH 65/85] chore: change log --- .../1941-feature-support-calculate-field_2024-06-18-12-05.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json b/common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json index a2461926d..a6d8d08d7 100644 --- a/common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json +++ b/common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json @@ -2,7 +2,7 @@ "changes": [ { "comment": "feat: support calculate field for PivotTable #1941\n\n", - "type": "none", + "type": "minor", "packageName": "@visactor/vtable" } ], From ebd707170ce2f069f12aa6d21361c2c70b44b161 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 20 Jun 2024 11:59:16 +0800 Subject: [PATCH 66/85] fix: merge cell value udpate #1945 --- packages/vtable/src/ListTable.ts | 29 +++++++++++++++++++++++++++-- packages/vtable/src/PivotTable.ts | 27 +++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/packages/vtable/src/ListTable.ts b/packages/vtable/src/ListTable.ts index 1c213561d..e656e5a8f 100644 --- a/packages/vtable/src/ListTable.ts +++ b/packages/vtable/src/ListTable.ts @@ -1211,6 +1211,29 @@ export class ListTable extends BaseTable implements ListTableAPI { let pasteColEnd = startCol; let pasteRowEnd = startRow; // const rowCount = values.length; + //#region 提前组织好未更改前的数据 + const beforeChangeValues: (string | number)[][] = []; + const oldValues: (string | number)[][] = []; + for (let i = 0; i < values.length; i++) { + if (startRow + i > this.rowCount - 1) { + break; + } + const rowValues = values[i]; + const rawRowValues: (string | number)[] = []; + const oldRowValues: (string | number)[] = []; + beforeChangeValues.push(rawRowValues); + oldValues.push(oldRowValues); + for (let j = 0; j < rowValues.length; j++) { + if (startCol + j > this.colCount - 1) { + break; + } + const beforeChangeValue = this.getCellRawValue(startCol + j, startRow + i); + rawRowValues.push(beforeChangeValue); + const oldValue = this.getCellOriginValue(startCol + j, startRow + i); + oldRowValues.push(oldValue); + } + } + //#endregion for (let i = 0; i < values.length; i++) { if (startRow + i > this.rowCount - 1) { break; @@ -1230,8 +1253,10 @@ export class ListTable extends BaseTable implements ListTableAPI { const value = rowValues[j]; const recordIndex = this.getRecordShowIndexByCell(startCol + j, startRow + i); const { field } = this.internalProps.layoutMap.getBody(startCol + j, startRow + i); - const beforeChangeValue = this.getCellRawValue(startCol + j, startRow + i); - const oldValue = this.getCellOriginValue(startCol + j, startRow + i); + // const beforeChangeValue = this.getCellRawValue(startCol + j, startRow + i); + // const oldValue = this.getCellOriginValue(startCol + j, startRow + i); + const beforeChangeValue = beforeChangeValues[i][j]; + const oldValue = oldValues[i][j]; if (this.isHeader(startCol + j, startRow + i)) { this.internalProps.layoutMap.updateColumnTitle(startCol + j, startRow + i, value as string); } else { diff --git a/packages/vtable/src/PivotTable.ts b/packages/vtable/src/PivotTable.ts index 712b0512e..839ed69cd 100644 --- a/packages/vtable/src/PivotTable.ts +++ b/packages/vtable/src/PivotTable.ts @@ -1621,6 +1621,29 @@ export class PivotTable extends BaseTable implements PivotTableAPI { let pasteColEnd = startCol; let pasteRowEnd = startRow; // const rowCount = values.length; + //#region 提前组织好未更改前的数据 + const beforeChangeValues: (string | number)[][] = []; + const oldValues: (string | number)[][] = []; + for (let i = 0; i < values.length; i++) { + if (startRow + i > this.rowCount - 1) { + break; + } + const rowValues = values[i]; + const rawRowValues: (string | number)[] = []; + const oldRowValues: (string | number)[] = []; + beforeChangeValues.push(rawRowValues); + oldValues.push(oldRowValues); + for (let j = 0; j < rowValues.length; j++) { + if (startCol + j > this.colCount - 1) { + break; + } + const beforeChangeValue = this.getCellRawValue(startCol + j, startRow + i); + rawRowValues.push(beforeChangeValue); + const oldValue = this.getCellOriginValue(startCol + j, startRow + i); + oldRowValues.push(oldValue); + } + } + //#endregion for (let i = 0; i < values.length; i++) { if (startRow + i > this.rowCount - 1) { break; @@ -1640,8 +1663,8 @@ export class PivotTable extends BaseTable implements PivotTableAPI { ) { const value = rowValues[j]; let newValue: string | number = value; - const oldValue = this.getCellOriginValue(startCol + j, startRow + i); - const rawValue = this.getCellRawValue(startCol + j, startRow + i); + const oldValue = oldValues[i][j]; + const rawValue = beforeChangeValues[i][j]; if (typeof rawValue === 'number' && isAllDigits(value)) { newValue = parseFloat(value); } From 7368f94ab126fb181fd88f587b2cf163e76e231a Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 20 Jun 2024 14:29:37 +0800 Subject: [PATCH 67/85] test: add test case for cornerHeader edit --- .../vtable-editors/src/date-input-editor.ts | 8 +- .../vtable/__tests__/edit/pivotTable.test.ts | 498 ++++++++++++++++++ 2 files changed, 500 insertions(+), 6 deletions(-) create mode 100644 packages/vtable/__tests__/edit/pivotTable.test.ts diff --git a/packages/vtable-editors/src/date-input-editor.ts b/packages/vtable-editors/src/date-input-editor.ts index d26b2f105..fa086a8a9 100644 --- a/packages/vtable-editors/src/date-input-editor.ts +++ b/packages/vtable-editors/src/date-input-editor.ts @@ -1,13 +1,9 @@ +import type { InputEditorConfig } from './input-editor'; import { InputEditor } from './input-editor'; import type { IEditor } from './types'; -export interface DateInputEditorConfig { - max?: number; - min?: number; -} - export class DateInputEditor extends InputEditor implements IEditor { editorType: string = 'DateInput'; - constructor(editorConfig?: DateInputEditorConfig) { + constructor(editorConfig?: InputEditorConfig) { super(editorConfig); this.editorConfig = editorConfig; } diff --git a/packages/vtable/__tests__/edit/pivotTable.test.ts b/packages/vtable/__tests__/edit/pivotTable.test.ts new file mode 100644 index 000000000..29042df2b --- /dev/null +++ b/packages/vtable/__tests__/edit/pivotTable.test.ts @@ -0,0 +1,498 @@ +/* eslint-disable prettier/prettier */ +// @ts-nocheck +// 有问题可对照demo unitTestPivotTable +import records from '../data/marketsales.json'; +import { PivotTable } from '../../src/PivotTable'; +import { register } from '../../src'; +import { InputEditor } from '@visactor/vtable-editors'; +import { createDiv } from '../dom'; +global.__VERSION__ = 'none'; +const input_editor = new InputEditor({}); +register.editor('input', input_editor); +describe('pivotTable init test', () => { + const containerDom: HTMLElement = createDiv(); + containerDom.style.position = 'relative'; + containerDom.style.width = '500px'; + containerDom.style.height = '500px'; + + const rowTree = [ + { + dimensionKey: '地区', + value: '东北', + children: [ + { + dimensionKey: '省/自治区', + value: '吉林' + }, + { + dimensionKey: '省/自治区', + value: '辽宁' + }, + { + dimensionKey: '省/自治区', + value: '黑龙江' + } + ] + }, + { + dimensionKey: '地区', + value: '中南', + children: [ + { + dimensionKey: '省/自治区', + value: '广东' + }, + { + dimensionKey: '省/自治区', + value: '广西' + }, + { + dimensionKey: '省/自治区', + value: '河南' + }, + { + dimensionKey: '省/自治区', + value: '海南' + }, + { + dimensionKey: '省/自治区', + value: '湖北' + }, + { + dimensionKey: '省/自治区', + value: '湖南' + } + ] + }, + { + dimensionKey: '地区', + value: '华东', + children: [ + { + dimensionKey: '省/自治区', + value: '上海' + }, + { + dimensionKey: '省/自治区', + value: '安徽' + }, + { + dimensionKey: '省/自治区', + value: '山东' + }, + { + dimensionKey: '省/自治区', + value: '江苏' + }, + { + dimensionKey: '省/自治区', + value: '江西' + }, + { + dimensionKey: '省/自治区', + value: '浙江' + }, + { + dimensionKey: '省/自治区', + value: '福建' + } + ] + }, + { + dimensionKey: '地区', + value: '华北', + children: [ + { + dimensionKey: '省/自治区', + value: '内蒙古' + }, + { + dimensionKey: '省/自治区', + value: '北京' + }, + { + dimensionKey: '省/自治区', + value: '天津' + }, + { + dimensionKey: '省/自治区', + value: '山西' + }, + { + dimensionKey: '省/自治区', + value: '河北' + } + ] + }, + { + dimensionKey: '地区', + value: '西北', + children: [ + { + dimensionKey: '省/自治区', + value: '宁夏' + }, + { + dimensionKey: '省/自治区', + value: '新疆' + }, + { + dimensionKey: '省/自治区', + value: '甘肃' + }, + { + dimensionKey: '省/自治区', + value: '陕西' + }, + { + dimensionKey: '省/自治区', + value: '青海' + } + ] + }, + { + dimensionKey: '地区', + value: '西南', + children: [ + { + dimensionKey: '省/自治区', + value: '云南' + }, + { + dimensionKey: '省/自治区', + value: '四川' + }, + { + dimensionKey: '省/自治区', + value: '海南' + }, + { + dimensionKey: '省/自治区', + value: '西藏自治区' + }, + { + dimensionKey: '省/自治区', + value: '贵州' + }, + { + dimensionKey: '省/自治区', + value: '重庆' + } + ] + } + ]; + const columnTree = [ + { + dimensionKey: '子类别', + value: '书架', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '信封', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '器具', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '复印机', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '收纳具', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '标签', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '桌子', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '椅子', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '用具', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '用品', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '电话', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '系固件', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '纸张', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '美术', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '装订机', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '设备', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + }, + { + dimensionKey: '子类别', + value: '配件', + children: [ + { + indicatorKey: '利润' + }, + { + indicatorKey: '销售额' + } + ] + } + ]; + const rows = [ + { + dimensionKey: '地区', + title: '地区', + headerStyle: { + textStick: true, + color: 'red', + bgColor: 'yellow' + }, + width: 'auto', + showSort: false + }, + { + dimensionKey: '省/自治区', + title: '省/自治区', + width: 'auto', + showSort: false, + headerStyle: { + textStick: true, + color: 'red', + bgColor: 'yellow', + marked(arg) { + const cellHeaderPaths = arg.table.getCellHeaderPaths(arg.col, arg.row); + if (cellHeaderPaths.rowHeaderPaths[1].value === '辽宁') { + return true; + } + return false; + } + } + } + ]; + const columns = [ + { + dimensionKey: '子类别', + title: '子类别', + headerStyle: { + textStick: true + }, + showSort: false + } + ]; + const indicators = [ + { + indicatorKey: '利润', + title: '利润', + width: 'auto', + style: { + borderColor: 'red', + bgColor(arg) { + if (Number(Math.ceil(arg.row)) % 2 === 1) { + return 'gray'; + } + return '#f6d7b8'; + } + } + }, + { + indicatorKey: '销售额', + title: '销售额', + width: 'auto' + } + ]; + const option = { + rowTree, + columnTree, + rows, + columns, + indicators, + corner: { + titleOnDimension: 'row' + }, + headerEditor: 'input', + showColumnHeader: true, + showRowHeader: true, + hideIndicatorName: false, + defaultColWidth: 150, + heightMode: 'autoHeight', + autoWrapText: true, + dragHeaderMode: 'all' + }; + + option.container = containerDom; + option.records = records; + const pivotTable = new PivotTable(option); + test('pivotTable change_cell_value args', () => { + let count = 0; + pivotTable.on('change_cell_value', arg => { + if (count === 0) { + expect(arg).toEqual({ + col: 0, + row: 0, + rawValue: '地区', + currentValue: '地区', + changedValue: '1' + }); + } else { + expect(arg).toEqual({ + col: 0, + row: 1, + rawValue: '地区', + currentValue: '地区', + changedValue: '1' + }); + } + count++; + }); + pivotTable.changeCellValues(0, 0, [['1'], ['1']]); + }); +}); From 5e588d100b231111a1a8e9b76679f21a1659717d Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 20 Jun 2024 17:05:11 +0800 Subject: [PATCH 68/85] fix: when drag cell and enter edit state but can not exit edit rightly #1945 --- packages/vtable/src/PivotTable.ts | 1 + packages/vtable/src/event/listener/table-group.ts | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/vtable/src/PivotTable.ts b/packages/vtable/src/PivotTable.ts index 839ed69cd..41433181c 100644 --- a/packages/vtable/src/PivotTable.ts +++ b/packages/vtable/src/PivotTable.ts @@ -1501,6 +1501,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { /** 开启单元格编辑 */ startEditCell(col?: number, row?: number) { if (isValid(col) && isValid(row)) { + this.eventManager.isDraging = false; this.selectCell(col, row); this.editorManager.startEditCell(col, row); } else if (this.stateManager.select?.cellPos) { diff --git a/packages/vtable/src/event/listener/table-group.ts b/packages/vtable/src/event/listener/table-group.ts index 4882d89d6..23a240ba3 100644 --- a/packages/vtable/src/event/listener/table-group.ts +++ b/packages/vtable/src/event/listener/table-group.ts @@ -40,7 +40,10 @@ export function bindTableGroupListener(eventManager: EventManager) { // if (stateManager.interactionState === InteractionState.scrolling) { // return; // } - if (stateManager.interactionState === InteractionState.grabing) { + if ( + stateManager.interactionState === InteractionState.grabing && + !(table as ListTableAPI).editorManager.editingEditor + ) { if (Math.abs(lastX - e.x) + Math.abs(lastY - e.y) >= 1) { if (stateManager.isResizeCol()) { /* do nothing */ @@ -53,7 +56,11 @@ export function bindTableGroupListener(eventManager: EventManager) { } } return; - } else if (table.eventManager.isDraging && stateManager.isSelecting()) { + } else if ( + table.eventManager.isDraging && + stateManager.isSelecting() && + !(table as ListTableAPI).editorManager.editingEditor + ) { eventManager.dealTableSelect(eventArgsSet, true); } // 更新列宽调整pointer From 3ffce859a801c9e6822979a73cad7d9d9aeb93b8 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 20 Jun 2024 17:05:40 +0800 Subject: [PATCH 69/85] docs: update changlog of rush --- ...r-when-editing-corner-header_2024-06-20-09-05.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-09-05.json diff --git a/common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-09-05.json b/common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-09-05.json new file mode 100644 index 000000000..c3f5e5ea4 --- /dev/null +++ b/common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-09-05.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: when drag cell and enter edit state but can not exit edit rightly #1945\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From c49c51ddf236405435109cc2ebba9975cae247ab Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 20 Jun 2024 17:33:34 +0800 Subject: [PATCH 70/85] fix: when drag cell and enter edit state but can not exit edit rightly --- ...-bug-error-when-editing-corner-header_2024-06-20-09-05.json} | 2 +- packages/vtable/src/ListTable.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename common/changes/@visactor/vtable/{1945-bug-error-when-editing-corner-header_2024-06-20-09-05.json => 1956-bug-error-when-editing-corner-header_2024-06-20-09-05.json} (86%) diff --git a/common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-09-05.json b/common/changes/@visactor/vtable/1956-bug-error-when-editing-corner-header_2024-06-20-09-05.json similarity index 86% rename from common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-09-05.json rename to common/changes/@visactor/vtable/1956-bug-error-when-editing-corner-header_2024-06-20-09-05.json index c3f5e5ea4..74940d6ad 100644 --- a/common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-09-05.json +++ b/common/changes/@visactor/vtable/1956-bug-error-when-editing-corner-header_2024-06-20-09-05.json @@ -1,7 +1,7 @@ { "changes": [ { - "comment": "fix: when drag cell and enter edit state but can not exit edit rightly #1945\n\n", + "comment": "fix: when drag cell and enter edit state but can not exit edit rightly #1956\n\n", "type": "none", "packageName": "@visactor/vtable" } diff --git a/packages/vtable/src/ListTable.ts b/packages/vtable/src/ListTable.ts index e656e5a8f..9d14afd2f 100644 --- a/packages/vtable/src/ListTable.ts +++ b/packages/vtable/src/ListTable.ts @@ -1059,6 +1059,7 @@ export class ListTable extends BaseTable implements ListTableAPI { /** 开启单元格编辑 */ startEditCell(col?: number, row?: number) { if (isValid(col) && isValid(row)) { + this.eventManager.isDraging = false; this.selectCell(col, row); this.editorManager.startEditCell(col, row); } else if (this.stateManager.select?.cellPos) { From 03636b08ac66ba35d589ab55f6b95eab5b014a12 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 20 Jun 2024 20:01:36 +0800 Subject: [PATCH 71/85] fix: getCellRect api when cell is frozen get bounds error #1955 --- packages/vtable/src/core/BaseTable.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 8a6faa10f..fcf955dde 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -1468,7 +1468,11 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { const width = this.getColWidth(col); if (isFrozenCell && isFrozenCell.col) { if (this.isRightFrozenColumn(col, row)) { - absoluteLeft = this.tableNoFrameWidth - (this.getColsWidth(col, this.colCount - 1) ?? 0); + if (this.getAllColsWidth() <= this.tableNoFrameWidth) { + absoluteLeft = this.getColsWidth(0, col - 1) || 0; + } else { + absoluteLeft = this.tableNoFrameWidth - (this.getColsWidth(col, this.colCount - 1) ?? 0); + } } else { absoluteLeft = this.getColsWidth(0, col - 1) || 0; // absoluteLeft += this.scrollLeft; @@ -1481,7 +1485,11 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { const height = this.getRowHeight(row); if (isFrozenCell && isFrozenCell.row) { if (this.isBottomFrozenRow(col, row)) { - absoluteTop = this.tableNoFrameHeight - (this.getRowsHeight(row, this.rowCount - 1) ?? 0); + if (this.getAllRowsHeight() <= this.tableNoFrameHeight) { + absoluteTop = this.getRowsHeight(0, row - 1); + } else { + absoluteTop = this.tableNoFrameHeight - (this.getRowsHeight(row, this.rowCount - 1) ?? 0); + } } else { absoluteTop = this.getRowsHeight(0, row - 1); // absoluteTop += this.scrollTop; From c4fb0761df540bac5e1159bbe27ede7ac9b47340 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Thu, 20 Jun 2024 19:59:27 +0800 Subject: [PATCH 72/85] fix: fix column update problem #1951 --- .../fix-column-update_2024-06-20-11-59.json | 10 +++ packages/vtable/examples/debug/scroll.ts | 80 +++++++++++++++++++ packages/vtable/examples/menu.ts | 4 + packages/vtable/src/core/BaseTable.ts | 18 ++--- .../group-creater/progress/proxy.ts | 25 ++++-- .../progress/update-position/dynamic-set-x.ts | 7 +- .../progress/update-position/dynamic-set-y.ts | 31 +++---- .../update-position/update-auto-row.ts | 28 +++++-- packages/vtable/src/ts-types/base-table.ts | 18 ++--- packages/vtable/src/ts-types/table-engine.ts | 3 + 10 files changed, 170 insertions(+), 54 deletions(-) create mode 100644 common/changes/@visactor/vtable/fix-column-update_2024-06-20-11-59.json create mode 100644 packages/vtable/examples/debug/scroll.ts diff --git a/common/changes/@visactor/vtable/fix-column-update_2024-06-20-11-59.json b/common/changes/@visactor/vtable/fix-column-update_2024-06-20-11-59.json new file mode 100644 index 000000000..7e6c1cf13 --- /dev/null +++ b/common/changes/@visactor/vtable/fix-column-update_2024-06-20-11-59.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "fix: fix column update problem #1951", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/packages/vtable/examples/debug/scroll.ts b/packages/vtable/examples/debug/scroll.ts new file mode 100644 index 000000000..b364f7c0a --- /dev/null +++ b/packages/vtable/examples/debug/scroll.ts @@ -0,0 +1,80 @@ +/* eslint-disable */ +import * as VTable from '../../src'; +import VChart from '@visactor/vchart'; +import { bindDebugTool } from '../../src/scenegraph/debug-tool'; + +const CONTAINER_ID = 'vTable'; +VTable.register.chartModule('vchart', VChart); + +function createColumn(col: number) { + const arr: any[] = []; + for (let i = 0; i < col; i++) { + const obj = { + title: i, + field: i + // width: "auto", + }; + arr.push(obj); + } + return arr; +} + +function createRecords(col: number, row: number) { + const arr: any[] = []; + for (let i = 0; i < row; i++) { + const obj = {}; + for (let j = 0; j < col; j++) { + obj[j] = `c${j}r${i}`; + } + arr.push(obj); + } + return arr; +} + +export function createTable() { + const records = createRecords(500, 500); + const columns = createColumn(500); + + const option = { + records, + columns, + // 表格列宽度的计算模式,可以是 'standard'(标准模式)、'adaptive'(自适应容器宽度模式)或 'autoWidth'(自动宽度模式),默认为 'standard'。 + widthMode: 'autoWidth', + heightMode: 'autoHeight', + defaultColWidth: 120 + // 冻结列数 + // frozenColCount: 3, + }; + + // document.getElementById(CONTAINER_ID).parentElement.style.display = 'none'; + const instance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); + window.tableInstance = instance; + + // tableInstance.onVChartEvent('mouseover', args => { + // console.log('listenChart mouseover', args); + // }); + + bindDebugTool(tableInstance.scenegraph.stage, { + customGrapicKeys: ['col', 'row'] + }); + + window.update = () => { + (option.rowTree = [ + { + dimensionKey: '20001', + value: '销售额' + } + ]), + (option.rows = [ + { + dimensionKey: '20001', + title: '销售额', + headerStyle: { + color: 'red', + cursor: 'pointer' + } + } + ]), + tableInstance.updateOption(option); + }; +} diff --git a/packages/vtable/examples/menu.ts b/packages/vtable/examples/menu.ts index cdba02a22..35b400247 100644 --- a/packages/vtable/examples/menu.ts +++ b/packages/vtable/examples/menu.ts @@ -17,6 +17,10 @@ export const menus = [ { path: 'debug', name: 'animation' + }, + { + path: 'debug', + name: 'scroll' } ] }, diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 8a6faa10f..94d24ddfe 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -49,7 +49,9 @@ import type { TableEventOptions, WidthAdaptiveModeDef, HeightAdaptiveModeDef, - ListTableAPI + ListTableAPI, + ColumnInfo, + RowInfo } from '../ts-types'; import { event, style as utilStyle } from '../tools/helper'; @@ -2460,7 +2462,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @param absoluteX * @returns */ - getTargetColAt(absoluteX: number): { col: number; left: number; right: number; width: number } | null { + getTargetColAt(absoluteX: number): ColumnInfo | null { if (absoluteX === 0) { return { left: 0, col: 0, right: 0, width: 0 }; } @@ -2529,7 +2531,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @param absoluteX * @returns */ - getTargetRowAt(absoluteY: number): { row: number; top: number; bottom: number; height: number } | null { + getTargetRowAt(absoluteY: number): RowInfo | null { if (absoluteY === 0) { return { top: 0, row: 0, bottom: 0, height: 0 }; } @@ -2604,10 +2606,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @param absoluteX * @returns */ - getTargetColAtConsiderRightFrozen( - absoluteX: number, - isConsider: boolean - ): { col: number; left: number; right: number; width: number } | null { + getTargetColAtConsiderRightFrozen(absoluteX: number, isConsider: boolean): ColumnInfo | null { if (absoluteX === 0) { return { left: 0, col: 0, right: 0, width: 0 }; } @@ -2636,10 +2635,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @param absoluteX * @returns */ - getTargetRowAtConsiderBottomFrozen( - absoluteY: number, - isConsider: boolean - ): { row: number; top: number; bottom: number; height: number } | null { + getTargetRowAtConsiderBottomFrozen(absoluteY: number, isConsider: boolean): RowInfo | null { if (absoluteY === 0) { return { top: 0, row: 0, bottom: 0, height: 0 }; } diff --git a/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts b/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts index bcf58c824..801a24b9c 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts @@ -15,6 +15,7 @@ import { sortHorizontal } from './update-position/sort-horizontal'; import { updateAutoColumn } from './update-position/update-auto-column'; import { getDefaultHeight, getDefaultWidth } from './default-width-height'; import { handleTextStick } from '../../stick-text'; +import type { ColumnInfo, RowInfo } from '../../../ts-types'; export class SceneProxy { table: BaseTableAPI; @@ -453,6 +454,12 @@ export class SceneProxy { const yLimitTop = this.table.getRowsHeight(this.bodyTopRow, this.bodyTopRow + (this.rowEnd - this.rowStart + 1)) / 2; const yLimitBottom = this.table.getAllRowsHeight() - yLimitTop; + + const screenTop = this.table.getTargetRowAt(y + this.table.scenegraph.colHeaderGroup.attribute.height); + if (screenTop) { + this.screenTopRow = screenTop.row; + } + if (y < yLimitTop && this.rowStart === this.bodyTopRow) { // 执行真实body group坐标修改 this.updateDeltaY(y); @@ -471,7 +478,7 @@ export class SceneProxy { this.updateBody(y - this.deltaY); } else { // 执行动态更新节点 - this.dynamicSetY(y, isEnd); + this.dynamicSetY(y, screenTop, isEnd); } } @@ -479,6 +486,12 @@ export class SceneProxy { const xLimitLeft = this.table.getColsWidth(this.bodyLeftCol, this.bodyLeftCol + (this.colEnd - this.colStart + 1)) / 2; const xLimitRight = this.table.getAllColsWidth() - xLimitLeft; + + const screenLeft = this.table.getTargetColAt(x + this.table.scenegraph.rowHeaderGroup.attribute.width); + if (screenLeft) { + this.screenLeftCol = screenLeft.col; + } + if (x < xLimitLeft && this.colStart === this.bodyLeftCol) { // 执行真实body group坐标修改 this.updateDeltaX(x); @@ -496,15 +509,15 @@ export class SceneProxy { this.table.scenegraph.setBodyAndColHeaderX(-x + this.deltaX); } else { // 执行动态更新节点 - this.dynamicSetX(x, isEnd); + this.dynamicSetX(x, screenLeft, isEnd); } } - async dynamicSetY(y: number, isEnd = false) { - dynamicSetY(y, isEnd, this); + async dynamicSetY(y: number, screenTop: RowInfo | null, isEnd = false) { + dynamicSetY(y, screenTop, isEnd, this); } - async dynamicSetX(x: number, isEnd = false) { - dynamicSetX(x, isEnd, this); + async dynamicSetX(x: number, screenLeft: ColumnInfo | null, isEnd = false) { + dynamicSetX(x, screenLeft, isEnd, this); } updateBody(y: number) { diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-x.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-x.ts index dc10c4fc8..5f43d9b36 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-x.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-x.ts @@ -1,3 +1,4 @@ +import type { ColumnInfo } from '../../../../ts-types'; import type { BaseTableAPI } from '../../../../ts-types/base-table'; import type { Group } from '../../../graphic/group'; import { computeColsWidth } from '../../../layout/compute-col-width'; @@ -5,16 +6,12 @@ import type { SceneProxy } from '../proxy'; import { updateAutoColumn } from './update-auto-column'; import { checkFirstColMerge, getFirstChild, getLastChild } from './util'; -export async function dynamicSetX(x: number, isEnd: boolean, proxy: SceneProxy) { - const screenLeft = (proxy.table as BaseTableAPI).getTargetColAt( - x + proxy.table.scenegraph.rowHeaderGroup.attribute.width - ); +export async function dynamicSetX(x: number, screenLeft: ColumnInfo | null, isEnd: boolean, proxy: SceneProxy) { if (!screenLeft) { return; } const screenLeftCol = screenLeft.col; const screenLeftX = screenLeft.left; - proxy.screenLeftCol = screenLeftCol; let deltaCol; if (isEnd) { diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts index 9226466f2..a51c21d1c 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts @@ -1,18 +1,16 @@ +import type { RowInfo } from '../../../../ts-types'; import type { Group } from '../../../graphic/group'; import { computeRowsHeight } from '../../../layout/compute-row-height'; import type { SceneProxy } from '../proxy'; import { updateAutoRow } from './update-auto-row'; -export async function dynamicSetY(y: number, isEnd: boolean, proxy: SceneProxy) { - // 计算变动row range - // const screenTopRow = proxy.table.getRowAt(y).row; - const screenTop = (proxy.table as any).getTargetRowAt(y + proxy.table.scenegraph.colHeaderGroup.attribute.height); +export async function dynamicSetY(y: number, screenTop: RowInfo | null, isEnd: boolean, proxy: SceneProxy) { if (!screenTop) { return; } const screenTopRow = screenTop.row; const screenTopY = screenTop.top; - proxy.screenTopRow = screenTopRow; + let deltaRow; if (isEnd) { deltaRow = proxy.bodyBottomRow - proxy.rowEnd; @@ -108,7 +106,8 @@ async function moveCell( proxy.rowStart = direction === 'up' ? proxy.rowStart + count : proxy.rowStart - count; proxy.rowEnd = direction === 'up' ? proxy.rowEnd + count : proxy.rowEnd - count; - updateRowContent(syncTopRow, syncBottomRow, proxy, true); + // 本次行更新是否同步完成,列数超过limit时为false + const sync = updateRowContent(syncTopRow, syncBottomRow, proxy, true); if (proxy.table.heightMode === 'autoHeight') { // body group @@ -168,7 +167,7 @@ async function moveCell( proxy.referenceRow = proxy.rowStart + Math.floor((proxy.rowEnd - proxy.rowStart) / 2); // proxy.referenceRow = screenTopRow; // proxy.rowUpdatePos = Math.min(proxy.rowUpdatePos, distStartRow); - if (proxy.table.heightMode === 'autoHeight') { + if (proxy.table.heightMode === 'autoHeight' && sync) { proxy.rowUpdatePos = Math.min(proxy.rowUpdatePos, proxy.rowEnd + 1); } else { proxy.rowUpdatePos = Math.min(proxy.rowUpdatePos, distStartRow); @@ -176,9 +175,7 @@ async function moveCell( proxy.rowUpdateDirection = direction; proxy.table.scenegraph.updateNextFrame(); - if (proxy.table.heightMode !== 'autoHeight') { - await proxy.progress(); - } + await proxy.progress(); } else { const distStartRow = direction === 'up' ? proxy.rowStart + count : proxy.rowStart - count; const distEndRow = direction === 'up' ? proxy.rowEnd + count : proxy.rowEnd - count; @@ -202,7 +199,7 @@ async function moveCell( proxy.rowStart = distStartRow; proxy.rowEnd = distEndRow; - updateRowContent(syncTopRow, syncBottomRow, proxy, true); + const sync = updateRowContent(syncTopRow, syncBottomRow, proxy, true); if (proxy.table.heightMode === 'autoHeight') { // body group @@ -263,7 +260,7 @@ async function moveCell( ); proxy.referenceRow = proxy.rowStart + Math.floor((proxy.rowEnd - proxy.rowStart) / 2); // proxy.referenceRow = screenTopRow; - if (proxy.table.heightMode === 'autoHeight') { + if (proxy.table.heightMode === 'autoHeight' && sync) { proxy.rowUpdatePos = proxy.rowEnd + 1; } else { proxy.rowUpdatePos = proxy.rowStart; @@ -271,9 +268,7 @@ async function moveCell( proxy.rowUpdateDirection = distEndRow > proxy.bodyBottomRow - (proxy.rowEnd - proxy.rowStart + 1) ? 'down' : 'up'; proxy.table.scenegraph.updateNextFrame(); - if (proxy.table.heightMode !== 'autoHeight') { - await proxy.progress(); - } + await proxy.progress(); } } @@ -396,10 +391,14 @@ export function updateRowContent(syncTopRow: number, syncBottomRow: number, prox // body group let leftCol = proxy.bodyLeftCol; let rightCol = proxy.bodyRightCol; + let sync = true; if (async) { const screenLeftCol = proxy.screenLeftCol; leftCol = Math.max(proxy.bodyLeftCol, screenLeftCol - proxy.screenColCount * 1); rightCol = Math.min(proxy.bodyRightCol, screenLeftCol + proxy.screenColCount * 2); + if (leftCol !== proxy.bodyLeftCol || rightCol !== proxy.bodyRightCol) { + sync = false; + } } for (let col = leftCol; col <= rightCol; col++) { for (let row = syncTopRow; row <= syncBottomRow; row++) { @@ -409,4 +408,6 @@ export function updateRowContent(syncTopRow: number, syncBottomRow: number, prox } } proxy.table.scenegraph.updateNextFrame(); + + return sync; } diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/update-auto-row.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/update-auto-row.ts index cfe38d2cf..051041227 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/update-position/update-auto-row.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/update-auto-row.ts @@ -11,12 +11,13 @@ export function updateAutoRow( direction: 'up' | 'down' = 'up', part?: boolean ) { + // return; // 更新y位置 if (direction === 'up') { for (let col = colStart; col <= colEnd; col++) { for (let row = rowStart; row <= rowEnd; row++) { const cellGroup = table.scenegraph.highPerformanceGetCell(col, row, true); - if (!cellGroup.row) { + if (cellGroup.role !== 'cell' || !cellGroup.row) { continue; } let y; @@ -27,7 +28,7 @@ export function updateAutoRow( const baseCellGroup = table.scenegraph.highPerformanceGetCell(col, rowEnd + 1, true); y = baseCellGroup.attribute.y; if (isValid(y)) { - for (let r = rowStart; r <= rowEnd; r++) { + for (let r = row; r <= rowEnd; r++) { y -= table.getRowHeight(r); } } @@ -44,7 +45,7 @@ export function updateAutoRow( for (let col = colStart; col <= colEnd; col++) { for (let row = rowEnd; row >= rowStart; row--) { const cellGroup = table.scenegraph.highPerformanceGetCell(col, row, true); - if (!cellGroup.row) { + if (cellGroup.role !== 'cell' || !cellGroup.row) { continue; } let y; @@ -54,15 +55,18 @@ export function updateAutoRow( } else if (part) { const baseCellGroup = table.scenegraph.highPerformanceGetCell(col, rowStart - 1, true); y = baseCellGroup.attribute.y; - for (let r = rowStart - 1; r < rowEnd; r++) { - y += table.getRowHeight(r); + for (let r = rowStart - 1; r < row; r++) { + const height = table.getRowHeight(r); + y += height; } } else { // 估计位置 y = table.getRowsHeight(table.columnHeaderLevelCount, cellGroup.row - 1); // console.log('估计位置', table.getRowsHeight(table.columnHeaderLevelCount, cellGroup.row)); } - cellGroup.setAttribute('y', y); + if (isValid(y)) { + cellGroup.setAttribute('y', y); + } } } } @@ -80,4 +84,16 @@ export function updateAutoRow( const totalHeight = table.getRowsHeight(table.columnHeaderLevelCount, table.rowCount - 1); table.scenegraph.proxy.yLimitTop = totalBodyHeight / 2; table.scenegraph.proxy.yLimitBottom = totalHeight - totalBodyHeight / 2; + + // // check + // const columnGroup = table.scenegraph.bodyGroup.firstChild; + // let y; + // columnGroup.forEachChildren(child => { + // if (!isValid(y)) { + // y = child.attribute.y + child.attribute.height; + // } else if (child.attribute.y !== y) { + // debugger; + // } + // y = child.attribute.y + child.attribute.height; + // }); } diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index dcb2d878a..787a372e5 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -67,7 +67,9 @@ import type { ColumnSeriesNumber, ColumnStyleOption, WidthAdaptiveModeDef, - HeightAdaptiveModeDef + HeightAdaptiveModeDef, + ColumnInfo, + RowInfo } from '.'; import type { TooltipOptions } from './tooltip'; import type { IWrapTextGraphicAttribute } from '../scenegraph/graphic/text'; @@ -761,16 +763,10 @@ export interface BaseTableAPI { getMergeCellRect: (col: number, row: number) => Rect; - getTargetColAt: (absoluteX: number) => { col: number; left: number; right: number; width: number } | null; - getTargetRowAt: (absoluteY: number) => { row: number; top: number; bottom: number; height: number } | null; - getTargetColAtConsiderRightFrozen: ( - absoluteX: number, - isConsider: boolean - ) => { col: number; left: number; right: number; width: number } | null; - getTargetRowAtConsiderBottomFrozen: ( - absoluteY: number, - isConsider: boolean - ) => { row: number; top: number; bottom: number; height: number } | null; + getTargetColAt: (absoluteX: number) => ColumnInfo | null; + getTargetRowAt: (absoluteY: number) => RowInfo | null; + getTargetColAtConsiderRightFrozen: (absoluteX: number, isConsider: boolean) => ColumnInfo | null; + getTargetRowAtConsiderBottomFrozen: (absoluteY: number, isConsider: boolean) => RowInfo | null; renderWithRecreateCells: () => void; //#endregion tableAPI diff --git a/packages/vtable/src/ts-types/table-engine.ts b/packages/vtable/src/ts-types/table-engine.ts index 28472b9e3..8cff11ff9 100644 --- a/packages/vtable/src/ts-types/table-engine.ts +++ b/packages/vtable/src/ts-types/table-engine.ts @@ -540,3 +540,6 @@ export type CustomMerge = { customLayout?: ICustomLayout; customRender?: ICustomRender; }; + +export type ColumnInfo = { col: number; left: number; right: number; width: number }; +export type RowInfo = { row: number; top: number; bottom: number; height: number }; From 62bb9ead88c38bc867504325a30934d2df79a315 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 20 Jun 2024 12:21:31 +0000 Subject: [PATCH 73/85] build: prelease version 1.3.3 --- .../vtable/fix-column-update_2024-06-20-11-59.json | 10 ---------- common/config/rush/version-policies.json | 2 +- packages/openinula-vtable/package.json | 2 +- packages/react-vtable/package.json | 2 +- packages/vtable-editors/package.json | 2 +- packages/vtable-export/package.json | 2 +- packages/vtable-search/package.json | 2 +- packages/vtable/CHANGELOG.json | 12 ++++++++++++ packages/vtable/CHANGELOG.md | 9 ++++++++- packages/vtable/package.json | 2 +- 10 files changed, 27 insertions(+), 18 deletions(-) delete mode 100644 common/changes/@visactor/vtable/fix-column-update_2024-06-20-11-59.json diff --git a/common/changes/@visactor/vtable/fix-column-update_2024-06-20-11-59.json b/common/changes/@visactor/vtable/fix-column-update_2024-06-20-11-59.json deleted file mode 100644 index 7e6c1cf13..000000000 --- a/common/changes/@visactor/vtable/fix-column-update_2024-06-20-11-59.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vtable", - "comment": "fix: fix column update problem #1951", - "type": "none" - } - ], - "packageName": "@visactor/vtable" -} \ No newline at end of file diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json index 45c56d49c..99aefbb35 100644 --- a/common/config/rush/version-policies.json +++ b/common/config/rush/version-policies.json @@ -1 +1 @@ -[{"definitionName":"lockStepVersion","policyName":"vtableMain","version":"1.3.2","mainProject":"@visactor/vtable","nextBump":"patch"}] +[{"definitionName":"lockStepVersion","policyName":"vtableMain","version":"1.3.3","mainProject":"@visactor/vtable","nextBump":"patch"}] diff --git a/packages/openinula-vtable/package.json b/packages/openinula-vtable/package.json index dcdc28bcf..b35ee56da 100644 --- a/packages/openinula-vtable/package.json +++ b/packages/openinula-vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/openinula-vtable", - "version": "1.3.2", + "version": "1.3.3", "description": "The openinula version of VTable", "keywords": [ "openinula", diff --git a/packages/react-vtable/package.json b/packages/react-vtable/package.json index a53afa788..3c8c79ed5 100644 --- a/packages/react-vtable/package.json +++ b/packages/react-vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vtable", - "version": "1.3.2", + "version": "1.3.3", "description": "The react version of VTable", "keywords": [ "react", diff --git a/packages/vtable-editors/package.json b/packages/vtable-editors/package.json index b9bcf90ed..5f5e92984 100644 --- a/packages/vtable-editors/package.json +++ b/packages/vtable-editors/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-editors", - "version": "1.3.2", + "version": "1.3.3", "description": "", "sideEffects": false, "main": "cjs/index.js", diff --git a/packages/vtable-export/package.json b/packages/vtable-export/package.json index 05d524594..b8e1ab751 100644 --- a/packages/vtable-export/package.json +++ b/packages/vtable-export/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-export", - "version": "1.3.2", + "version": "1.3.3", "description": "The export util of VTable", "author": { "name": "VisActor", diff --git a/packages/vtable-search/package.json b/packages/vtable-search/package.json index 160440955..2b812927e 100644 --- a/packages/vtable-search/package.json +++ b/packages/vtable-search/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-search", - "version": "1.3.2", + "version": "1.3.3", "description": "The search util of VTable", "author": { "name": "VisActor", diff --git a/packages/vtable/CHANGELOG.json b/packages/vtable/CHANGELOG.json index b81762de2..189d1e0b6 100644 --- a/packages/vtable/CHANGELOG.json +++ b/packages/vtable/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@visactor/vtable", "entries": [ + { + "version": "1.3.3", + "tag": "@visactor/vtable_v1.3.3", + "date": "Thu, 20 Jun 2024 12:19:07 GMT", + "comments": { + "none": [ + { + "comment": "fix: fix column update problem #1951" + } + ] + } + }, { "version": "1.3.2", "tag": "@visactor/vtable_v1.3.2", diff --git a/packages/vtable/CHANGELOG.md b/packages/vtable/CHANGELOG.md index 9cae5822a..10696d417 100644 --- a/packages/vtable/CHANGELOG.md +++ b/packages/vtable/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log - @visactor/vtable -This log was last generated on Mon, 17 Jun 2024 11:51:18 GMT and should not be manually modified. +This log was last generated on Thu, 20 Jun 2024 12:19:07 GMT and should not be manually modified. + +## 1.3.3 +Thu, 20 Jun 2024 12:19:07 GMT + +### Updates + +- fix: fix column update problem #1951 ## 1.3.2 Mon, 17 Jun 2024 11:51:18 GMT diff --git a/packages/vtable/package.json b/packages/vtable/package.json index 5205664b8..cdfb3a653 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable", - "version": "1.3.2", + "version": "1.3.3", "description": "canvas table width high performance", "keywords": [ "grid", From 2949a49c0e2c0630bdb29559d02495e81f74c5e6 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 20 Jun 2024 20:22:56 +0800 Subject: [PATCH 74/85] fix: getCellRect api when cell is frozen get bounds error #1955 --- .../api/listTable-getCellRect.test.ts | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 packages/vtable/__tests__/api/listTable-getCellRect.test.ts diff --git a/packages/vtable/__tests__/api/listTable-getCellRect.test.ts b/packages/vtable/__tests__/api/listTable-getCellRect.test.ts new file mode 100644 index 000000000..e304c94d5 --- /dev/null +++ b/packages/vtable/__tests__/api/listTable-getCellRect.test.ts @@ -0,0 +1,60 @@ +// @ts-nocheck +// 有问题可对照demo unitTestListTable +import records from '../data/marketsales.json'; +import { ListTable } from '../../src/ListTable'; +import { createDiv } from '../dom'; +global.__VERSION__ = 'none'; +describe('listTable getCellRect test', () => { + const containerDom: HTMLElement = createDiv(); + containerDom.style.position = 'relative'; + containerDom.style.width = '1000px'; + containerDom.style.height = '800px'; + const columns = [ + { + field: '订单 ID', + caption: '订单 ID', + sort: true, + width: 'auto', + description: '这是订单的描述信息', + style: { + fontFamily: 'Arial', + fontSize: 14 + } + }, + { + field: '订单日期', + caption: '订单日期' + }, + { + field: '发货日期', + caption: '发货日期' + }, + { + field: '客户名称', + caption: '客户名称', + style: { + padding: [10, 0, 10, 60] + } + } + ]; + const option = { + columns, + defaultColWidth: 150, + allowFrozenColCount: 5, + rightFrozenColCount: 1 + }; + + option.container = containerDom; + option.records = records; + const listTable = new ListTable(option); + test('listTable getCellValue', () => { + expect(listTable.getCellRect(3, 3)).toEqual({ + bounds: { + x1: 451, + x2: 601, + y1: 120, + y2: 160 + } + }); + }); +}); From 9a1e6dd50165a845453af3e58bf559a8e661c3cf Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Thu, 20 Jun 2024 20:24:49 +0800 Subject: [PATCH 75/85] docs: update changlog of rush --- .../1955-bug-getCellRect-api_2024-06-20-12-24.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/1955-bug-getCellRect-api_2024-06-20-12-24.json diff --git a/common/changes/@visactor/vtable/1955-bug-getCellRect-api_2024-06-20-12-24.json b/common/changes/@visactor/vtable/1955-bug-getCellRect-api_2024-06-20-12-24.json new file mode 100644 index 000000000..3b856ef2c --- /dev/null +++ b/common/changes/@visactor/vtable/1955-bug-getCellRect-api_2024-06-20-12-24.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: getCellRect api when cell is frozen get bounds error #1955\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From 784f227154ae9c7fc0d2bd61c680998c25cc5027 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 21 Jun 2024 11:45:59 +0800 Subject: [PATCH 76/85] fix: updateSortState api occor error #1939 --- packages/vtable/src/ListTable.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/vtable/src/ListTable.ts b/packages/vtable/src/ListTable.ts index 1c213561d..a7be18513 100644 --- a/packages/vtable/src/ListTable.ts +++ b/packages/vtable/src/ListTable.ts @@ -868,12 +868,13 @@ export class ListTable extends BaseTable implements ListTableAPI { // 解除排序状态 if (this.internalProps.sortState) { if (Array.isArray(this.internalProps.sortState)) { - for (let i = 0; i < (this.internalProps.sortState).length; i++) { - const sortState: SortState = this.internalProps.sortState[i]; - sortState.order = 'normal'; - } + // for (let i = 0; i < (this.internalProps.sortState).length; i++) { + sortState = this.internalProps.sortState?.[0]; + sortState && (sortState.order = 'normal'); + // } } else { (this.internalProps.sortState).order = 'normal'; + sortState = this.internalProps.sortState; } } } else { @@ -884,8 +885,10 @@ export class ListTable extends BaseTable implements ListTableAPI { let order: any; let field: any; if (Array.isArray(this.internalProps.sortState)) { - ({ order, field } = this.internalProps.sortState?.[0]); - } else { + if (this.internalProps.sortState?.[0]) { + ({ order, field } = this.internalProps.sortState?.[0]); + } + } else if (this.internalProps.sortState) { ({ order, field } = this.internalProps.sortState as SortState); } if (field && executeSort) { @@ -901,7 +904,9 @@ export class ListTable extends BaseTable implements ListTableAPI { this.scenegraph.sortCell(); } } - this.stateManager.updateSortState(sortState as SortState); + if (sortState) { + this.stateManager.updateSortState(sortState as SortState); + } } updateFilterRules(filterRules: FilterRules) { this.scenegraph.clearCells(); From 99a15ad6a1cf2b625eb5c72da2b6416b6adf8941 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 21 Jun 2024 11:46:51 +0800 Subject: [PATCH 77/85] docs: update changlog of rush --- ...bug-updatesortstate-set-null_2024-06-21-03-46.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/1939-bug-updatesortstate-set-null_2024-06-21-03-46.json diff --git a/common/changes/@visactor/vtable/1939-bug-updatesortstate-set-null_2024-06-21-03-46.json b/common/changes/@visactor/vtable/1939-bug-updatesortstate-set-null_2024-06-21-03-46.json new file mode 100644 index 000000000..709b8c95f --- /dev/null +++ b/common/changes/@visactor/vtable/1939-bug-updatesortstate-set-null_2024-06-21-03-46.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: updateSortState api occor error #1939\n\n", + "type": "none", + "packageName": "@visactor/vtable" + } + ], + "packageName": "@visactor/vtable", + "email": "892739385@qq.com" +} \ No newline at end of file From 7b068dbb713b08e30f96b496482d3a933df9e9e7 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 21 Jun 2024 14:26:39 +0800 Subject: [PATCH 78/85] fix: fix custom width problem #1905 --- .../vtable/fix-compute-size_2024-06-21-06-26.json | 10 ++++++++++ .../vtable/src/scenegraph/layout/compute-col-width.ts | 1 + 2 files changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-26.json diff --git a/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-26.json b/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-26.json new file mode 100644 index 000000000..ab6b6081f --- /dev/null +++ b/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-26.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "fix: fix custom width problem #1905", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/packages/vtable/src/scenegraph/layout/compute-col-width.ts b/packages/vtable/src/scenegraph/layout/compute-col-width.ts index dee0da2db..03cd9283c 100644 --- a/packages/vtable/src/scenegraph/layout/compute-col-width.ts +++ b/packages/vtable/src/scenegraph/layout/compute-col-width.ts @@ -481,6 +481,7 @@ function computeCustomRenderWidth(col: number, row: number, table: BaseTableAPI) width = customRender?.expectedWidth ?? 0; renderDefault = customRender?.renderDefault; } + width = Math.ceil(width); if (enableCellPadding) { const actStyle = table._getCellStyle(col, row); const padding = getQuadProps(getProp('padding', actStyle, col, row, table)); From 98805593912b3c6fd279f9c9c4c1670c432ce883 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 21 Jun 2024 14:29:00 +0800 Subject: [PATCH 79/85] fix: fix content judgement in getCellRange() #1911 --- .../vtable/fix-compute-size_2024-06-21-06-28.json | 10 ++++++++++ packages/vtable/src/core/BaseTable.ts | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-28.json diff --git a/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-28.json b/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-28.json new file mode 100644 index 000000000..a97ed0f1a --- /dev/null +++ b/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-28.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "fix: fix content judgement in getCellRange() #1911", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index e47246cd4..fded1c8ca 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -3077,7 +3077,11 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { getCellRange(col: number, row: number): CellRange { if (this.internalProps.customMergeCell) { const customMerge = this.internalProps.customMergeCell(col, row, this); - if (customMerge && customMerge.range && customMerge.text) { + if ( + customMerge && + customMerge.range && + (customMerge.text || customMerge.customLayout || customMerge.customRender) + ) { return customMerge.range; } } From 00630b9c6a578d7025e4ebdb6c0a586bae0b0223 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 21 Jun 2024 17:11:12 +0800 Subject: [PATCH 80/85] fix: fix no autoWrapText height compute in multilinesForXTable mode --- packages/vtable/src/scenegraph/layout/compute-row-height.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/vtable/src/scenegraph/layout/compute-row-height.ts b/packages/vtable/src/scenegraph/layout/compute-row-height.ts index afa7d8f05..1461bdedc 100644 --- a/packages/vtable/src/scenegraph/layout/compute-row-height.ts +++ b/packages/vtable/src/scenegraph/layout/compute-row-height.ts @@ -764,7 +764,11 @@ function computeTextHeight(col: number, row: number, cellType: ColumnTypeOption, maxHeight = bounds.height() || (typeof lineHeight === 'number' ? lineHeight : fontSize); } else { // autoWrapText = false - maxHeight = lines.length * lineHeight; + if (table.options.customConfig?.multilinesForXTable) { + maxHeight = lineHeight; + } else { + maxHeight = lines.length * lineHeight; + } } } return (Math.max(maxHeight, iconHeight) + padding[0] + padding[2]) / spanRow; From a2857785cd6d15a9e54cc5fe6440e813231b05b1 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Thu, 20 Jun 2024 21:09:42 +0800 Subject: [PATCH 81/85] feat: add indent in vtable-export --- .../feat-export-indent_2024-06-20-13-09.json | 10 +++++++ packages/vtable-export/src/excel/index.ts | 7 +++-- packages/vtable-export/src/excel/style.ts | 5 ++-- packages/vtable-export/src/util/indent.ts | 29 +++++++++++++++++++ 4 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 common/changes/@visactor/vtable/feat-export-indent_2024-06-20-13-09.json create mode 100644 packages/vtable-export/src/util/indent.ts diff --git a/common/changes/@visactor/vtable/feat-export-indent_2024-06-20-13-09.json b/common/changes/@visactor/vtable/feat-export-indent_2024-06-20-13-09.json new file mode 100644 index 000000000..27947acce --- /dev/null +++ b/common/changes/@visactor/vtable/feat-export-indent_2024-06-20-13-09.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "feat: add indent in vtable-export", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/packages/vtable-export/src/excel/index.ts b/packages/vtable-export/src/excel/index.ts index 6f2ad25c6..371022296 100644 --- a/packages/vtable-export/src/excel/index.ts +++ b/packages/vtable-export/src/excel/index.ts @@ -5,6 +5,7 @@ import { getCellAlignment, getCellBorder, getCellFill, getCellFont } from './sty import { updateCell, renderChart, graphicUtil } from '@visactor/vtable'; import { isArray } from '@visactor/vutils'; import type { ColumnDefine, IRowSeriesNumber } from '@visactor/vtable/src/ts-types'; +import { getHierarchyOffset } from '../util/indent'; export type CellInfo = { cellType: string; @@ -136,7 +137,8 @@ function addCell( cell.font = getCellFont(cellStyle, cellType); cell.fill = getCellFill(cellStyle); cell.border = getCellBorder(cellStyle); - cell.alignment = getCellAlignment(cellStyle); + const offset = getHierarchyOffset(col, row, tableInstance as any); + cell.alignment = getCellAlignment(cellStyle, Math.ceil(offset / cell.font.size)); return; } } @@ -168,7 +170,8 @@ function addCell( cell.font = getCellFont(cellStyle, cellType); cell.fill = getCellFill(cellStyle); cell.border = getCellBorder(cellStyle); - cell.alignment = getCellAlignment(cellStyle); + const offset = getHierarchyOffset(col, row, tableInstance as any); + cell.alignment = getCellAlignment(cellStyle, Math.ceil(offset / cell.font.size)); } else if (cellType === 'chart') { const cellGroup = tableInstance.scenegraph.getCell(col, row); renderChart(cellGroup.firstChild as any); // render chart first diff --git a/packages/vtable-export/src/excel/style.ts b/packages/vtable-export/src/excel/style.ts index 246309a5a..d51a9d2a4 100644 --- a/packages/vtable-export/src/excel/style.ts +++ b/packages/vtable-export/src/excel/style.ts @@ -93,11 +93,12 @@ function getBorderStyle(lineWidth: number, borderLineDash: LineDashsDef): ExcelJ return 'thick'; } -export function getCellAlignment(cellStyle: CellStyle): Partial { +export function getCellAlignment(cellStyle: CellStyle, indent: number): Partial { return { horizontal: cellStyle.textAlign || 'left', vertical: cellStyle.textBaseline || 'middle', - wrapText: cellStyle.autoWrapText || false + wrapText: cellStyle.autoWrapText || false, + indent: indent || 0 } as any; } diff --git a/packages/vtable-export/src/util/indent.ts b/packages/vtable-export/src/util/indent.ts new file mode 100644 index 000000000..bc7300b1f --- /dev/null +++ b/packages/vtable-export/src/util/indent.ts @@ -0,0 +1,29 @@ +import { isValid } from '@visactor/vutils'; +import type { IVTable } from './type'; +import type { ColumnDefine } from '@visactor/vtable'; + +export function getHierarchyOffset(col: number, row: number, table: IVTable): number { + // 处理树形展开 + let cellHierarchyIndent = 0; + const layoutMap = table.internalProps.layoutMap; + //判断是否为表头 + if (layoutMap.isHeader(col, row)) { + const hd = layoutMap.getHeader(col, row) as any; + if (isValid(hd?.hierarchyLevel)) { + cellHierarchyIndent = (hd.hierarchyLevel ?? 0) * ((layoutMap as any).rowHierarchyIndent ?? 0); + } + } else { + // 基本表格表身body单元格 如果是树形展开 需要考虑缩进值 + // const cellHierarchyState = table.getHierarchyState(col, row); + const define = table.getBodyColumnDefine(col, row); + if ((define as ColumnDefine)?.tree) { + const indexArr = table.dataSource.getIndexKey(table.getRecordShowIndexByCell(col, row)); + cellHierarchyIndent = + Array.isArray(indexArr) && table.getHierarchyState(col, row) !== 'none' + ? (indexArr.length - 1) * ((layoutMap as any).hierarchyIndent ?? 0) + : 0; + } + } + + return cellHierarchyIndent; +} From f0973b19185ed043c6869d35202bb191fcfe4bc3 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 21 Jun 2024 17:21:03 +0800 Subject: [PATCH 82/85] fix: fix size update problem in pivot table sort #1958 --- ...vot-sort-size-update_2024-06-21-09-20.json | 10 +++++++ packages/vtable/src/PivotChart.ts | 20 ------------- packages/vtable/src/PivotTable.ts | 30 +++++++++++++++---- packages/vtable/src/scenegraph/scenegraph.ts | 6 ++-- 4 files changed, 38 insertions(+), 28 deletions(-) create mode 100644 common/changes/@visactor/vtable/fix-pivot-sort-size-update_2024-06-21-09-20.json diff --git a/common/changes/@visactor/vtable/fix-pivot-sort-size-update_2024-06-21-09-20.json b/common/changes/@visactor/vtable/fix-pivot-sort-size-update_2024-06-21-09-20.json new file mode 100644 index 000000000..2fd1e8989 --- /dev/null +++ b/common/changes/@visactor/vtable/fix-pivot-sort-size-update_2024-06-21-09-20.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vtable", + "comment": "fix: fix size update problem in pivot table sort #1958", + "type": "none" + } + ], + "packageName": "@visactor/vtable" +} \ No newline at end of file diff --git a/packages/vtable/src/PivotChart.ts b/packages/vtable/src/PivotChart.ts index 866484242..30b5d7b9a 100644 --- a/packages/vtable/src/PivotChart.ts +++ b/packages/vtable/src/PivotChart.ts @@ -747,26 +747,6 @@ export class PivotChart extends BaseTable implements PivotChartAPI { getCellRawRecord(col: number, row: number) { return this.getCellOriginRecord(col, row); } - /** - * 全量更新排序规则 TODO 待完善 - * @param sortRules - */ - updateSortRules(sortRules: SortRules) { - if (this.internalProps.dataConfig) { - this.internalProps.dataConfig.sortRules = sortRules; - } else { - this.internalProps.dataConfig = { sortRules }; - } - this.dataset.updateSortRules(sortRules); - this.internalProps.layoutMap.resetHeaderTree(); - // 清空单元格内容 - this.scenegraph.clearCells(); - this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; - // 生成单元格场景树 - this.scenegraph.createSceneGraph(); - this.render(); - } getPivotSortState(col: number, row: number): SortOrder { if (!this.pivotSortState) { diff --git a/packages/vtable/src/PivotTable.ts b/packages/vtable/src/PivotTable.ts index dfad80b2d..2e47ffbcc 100644 --- a/packages/vtable/src/PivotTable.ts +++ b/packages/vtable/src/PivotTable.ts @@ -29,7 +29,7 @@ import { Dataset } from './dataset/dataset'; import { BaseTable } from './core/BaseTable'; import type { BaseTableAPI, HeaderData, PivotTableProtected } from './ts-types/base-table'; import { Title } from './components/title/title'; -import { cloneDeep, isValid } from '@visactor/vutils'; +import { cloneDeep, isNumber, isValid } from '@visactor/vutils'; import { Env } from './tools/env'; import type { ITreeLayoutHeadNode } from './layout/tree-helper'; import { DimensionTree, type LayouTreeNode } from './layout/tree-helper'; @@ -973,7 +973,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { * 全量更新排序规则 * @param sortRules */ - updateSortRules(sortRules: SortRules) { + updateSortRules(sortRules: SortRules, col?: number, row?: number) { if (this.internalProps.dataConfig) { this.internalProps.dataConfig.sortRules = sortRules; } else { @@ -981,13 +981,31 @@ export class PivotTable extends BaseTable implements PivotTableAPI { } this.dataset.updateSortRules(sortRules); this._changePivotSortStateBySortRules(); - this.internalProps.layoutMap.resetHeaderTree(); + const { layoutMap } = this.internalProps; + layoutMap.resetHeaderTree(); // 清空单元格内容 this.scenegraph.clearCells(); - this.refreshHeader(); + if (isNumber(col) && isNumber(row)) { + if (this.isRowHeader(col, row)) { + this.setMinMaxLimitWidth(true); + this.internalProps._widthResizedColMap.clear(); + } else if (this.isCornerHeader(col, row)) { + if (layoutMap.cornerSetting.titleOnDimension === 'column') { + this.setMinMaxLimitWidth(true); + this.internalProps._widthResizedColMap.clear(); + } else if (layoutMap.cornerSetting.titleOnDimension === 'row') { + this.internalProps._heightResizedRowMap.clear(); + } + } else if (this.isColumnHeader(col, row)) { + this.internalProps._heightResizedRowMap.clear(); + } + this.refreshRowColCount(); + } else { + this.refreshHeader(); + } this.internalProps.useOneRowHeightFillAll = false; // 生成单元格场景树 - this.scenegraph.createSceneGraph(); + this.scenegraph.createSceneGraph(true); this.render(); } _changePivotSortStateBySortRules() { @@ -1157,7 +1175,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { } } - (this as PivotTable).updateSortRules((this as PivotTable).dataset.sortRules); + (this as PivotTable).updateSortRules((this as PivotTable).dataset.sortRules, col, row); } } diff --git a/packages/vtable/src/scenegraph/scenegraph.ts b/packages/vtable/src/scenegraph/scenegraph.ts index caabf5c01..0b5b85f4d 100644 --- a/packages/vtable/src/scenegraph/scenegraph.ts +++ b/packages/vtable/src/scenegraph/scenegraph.ts @@ -344,8 +344,10 @@ export class Scenegraph { * @description: 依据数据创建表格场景树 * @return {*} */ - createSceneGraph() { - this.table.rowHeightsMap.clear(); + createSceneGraph(skipRowHeightClear = false) { + if (!skipRowHeightClear) { + this.table.rowHeightsMap.clear(); + } // if (this.table.heightMode === 'autoHeight') { // this.table.defaultRowHeight = getDefaultHeight(this.table); From 82f4f0ef7229a7a48a833a34deb59f79557898ac Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 21 Jun 2024 10:28:43 +0000 Subject: [PATCH 83/85] build: prelease version 1.4.0 --- ...tesortstate-set-null_2024-06-21-03-46.json | 11 ---- ...port-calculate-field_2024-06-18-12-05.json | 11 ---- ...diting-corner-header_2024-06-20-03-03.json | 11 ---- ...-setRecords-emptytip_2024-06-19-11-17.json | 11 ---- ...-bug-getCellRect-api_2024-06-20-12-24.json | 11 ---- ...diting-corner-header_2024-06-20-09-05.json | 11 ---- .../chore-updateVrender_2024-06-19-06-19.json | 11 ---- .../feat-export-indent_2024-06-20-13-09.json | 10 ---- ...-component-container_2024-05-07-09-28.json | 10 ---- ...-component-container_2024-05-15-06-22.json | 10 ---- .../fix-compute-size_2024-06-21-06-26.json | 10 ---- .../fix-compute-size_2024-06-21-06-28.json | 10 ---- ...vot-sort-size-update_2024-06-21-09-20.json | 10 ---- common/config/rush/version-policies.json | 2 +- packages/openinula-vtable/package.json | 4 +- packages/react-vtable/package.json | 4 +- packages/vtable-editors/package.json | 2 +- packages/vtable-export/package.json | 4 +- packages/vtable-search/package.json | 4 +- packages/vtable/CHANGELOG.json | 50 +++++++++++++++++++ packages/vtable/CHANGELOG.md | 38 +++++++++++++- packages/vtable/package.json | 4 +- 22 files changed, 99 insertions(+), 150 deletions(-) delete mode 100644 common/changes/@visactor/vtable/1939-bug-updatesortstate-set-null_2024-06-21-03-46.json delete mode 100644 common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json delete mode 100644 common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-03-03.json delete mode 100644 common/changes/@visactor/vtable/1953-feature-pivotTable-setRecords-emptytip_2024-06-19-11-17.json delete mode 100644 common/changes/@visactor/vtable/1955-bug-getCellRect-api_2024-06-20-12-24.json delete mode 100644 common/changes/@visactor/vtable/1956-bug-error-when-editing-corner-header_2024-06-20-09-05.json delete mode 100644 common/changes/@visactor/vtable/chore-updateVrender_2024-06-19-06-19.json delete mode 100644 common/changes/@visactor/vtable/feat-export-indent_2024-06-20-13-09.json delete mode 100644 common/changes/@visactor/vtable/feat-react-component-container_2024-05-07-09-28.json delete mode 100644 common/changes/@visactor/vtable/feat-react-component-container_2024-05-15-06-22.json delete mode 100644 common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-26.json delete mode 100644 common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-28.json delete mode 100644 common/changes/@visactor/vtable/fix-pivot-sort-size-update_2024-06-21-09-20.json diff --git a/common/changes/@visactor/vtable/1939-bug-updatesortstate-set-null_2024-06-21-03-46.json b/common/changes/@visactor/vtable/1939-bug-updatesortstate-set-null_2024-06-21-03-46.json deleted file mode 100644 index 709b8c95f..000000000 --- a/common/changes/@visactor/vtable/1939-bug-updatesortstate-set-null_2024-06-21-03-46.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: updateSortState api occor error #1939\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json b/common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json deleted file mode 100644 index a6d8d08d7..000000000 --- a/common/changes/@visactor/vtable/1941-feature-support-calculate-field_2024-06-18-12-05.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "feat: support calculate field for PivotTable #1941\n\n", - "type": "minor", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-03-03.json b/common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-03-03.json deleted file mode 100644 index 795d0bf33..000000000 --- a/common/changes/@visactor/vtable/1945-bug-error-when-editing-corner-header_2024-06-20-03-03.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "feat: support corner header cell edit value #1945\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/1953-feature-pivotTable-setRecords-emptytip_2024-06-19-11-17.json b/common/changes/@visactor/vtable/1953-feature-pivotTable-setRecords-emptytip_2024-06-19-11-17.json deleted file mode 100644 index f598c24f9..000000000 --- a/common/changes/@visactor/vtable/1953-feature-pivotTable-setRecords-emptytip_2024-06-19-11-17.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: when setRecords should update emptyTip #1953\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/1955-bug-getCellRect-api_2024-06-20-12-24.json b/common/changes/@visactor/vtable/1955-bug-getCellRect-api_2024-06-20-12-24.json deleted file mode 100644 index 3b856ef2c..000000000 --- a/common/changes/@visactor/vtable/1955-bug-getCellRect-api_2024-06-20-12-24.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: getCellRect api when cell is frozen get bounds error #1955\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/1956-bug-error-when-editing-corner-header_2024-06-20-09-05.json b/common/changes/@visactor/vtable/1956-bug-error-when-editing-corner-header_2024-06-20-09-05.json deleted file mode 100644 index 74940d6ad..000000000 --- a/common/changes/@visactor/vtable/1956-bug-error-when-editing-corner-header_2024-06-20-09-05.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: when drag cell and enter edit state but can not exit edit rightly #1956\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/chore-updateVrender_2024-06-19-06-19.json b/common/changes/@visactor/vtable/chore-updateVrender_2024-06-19-06-19.json deleted file mode 100644 index cfce0c96a..000000000 --- a/common/changes/@visactor/vtable/chore-updateVrender_2024-06-19-06-19.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "chore: update vrender version\n\n", - "type": "none", - "packageName": "@visactor/vtable" - } - ], - "packageName": "@visactor/vtable", - "email": "892739385@qq.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/feat-export-indent_2024-06-20-13-09.json b/common/changes/@visactor/vtable/feat-export-indent_2024-06-20-13-09.json deleted file mode 100644 index 27947acce..000000000 --- a/common/changes/@visactor/vtable/feat-export-indent_2024-06-20-13-09.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vtable", - "comment": "feat: add indent in vtable-export", - "type": "none" - } - ], - "packageName": "@visactor/vtable" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/feat-react-component-container_2024-05-07-09-28.json b/common/changes/@visactor/vtable/feat-react-component-container_2024-05-07-09-28.json deleted file mode 100644 index efabbdee6..000000000 --- a/common/changes/@visactor/vtable/feat-react-component-container_2024-05-07-09-28.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vtable", - "comment": "feat: add CustomComponent in react-vtable", - "type": "none" - } - ], - "packageName": "@visactor/vtable" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/feat-react-component-container_2024-05-15-06-22.json b/common/changes/@visactor/vtable/feat-react-component-container_2024-05-15-06-22.json deleted file mode 100644 index da8e03133..000000000 --- a/common/changes/@visactor/vtable/feat-react-component-container_2024-05-15-06-22.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vtable", - "comment": "feat: add CustomLayout component in react-vtable", - "type": "none" - } - ], - "packageName": "@visactor/vtable" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-26.json b/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-26.json deleted file mode 100644 index ab6b6081f..000000000 --- a/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-26.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vtable", - "comment": "fix: fix custom width problem #1905", - "type": "none" - } - ], - "packageName": "@visactor/vtable" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-28.json b/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-28.json deleted file mode 100644 index a97ed0f1a..000000000 --- a/common/changes/@visactor/vtable/fix-compute-size_2024-06-21-06-28.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vtable", - "comment": "fix: fix content judgement in getCellRange() #1911", - "type": "none" - } - ], - "packageName": "@visactor/vtable" -} \ No newline at end of file diff --git a/common/changes/@visactor/vtable/fix-pivot-sort-size-update_2024-06-21-09-20.json b/common/changes/@visactor/vtable/fix-pivot-sort-size-update_2024-06-21-09-20.json deleted file mode 100644 index 2fd1e8989..000000000 --- a/common/changes/@visactor/vtable/fix-pivot-sort-size-update_2024-06-21-09-20.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vtable", - "comment": "fix: fix size update problem in pivot table sort #1958", - "type": "none" - } - ], - "packageName": "@visactor/vtable" -} \ No newline at end of file diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json index 99aefbb35..a2ec57638 100644 --- a/common/config/rush/version-policies.json +++ b/common/config/rush/version-policies.json @@ -1 +1 @@ -[{"definitionName":"lockStepVersion","policyName":"vtableMain","version":"1.3.3","mainProject":"@visactor/vtable","nextBump":"patch"}] +[{"definitionName":"lockStepVersion","policyName":"vtableMain","version":"1.4.0","mainProject":"@visactor/vtable","nextBump":"minor"}] diff --git a/packages/openinula-vtable/package.json b/packages/openinula-vtable/package.json index c2c1c29ec..30fa5f41e 100644 --- a/packages/openinula-vtable/package.json +++ b/packages/openinula-vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/openinula-vtable", - "version": "1.3.3", + "version": "1.4.0", "description": "The openinula version of VTable", "keywords": [ "openinula", @@ -93,4 +93,4 @@ "peerDependencies": { "openinula": "~0.1.2-SNAPSHOT" } -} \ No newline at end of file +} diff --git a/packages/react-vtable/package.json b/packages/react-vtable/package.json index 4e5564461..d45a03304 100644 --- a/packages/react-vtable/package.json +++ b/packages/react-vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vtable", - "version": "1.3.3", + "version": "1.4.0", "description": "The react version of VTable", "keywords": [ "react", @@ -101,4 +101,4 @@ "@arco-design/web-react": "2.60.2", "@types/react-reconciler": "0.28.8" } -} \ No newline at end of file +} diff --git a/packages/vtable-editors/package.json b/packages/vtable-editors/package.json index 5f5e92984..cee4c5a7f 100644 --- a/packages/vtable-editors/package.json +++ b/packages/vtable-editors/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-editors", - "version": "1.3.3", + "version": "1.4.0", "description": "", "sideEffects": false, "main": "cjs/index.js", diff --git a/packages/vtable-export/package.json b/packages/vtable-export/package.json index df654b2a4..ec947c211 100644 --- a/packages/vtable-export/package.json +++ b/packages/vtable-export/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-export", - "version": "1.3.3", + "version": "1.4.0", "description": "The export util of VTable", "author": { "name": "VisActor", @@ -87,4 +87,4 @@ "@types/react-is": "^17.0.3", "rollup-plugin-node-resolve": "5.2.0" } -} \ No newline at end of file +} diff --git a/packages/vtable-search/package.json b/packages/vtable-search/package.json index 1d5adccf0..efa32b9ee 100644 --- a/packages/vtable-search/package.json +++ b/packages/vtable-search/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-search", - "version": "1.3.3", + "version": "1.4.0", "description": "The search util of VTable", "author": { "name": "VisActor", @@ -83,4 +83,4 @@ "@types/react-is": "^17.0.3", "rollup-plugin-node-resolve": "5.2.0" } -} \ No newline at end of file +} diff --git a/packages/vtable/CHANGELOG.json b/packages/vtable/CHANGELOG.json index 189d1e0b6..272335dc3 100644 --- a/packages/vtable/CHANGELOG.json +++ b/packages/vtable/CHANGELOG.json @@ -1,6 +1,56 @@ { "name": "@visactor/vtable", "entries": [ + { + "version": "1.4.0", + "tag": "@visactor/vtable_v1.4.0", + "date": "Fri, 21 Jun 2024 10:26:08 GMT", + "comments": { + "none": [ + { + "comment": "fix: updateSortState api occor error #1939\n\n" + }, + { + "comment": "feat: support corner header cell edit value #1945\n\n" + }, + { + "comment": "fix: when setRecords should update emptyTip #1953\n\n" + }, + { + "comment": "fix: getCellRect api when cell is frozen get bounds error #1955\n\n" + }, + { + "comment": "fix: when drag cell and enter edit state but can not exit edit rightly #1956\n\n" + }, + { + "comment": "chore: update vrender version\n\n" + }, + { + "comment": "feat: add indent in vtable-export" + }, + { + "comment": "feat: add CustomComponent in react-vtable" + }, + { + "comment": "feat: add CustomLayout component in react-vtable" + }, + { + "comment": "fix: fix custom width problem #1905" + }, + { + "comment": "fix: fix content judgement in getCellRange() #1911" + }, + { + "comment": "fix: fix size update problem in pivot table sort #1958" + } + ], + "minor": [ + { + "comment": "feat: support calculate field for PivotTable #1941\n\n" + } + ] + } + }, { "version": "1.3.3", "tag": "@visactor/vtable_v1.3.3", diff --git a/packages/vtable/CHANGELOG.md b/packages/vtable/CHANGELOG.md index 10696d417..fab4cf64d 100644 --- a/packages/vtable/CHANGELOG.md +++ b/packages/vtable/CHANGELOG.md @@ -1,6 +1,42 @@ # Change Log - @visactor/vtable -This log was last generated on Thu, 20 Jun 2024 12:19:07 GMT and should not be manually modified. +This log was last generated on Fri, 21 Jun 2024 10:26:08 GMT and should not be manually modified. + +## 1.4.0 +Fri, 21 Jun 2024 10:26:08 GMT + +### Minor changes + +- feat: support calculate field for PivotTable #1941 + + + +### Updates + +- fix: updateSortState api occor error #1939 + + +- feat: support corner header cell edit value #1945 + + +- fix: when setRecords should update emptyTip #1953 + + +- fix: getCellRect api when cell is frozen get bounds error #1955 + + +- fix: when drag cell and enter edit state but can not exit edit rightly #1956 + + +- chore: update vrender version + + +- feat: add indent in vtable-export +- feat: add CustomComponent in react-vtable +- feat: add CustomLayout component in react-vtable +- fix: fix custom width problem #1905 +- fix: fix content judgement in getCellRange() #1911 +- fix: fix size update problem in pivot table sort #1958 ## 1.3.3 Thu, 20 Jun 2024 12:19:07 GMT diff --git a/packages/vtable/package.json b/packages/vtable/package.json index fde393b34..920b363a4 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable", - "version": "1.3.3", + "version": "1.4.0", "description": "canvas table width high performance", "keywords": [ "grid", @@ -123,4 +123,4 @@ "url": "https://github.com/VisActor/VTable.git", "directory": "packages/vtable" } -} \ No newline at end of file +} From 41b0be0d0f84b2691ad565d1ccd2bf9e83854da5 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 21 Jun 2024 10:38:57 +0000 Subject: [PATCH 84/85] docs: generate changelog of release v1.4.0 --- docs/assets/changelog/en/release.md | 29 +++++++++++++++++++++++++++++ docs/assets/changelog/zh/release.md | 29 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/docs/assets/changelog/en/release.md b/docs/assets/changelog/en/release.md index 0b0b0299b..50c50b5de 100644 --- a/docs/assets/changelog/en/release.md +++ b/docs/assets/changelog/en/release.md @@ -1,3 +1,32 @@ +# v1.4.0 + +2024-06-21 + + +**🆕 New feature** + +- **@visactor/vtable**: support corner header cell edit value [#1945](https://github.com/VisActor/VTable/issues/1945) +- **@visactor/vtable**: add indent in vtable-export +- **@visactor/vtable**: add CustomComponent in react-vtable +- **@visactor/vtable**: add CustomLayout component in react-vtable +- **@visactor/vtable**: support calculate field for PivotTable [#1941](https://github.com/VisActor/VTable/issues/1941) + +**🐛 Bug fix** + +- **@visactor/vtable**: updateSortState api occor error [#1939](https://github.com/VisActor/VTable/issues/1939) +- **@visactor/vtable**: when setRecords should update emptyTip [#1953](https://github.com/VisActor/VTable/issues/1953) +- **@visactor/vtable**: getCellRect api when cell is frozen get bounds error [#1955](https://github.com/VisActor/VTable/issues/1955) +- **@visactor/vtable**: when drag cell and enter edit state but can not exit edit rightly [#1956](https://github.com/VisActor/VTable/issues/1956) +- **@visactor/vtable**: fix custom width problem [#1905](https://github.com/VisActor/VTable/issues/1905) +- **@visactor/vtable**: fix content judgement in getCellRange() [#1911](https://github.com/VisActor/VTable/issues/1911) +- **@visactor/vtable**: fix size update problem in pivot table sort [#1958](https://github.com/VisActor/VTable/issues/1958) + +**🔧 Configuration releated** + +- **@visactor/vtable**: update vrender version + +[more detail about v1.4.0](https://github.com/VisActor/VTable/releases/tag/v1.4.0) + # v1.3.2 2024-06-17 diff --git a/docs/assets/changelog/zh/release.md b/docs/assets/changelog/zh/release.md index c70e7fb73..1ac257625 100644 --- a/docs/assets/changelog/zh/release.md +++ b/docs/assets/changelog/zh/release.md @@ -1,3 +1,32 @@ +# v1.4.0 + +2024-06-21 + + +**🆕 新增功能** + +- **@visactor/vtable**: support corner header cell edit value [#1945](https://github.com/VisActor/VTable/issues/1945) +- **@visactor/vtable**: add indent in vtable-export +- **@visactor/vtable**: add CustomComponent in react-vtable +- **@visactor/vtable**: add CustomLayout component in react-vtable +- **@visactor/vtable**: support calculate field for PivotTable [#1941](https://github.com/VisActor/VTable/issues/1941) + +**🐛 功能修复** + +- **@visactor/vtable**: updateSortState api occor error [#1939](https://github.com/VisActor/VTable/issues/1939) +- **@visactor/vtable**: when setRecords should update emptyTip [#1953](https://github.com/VisActor/VTable/issues/1953) +- **@visactor/vtable**: getCellRect api when cell is frozen get bounds error [#1955](https://github.com/VisActor/VTable/issues/1955) +- **@visactor/vtable**: when drag cell and enter edit state but can not exit edit rightly [#1956](https://github.com/VisActor/VTable/issues/1956) +- **@visactor/vtable**: fix custom width problem [#1905](https://github.com/VisActor/VTable/issues/1905) +- **@visactor/vtable**: fix content judgement in getCellRange() [#1911](https://github.com/VisActor/VTable/issues/1911) +- **@visactor/vtable**: fix size update problem in pivot table sort [#1958](https://github.com/VisActor/VTable/issues/1958) + +**🔧 项目配置** + +- **@visactor/vtable**: update vrender version + +[更多详情请查看 v1.4.0](https://github.com/VisActor/VTable/releases/tag/v1.4.0) + # v1.3.2 2024-06-17 From 8ce320dc32db27f08997f03a92ca4ccfa7567920 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Fri, 21 Jun 2024 18:55:11 +0800 Subject: [PATCH 85/85] docs: trasnlate release docs --- docs/assets/changelog/zh/release.md | 61 ++++++++++++----------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/docs/assets/changelog/zh/release.md b/docs/assets/changelog/zh/release.md index 1ac257625..97469de96 100644 --- a/docs/assets/changelog/zh/release.md +++ b/docs/assets/changelog/zh/release.md @@ -4,26 +4,21 @@ **🆕 新增功能** - -- **@visactor/vtable**: support corner header cell edit value [#1945](https://github.com/VisActor/VTable/issues/1945) -- **@visactor/vtable**: add indent in vtable-export -- **@visactor/vtable**: add CustomComponent in react-vtable -- **@visactor/vtable**: add CustomLayout component in react-vtable -- **@visactor/vtable**: support calculate field for PivotTable [#1941](https://github.com/VisActor/VTable/issues/1941) + +- **@visactor/vtable**: 支持角头单元格编辑 [#1945](https://github.com/VisActor/VTable/issues/1945) +- **@visactor/vtable**: vtable-export支持缩进导出 +- **@visactor/vtable**: react-vtable支持 CustomComponent & CustomLayout component 组件 +- **@visactor/vtable**: PivotTable支持field计算 [#1941](https://github.com/VisActor/VTable/issues/1941) **🐛 功能修复** - -- **@visactor/vtable**: updateSortState api occor error [#1939](https://github.com/VisActor/VTable/issues/1939) -- **@visactor/vtable**: when setRecords should update emptyTip [#1953](https://github.com/VisActor/VTable/issues/1953) -- **@visactor/vtable**: getCellRect api when cell is frozen get bounds error [#1955](https://github.com/VisActor/VTable/issues/1955) -- **@visactor/vtable**: when drag cell and enter edit state but can not exit edit rightly [#1956](https://github.com/VisActor/VTable/issues/1956) -- **@visactor/vtable**: fix custom width problem [#1905](https://github.com/VisActor/VTable/issues/1905) -- **@visactor/vtable**: fix content judgement in getCellRange() [#1911](https://github.com/VisActor/VTable/issues/1911) -- **@visactor/vtable**: fix size update problem in pivot table sort [#1958](https://github.com/VisActor/VTable/issues/1958) -**🔧 项目配置** - -- **@visactor/vtable**: update vrender version +- **@visactor/vtable**: 修复updateSortState api 调用问题 [#1939](https://github.com/VisActor/VTable/issues/1939) +- **@visactor/vtable**: 调用 setRecords 时更新 emptyTip 组件 [#1953](https://github.com/VisActor/VTable/issues/1953) +- **@visactor/vtable**: 修复冻结单元格 getCellRect api 获取 bounds 错误 [#1955](https://github.com/VisActor/VTable/issues/1955) +- **@visactor/vtable**: when drag cell and enter edit state but can not exit edit rightly [#1956](https://github.com/VisActor/VTable/issues/1956) +- **@visactor/vtable**: 修复自定义单元格列宽计算问题 [#1905](https://github.com/VisActor/VTable/issues/1905) +- **@visactor/vtable**: 修复 getCellRange 中的内容判断逻辑 [#1911](https://github.com/VisActor/VTable/issues/1911) +- **@visactor/vtable**: 修复透视表排序时尺寸更新问题 [#1958](https://github.com/VisActor/VTable/issues/1958) [更多详情请查看 v1.4.0](https://github.com/VisActor/VTable/releases/tag/v1.4.0) @@ -33,20 +28,20 @@ **🆕 新增功能** - -- **@visactor/vtable**: add blankAreaClickDeselect and outsideClickDeselect config + +- **@visactor/vtable**: 增加 blankAreaClickDeselect & outsideClickDeselect 配置 **🐛 功能修复** - -- **@visactor/vtable**: cellIsInVisualView api error [#1864](https://github.com/VisActor/VTable/issues/1864) -- **@visactor/vtable**: if set style autoWrapText, this config not wort when resize column width [#1892](https://github.com/VisActor/VTable/issues/1892) + +- **@visactor/vtable**: 修复cellIsInVisualView api调用问题 [#1864](https://github.com/VisActor/VTable/issues/1864) +- **@visactor/vtable**: 修复改变列宽时autoWrapText不生效问题 [#1892](https://github.com/VisActor/VTable/issues/1892) **🔨 功能重构** - -- **@visactor/vtable**: tooltip support scroll [#1887](https://github.com/VisActor/VTable/issues/1887) -- **@visactor/vtable**: when not records pivot table can show corner header [#1895](https://github.com/VisActor/VTable/issues/1895) -- **@visactor/vtable**: when rowTree children not set value can supplement indicators [#1924](https://github.com/VisActor/VTable/issues/1924) - + +- **@visactor/vtable**: 支持tooltip滚动 [#1887](https://github.com/VisActor/VTable/issues/1887) +- **@visactor/vtable**: 支持透视表没有数据是的角头展示 [#1895](https://github.com/VisActor/VTable/issues/1895) +- **@visactor/vtable**: 支持rowTree没有children时的指标展示 [#1924](https://github.com/VisActor/VTable/issues/1924) + [更多详情请查看 v1.3.2](https://github.com/VisActor/VTable/releases/tag/v1.3.2) @@ -57,16 +52,10 @@ **🐛 功能修复** - -- **@visactor/vtable**: fix frozenColCount large than colCount error [#1872](https://github.com/VisActor/VTable/issues/1872) -- **@visactor/vtable**: fix merge cell size update [#1869](https://github.com/VisActor/VTable/issues/1869) -- **@visactor/vtable**: optimize row height update when useOneRowHeightFillAll - -**📖 文档更新** - -- **@visactor/vtable**: update changlog of rush - +- **@visactor/vtable**: 修复frozenColCount超过列数时的显示问题 [#1872](https://github.com/VisActor/VTable/issues/1872) +- **@visactor/vtable**: 修复合并单元格的尺寸更新问题 [#1869](https://github.com/VisActor/VTable/issues/1869) +- **@visactor/vtable**: 修复单行填充所有行时的行高更新问题 [更多详情请查看 v1.3.1](https://github.com/VisActor/VTable/releases/tag/v1.3.1)