From 4058ba5344a4942dbe00b04e77d950cd1e6aa805 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 15 Jan 2024 15:20:30 +0800 Subject: [PATCH] chore: merge 5.1 branch into v5 (#5345) * refactor: remove IGraph usage (#5336) * refactor: remove IGraph definition and usage * chore: mark the type problems * chore: update ci script * chore: update ci * refactor: remove history plugin (#5338) * refactor: upgrade to register plugins globally (#5337) * refactor: upgrade to register plugins globally * fix: ci * feat: register once default plugins during initialization * refactor: upgrade to register plugins globally --------- Co-authored-by: yvonneyx * feat: add new spec definition (#5342) * feat: add new spec definition * refactor: remove background, cursor option * refactor: adjust palette option * refactor: adjust spec definition * refactor: use non-strict type checking * refactor: adjust type naming * refactor: add container option --------- Co-authored-by: Yuxin <55794321+yvonneyx@users.noreply.github.com> Co-authored-by: yvonneyx --- .github/workflows/build.yml | 26 - package.json | 4 +- packages/g6/src/constant/shape.ts | 4 +- packages/g6/src/index.ts | 27 +- packages/g6/src/item/combo.ts | 4 +- packages/g6/src/item/edge.ts | 4 +- packages/g6/src/item/item.ts | 4 +- packages/g6/src/item/node.ts | 4 +- .../src/plugin/behavior/activate-relations.ts | 20 +- .../g6/src/plugin/behavior/click-select.ts | 24 +- .../g6/src/plugin/behavior/create-edge.ts | 2 + .../g6/src/plugin/behavior/drag-canvas.ts | 10 +- packages/g6/src/plugin/behavior/drag-combo.ts | 44 +- packages/g6/src/plugin/behavior/drag-node.ts | 112 ++- .../g6/src/plugin/behavior/lasso-select.ts | 4 +- .../g6/src/plugin/behavior/scroll-canvas.ts | 6 +- .../g6/src/plugin/behavior/zoom-canvas.ts | 10 +- packages/g6/src/plugin/index.ts | 31 +- packages/g6/src/plugin/item/edge/base.ts | 2 +- packages/g6/src/plugin/item/node/base.ts | 6 +- packages/g6/src/plugin/item/node/base3d.ts | 3 +- packages/g6/src/plugin/register.ts | 240 ++++++ packages/g6/src/plugin/selector/lasso.ts | 6 +- packages/g6/src/plugin/selector/rect.ts | 6 +- packages/g6/src/plugin/theme-solver/base.ts | 1 + .../src/plugin/widget/edge-bundling/index.ts | 4 +- .../plugin/widget/edge-filter-lens/index.ts | 4 +- .../g6/src/plugin/widget/fisheye/index.ts | 4 +- packages/g6/src/plugin/widget/grid/index.ts | 4 +- .../plugin/widget/history/combo-command.ts | 24 - .../g6/src/plugin/widget/history/command.ts | 66 -- .../g6/src/plugin/widget/history/index.ts | 333 -------- .../widget/history/item-data-command.ts | 101 --- .../widget/history/layer-updated-command.ts | 24 - .../widget/history/state-updated-command.ts | 36 - .../history/visibility-updated-command.ts | 41 - .../g6/src/plugin/widget/hull/bubbleset.ts | 20 +- .../src/plugin/widget/hull/hullComponent.ts | 7 +- packages/g6/src/plugin/widget/hull/index.ts | 4 +- packages/g6/src/plugin/widget/hull/util.ts | 6 +- packages/g6/src/plugin/widget/index.ts | 1 - packages/g6/src/plugin/widget/legend/index.ts | 4 +- .../src/plugin/widget/lod-controller/index.ts | 8 +- packages/g6/src/plugin/widget/menu/index.ts | 4 +- .../g6/src/plugin/widget/minimap/index.ts | 4 +- .../g6/src/plugin/widget/snapline/index.ts | 4 +- .../g6/src/plugin/widget/timebar/index.ts | 6 +- .../g6/src/plugin/widget/toolbar/index.ts | 12 +- .../g6/src/plugin/widget/tooltip/index.ts | 6 +- packages/g6/src/plugin/widget/types.ts | 1 - .../g6/src/plugin/widget/watermarker/index.ts | 4 +- packages/g6/src/runtime/controller/data.ts | 9 +- .../g6/src/runtime/controller/interaction.ts | 10 +- packages/g6/src/runtime/controller/item.ts | 77 +- packages/g6/src/runtime/controller/layout.ts | 13 +- packages/g6/src/runtime/controller/plugin.ts | 15 +- packages/g6/src/runtime/controller/theme.ts | 20 +- .../g6/src/runtime/controller/viewport.ts | 6 +- packages/g6/src/runtime/graph.ts | 215 +---- .../g6/src/runtime/layered-canvas/types.ts | 1 + packages/g6/src/spec/canvas/index.ts | 35 + packages/g6/src/spec/canvas/io.ts | 13 + packages/g6/src/spec/data/index.ts | 57 ++ packages/g6/src/spec/data/io.ts | 13 + packages/g6/src/spec/element/combo/index.ts | 45 + packages/g6/src/spec/element/combo/io.ts | 13 + packages/g6/src/spec/element/edge/index.ts | 63 ++ packages/g6/src/spec/element/edge/io.ts | 13 + packages/g6/src/spec/element/index.ts | 3 + packages/g6/src/spec/element/node/index.ts | 45 + packages/g6/src/spec/element/types.ts | 56 ++ packages/g6/src/spec/index.ts | 73 ++ packages/g6/src/spec/layout/index.ts | 26 + packages/g6/src/spec/layout/io.ts | 13 + packages/g6/src/spec/mode/index.ts | 24 + packages/g6/src/spec/mode/io.ts | 13 + packages/g6/src/spec/optimize/index.ts | 35 + packages/g6/src/spec/optimize/io.ts | 13 + packages/g6/src/spec/theme/index.ts | 6 + packages/g6/src/spec/theme/io.ts | 13 + packages/g6/src/spec/viewport/index.ts | 66 ++ packages/g6/src/spec/viewport/io.ts | 13 + packages/g6/src/spec/widget/index.ts | 27 + packages/g6/src/spec/widget/io.ts | 13 + packages/g6/src/types/animate.ts | 42 +- packages/g6/src/types/behavior.ts | 5 +- packages/g6/src/types/callable.ts | 31 + packages/g6/src/types/common.ts | 2 +- packages/g6/src/types/edge.ts | 6 +- packages/g6/src/types/event.ts | 4 +- packages/g6/src/types/graph.ts | 789 +----------------- packages/g6/src/types/history.ts | 31 - packages/g6/src/types/index.ts | 5 +- packages/g6/src/types/layout.ts | 92 +- packages/g6/src/types/palette.ts | 43 + packages/g6/src/types/plugin.ts | 11 +- packages/g6/src/types/position.ts | 10 + packages/g6/src/types/spec.ts | 9 +- packages/g6/src/types/stdlib.ts | 25 - packages/g6/src/types/theme.ts | 8 +- packages/g6/src/utils/data.ts | 8 +- packages/g6/src/utils/event.ts | 4 +- packages/g6/src/utils/extend.ts | 48 -- packages/g6/src/utils/extension.ts | 39 +- packages/g6/src/utils/index.ts | 1 - packages/g6/src/utils/item.ts | 4 +- packages/g6/src/utils/shape.ts | 8 +- .../demo/behaviors/activate-relations.ts | 12 +- .../g6/tests/demo/behaviors/brush-select.ts | 17 +- .../g6/tests/demo/behaviors/create-edge.ts | 13 +- .../g6/tests/demo/behaviors/scroll-canvas.ts | 11 +- .../g6/tests/demo/behaviors/shortcuts-call.ts | 11 +- .../g6/tests/demo/behaviors/zoom-canvas.ts | 15 +- packages/g6/tests/demo/combo/combo-basic.ts | 11 +- packages/g6/tests/demo/combo/combo-rect.ts | 20 +- packages/g6/tests/demo/data/data-from-v4.ts | 24 +- .../tests/demo/data/process-parallel-edges.ts | 18 +- packages/g6/tests/demo/demo/demo.ts | 38 +- .../g6/tests/demo/demo/demoForPolyline.ts | 12 +- packages/g6/tests/demo/demo/diamond.ts | 11 +- packages/g6/tests/demo/demo/ellipse.ts | 12 +- packages/g6/tests/demo/demo/hexagon.ts | 12 +- packages/g6/tests/demo/demo/menu.ts | 12 +- packages/g6/tests/demo/demo/modelRect.ts | 11 +- packages/g6/tests/demo/demo/quadratic.ts | 11 +- packages/g6/tests/demo/demo/star.ts | 12 +- packages/g6/tests/demo/demo/tooltip.ts | 15 +- packages/g6/tests/demo/demo/triangle.ts | 9 +- packages/g6/tests/demo/index.ts | 18 - packages/g6/tests/demo/item/edge/arrow.ts | 10 +- .../g6/tests/demo/item/edge/cubic-edge.ts | 13 +- .../demo/item/edge/cubic-horizontal-edge.ts | 11 +- .../demo/item/edge/cubic-vertical-edge.ts | 11 +- packages/g6/tests/demo/item/edge/line-edge.ts | 4 +- packages/g6/tests/demo/item/edge/loop-edge.ts | 20 +- .../g6/tests/demo/item/edge/polyline-edge.ts | 16 +- packages/g6/tests/demo/item/label.ts | 8 +- packages/g6/tests/demo/item/node/cube.ts | 11 +- .../g6/tests/demo/item/node/donut-node.ts | 15 +- .../g6/tests/demo/layouts/combo-combined.ts | 12 +- packages/g6/tests/demo/layouts/custom.ts | 13 +- packages/g6/tests/demo/layouts/d3force.ts | 12 +- packages/g6/tests/demo/layouts/dagre-combo.ts | 11 +- .../g6/tests/demo/layouts/dagre-update.ts | 20 +- packages/g6/tests/demo/layouts/dagre.ts | 17 +- packages/g6/tests/demo/layouts/force-3d.ts | 12 +- .../g6/tests/demo/layouts/force-wasm-3d.ts | 22 +- packages/g6/tests/demo/layouts/force-wasm.ts | 14 +- .../g6/tests/demo/layouts/forceatlas2-wasm.ts | 14 +- .../g6/tests/demo/layouts/fruchterman-gpu.ts | 14 +- .../g6/tests/demo/layouts/fruchterman-wasm.ts | 13 +- packages/g6/tests/demo/performance/fps.ts | 14 +- .../g6/tests/demo/performance/layout-3d.ts | 22 +- .../g6/tests/demo/performance/performance.ts | 20 +- .../g6/tests/demo/plugins/edgeBundling.ts | 16 +- .../g6/tests/demo/plugins/edgeFilterLens.ts | 11 +- packages/g6/tests/demo/plugins/fisheye.ts | 14 +- .../g6/tests/demo/plugins/history-combo.ts | 167 ---- packages/g6/tests/demo/plugins/history.ts | 268 ------ packages/g6/tests/demo/plugins/legend.ts | 12 +- packages/g6/tests/demo/plugins/map.ts | 16 +- packages/g6/tests/demo/plugins/minimap.ts | 12 +- packages/g6/tests/demo/plugins/snapline.ts | 13 +- .../g6/tests/demo/plugins/timebar-chart.ts | 10 +- .../g6/tests/demo/plugins/timebar-time.ts | 10 +- packages/g6/tests/demo/plugins/toolbar.ts | 13 +- packages/g6/tests/demo/plugins/watermarker.ts | 11 +- packages/g6/tests/demo/visual/visual.ts | 19 +- .../integration/plugins-history-combo.spec.ts | 119 --- .../tests/integration/plugins-history.spec.ts | 146 ---- packages/g6/tests/unit/spec.spec.ts | 295 +++++++ packages/site/docs/apis/graph/Graph.en.md | 83 -- packages/site/docs/apis/graph/Graph.zh.md | 82 -- .../site/docs/apis/graph/Specification.en.md | 12 - .../docs/apis/plugins/HistoryConfig.en.md | 145 ---- .../docs/apis/plugins/HistoryConfig.zh.md | 145 ---- packages/site/docs/apis/plugins/TimeBar.en.md | 2 +- packages/site/docs/apis/plugins/TimeBar.zh.md | 2 +- .../site/docs/common/IPluginBaseConfig.en.md | 2 +- .../site/docs/common/IPluginBaseConfig.zh.md | 2 +- .../docs/common/PluginHistoryCommand.en.md | 13 - .../docs/common/PluginHistoryCommand.zh.md | 13 - packages/site/docs/common/StackCfg.en.md | 31 - packages/site/docs/common/StackCfg.zh.md | 31 - .../site/docs/manual/customize/overview.en.md | 1 - .../site/docs/manual/customize/overview.zh.md | 1 - packages/site/docs/manual/new-features.en.md | 4 +- packages/site/docs/manual/new-features.zh.md | 4 +- .../examples/tool/history/demo/history.ts | 180 ---- .../site/examples/tool/history/demo/meta.json | 11 +- .../site/examples/tool/history/index.en.md | 148 ---- .../site/examples/tool/history/index.zh.md | 4 - .../tool/toolbar/demo/self-toolbar.ts | 19 - 193 files changed, 2047 insertions(+), 4332 deletions(-) create mode 100644 packages/g6/src/plugin/register.ts delete mode 100644 packages/g6/src/plugin/widget/history/combo-command.ts delete mode 100644 packages/g6/src/plugin/widget/history/command.ts delete mode 100644 packages/g6/src/plugin/widget/history/index.ts delete mode 100644 packages/g6/src/plugin/widget/history/item-data-command.ts delete mode 100644 packages/g6/src/plugin/widget/history/layer-updated-command.ts delete mode 100644 packages/g6/src/plugin/widget/history/state-updated-command.ts delete mode 100644 packages/g6/src/plugin/widget/history/visibility-updated-command.ts create mode 100644 packages/g6/src/runtime/layered-canvas/types.ts create mode 100644 packages/g6/src/spec/canvas/index.ts create mode 100644 packages/g6/src/spec/canvas/io.ts create mode 100644 packages/g6/src/spec/data/index.ts create mode 100644 packages/g6/src/spec/data/io.ts create mode 100644 packages/g6/src/spec/element/combo/index.ts create mode 100644 packages/g6/src/spec/element/combo/io.ts create mode 100644 packages/g6/src/spec/element/edge/index.ts create mode 100644 packages/g6/src/spec/element/edge/io.ts create mode 100644 packages/g6/src/spec/element/index.ts create mode 100644 packages/g6/src/spec/element/node/index.ts create mode 100644 packages/g6/src/spec/element/types.ts create mode 100644 packages/g6/src/spec/index.ts create mode 100644 packages/g6/src/spec/layout/index.ts create mode 100644 packages/g6/src/spec/layout/io.ts create mode 100644 packages/g6/src/spec/mode/index.ts create mode 100644 packages/g6/src/spec/mode/io.ts create mode 100644 packages/g6/src/spec/optimize/index.ts create mode 100644 packages/g6/src/spec/optimize/io.ts create mode 100644 packages/g6/src/spec/theme/index.ts create mode 100644 packages/g6/src/spec/theme/io.ts create mode 100644 packages/g6/src/spec/viewport/index.ts create mode 100644 packages/g6/src/spec/viewport/io.ts create mode 100644 packages/g6/src/spec/widget/index.ts create mode 100644 packages/g6/src/spec/widget/io.ts create mode 100644 packages/g6/src/types/callable.ts delete mode 100644 packages/g6/src/types/history.ts create mode 100644 packages/g6/src/types/palette.ts create mode 100644 packages/g6/src/types/position.ts delete mode 100644 packages/g6/src/types/stdlib.ts delete mode 100644 packages/g6/src/utils/extend.ts delete mode 100644 packages/g6/tests/demo/plugins/history-combo.ts delete mode 100644 packages/g6/tests/demo/plugins/history.ts delete mode 100644 packages/g6/tests/integration/plugins-history-combo.spec.ts delete mode 100644 packages/g6/tests/integration/plugins-history.spec.ts create mode 100644 packages/g6/tests/unit/spec.spec.ts delete mode 100644 packages/site/docs/apis/plugins/HistoryConfig.en.md delete mode 100644 packages/site/docs/apis/plugins/HistoryConfig.zh.md delete mode 100644 packages/site/docs/common/PluginHistoryCommand.en.md delete mode 100644 packages/site/docs/common/PluginHistoryCommand.zh.md delete mode 100644 packages/site/docs/common/StackCfg.en.md delete mode 100644 packages/site/docs/common/StackCfg.zh.md delete mode 100644 packages/site/examples/tool/history/demo/history.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f86692486f..3f411e854c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,39 +24,13 @@ jobs: version: 8 run_install: false - - uses: actions/cache@v3 - name: Setup pnpm cache - id: cache - with: - path: | - node_modules/ - packages/g6/node_modules/ - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- - - name: Install Dependencies - if: steps.cache.outputs.cache-hit != 'true' run: pnpm install --no-frozen-lockfile - name: Run CI run: | - cd packages/g6 npm run ci - - name: Workflow failed alert - if: ${{ failure() }} - uses: actions-cool/maintain-one-comment@main - with: - token: ${{ secrets.GITHUB_TOKEN }} - body: | - 你好, @${{ github.event.pull_request.user.login }} CI 执行失败, 请点击 [Details] 按钮查看, 并根据日志修复 - - Hello, @${{ github.event.pull_request.user.login }} CI run failed, please click the [Details] button for detailed log information and fix it. - - emojis: 'eyes' - body-include: '' - - name: Upload blob report to GitHub Actions Artifacts if: always() uses: actions/upload-artifact@v3 diff --git a/package.json b/package.json index 8c0ede0125..439319de0e 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,9 @@ "build:g6": "cd ./packages/g6 && npm run build", "build:map-view": "cd ./packages/g6-plugin-map-view && npm run build", "build:react-node": "cd ./packages/react-node && npm run build", - "build:site": "cd ./packages/site && npm run build" + "build:site": "cd ./packages/site && npm run build", + "ci:g6": "cd ./packages/g6 && npm run ci", + "ci": "run-s ci:*" }, "commitlint": { "extends": [ diff --git a/packages/g6/src/constant/shape.ts b/packages/g6/src/constant/shape.ts index 3063cf072a..99ce27cb89 100644 --- a/packages/g6/src/constant/shape.ts +++ b/packages/g6/src/constant/shape.ts @@ -1,4 +1,4 @@ -import type { StandardPadding } from '../types/common'; +import type { STDPadding } from '../types/common'; import { ShapeStyle } from '../types/item'; export const RESERVED_SHAPE_IDS = [ @@ -13,7 +13,7 @@ export const RESERVED_SHAPE_IDS = [ ]; export const OTHER_SHAPES_FIELD_NAME = 'otherShapes'; -export const DEFAULT_LABEL_BG_PADDING: StandardPadding = [4, 4, 4, 4]; +export const DEFAULT_LABEL_BG_PADDING: STDPadding = [4, 4, 4, 4]; /** Default shape style to avoid shape value missing */ export const DEFAULT_SHAPE_STYLE = { opacity: 1, diff --git a/packages/g6/src/index.ts b/packages/g6/src/index.ts index 79ea22753b..e46a0d9c7a 100644 --- a/packages/g6/src/index.ts +++ b/packages/g6/src/index.ts @@ -1,11 +1,18 @@ import { runtime } from '@antv/g'; import { Extensions, stdLib } from './plugin'; -import { Graph as EmptyGraph } from './runtime/graph'; +import { getRegisterPlugin, getRegisterPlugins, register, unregister } from './plugin/register'; +import { Graph } from './runtime/graph'; import * as Util from './utils'; -import { extend } from './utils/extend'; export * from './types'; +export type { + /** + * @deprecated Please use `Graph` instead + */ + Graph as IGraph, +} from './types'; + /** * Disable CSS parsing for better performance. */ @@ -17,8 +24,16 @@ runtime.enableCSSParsing = false; const version = '5.0.0'; -const Graph = extend(EmptyGraph, stdLib); +export { Extensions, Graph, Util, getRegisterPlugin, getRegisterPlugins, register, stdLib, unregister, version }; -export { Extensions, Graph, Util, extend, stdLib, version }; - -export default { Graph, Util, stdLib, Extensions, extend, version }; +export default { + Graph, + Util, + stdLib, + Extensions, + version, + register, + unregister, + getRegisterPlugins, + getRegisterPlugin, +}; diff --git a/packages/g6/src/item/combo.ts b/packages/g6/src/item/combo.ts index 55e9ac8803..087e55a086 100644 --- a/packages/g6/src/item/combo.ts +++ b/packages/g6/src/item/combo.ts @@ -1,6 +1,6 @@ import { Group, Tuple3Number } from '@antv/g'; import { clone, throttle } from '@antv/util'; -import { ComboDisplayModel, ComboModel, IGraph } from '../types'; +import { ComboDisplayModel, ComboModel, Graph } from '../types'; import { ComboModelData, ComboUserModelData } from '../types/combo'; import { Point } from '../types/common'; import { DisplayMapper, LodLevelRanges, State } from '../types/item'; @@ -10,7 +10,7 @@ import Node from './node'; interface IProps { model: ComboModel; - graph: IGraph; + graph: Graph; renderExtensions: any; containerGroup: Group; labelContainerGroup: Group; diff --git a/packages/g6/src/item/edge.ts b/packages/g6/src/item/edge.ts index a45249b7a1..9bc103f661 100644 --- a/packages/g6/src/item/edge.ts +++ b/packages/g6/src/item/edge.ts @@ -1,6 +1,6 @@ import { Group } from '@antv/g'; import { clone, throttle } from '@antv/util'; -import { EdgeDisplayModel, EdgeModel, ID, IGraph, Point } from '../types'; +import { EdgeDisplayModel, EdgeModel, Graph, ID, Point } from '../types'; import { EdgeModelData } from '../types/edge'; import { DisplayMapper, LodLevelRanges, State } from '../types/item'; import { EdgeStyleSet } from '../types/theme'; @@ -13,7 +13,7 @@ import Item from './item'; import Node from './node'; interface IProps { - graph: IGraph; + graph: Graph; model: EdgeModel; renderExtensions: any; // TODO: type containerGroup: Group; diff --git a/packages/g6/src/item/item.ts b/packages/g6/src/item/item.ts index 6187c120f5..9a3e56b486 100644 --- a/packages/g6/src/item/item.ts +++ b/packages/g6/src/item/item.ts @@ -1,7 +1,7 @@ import { AABB, DisplayObject, Group, IAnimation } from '@antv/g'; import { isFunction, isObject, throttle } from '@antv/util'; import { OTHER_SHAPES_FIELD_NAME, RESERVED_SHAPE_IDS } from '../constant'; -import { IGraph } from '../types'; +import { Graph } from '../types'; import { AnimateTiming, IAnimates, IStateAnimate } from '../types/animate'; import { EdgeShapeMap } from '../types/edge'; import { @@ -26,7 +26,7 @@ import { isEncode } from '../utils/type'; import { formatLodLevels } from '../utils/zoom'; export default abstract class Item implements IItem { - public graph: IGraph; + public graph: Graph; public destroyed = false; /** Inner model. */ public model: ItemModel; diff --git a/packages/g6/src/item/node.ts b/packages/g6/src/item/node.ts index e543adb07f..fa3fe1314a 100644 --- a/packages/g6/src/item/node.ts +++ b/packages/g6/src/item/node.ts @@ -1,6 +1,6 @@ import { AABB, Group } from '@antv/g'; import { clone } from '@antv/util'; -import { ComboDisplayModel, ComboModel, ID, IGraph, NodeModel } from '../types'; +import { ComboDisplayModel, ComboModel, Graph, ID, NodeModel } from '../types'; import { ComboModelData } from '../types/combo'; import { Point } from '../types/common'; import { DisplayMapper, LodLevelRanges, State } from '../types/item'; @@ -17,7 +17,7 @@ import { updateShapes } from '../utils/shape'; import Item from './item'; interface IProps { - graph: IGraph; + graph: Graph; model: NodeModel | ComboModel; renderExtensions: any; containerGroup: Group; diff --git a/packages/g6/src/plugin/behavior/activate-relations.ts b/packages/g6/src/plugin/behavior/activate-relations.ts index 170395f98c..3538b70db3 100644 --- a/packages/g6/src/plugin/behavior/activate-relations.ts +++ b/packages/g6/src/plugin/behavior/activate-relations.ts @@ -106,24 +106,20 @@ export class ActivateRelations extends Behavior { const { active: activeNodeIds, inactive: inactiveNodeIds } = compare(this.prevNodeIds, nodeIds); const { active: activeEdgeIds, inactive: inactiveEdgeIds } = compare(this.prevEdgeIds, edgeIds); - graph.historyBatch(() => { - /** 节点 */ - graph.setItemState(activeNodeIds, ACTIVE_STATE, true); - graph.setItemState(inactiveNodeIds, ACTIVE_STATE, false); - /** 边 */ - graph.setItemState(activeEdgeIds, ACTIVE_STATE, true); - graph.setItemState(inactiveEdgeIds, ACTIVE_STATE, false); - }); + /** 节点 */ + graph.setItemState(activeNodeIds, ACTIVE_STATE, true); + graph.setItemState(inactiveNodeIds, ACTIVE_STATE, false); + /** 边 */ + graph.setItemState(activeEdgeIds, ACTIVE_STATE, true); + graph.setItemState(inactiveEdgeIds, ACTIVE_STATE, false); this.prevNodeIds = nodeIds; this.prevEdgeIds = edgeIds; } public clearActiveState(e: any) { const { activeState: ACTIVE_STATE } = this.options; - this.graph.historyBatch(() => { - this.graph.setItemState(this.prevNodeIds, ACTIVE_STATE, false); - this.graph.setItemState(this.prevEdgeIds, ACTIVE_STATE, false); - }); + this.graph.setItemState(this.prevNodeIds, ACTIVE_STATE, false); + this.graph.setItemState(this.prevEdgeIds, ACTIVE_STATE, false); this.prevNodeIds = []; this.prevEdgeIds = []; } diff --git a/packages/g6/src/plugin/behavior/click-select.ts b/packages/g6/src/plugin/behavior/click-select.ts index fcf7bc9332..5289fa4430 100644 --- a/packages/g6/src/plugin/behavior/click-select.ts +++ b/packages/g6/src/plugin/behavior/click-select.ts @@ -130,20 +130,18 @@ export class ClickSelect extends Behavior { // Select/Unselect item. if (this.options.shouldUpdate(event)) { - this.graph.historyBatch(() => { - if (!multiple) { - // Not multiple, clear all currently selected items - this.graph.setItemState(this.selectedIds, state, false); - this.selectedIds = []; + if (!multiple) { + // Not multiple, clear all currently selected items + this.graph.setItemState(this.selectedIds, state, false); + this.selectedIds = []; + } + if (isSelectAction) { + if (!this.selectedIds.includes(itemId)) { + this.graph.setItemState(itemId, state, true); } - if (isSelectAction) { - if (!this.selectedIds.includes(itemId)) { - this.graph.setItemState(itemId, state, true); - } - } else { - this.graph.setItemState(itemId, state, false); - } - }); + } else { + this.graph.setItemState(itemId, state, false); + } if (isSelectAction) { this.selectedIds.push(itemId); diff --git a/packages/g6/src/plugin/behavior/create-edge.ts b/packages/g6/src/plugin/behavior/create-edge.ts index 5b067f0f22..05622a3e91 100644 --- a/packages/g6/src/plugin/behavior/create-edge.ts +++ b/packages/g6/src/plugin/behavior/create-edge.ts @@ -243,11 +243,13 @@ export class CreateEdge extends Behavior { const sourceId = addingEdge.source, targetId = addingEdge.target; + // @ts-expect-error TODO: Need to fix the type if (!graph.getItemById(sourceId)) { this.addingEdge = null; return; } + // @ts-expect-error TODO: Need to fix the type graph.updatePosition('node', { id: targetId, data: { diff --git a/packages/g6/src/plugin/behavior/drag-canvas.ts b/packages/g6/src/plugin/behavior/drag-canvas.ts index e6f10b7c7d..dddc9aa694 100644 --- a/packages/g6/src/plugin/behavior/drag-canvas.ts +++ b/packages/g6/src/plugin/behavior/drag-canvas.ts @@ -159,11 +159,9 @@ export class DragCanvas extends Behavior { return; } const section = sections.shift(); - graph.executeWithNoStack(() => { - graph.hideItem(section, { - disableAnimate: false, - keepKeyShape: true, - }); + graph.hideItem(section, { + disableAnimate: false, + keepKeyShape: true, }); this.tileRequestId = requestAnimationFrame(update); }; @@ -296,9 +294,7 @@ export class DragCanvas extends Behavior { this.tileRequestId = undefined; return; } - graph.startHistoryBatch(); graph.showItem(sections.shift(), { disableAnimate: false }); - graph.stopHistoryBatch(); this.tileRequestId = requestAnimationFrame(update); }; this.tileRequestId = requestAnimationFrame(update); diff --git a/packages/g6/src/plugin/behavior/drag-combo.ts b/packages/g6/src/plugin/behavior/drag-combo.ts index 5165f91657..394f2b2772 100644 --- a/packages/g6/src/plugin/behavior/drag-combo.ts +++ b/packages/g6/src/plugin/behavior/drag-combo.ts @@ -233,16 +233,14 @@ export class DragCombo extends Behavior { if (this.options.hideRelatedEdges && !enableTransient) { this.hiddenComboTreeRoots = this.getComboTreeItems(selectedComboIds); this.hiddenEdges = this.getRelatedEdges(selectedComboIds, this.hiddenComboTreeRoots); - this.graph.executeWithNoStack(() => { - this.graph.hideItem( - this.hiddenEdges.map((edge) => edge.id), - { disableAnimate: true }, - ); - this.graph.hideItem( - this.hiddenComboTreeRoots.map((child) => child.id), - { disableAnimate: true }, - ); - }); + this.graph.hideItem( + this.hiddenEdges.map((edge) => edge.id), + { disableAnimate: true }, + ); + this.graph.hideItem( + this.hiddenComboTreeRoots.map((child) => child.id), + { disableAnimate: true }, + ); } // Draw transient nodes and edges. @@ -260,17 +258,15 @@ export class DragCombo extends Behavior { }); // Hide original edges and nodes. They will be restored when pointerup. - this.graph.executeWithNoStack(() => { - this.graph.hideItem(selectedComboIds, { disableAnimate: true }); - this.graph.hideItem( - this.hiddenEdges.map((edge) => edge.id), - { disableAnimate: true }, - ); - this.graph.hideItem( - this.hiddenComboTreeRoots.map((child) => child.id), - { disableAnimate: true }, - ); - }); + this.graph.hideItem(selectedComboIds, { disableAnimate: true }); + this.graph.hideItem( + this.hiddenEdges.map((edge) => edge.id), + { disableAnimate: true }, + ); + this.graph.hideItem( + this.hiddenComboTreeRoots.map((child) => child.id), + { disableAnimate: true }, + ); } else { this.graph.frontItem(selectedComboIds); } @@ -391,7 +387,6 @@ export class DragCombo extends Behavior { } public restoreHiddenItems(positions?: Position[]) { - this.graph.pauseStack(); if (this.hiddenEdges.length) { this.graph.showItem( this.hiddenEdges.map((edge) => edge.id), @@ -413,7 +408,6 @@ export class DragCombo extends Behavior { { disableAnimate: true }, ); } - this.graph.resumeStack(); } public onPointerUp(event: IG6GraphEvent) { @@ -513,7 +507,6 @@ export class DragCombo extends Behavior { public onDropCombo(event: IG6GraphEvent) { const newParentId = event.itemId; - this.graph.startHistoryBatch(); this.originPositions.forEach(({ id }) => { const model = this.graph.getComboData(id); if (!model || model.id === newParentId) return; @@ -522,12 +515,10 @@ export class DragCombo extends Behavior { // event.stopPropagation(); this.graph.updateData('combo', { id, data: { parentId: newParentId } }); }); - this.graph.stopHistoryBatch(); this.onPointerUp(event); } public onDropCanvas(event: IG6GraphEvent) { - this.graph.startHistoryBatch(); this.originPositions.forEach(({ id }) => { const model = this.graph.getComboData(id); if (!model) return; @@ -535,7 +526,6 @@ export class DragCombo extends Behavior { if (!parentId) return; this.graph.updateData('combo', { id, data: { parentId: undefined } }); }); - this.graph.stopHistoryBatch(); this.onPointerUp(event); } } diff --git a/packages/g6/src/plugin/behavior/drag-node.ts b/packages/g6/src/plugin/behavior/drag-node.ts index 8376d2a3b3..ccb5ca5768 100644 --- a/packages/g6/src/plugin/behavior/drag-node.ts +++ b/packages/g6/src/plugin/behavior/drag-node.ts @@ -264,33 +264,31 @@ export class DragNode extends Behavior { this.hiddenComboTreeItems = this.getComboTreeItems(this.selectedNodeIds); this.hiddenEdges = this.getRelatedEdges(this.selectedNodeIds, this.hiddenComboTreeItems); this.hiddenRelatedNodes = this.getRelatedNodes(this.selectedNodeIds); - this.graph.executeWithNoStack(() => { - const hiddenEdgeIds = this.hiddenEdges.map((edge) => edge.id); - hiddenEdgeIds.forEach((edgeId) => { - this.hiddenShapeCache.set(edgeId, this.graph.getItemVisibleShapeIds(edgeId)); - }); - this.graph.hideItem(hiddenEdgeIds, { - disableAnimate: true, - }); - const hiddenRelatedNodeIds = this.hiddenRelatedNodes.map((node) => node.id); - hiddenRelatedNodeIds.forEach((nodeId) => { - this.hiddenShapeCache.set(nodeId, this.graph.getItemVisibleShapeIds(nodeId)); - }); - this.graph.hideItem(hiddenRelatedNodeIds, { - disableAnimate: true, - keepRelated: true, - }); - const hiddenComboTreeItemIds = this.hiddenComboTreeItems.map((child) => child.id); - hiddenComboTreeItemIds.forEach((itemId) => { - this.hiddenShapeCache.set(itemId, this.graph.getItemVisibleShapeIds(itemId)); - }); - this.graph.hideItem( - this.hiddenComboTreeItems.map((child) => child.id), - { - disableAnimate: true, - }, - ); + const hiddenEdgeIds = this.hiddenEdges.map((edge) => edge.id); + hiddenEdgeIds.forEach((edgeId) => { + this.hiddenShapeCache.set(edgeId, this.graph.getItemVisibleShapeIds(edgeId)); }); + this.graph.hideItem(hiddenEdgeIds, { + disableAnimate: true, + }); + const hiddenRelatedNodeIds = this.hiddenRelatedNodes.map((node) => node.id); + hiddenRelatedNodeIds.forEach((nodeId) => { + this.hiddenShapeCache.set(nodeId, this.graph.getItemVisibleShapeIds(nodeId)); + }); + this.graph.hideItem(hiddenRelatedNodeIds, { + disableAnimate: true, + keepRelated: true, + }); + const hiddenComboTreeItemIds = this.hiddenComboTreeItems.map((child) => child.id); + hiddenComboTreeItemIds.forEach((itemId) => { + this.hiddenShapeCache.set(itemId, this.graph.getItemVisibleShapeIds(itemId)); + }); + this.graph.hideItem( + this.hiddenComboTreeItems.map((child) => child.id), + { + disableAnimate: true, + }, + ); } // Draw transient nodes and edges. @@ -311,34 +309,32 @@ export class DragNode extends Behavior { }); // Hide original edges and nodes. They will be restored when pointerup. - this.graph.executeWithNoStack(() => { - this.selectedNodeIds.forEach((itemId) => { - this.hiddenShapeCache.set(itemId, this.graph.getItemVisibleShapeIds(itemId)); - }); - this.graph.hideItem(this.selectedNodeIds, { disableAnimate: true }); - - const hiddenEdgeIds = this.hiddenEdges.map((edge) => edge.id); - hiddenEdgeIds.forEach((itemId) => { - this.hiddenShapeCache.set(itemId, this.graph.getItemVisibleShapeIds(itemId)); - }); - this.graph.hideItem(hiddenEdgeIds, { disableAnimate: true }); - const hiddenRelatedNodeIds = this.hiddenRelatedNodes.map((node) => node.id); - hiddenRelatedNodeIds.forEach((itemId) => { - this.hiddenShapeCache.set(itemId, this.graph.getItemVisibleShapeIds(itemId)); - }); - this.graph.hideItem(hiddenRelatedNodeIds, { - disableAnimate: true, - keepRelated: true, - }); - const hiddenComboTreeItemIds = this.hiddenComboTreeItems.map((combo) => combo.id); - hiddenComboTreeItemIds.forEach((itemId) => { - this.hiddenShapeCache.set(itemId, this.graph.getItemVisibleShapeIds(itemId)); - }); - this.graph.hideItem( - this.hiddenComboTreeItems.map((combo) => combo.id), - { disableAnimate: true }, - ); + this.selectedNodeIds.forEach((itemId) => { + this.hiddenShapeCache.set(itemId, this.graph.getItemVisibleShapeIds(itemId)); }); + this.graph.hideItem(this.selectedNodeIds, { disableAnimate: true }); + + const hiddenEdgeIds = this.hiddenEdges.map((edge) => edge.id); + hiddenEdgeIds.forEach((itemId) => { + this.hiddenShapeCache.set(itemId, this.graph.getItemVisibleShapeIds(itemId)); + }); + this.graph.hideItem(hiddenEdgeIds, { disableAnimate: true }); + const hiddenRelatedNodeIds = this.hiddenRelatedNodes.map((node) => node.id); + hiddenRelatedNodeIds.forEach((itemId) => { + this.hiddenShapeCache.set(itemId, this.graph.getItemVisibleShapeIds(itemId)); + }); + this.graph.hideItem(hiddenRelatedNodeIds, { + disableAnimate: true, + keepRelated: true, + }); + const hiddenComboTreeItemIds = this.hiddenComboTreeItems.map((combo) => combo.id); + hiddenComboTreeItemIds.forEach((itemId) => { + this.hiddenShapeCache.set(itemId, this.graph.getItemVisibleShapeIds(itemId)); + }); + this.graph.hideItem( + this.hiddenComboTreeItems.map((combo) => combo.id), + { disableAnimate: true }, + ); } else { this.graph.frontItem(this.selectedNodeIds); } @@ -501,7 +497,6 @@ export class DragNode extends Behavior { } public restoreHiddenItems(positions?: Position[]) { - this.graph.pauseStack(); if (this.hiddenEdges.length) { this.hiddenEdges.forEach((edge) => { this.graph.showItem(edge.id, { @@ -549,7 +544,6 @@ export class DragNode extends Behavior { this.hiddenShapeCache.delete(pos.id); }); } - this.graph.resumeStack(); } public clearState() { @@ -640,7 +634,6 @@ export class DragNode extends Behavior { // drop on a node A, move the dragged node to the same parent of A const newParentId = this.graph.getNodeData(dropId) ? this.graph.getNodeData(dropId).data.parentId : dropId; - this.graph.startHistoryBatch(); this.originPositions.forEach(({ id }) => { const model = this.graph.getNodeData(id); if (!model) return; @@ -653,13 +646,12 @@ export class DragNode extends Behavior { this.graph.updateData('node', { id, data: { parentId: newParentId } }); }); this.onPointerUp(event); - this.graph.stopHistoryBatch(); } public onDropCombo(event: IG6GraphEvent) { event.stopPropagation(); const newParentId = event.itemId; - this.graph.startHistoryBatch(); + this.onPointerUp(event); this.originPositions.forEach(({ id }) => { const model = this.graph.getNodeData(id); @@ -669,7 +661,6 @@ export class DragNode extends Behavior { this.graph.updateData('node', { id, data: { parentId: newParentId } }); }); this.clearState(); - this.graph.stopHistoryBatch(); } public async onDropCanvas(event: IG6GraphEvent) { @@ -682,7 +673,7 @@ export class DragNode extends Behavior { // the top item which is not in draggingIds const dropId = currentIds.find((id) => this.graph.getComboData(id) || this.graph.getNodeData(id)); const parentId = this.graph.getNodeData(dropId) ? this.graph.getNodeData(dropId).data.parentId : dropId; - this.graph.startHistoryBatch(); + this.onPointerUp(event); const nodeToUpdate = []; this.originPositions.forEach(({ id }) => { @@ -696,6 +687,5 @@ export class DragNode extends Behavior { }); if (nodeToUpdate.length) this.graph.updateData('node', nodeToUpdate); this.clearState(); - this.graph.stopHistoryBatch(); } } diff --git a/packages/g6/src/plugin/behavior/lasso-select.ts b/packages/g6/src/plugin/behavior/lasso-select.ts index 052d5baf6c..35f61ab6f0 100644 --- a/packages/g6/src/plugin/behavior/lasso-select.ts +++ b/packages/g6/src/plugin/behavior/lasso-select.ts @@ -1,6 +1,6 @@ import { DisplayObject } from '@antv/g'; import { ID } from '@antv/graphlib'; -import { IGraph } from '../../types'; +import { Graph } from '../../types'; import { Point } from '../../types/common'; import { IG6GraphEvent } from '../../types/event'; import lassoSelector from '../selector/lasso'; @@ -24,7 +24,7 @@ export class LassoSelect extends BrushSelect { points: Point[] = []; declare beginPoint: Point; declare mousedown: boolean; - declare graph: IGraph; + declare graph: Graph; public onMouseDown = (event: IG6GraphEvent) => { this.points = []; diff --git a/packages/g6/src/plugin/behavior/scroll-canvas.ts b/packages/g6/src/plugin/behavior/scroll-canvas.ts index 4be2fb0415..509fd456e0 100644 --- a/packages/g6/src/plugin/behavior/scroll-canvas.ts +++ b/packages/g6/src/plugin/behavior/scroll-canvas.ts @@ -250,9 +250,7 @@ export class ScrollCanvas extends Behavior { return; } const section = sections.shift(); - graph.startHistoryBatch(); graph.hideItem(section, { disableAnimate: false, keepKeyShape: true }); - graph.stopHistoryBatch(); requestId = requestAnimationFrame(update); }; requestId = requestAnimationFrame(update); @@ -294,9 +292,7 @@ export class ScrollCanvas extends Behavior { cancelAnimationFrame(requestId); return; } - graph.executeWithNoStack(() => { - graph.showItem(sections.shift(), { disableAnimate: false }); - }); + graph.showItem(sections.shift(), { disableAnimate: false }); requestId = requestAnimationFrame(update); }; requestId = requestAnimationFrame(update); diff --git a/packages/g6/src/plugin/behavior/zoom-canvas.ts b/packages/g6/src/plugin/behavior/zoom-canvas.ts index 9a4b75b673..33c4a38efb 100644 --- a/packages/g6/src/plugin/behavior/zoom-canvas.ts +++ b/packages/g6/src/plugin/behavior/zoom-canvas.ts @@ -170,9 +170,7 @@ export class ZoomCanvas extends Behavior { return; } const section = sections.shift(); - graph.startHistoryBatch(); graph.hideItem(section, { disableAnimate: false, keepKeyShape: true }); - graph.stopHistoryBatch(); this.tileRequestId = requestAnimationFrame(update); }; this.tileRequestId = requestAnimationFrame(update); @@ -202,9 +200,7 @@ export class ZoomCanvas extends Behavior { this.tileRequestId = undefined; return; } - graph.executeWithNoStack(() => { - graph.showItem(sections.shift(), { disableAnimate: false }); - }); + graph.showItem(sections.shift(), { disableAnimate: false }); this.tileRequestId = requestAnimationFrame(update); }; this.tileRequestId = requestAnimationFrame(update); @@ -276,7 +272,9 @@ export class ZoomCanvas extends Behavior { private clearCache() { this.zoomCache.fixIds.forEach((fixId) => { + // @ts-expect-error TODO: Need to fix the type const item = this.graph.itemController.itemMap.get(fixId); + // @ts-expect-error TODO: Need to fix the type item.displayModel.labelShapeVisible = undefined; }); this.zoomCache.fixIds.clear(); @@ -304,6 +302,7 @@ export class ZoomCanvas extends Behavior { if (!fixIds.length) return; this.zoomCache.fixIds = new Set([...fixIds]); fixIds.forEach((id) => { + // @ts-expect-error TODO: Need to fix the type const item = graph.itemController.itemMap.get(id); const balanceRatio = 1 / zoom || 1; @@ -314,6 +313,7 @@ export class ZoomCanvas extends Behavior { const balanceLabelShape = () => { item.updateLabelPosition(); + // @ts-expect-error TODO: Need to fix the type item.displayModel.labelShapeVisible = true; graph.showItem(id, { shapeIds: ['labelShape', 'labelBackgroundShape'], diff --git a/packages/g6/src/plugin/index.ts b/packages/g6/src/plugin/index.ts index a8ea710a0f..550c0c22dd 100644 --- a/packages/g6/src/plugin/index.ts +++ b/packages/g6/src/plugin/index.ts @@ -1,6 +1,5 @@ import Hierarchy from '@antv/hierarchy'; import * as Layouts from '@antv/layout'; -import { Lib } from '../types/stdlib'; import { Behavior as BaseBehavior } from '../types/behavior'; import { Plugin as BasePlugin } from '../types/plugin'; @@ -11,7 +10,7 @@ import * as Edges from './item/edge'; import * as Nodes from './item/node'; import * as Themes from './theme'; import * as ThemeSolvers from './theme-solver'; -import * as Plugins from './widget'; +import * as Widgets from './widget'; const { ValidateData, TransformV4Data, MapNodeSize, ProcessParallelEdges } = Transforms; @@ -61,8 +60,8 @@ const { ShortcutsCall, ScrollCanvas, } = Behaviors; + const { - History, Tooltip, Minimap, Grid, @@ -75,7 +74,7 @@ const { EdgeFilterLens, LodController, EdgeBundling, -} = Plugins; +} = Widgets; const { ForceLayout, @@ -97,7 +96,7 @@ import rectSelector from './selector/rect'; import Hull from './widget/hull'; import { WaterMarker } from './widget/watermarker'; -const stdLib = { +const builtInPlugins = { transforms: { 'validate-data': ValidateData, 'transform-v4-data': TransformV4Data, @@ -127,8 +126,7 @@ const stdLib = { 'collapse-expand-tree': CollapseExpandTree, 'click-select': ClickSelect, }, - plugins: { - history: History, + widgets: { 'lod-controller': LodController, }, nodes: { @@ -144,6 +142,9 @@ const stdLib = { 'circle-combo': CircleCombo, 'rect-combo': RectCombo, }, +}; + +const stdLib = { markers: { collapse: (x, y, r) => { return [ @@ -178,24 +179,11 @@ const stdLib = { }, }; -const useLib: Lib = { - transforms: {}, - themes: {}, - layouts: {}, - behaviors: {}, - plugins: {}, - nodes: {}, - edges: {}, - combos: {}, -}; - const utils = { rectSelector, lassoSelector, }; -const registry = { useLib }; - const Extensions = { // transforms ValidateData, @@ -290,5 +278,4 @@ const Extensions = { EdgeBundling, }; -export default registry; -export { Extensions, registry, stdLib, utils }; +export { Extensions, builtInPlugins, stdLib, utils }; diff --git a/packages/g6/src/plugin/item/edge/base.ts b/packages/g6/src/plugin/item/edge/base.ts index 4f6a288c01..154bc5684b 100644 --- a/packages/g6/src/plugin/item/edge/base.ts +++ b/packages/g6/src/plugin/item/edge/base.ts @@ -11,7 +11,7 @@ import { formatPadding, mergeStyles, upsertShape } from '../../../utils/shape'; import { getWordWrapWidthByEnds } from '../../../utils/text'; export abstract class BaseEdge { - type: string; + static type: string; defaultStyles: EdgeShapeStyles = {}; themeStyles: EdgeShapeStyles; mergedStyles: EdgeShapeStyles; diff --git a/packages/g6/src/plugin/item/node/base.ts b/packages/g6/src/plugin/item/node/base.ts index 7a090a3be4..68c86a4175 100644 --- a/packages/g6/src/plugin/item/node/base.ts +++ b/packages/g6/src/plugin/item/node/base.ts @@ -1,8 +1,8 @@ import { AABB, DisplayObject } from '@antv/g'; import { OTHER_SHAPES_FIELD_NAME, RESERVED_SHAPE_IDS } from '../../../constant'; +import type { Graph } from '../../../types'; import { NodeDisplayModel } from '../../../types'; import { ComboDisplayModel, ComboModelData, ComboShapeMap, ComboShapeStyles } from '../../../types/combo'; -import type { IGraph } from '../../../types/graph'; import { GShapeStyle, LodLevelRanges, SHAPE_TYPE, SHAPE_TYPE_3D, ShapeStyle, State } from '../../../types/item'; import { IAnchorPositionMap, NodeModelData, NodeShapeMap, NodeShapeStyles } from '../../../types/node'; import { formatPadding, getShapeLocalBoundsByStyle, mergeStyles, upsertShape } from '../../../utils/shape'; @@ -10,8 +10,8 @@ import { getWordWrapWidthByBox } from '../../../utils/text'; import { convertToNumber } from '../../../utils/type'; export abstract class BaseNode { - type: string; - graph: IGraph; + static type: string; + graph: Graph; defaultStyles: NodeShapeStyles | ComboShapeStyles; themeStyles: NodeShapeStyles | ComboShapeStyles; mergedStyles: NodeShapeStyles | ComboShapeStyles; diff --git a/packages/g6/src/plugin/item/node/base3d.ts b/packages/g6/src/plugin/item/node/base3d.ts index 66694c0342..cfc6b5256d 100644 --- a/packages/g6/src/plugin/item/node/base3d.ts +++ b/packages/g6/src/plugin/item/node/base3d.ts @@ -6,12 +6,13 @@ import { upsertShape3D } from '../../../utils/shape3d'; import { BaseNode } from './base'; export abstract class BaseNode3D extends BaseNode { - declare type: string; + declare static type: string; declare defaultStyles: NodeShapeStyles; declare themeStyles: NodeShapeStyles; declare mergedStyles: NodeShapeStyles; device: any; // for 3d renderer dimensions: number = 3; + constructor(props) { super(props); this.device = props.device; diff --git a/packages/g6/src/plugin/register.ts b/packages/g6/src/plugin/register.ts new file mode 100644 index 0000000000..52358ae972 --- /dev/null +++ b/packages/g6/src/plugin/register.ts @@ -0,0 +1,240 @@ +/** + * @file Overview registry of built-in plugins and user-defined plugins. + */ +import { builtInPlugins } from '../plugin'; +import type { BehaviorRegistry } from '../types/behavior'; +import type { EdgeRegistry } from '../types/edge'; +import type { LayoutRegistry } from '../types/layout'; +import type { NodeRegistry } from '../types/node'; +import type { PluginRegistry as WidgetRegistry } from '../types/plugin'; +import type { ThemeRegistry, ThemeSolverRegistry } from '../types/theme'; + +/** + * 转换对象类型 T 的复数 key 为其单数形式 + * Converts plural keys of an object type T to their singular form. + * @example -- `{ nodes: MyType }` becomes `{ node: MyType }` + */ +type SingularKeys = { + [K in keyof T as K extends `${infer R}s` ? R : never]: T[K]; +}; + +/** + * 将对象类型 T 中的 Record 类型的值转换为 U 类型 + * Converts the values of type Record in object type T to type U. + * @example - `{ key: { [key: string]: MyType } }` becomes `{ key: MyType }` + */ +type UnwrapRecordValues = { + [K in keyof T]: T[K] extends Record ? U : T[K]; +}; + +/** + * 用于将一个对象类型的 key 转换为其单数形式,并将对应的值类型转换为其子类型 + * Used to convert the key of an object type to its singular form, and convert the corresponding value type to its child type. + * @example { nodes: { [key: string] : typeof BaseNode }, ... } => { node: typeof BaseNode, ... } + */ +type Singular = UnwrapRecordValues>; + +type Plugins = { + nodes: NodeRegistry; + edges: EdgeRegistry; + combos: NodeRegistry; + layouts: LayoutRegistry; + widgets: WidgetRegistry; + behaviors: BehaviorRegistry; + themeSolvers: ThemeSolverRegistry; + themes: ThemeRegistry; + transforms: any; //TODO: 待数据处理移除后删除 +}; + +/** + * 插件类型映射 + * + * Plugin type mapping + */ +type STDPlugins = Singular; + +/** + * 插件类型,即复数形式,例如 nodes + * + * Plugin category, i.e. plural form, e.g. nodes. + */ +type PluginCategory = keyof Plugins; + +/** + * 标准插件类型,即单数形式,例如 node + * + * Standard plugin category, i.e. singular form, e.g. node. + */ +type STDPluginCategory = keyof STDPlugins; + +/** + * 插件条目,包含插件名称和插件类,例如 { name: 'node', plugin: BaseNode } + * + * Plugin entry, including plugin name and plugin class, e.g. { name: 'node', plugin: BaseNode } + */ +type PluginEntry = { + name: string; + plugin: STDPlugins[T]; +}; + +/** + * 转换后的插件集合,例如 { nodes: [{ name: 'node', plugin: BaseNode }] } + * + * Transformed plugin collection, e.g. { nodes: [{ name: 'node', plugin: BaseNode }] } + */ +type TransformedPlugins = { + [category: string]: PluginEntry[]; +}; + +const pluginCategoryList: PluginCategory[] = [ + 'nodes', + 'edges', + 'combos', + 'behaviors', + 'layouts', + 'widgets', + 'themes', + 'themeSolvers', + 'transforms', +]; + +class PluginRegistry { + private nodes: Map = new Map(); + + private edges: Map = new Map(); + + private combos: Map = new Map(); + + private layouts: Map = new Map(); + + private widgets: Map = new Map(); + + private behaviors: Map = new Map(); + + private themeSolvers: Map = new Map(); + + private themes: Map = new Map(); + + private transforms: Map = new Map(); //TODO: 待数据处理移除后删除 + + constructor() { + // Initialize the registry with built-in plugins. + this.registerBuiltInPlugins(); + } + + /** + * 注册内置插件 + * + * Register built-in plugins. + * @private + */ + private registerBuiltInPlugins() { + Object.keys(builtInPlugins).forEach((category) => { + Object.keys(builtInPlugins[category]).forEach((key) => { + this.register(category.slice(0, -1) as STDPluginCategory, key, builtInPlugins[category][key]); + }); + }); + } + + /** + * 根据 type 获取插件类型 + * + * Get the plugin category by type. + * @param type - 插件类型 | The plugin type. + * @returns - 插件类型 | The plugin category. + * @example getPluginCategory('node') => 'nodes' + * @private + */ + private getPluginCategory(type: T): PluginCategory { + return `${type}s` as PluginCategory; + } + + /** + * 注册插件 + * + * Register a plugin. + * @param type 插件类型 | The type of the plugin. + * @param key 插件的唯一标识 | The unique identifier of the plugin. + * @param pluginClass 插件类 | The plugin class. + * @public + */ + public register( + type: T, + key: string, + pluginClass: STDPlugins[T] & { type: string }, + ): void { + const category = this.getPluginCategory(type); + if (this[category].has(key)) { + console.warn(`Plugin with key '${key}' is already registered for type '${category}'.`); + } else { + pluginClass.type = key; + this[category].set(key, pluginClass); + } + } + + /** + * 获取已注册的插件集合 + * + * Get registered plugins. + * @returns - 已注册的插件 | The registered plugins. + * @public + */ + public getRegisterPlugins(): TransformedPlugins { + const transformedPlugins: TransformedPlugins = {}; + for (const category of pluginCategoryList) { + if (this[category] instanceof Map) { + transformedPlugins[category] = Array.from(this[category].entries()).map(([key, plugin]) => ({ + name: key, + plugin: plugin, + })); + } + } + + return transformedPlugins; + } + + /** + * 获取指定插件 + * + * Get a specific plugin. + * @param type - 插件类型 | The type of the plugin to retrieve. + * @param key - 插件的唯一标识 | The key of the specific plugin to retrieve. + * @returns - 已注册的插件 | The registered plugin. + * @public + */ + public getRegisterPlugin(type: T, key: string): PluginEntry { + const category = this.getPluginCategory(type); + return { + name: key, + plugin: this[category].get(key) as STDPlugins[T], + }; + } + + /** + * 注销插件 + * + * Unregister a plugin. + * @param type - 插件类型 | The type of the plugin to unregister. + * @param key - 插件的唯一标识 | The key of the plugin to unregister. + * @public + */ + public unregister(type: T, key: string): void { + const category = this.getPluginCategory(type); + if (this[category].has(key)) { + this[category].delete(key); + } else { + console.warn(`No plugin with key '${key}' found to unregister for type '${type}'.`); + } + } +} + +const pluginRegistry = new PluginRegistry(); + +const register = pluginRegistry.register.bind(pluginRegistry); +const getRegisterPlugin = pluginRegistry.getRegisterPlugin.bind(pluginRegistry); +const getRegisterPlugins = pluginRegistry.getRegisterPlugins.bind(pluginRegistry); +const unregister = pluginRegistry.unregister.bind(pluginRegistry); + +export { getRegisterPlugin, getRegisterPlugins, register, unregister }; + +export type { PluginEntry, STDPluginCategory }; diff --git a/packages/g6/src/plugin/selector/lasso.ts b/packages/g6/src/plugin/selector/lasso.ts index 90e6257ab5..b94567e9bb 100644 --- a/packages/g6/src/plugin/selector/lasso.ts +++ b/packages/g6/src/plugin/selector/lasso.ts @@ -1,5 +1,5 @@ import { ID } from '@antv/graphlib'; -import { IGraph } from '../../types'; +import { Graph } from '../../types'; import { Point } from '../../types/common'; import { ITEM_TYPE } from '../../types/item'; import { getEdgesBetween } from '../../utils/item'; @@ -14,7 +14,7 @@ import { isPolygonsIntersect } from '../../utils/shape'; * @param points * @param itemTypes */ -export default (graph: IGraph, points: Point[], itemTypes: ITEM_TYPE[]) => { +export default (graph: Graph, points: Point[], itemTypes: ITEM_TYPE[]) => { const lassoContour = points.map((point) => [point.x, point.y]); const selectedNodeIds = []; let selectedEdgeIds = []; @@ -52,7 +52,7 @@ export default (graph: IGraph, points: Point[], itemTypes: ITEM_TYPE[]) => { combos: selectedComboIds, }; }; -const isItemIntersectPolygon = (graph: IGraph, id: ID, polyPoints: number[][]) => { +const isItemIntersectPolygon = (graph: Graph, id: ID, polyPoints: number[][]) => { // TODO // const shape = item.getKeyShape(); // if (item.get('type') === 'path') { diff --git a/packages/g6/src/plugin/selector/rect.ts b/packages/g6/src/plugin/selector/rect.ts index 11891a644f..fea5e7df5c 100644 --- a/packages/g6/src/plugin/selector/rect.ts +++ b/packages/g6/src/plugin/selector/rect.ts @@ -1,5 +1,5 @@ import { ID } from '@antv/graphlib'; -import { IGraph } from '../../types'; +import { Graph } from '../../types'; import { Point } from '../../types/common'; import { ITEM_TYPE } from '../../types/item'; import { getEdgesBetween } from '../../utils/item'; @@ -13,7 +13,7 @@ import { getEdgesBetween } from '../../utils/item'; * @param points * @param itemTypes */ -export default (graph: IGraph, points: Point[], itemTypes: ITEM_TYPE[]) => { +export default (graph: Graph, points: Point[], itemTypes: ITEM_TYPE[]) => { const [p1, p2] = points; const left = Math.min(p1.x, p2.x); const right = Math.max(p1.x, p2.x); @@ -59,7 +59,7 @@ export default (graph: IGraph, points: Point[], itemTypes: ITEM_TYPE[]) => { }; }; -const isBBoxCenterInRect = (graph: IGraph, id: ID, left: number, right: number, top: number, bottom: number) => { +const isBBoxCenterInRect = (graph: Graph, id: ID, left: number, right: number, top: number, bottom: number) => { const bbox = graph.getRenderBBox(id); if (!bbox) return false; return bbox.center[0] >= left && bbox.center[0] <= right && bbox.center[1] >= top && bbox.center[1] <= bottom; diff --git a/packages/g6/src/plugin/theme-solver/base.ts b/packages/g6/src/plugin/theme-solver/base.ts index 50a2812920..8aa3e6b83a 100644 --- a/packages/g6/src/plugin/theme-solver/base.ts +++ b/packages/g6/src/plugin/theme-solver/base.ts @@ -5,6 +5,7 @@ export interface ThemeSpecificationMap { [themeName: string]: ThemeSpecification; } export abstract class BaseThemeSolver { + static type: string; protected specification: ThemeSpecification; protected options: ThemeSolverOptions; constructor(options: ThemeSolverOptions, themes: ThemeSpecificationMap) { diff --git a/packages/g6/src/plugin/widget/edge-bundling/index.ts b/packages/g6/src/plugin/widget/edge-bundling/index.ts index c48a36e860..839d409cb8 100644 --- a/packages/g6/src/plugin/widget/edge-bundling/index.ts +++ b/packages/g6/src/plugin/widget/edge-bundling/index.ts @@ -1,4 +1,4 @@ -import { GraphData, IGraph, NodeModel } from 'types'; +import { Graph, GraphData, NodeModel } from 'types'; import { EdgeModel, IEdge } from 'types/edge'; import { Point } from '../../../types/common'; @@ -110,7 +110,7 @@ export class EdgeBundling extends Base { }; } - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); } diff --git a/packages/g6/src/plugin/widget/edge-filter-lens/index.ts b/packages/g6/src/plugin/widget/edge-filter-lens/index.ts index 1ef7d0637a..1b2c4694bc 100644 --- a/packages/g6/src/plugin/widget/edge-filter-lens/index.ts +++ b/packages/g6/src/plugin/widget/edge-filter-lens/index.ts @@ -1,5 +1,5 @@ import { DisplayObject } from '@antv/g'; -import { IGraph } from '../../../types'; +import { Graph } from '../../../types'; import { IG6GraphEvent } from '../../../types/event'; import { ShapeStyle } from '../../../types/item'; import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; @@ -84,7 +84,7 @@ export class EdgeFilterLens extends Base { return events; } - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); const showLabel = this.options.showLabel; const showNodeLabel = showLabel === 'node' || showLabel === 'both'; diff --git a/packages/g6/src/plugin/widget/fisheye/index.ts b/packages/g6/src/plugin/widget/fisheye/index.ts index 25c634f45b..f23e672610 100644 --- a/packages/g6/src/plugin/widget/fisheye/index.ts +++ b/packages/g6/src/plugin/widget/fisheye/index.ts @@ -1,6 +1,6 @@ import { DisplayObject } from '@antv/g'; import { throttle, uniqueId } from '@antv/util'; -import { IGraph } from '../../../types'; +import { Graph } from '../../../types'; import { Point } from '../../../types/common'; import { IG6GraphEvent } from '../../../types/event'; import { ShapeStyle } from '../../../types/item'; @@ -133,7 +133,7 @@ export class Fisheye extends Base { } } - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); const { r, d } = this.options; this.cachedTransientTexts = {}; diff --git a/packages/g6/src/plugin/widget/grid/index.ts b/packages/g6/src/plugin/widget/grid/index.ts index 58c404d765..b0c9f9ad72 100644 --- a/packages/g6/src/plugin/widget/grid/index.ts +++ b/packages/g6/src/plugin/widget/grid/index.ts @@ -1,7 +1,7 @@ // TODO: update type define. import { Canvas } from '@antv/g'; import { uniqueId } from '@antv/util'; -import { IGraph } from '../../../types'; +import { Graph } from '../../../types'; import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; import { createDOM, modifyCSS } from '../../../utils/dom'; @@ -39,7 +39,7 @@ export class Grid extends Base { }; } - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); const minZoom = graph.getZoom(); const graphContainer = graph.container; diff --git a/packages/g6/src/plugin/widget/history/combo-command.ts b/packages/g6/src/plugin/widget/history/combo-command.ts deleted file mode 100644 index 33b49e9dde..0000000000 --- a/packages/g6/src/plugin/widget/history/combo-command.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { ID, IGraph } from '../../../types'; -import { Command } from './command'; - -export class ComboCommand implements Command { - private action: 'expandCombo' | 'collapseCombo'; - private ids: ID[]; - - constructor(action, ids) { - this.action = action; - this.ids = ids; - } - - undo(graph: IGraph) { - graph.executeWithNoStack(() => { - this.action === 'expandCombo' ? graph.collapseCombo(this.ids) : graph.expandCombo(this.ids); - }); - } - - redo(graph: IGraph) { - graph.executeWithNoStack(() => { - this.action === 'collapseCombo' ? graph.collapseCombo(this.ids) : graph.expandCombo(this.ids); - }); - } -} diff --git a/packages/g6/src/plugin/widget/history/command.ts b/packages/g6/src/plugin/widget/history/command.ts deleted file mode 100644 index 2fbe6bd54f..0000000000 --- a/packages/g6/src/plugin/widget/history/command.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { groupBy } from '@antv/util'; -import { ID, IGraph } from '../../../types'; -import type { ITEM_TYPE } from '../../../types/item'; -import { ComboCommand } from './combo-command'; -import { ItemDataCommand } from './item-data-command'; -import { LayerUpdatedCommand } from './layer-updated-command'; -import { StateUpdatedCommand } from './state-updated-command'; -import { VisibilityUpdatedCommand } from './visibility-updated-command'; - -export interface Command { - redo: (graph: IGraph) => void; - undo: (graph: IGraph) => void; -} -interface CreateProps { - type: ITEM_TYPE; - ids: ID[]; - changes: any; - action?: 'updatePosition' | 'updateState' | 'updateVisibility' | 'front' | 'back' | 'expandCombo' | 'collapseCombo'; - upsertAncestors?: boolean; - disableAnimate?: boolean; -} - -export default class CommandFactory { - static create({ type: itemType, action, changes, ...rest }: CreateProps): Command[] { - const commands = []; - - const groupedByType = groupBy(changes, 'type'); - - for (const type in groupedByType) { - const itemDataCommandMap = { - NodeDataUpdated: 'node', - EdgeDataUpdated: 'edge', - NodeAdded: 'node', - EdgeAdded: 'edge', - NodeRemoved: 'node', - EdgeRemoved: 'edge', - TreeStructureChanged: 'combo', - }; - if (itemDataCommandMap[type]) { - commands.push( - new ItemDataCommand( - action, - itemType || itemDataCommandMap[type], - groupedByType[type], - type === 'NodeDataUpdated' ? rest.upsertAncestors : undefined, - ), - ); - } - } - - const actionCommandMap = { - updateState: new StateUpdatedCommand(changes), - updateVisibility: new VisibilityUpdatedCommand(changes, rest.disableAnimate), - front: new LayerUpdatedCommand('front', rest.ids), - back: new LayerUpdatedCommand('back', rest.ids), - expandCombo: new ComboCommand('expandCombo', rest.ids), - collapseCombo: new ComboCommand('collapseCombo', rest.ids), - }; - - if (actionCommandMap[action]) { - commands.push(actionCommandMap[action]); - } - - return commands; - } -} diff --git a/packages/g6/src/plugin/widget/history/index.ts b/packages/g6/src/plugin/widget/history/index.ts deleted file mode 100644 index 21825dd666..0000000000 --- a/packages/g6/src/plugin/widget/history/index.ts +++ /dev/null @@ -1,333 +0,0 @@ -import { deepMix, each, isEmpty, upperFirst } from '@antv/util'; -import type { IGraph } from 'types'; -import { STACK_TYPE, StackCfg, StackType } from '../../../types/history'; -import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; -import CommandFactory, { Command } from './command'; - -/** - * The `HistoryConfig` interface contains the following properties: - * - * - `enableStack`: An optional boolean value that indicates whether to enable the stack. - * - `stackCfg`: A required object of type `StackCfg` representing the stack configuration. - * - * The `StackCfg` type is defined as an object with the following properties: - * - * - `stackSize`: An optional number representing the size of the stack. - * - `stackActive`: An optional boolean value indicating whether the stack is active. If active, operations can be pushed onto the stack; otherwise, they cannot. - * - `excludes`: An optional array of strings representing APIs that should be excluded from being put on the stack, even if their operation type is not ignored. - * - `includes`: An optional array of strings representing APIs that should be included in being put on the stack. - * - `ignoreAdd`: An optional boolean value indicating whether to ignore add operations. - * - `ignoreRemove`: An optional boolean value indicating whether to ignore remove operations. - * - `ignoreUpdate`: An optional boolean value indicating whether to ignore update operations. - * - `ignoreStateChange`: An optional boolean value indicating whether to ignore state change operations. - * - `ignoreLayerChange`: An optional boolean value indicating whether to ignore layer change operations. - * - `ignoreDisplayChange`: An optional boolean value indicating whether to ignore display change operations. - * - */ -export interface HistoryConfig extends IPluginBaseConfig { - enableStack?: boolean; - stackCfg: StackCfg; -} - -const apiMap = { - add: ['addData', 'addCombo'], - remove: ['removeData'], - update: [ - 'updateData', - 'updateNodePosition', - 'updateComboPosition', - 'updatePosition', - 'moveCombo', - 'collapseCombo', - 'expandCombo', - ], - stateChange: ['setItemState', 'clearItemState'], - layerChange: ['frontItem', 'backItem'], - displayChange: ['showItem', 'hideItem'], -}; - -/** - * Retrieve the category of a given API based on its name. - * @param apiName name of API - */ -export const getCategoryByApiName = (apiName): keyof typeof apiName => { - for (const [categoryKey, apiList] of Object.entries(apiMap)) { - if (apiList.includes(apiName)) { - return categoryKey as keyof typeof apiName; - } - } - throw new Error(`Unknown apiName: ${apiName}. Unable to determine category.`); -}; - -class HistoryStack { - private items: T[]; - private maxStep: number; - - constructor(maxStep = 0) { - this.items = []; - this.maxStep = maxStep; - } - - public push(item: T): void { - if (this.maxStep !== 0 && this.items.length === this.maxStep) { - this.items.shift(); - } - this.items.push(item); - } - - public pop(): T { - if (this.items.length !== 0) { - return this.items.pop(); - } - throw new Error('Stack is empty'); - } - - public size(): number { - return this.items.length; - } - - public clear(): void { - this.items = []; - } - - public toArray(): T[] { - return this.items; - } -} - -export class History extends Base { - public readonly cfg: StackCfg; - public readonly enableStack: boolean; - protected undoStack: HistoryStack; - protected redoStack: HistoryStack; - protected stackSize = 0; - protected stackActive = true; - protected withoutStackingCounter = 0; - protected isBatching: boolean; - protected batchCommands: Command[]; - - constructor(options?: HistoryConfig) { - super(); - const { enableStack, stackCfg } = deepMix(this.getDefaultCfgs(), options); - this.enableStack = enableStack; - this.cfg = stackCfg; - this.isBatching = false; - this.undoStack = new HistoryStack(this.cfg.stackSize); - this.redoStack = new HistoryStack(this.cfg.stackSize); - this.initBatchCommands(); - } - - public getDefaultCfgs(): HistoryConfig { - return { - enableStack: true, - stackCfg: { - stackSize: 0, - stackActive: true, - includes: [], - excludes: [], - ignoreAdd: false, - ignoreRemove: false, - ignoreUpdate: false, - ignoreStateChange: false, - ignoreLayerChange: false, - ignoreDisplayChange: false, - }, - }; - } - - public init(graph: IGraph) { - super.init(graph); - this.clear(); - } - - public getUndoStack(): Command[][] { - return this.undoStack.toArray(); - } - - public getRedoStack(): Command[][] { - return this.redoStack.toArray(); - } - - public getStack(): Record { - return { - redoStack: this.getRedoStack(), - undoStack: this.getUndoStack(), - }; - } - - public clear() { - this.clearUndoStack(); - this.clearRedoStack(); - } - - public clearUndoStack() { - this.undoStack.clear(); - } - - public clearRedoStack() { - this.redoStack.clear(); - } - - public isEnable() { - return this.enableStack; - } - - public push(cmd: Command[], stackType: StackType = STACK_TYPE.undo, isNew = true) { - if (this.stackActive) { - if (stackType === STACK_TYPE.undo) { - if (isNew) { - // Clear the redo stack when a new action is performed to maintain state consistency - this.clearRedoStack(); - } - if (isEmpty(cmd)) return; - this.undoStack.push(cmd); - this.initBatchCommands(); - } else { - this.redoStack.push(cmd); - } - this.graph.emit('history:change', cmd, stackType, isNew); - } else { - console.error('Stacking operations are currently paused. Unable to push to the stack.'); - } - } - - /** - * Pause stacking operations. - */ - pauseStack(): void { - this.withoutStackingCounter++; - - if (this.withoutStackingCounter === 1) { - // Only disable on the first call - this.stackActive = false; - } - } - - /** - * Resume stacking operations. - */ - resumeStack(): void { - if (this.withoutStackingCounter > 0) { - this.withoutStackingCounter--; - } - - if (this.withoutStackingCounter === 0) { - // Only enable when all pause requests are cleared - this.stackActive = true; - } - } - - public undo() { - if (this.isEnable()) { - const cmds = this.undoStack.pop(); - if (cmds) { - this.push(cmds, STACK_TYPE.redo, false); - for (let i = cmds.length - 1; i >= 0; i--) { - cmds[i].undo(this.graph); - } - } - } - return this; - } - - public redo() { - if (this.isEnable()) { - const cmds = this.redoStack.pop(); - if (cmds) { - this.push(cmds, STACK_TYPE.undo, false); - each(cmds, (cmd) => cmd.redo(this.graph)); - } - } - return this; - } - - public canUndo() { - return this.isEnable() && this.undoStack.size() > 0; - } - - public canRedo() { - return this.isEnable() && this.redoStack.size() > 0; - } - - private initBatchCommands() { - this.batchCommands = []; - } - - /** - * Begin a historyBatch operation. - * Any operations performed between `startHistoryBatch` and `stopHistoryBatch` are grouped together. - * treated as a single operation when undoing or redoing. - */ - public startHistoryBatch() { - if (this.isBatching) { - throw new Error('Ensure that historyBatch processing is stopped before starting.'); - } - this.initBatchCommands(); - this.isBatching = true; - } - - /** - * End a historyBatch operation. - * Any operations performed between `startHistoryBatch` and `stopHistoryBatch` are grouped together. - * treated as a single operation when undoing or redoing. - */ - public stopHistoryBatch() { - if (!this.isBatching) { - throw new Error('Ensure that historyBatch processing is started before stopping.'); - } - this.push(this.batchCommands); - this.isBatching = false; - } - - /** - * Execute the provided function in a historyBatch mode - * @param callback - */ - public historyBatch(callback) { - this.startHistoryBatch(); - callback(); - this.stopHistoryBatch(); - } - - public getEvents() { - return { - afteritemchange: this.handleUpdateHistory, - afteritemzindexchange: this.handleUpdateHistory, - afteritemstatechange: this.handleUpdateHistory, - afteritemvisibilitychange: this.handleUpdateHistory, - aftercollapsecombo: this.handleUpdateHistory, - afterexpandcombo: this.handleUpdateHistory, - }; - } - - private handleUpdateHistory(props) { - const { apiName, changes } = props; - if (changes && changes.length === 0) return; - if (this.shouldPushToStack(apiName)) { - this.batchCommands = [...this.batchCommands, ...CommandFactory.create(props)]; - if (this.isBatching) { - return; - } - this.push(this.batchCommands); - } - } - - /** - * Determine if a given operation should be pushed onto the history stack based on various configurations. - * @param apiName name of the API operation. - */ - private shouldPushToStack(apiName: string): boolean { - const { includes = [], excludes = [] } = this.cfg; - if (!this.enableStack || !this.stackActive) return false; - if (includes.includes(apiName)) return true; - if (excludes.includes(apiName)) return false; - let categoryKey: any = getCategoryByApiName(apiName); - if (!categoryKey) return true; - categoryKey = 'ignore' + upperFirst(categoryKey); - return !this.cfg[categoryKey]; - } - - public notify(graph, eventName, ...data) { - graph.emit(eventName, data); - } -} diff --git a/packages/g6/src/plugin/widget/history/item-data-command.ts b/packages/g6/src/plugin/widget/history/item-data-command.ts deleted file mode 100644 index c1d15d9679..0000000000 --- a/packages/g6/src/plugin/widget/history/item-data-command.ts +++ /dev/null @@ -1,101 +0,0 @@ -import type { IGraph } from '../../../types'; -import { STACK_TYPE, type StackType } from '../../../types/history'; -import type { ITEM_TYPE } from '../../../types/item'; -import type { GroupedChanges } from '../../../utils/event'; -import { Command } from './command'; - -export class ItemDataCommand implements Command { - private action: 'add' | 'remove' | 'update' | 'updatePosition'; - private type: ITEM_TYPE; - private changes: GroupedChanges[ - | 'NodeAdded' - | 'EdgeAdded' - | 'NodeRemoved' - | 'EdgeRemoved' - | 'NodeDataUpdated' - | 'EdgeDataUpdated' - | 'TreeStructureChanged']; - private upsertAncestors?: boolean; - - constructor(action, type, changes, upsertAncestors?) { - this.action = action; - this.type = type; - this.changes = changes; - this.upsertAncestors = upsertAncestors; - } - - private removeChangedData(graph) { - const ids = this.changes.map((data) => data.value?.id).filter(Boolean); - graph.executeWithNoStack(() => { - graph.removeData(this.type, ids); - }); - } - - private addChangedData(graph) { - const models = this.changes.map((data) => data.value).filter(Boolean); - graph.executeWithNoStack(() => { - graph.addData(this.type, models); - }); - } - - private updateChangedData(graph: IGraph, operationType: StackType, onlyMove = false) { - const modelMap = new Map(); - if (this.type === 'combo' && !onlyMove) { - this.changes.forEach((data) => { - const model = modelMap.get(data.nodeId) || {}; - modelMap.set(data.nodeId, { - id: data.nodeId, - data: { - ...model.data, - parentId: STACK_TYPE.undo ? data.oldParentId : data.newParentId, - }, - }); - }); - } else { - this.changes.forEach((data) => { - const value = operationType === STACK_TYPE.undo ? data.oldValue : data.newValue; - if ( - (typeof value === 'number' && isNaN(value)) || - (['x', 'y'].includes(data.propertyName) && value === undefined) - ) { - return; - } - - const model = modelMap.get(data.nodeId) || {}; - modelMap.set(data.id, { - id: data.id, - data: { - ...model.data, - [data.propertyName]: value, - }, - }); - }); - } - - graph.pauseStack(); - const models = Array.from(modelMap.values()); - if (onlyMove) { - // No matter it is node or combo, update the nodes' positions - graph.updateNodePosition(models, this.upsertAncestors); - } else { - graph.updateData(this.type, models); - } - graph.resumeStack(); - } - - undo(graph: IGraph) { - this.action === 'add' && this.removeChangedData(graph); - this.action === 'remove' && this.addChangedData(graph); - this.action === 'update' && this.updateChangedData(graph, STACK_TYPE.undo); - this.action === 'updatePosition' && - this.updateChangedData(graph, STACK_TYPE.undo, this.action === 'updatePosition'); - } - - redo(graph: IGraph) { - this.action === 'remove' && this.removeChangedData(graph); - this.action === 'add' && this.addChangedData(graph); - this.action === 'update' && this.updateChangedData(graph, STACK_TYPE.redo); - this.action === 'updatePosition' && - this.updateChangedData(graph, STACK_TYPE.redo, this.action === 'updatePosition'); - } -} diff --git a/packages/g6/src/plugin/widget/history/layer-updated-command.ts b/packages/g6/src/plugin/widget/history/layer-updated-command.ts deleted file mode 100644 index 9e1cec93a5..0000000000 --- a/packages/g6/src/plugin/widget/history/layer-updated-command.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { ID, IGraph } from '../../../types'; -import { Command } from './command'; - -export class LayerUpdatedCommand implements Command { - private action: 'front' | 'back'; - private ids: ID[]; - - constructor(action, ids) { - this.action = action; - this.ids = ids; - } - - undo(graph: IGraph) { - graph.executeWithNoStack(() => { - this.action === 'front' ? graph.backItem(this.ids) : graph.frontItem(this.ids); - }); - } - - redo(graph: IGraph) { - graph.executeWithNoStack(() => { - this.action === 'front' ? graph.frontItem(this.ids) : graph.backItem(this.ids); - }); - } -} diff --git a/packages/g6/src/plugin/widget/history/state-updated-command.ts b/packages/g6/src/plugin/widget/history/state-updated-command.ts deleted file mode 100644 index c35f5ce402..0000000000 --- a/packages/g6/src/plugin/widget/history/state-updated-command.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { ID, IGraph } from '../../../types'; -import { Command } from './command'; - -interface StateOption { - ids: ID | ID[]; - states: string; - value: boolean; -} - -export class StateUpdatedCommand implements Command { - private changes: { - newValue: StateOption[]; - oldValue: StateOption[]; - }; - - constructor(props) { - this.changes = props; - } - - private updateItemsStates(graph, stateOptions) { - stateOptions?.map((option) => { - const { ids, states, value } = option; - graph.executeWithNoStack(() => { - graph.setItemState(ids, states, value); - }); - }); - } - - undo(graph: IGraph) { - this.updateItemsStates(graph, this.changes.oldValue); - } - - redo(graph: IGraph) { - this.updateItemsStates(graph, this.changes.newValue); - } -} diff --git a/packages/g6/src/plugin/widget/history/visibility-updated-command.ts b/packages/g6/src/plugin/widget/history/visibility-updated-command.ts deleted file mode 100644 index 13d67f72ce..0000000000 --- a/packages/g6/src/plugin/widget/history/visibility-updated-command.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { each } from '@antv/util'; -import type { ID, IGraph } from '../../../types'; -import { Command } from './command'; - -interface Option { - ids: ID[]; - visible: boolean; -} - -export class VisibilityUpdatedCommand implements Command { - private changes: { - newValue: Option[]; - oldValue: Option[]; - }; - private disableAnimate?: boolean; - - constructor(changes, disableAnimate) { - this.changes = changes; - this.disableAnimate = disableAnimate; - } - - private toggleItemsVisible(graph: IGraph, values) { - graph.pauseStack(); - each(values, (value) => - value.visible - ? graph.showItem(value.ids, { disableAnimate: this.disableAnimate }) - : graph.hideItem(value.ids, { disableAnimate: this.disableAnimate }), - ); - graph.resumeStack(); - } - - undo(graph: IGraph) { - const { oldValue } = this.changes; - this.toggleItemsVisible(graph, oldValue); - } - - redo(graph: IGraph) { - const { newValue } = this.changes; - this.toggleItemsVisible(graph, newValue); - } -} diff --git a/packages/g6/src/plugin/widget/hull/bubbleset.ts b/packages/g6/src/plugin/widget/hull/bubbleset.ts index 3e828b1342..0cec1da06c 100644 --- a/packages/g6/src/plugin/widget/hull/bubbleset.ts +++ b/packages/g6/src/plugin/widget/hull/bubbleset.ts @@ -1,5 +1,5 @@ import { AABB } from '@antv/g'; -import { ComboModel, IGraph, NodeModel } from '../../../types'; +import { ComboModel, Graph, NodeModel } from '../../../types'; import { Bounds, Point } from '../../../types/common'; import { isPointInPolygon } from '../../../utils/shape'; import { BubblesetCfg } from './types'; @@ -177,7 +177,7 @@ const initGridCells = (width: number, height: number, pixelGroupSize: number) => * @param nonMembers */ const pickBestNeighbor = ( - graph: IGraph, + graph: Graph, model: NodeModel | ComboModel, visited: (NodeModel | ComboModel)[], nonMembers: (NodeModel | ComboModel)[], @@ -214,7 +214,7 @@ const pickBestNeighbor = ( * @param line */ const getIntersectItem = ( - graph: IGraph, + graph: Graph, items: (NodeModel | ComboModel)[], line: LineStructure, ): NodeModel | ComboModel | null => { @@ -241,7 +241,7 @@ const getIntersectItem = ( * @param morphBuffer */ const computeRoute = ( - graph: IGraph, + graph: Graph, directLine: LineStructure, nonMembers: (NodeModel | ComboModel)[], maxRoutingIterations: number, @@ -264,7 +264,7 @@ const computeRoute = ( }); return flag; }; - const isPointInNonMembers = (graph: IGraph, point: Point, _nonMembers: (NodeModel | ComboModel)[]) => { + const isPointInNonMembers = (graph: Graph, point: Point, _nonMembers: (NodeModel | ComboModel)[]) => { for (const model of _nonMembers) { const bbox = graph.getRenderBBox(model.id); if (!bbox) continue; @@ -350,7 +350,7 @@ const computeRoute = ( * @param morphBuffer */ function getRoute( - graph: IGraph, + graph: Graph, currentModel: NodeModel | ComboModel, nonMembers: (NodeModel | ComboModel)[], visited: (NodeModel | ComboModel)[], @@ -403,7 +403,7 @@ function getRoute( * @param ops */ export const genBubbleSet = ( - graph: IGraph, + graph: Graph, members: (NodeModel | ComboModel)[], nonMembers: (NodeModel | ComboModel)[], ops?: BubblesetCfg, @@ -508,7 +508,7 @@ export const genBubbleSet = ( * @param offset */ function getActiveRegion( - graph: IGraph, + graph: Graph, members: (NodeModel | ComboModel)[], edges: LineStructure[], offset: number, @@ -552,7 +552,7 @@ function getActiveRegion( * @param options */ function fillPotentialArea( - graph: IGraph, + graph: Graph, members: (NodeModel | ComboModel)[], nonMembers: (NodeModel | ComboModel)[], edges: LineStructure[], @@ -590,7 +590,7 @@ function fillPotentialArea( const endY = Math.min(pos2GridIx(bbox.max[1], -thresholdR + activeRegion.min[1]), potentialArea.height); return [startX, startY, endX, endY]; }; - const addItemInfluence = (graph: IGraph, model: NodeModel | ComboModel, influenceFactor: number) => { + const addItemInfluence = (graph: Graph, model: NodeModel | ComboModel, influenceFactor: number) => { const bbox = graph.getRenderBBox(model.id); if (!bbox) return; const [startX, startY, endX, endY] = getAffectedRegion(bbox, options.nodeR1); diff --git a/packages/g6/src/plugin/widget/hull/hullComponent.ts b/packages/g6/src/plugin/widget/hull/hullComponent.ts index e7c981dc8c..048039a0b8 100644 --- a/packages/g6/src/plugin/widget/hull/hullComponent.ts +++ b/packages/g6/src/plugin/widget/hull/hullComponent.ts @@ -1,6 +1,6 @@ import { DisplayObject } from '@antv/g'; import { isArray } from '@antv/util'; -import { ComboModel, ID, IGraph, NodeModel } from '../../../types'; +import { ComboModel, Graph, ID, NodeModel } from '../../../types'; import { ShapeStyle } from '../../../types/item'; import { pathToPoints } from '../../../utils/path'; import { isPolygonsIntersect } from '../../../utils/shape'; @@ -48,7 +48,7 @@ interface HullComponentFullOptions extends HullComponentOptions { * 通By configuring padding, you can adjust the tightness of the wrapping contour to the node. */ export default class Hull { - graph: IGraph; + graph: Graph; // TODO: PathArray is not exported by @antv/util 2.x but by 3.x. Correct the type String | PathArray after upgrading @antv/util path: any; @@ -67,7 +67,7 @@ export default class Hull { options: HullComponentFullOptions; - constructor(graph: IGraph, options: HullComponentFullOptions) { + constructor(graph: Graph, options: HullComponentFullOptions) { const { members: memberIds = [], nonMembers: nonMemberIds = [] } = options; this.options = options; this.graph = graph; @@ -459,6 +459,7 @@ export default class Hull { ]; // } shapePoints = shapePoints.map((canvasPoint) => { + // @ts-expect-error TODO: Need to fix the type const point = this.graph.getPointByCanvas(canvasPoint[0], canvasPoint[1]); return [point.x, point.y]; }); diff --git a/packages/g6/src/plugin/widget/hull/index.ts b/packages/g6/src/plugin/widget/hull/index.ts index fa5feee634..720f7c3e0f 100644 --- a/packages/g6/src/plugin/widget/hull/index.ts +++ b/packages/g6/src/plugin/widget/hull/index.ts @@ -1,6 +1,6 @@ import { isArray, throttle, uniqueId } from '@antv/util'; import { DEFAULT_TEXT_STYLE } from '../../../constant'; -import { ComboModel, EdgeModel, ID, IGraph, NodeModel } from '../../../types'; +import { ComboModel, EdgeModel, Graph, ID, NodeModel } from '../../../types'; import { ComboLabelPosition } from '../../../types/combo'; import { ITEM_TYPE, ShapeStyle } from '../../../types/item'; import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; @@ -56,7 +56,7 @@ export default class Hull extends Base { }; } - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); } diff --git a/packages/g6/src/plugin/widget/hull/util.ts b/packages/g6/src/plugin/widget/hull/util.ts index b2fb8738b3..21a127c8f4 100644 --- a/packages/g6/src/plugin/widget/hull/util.ts +++ b/packages/g6/src/plugin/widget/hull/util.ts @@ -1,6 +1,6 @@ import { AABB } from '@antv/g'; import { vec2 } from 'gl-matrix'; -import { ID, IGraph } from 'types'; +import { Graph, ID } from 'types'; import { Bounds, Point } from '../../../types/common'; import { getLineIntersect } from '../../../utils/shape'; @@ -273,7 +273,7 @@ export const squareDist = (a: Point, b: Point): number => { return (a.x - b.x) ** 2 + (a.y - b.y) ** 2; }; -export const fractionToLine = (graph: IGraph, itemId: ID, line: LineStructure) => { +export const fractionToLine = (graph: Graph, itemId: ID, line: LineStructure) => { const directions = ['top', 'left', 'bottom', 'right']; const bbox = graph.getRenderBBox(itemId); if (!bbox) return Infinity; @@ -326,7 +326,7 @@ export const isPointsOverlap = (p1, p2, e = 1e-3) => { return (p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2 < e ** 2; }; -export const itemIntersectByLine = (graph: IGraph, itemId: ID, line: LineStructure): [Point[], number] => { +export const itemIntersectByLine = (graph: Graph, itemId: ID, line: LineStructure): [Point[], number] => { const directions = ['top', 'left', 'bottom', 'right']; const bbox = graph.getRenderBBox(itemId); if (!bbox) return; diff --git a/packages/g6/src/plugin/widget/index.ts b/packages/g6/src/plugin/widget/index.ts index 7d45ab4c00..cb8e251757 100644 --- a/packages/g6/src/plugin/widget/index.ts +++ b/packages/g6/src/plugin/widget/index.ts @@ -2,7 +2,6 @@ export * from './edge-bundling'; export * from './edge-filter-lens'; export * from './fisheye'; export * from './grid'; -export * from './history'; export * from './legend'; export * from './lod-controller'; export * from './menu'; diff --git a/packages/g6/src/plugin/widget/legend/index.ts b/packages/g6/src/plugin/widget/legend/index.ts index e6109e1930..098867ae7a 100644 --- a/packages/g6/src/plugin/widget/legend/index.ts +++ b/packages/g6/src/plugin/widget/legend/index.ts @@ -2,7 +2,7 @@ import { Canvas, Circle, DisplayObject, Line } from '@antv/g'; import { ID } from '@antv/graphlib'; import { Category } from '@antv/gui'; import { isFunction, isString, uniqueId, upperFirst } from '@antv/util'; -import { IGraph } from '../../../types'; +import { Graph } from '../../../types'; import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; import { RendererName } from '../../../types/render'; import { createCanvas } from '../../../utils/canvas'; @@ -153,7 +153,7 @@ export class Legend extends Base { }; } - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); const { size = 'fit-content', orientation } = this.options; const graphSize = graph.getSize(); diff --git a/packages/g6/src/plugin/widget/lod-controller/index.ts b/packages/g6/src/plugin/widget/lod-controller/index.ts index 09f9c36f91..b854ed9721 100644 --- a/packages/g6/src/plugin/widget/lod-controller/index.ts +++ b/packages/g6/src/plugin/widget/lod-controller/index.ts @@ -5,8 +5,8 @@ import { ComboModel, EdgeDisplayModel, EdgeModel, + Graph, ID, - IGraph, NodeDisplayModel, NodeModel, } from '../../../types'; @@ -60,7 +60,7 @@ export class LodController extends Base { }; } - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); } @@ -102,6 +102,7 @@ export class LodController extends Base { * @param params */ protected updateCells = (params?: GraphTransformOptions) => { + // @ts-expect-error TODO: Need to fix the type if (!this.graph.canvasReady) return; const { zoom } = params || {}; if (params) { @@ -208,6 +209,7 @@ export class LodController extends Base { if (!disableLod && invisibleShapeIds.length) { graph.hideItem(id, { shapeIds: invisibleShapeIds, disableAnimate }); } + // @ts-expect-error TODO: Need to fix the type const item = graph.itemController.itemMap.get(id); if ( disableLod || @@ -269,6 +271,7 @@ export class LodController extends Base { // 1 && (2 || 3) inView.forEach((model) => { this.labelPositionDirty.set(model.id, true); + // @ts-expect-error TODO: Need to fix the type const item = graph.itemController.itemMap.get(model.id); if ( !item || @@ -548,6 +551,7 @@ export class LodController extends Base { private getDisplayModel = (id) => { let displayModel = this.displayModelCache.get(id); if (!displayModel) { + // @ts-expect-error TODO: Need to fix the type displayModel = this.graph.getDisplayModel(id); this.displayModelCache.set(id, displayModel); } diff --git a/packages/g6/src/plugin/widget/menu/index.ts b/packages/g6/src/plugin/widget/menu/index.ts index e865e140da..10ff8725f7 100644 --- a/packages/g6/src/plugin/widget/menu/index.ts +++ b/packages/g6/src/plugin/widget/menu/index.ts @@ -1,7 +1,7 @@ import { isString, uniqueId } from '@antv/util'; import insertCss from 'insert-css'; import Item from '../../../item/item'; -import { IGraph } from '../../../types'; +import { Graph } from '../../../types'; import { IG6GraphEvent } from '../../../types/event'; import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; import { createDOM, modifyCSS } from '../../../utils/dom'; @@ -111,7 +111,7 @@ export class Menu extends Base { : { contextmenu: this.onMenuShow }; } - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); const className = this.options.className; insertCss(` diff --git a/packages/g6/src/plugin/widget/minimap/index.ts b/packages/g6/src/plugin/widget/minimap/index.ts index db43b1aa27..ea4cde2b82 100644 --- a/packages/g6/src/plugin/widget/minimap/index.ts +++ b/packages/g6/src/plugin/widget/minimap/index.ts @@ -2,7 +2,7 @@ // @ts-nocheck import { Canvas, DisplayObject, Group, Rect } from '@antv/g'; import { debounce, each, isNil, isString, uniqueId } from '@antv/util'; -import { IGraph } from '../../../types'; +import { Graph } from '../../../types'; import { IG6GraphEvent } from '../../../types/event'; import { ShapeStyle } from '../../../types/item'; import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; @@ -599,7 +599,7 @@ export class Minimap extends Base { false, ); - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); const promise = this.initContainer(); promise.then(() => this.updateCanvas()); diff --git a/packages/g6/src/plugin/widget/snapline/index.ts b/packages/g6/src/plugin/widget/snapline/index.ts index d6875ea80c..c1d6e75e80 100644 --- a/packages/g6/src/plugin/widget/snapline/index.ts +++ b/packages/g6/src/plugin/widget/snapline/index.ts @@ -1,7 +1,7 @@ import { AABB, DisplayObject } from '@antv/g'; import { ID } from '@antv/graphlib'; import { throttle } from '@antv/util'; -import { IG6GraphEvent, IGraph, NodeModel } from '../../../types'; +import { Graph, IG6GraphEvent, NodeModel } from '../../../types'; import { Point } from '../../../types/common'; import { ITEM_TYPE, ShapeStyle } from '../../../types/item'; import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; @@ -705,7 +705,7 @@ export class Snapline extends Base { } } - getGraph(event: IG6GraphEvent): IGraph { + getGraph(event: IG6GraphEvent): Graph { return event.currentTarget; } diff --git a/packages/g6/src/plugin/widget/timebar/index.ts b/packages/g6/src/plugin/widget/timebar/index.ts index 675977aa4c..3cff8e4b36 100644 --- a/packages/g6/src/plugin/widget/timebar/index.ts +++ b/packages/g6/src/plugin/widget/timebar/index.ts @@ -3,7 +3,7 @@ import type { TimebarStyleProps } from '@antv/gui'; import { Timebar as GUITimebar } from '@antv/gui'; import { deepMix } from '@antv/util'; import type { EdgeModel, NodeModel } from '../../../types'; -import { GraphData, IGraph } from '../../../types'; +import { Graph, GraphData } from '../../../types'; import type { Padding } from '../../../types/common'; import type { ITEM_TYPE } from '../../../types/item'; import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; @@ -95,7 +95,7 @@ export interface TimebarConfig * manage graph manually when timebar range/value change * @description if it is not specified, the graph will be filtered by default */ - filter?: (graph: IGraph, values: Parameters) => void; + filter?: (graph: Graph, values: Parameters) => void; axisStyle?: SubStyleProps; chartStyle?: SubStyleProps; controllerStyle?: SubStyleProps; @@ -175,7 +175,7 @@ export class Timebar extends Base { }; } - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); } diff --git a/packages/g6/src/plugin/widget/toolbar/index.ts b/packages/g6/src/plugin/widget/toolbar/index.ts index 3d34cc53c1..7b40da43ff 100644 --- a/packages/g6/src/plugin/widget/toolbar/index.ts +++ b/packages/g6/src/plugin/widget/toolbar/index.ts @@ -1,21 +1,21 @@ import insertCss from 'insert-css'; -import { IGraph } from '../../../types'; +import { Graph } from '../../../types'; import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; import { createDOM, modifyCSS } from '../../../utils/dom'; /** * The `ToolbarConfig` interface contains the following properties: - * - `handleClick`: An optional function for handling clicks on the toolbar. It takes two arguments: `code` (of type string) and `graph` (of type IGraph), and has no return value. - * - `getContent`: A required function for getting the content of the toolbar. It takes an optional argument of type `IGraph`, and returns a value of type HTMLElement or string. + * - `handleClick`: An optional function for handling clicks on the toolbar. It takes two arguments: `code` (of type string) and `graph`, and has no return value. + * - `getContent`: A required function for getting the content of the toolbar. It takes an optional argument of type `Graph`, and returns a value of type HTMLElement or string. * - `zoomSensitivity`: An optional number representing the zoom sensitivity of the toolbar. The default value is 10. * - `minZoom`: An optional number representing the minimum zoom ratio of the toolbar. The default value is 0.00001. * - `maxZoom`: An optional number representing the maximum zoom ratio of the toolbar. The default value is 1000. */ export interface ToolbarConfig extends IPluginBaseConfig { /** Function for handling clicks on toolbar */ - handleClick?: (code: string, graph: IGraph) => void; + handleClick?: (code: string, graph: Graph) => void; /** Function for getting content of toolbar */ - getContent: (graph?: IGraph) => HTMLElement | string; + getContent: (graph?: Graph) => HTMLElement | string; /** Zoom sensitivity of toolbar */ zoomSensitivity: number; /** Minimum zoom ratio of toolbar */ @@ -97,7 +97,7 @@ export class Toolbar extends Base { } return this.containerDOM; } - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); this.getContainer(); this.insertStyle(); diff --git a/packages/g6/src/plugin/widget/tooltip/index.ts b/packages/g6/src/plugin/widget/tooltip/index.ts index 4511bf03e8..a42fd885e6 100644 --- a/packages/g6/src/plugin/widget/tooltip/index.ts +++ b/packages/g6/src/plugin/widget/tooltip/index.ts @@ -2,7 +2,7 @@ import { AABB } from '@antv/g'; import { isArray, isString, uniqueId } from '@antv/util'; import insertCss from 'insert-css'; -import { IGraph } from '../../../types'; +import { Graph } from '../../../types'; import { IG6GraphEvent } from '../../../types/event'; import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; import { createDOM, modifyCSS } from '../../../utils/dom'; @@ -146,7 +146,7 @@ export class Tooltip extends Base { }; } - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); const className = this.options.className; const tooltip = createDOM(`
`); @@ -295,7 +295,7 @@ export class Tooltip extends Base { }); return; } - const graph: IGraph = this.graph; + const graph: Graph = this.graph; const width: number = graph.getSize()[0]; const height: number = graph.getSize()[1]; const offsetX = this.options.offsetX || 0; diff --git a/packages/g6/src/plugin/widget/types.ts b/packages/g6/src/plugin/widget/types.ts index fcb8e984c3..219d4c75d5 100644 --- a/packages/g6/src/plugin/widget/types.ts +++ b/packages/g6/src/plugin/widget/types.ts @@ -1,7 +1,6 @@ export type { EdgeFilterLens } from './edge-filter-lens'; export type { FisheyeConfig } from './fisheye'; export type { GridConfig } from './grid'; -export type { HistoryConfig } from './history'; export type { LegendConfig } from './legend'; export type { MenuConfig } from './menu'; export type { MiniMapConfig } from './minimap'; diff --git a/packages/g6/src/plugin/widget/watermarker/index.ts b/packages/g6/src/plugin/widget/watermarker/index.ts index 923277bee7..46bc95b7f1 100644 --- a/packages/g6/src/plugin/widget/watermarker/index.ts +++ b/packages/g6/src/plugin/widget/watermarker/index.ts @@ -1,6 +1,6 @@ import { Canvas, Group, Image, Text, TextStyleProps } from '@antv/g'; import { isString, uniqueId } from '@antv/util'; -import { IGraph } from '../../../types'; +import { Graph } from '../../../types'; import { Plugin as Base, IPluginBaseConfig } from '../../../types/plugin'; import { createCanvas } from '../../../utils/canvas'; @@ -86,7 +86,7 @@ export class WaterMarker extends Base { * Initialize the WaterMarker plugin. * @param graph */ - public init(graph: IGraph) { + public init(graph: Graph) { super.init(graph); const promise = this.initCanvas(); promise.then(() => { diff --git a/packages/g6/src/runtime/controller/data.ts b/packages/g6/src/runtime/controller/data.ts index 38a2c86065..45410ebe4b 100644 --- a/packages/g6/src/runtime/controller/data.ts +++ b/packages/g6/src/runtime/controller/data.ts @@ -4,8 +4,7 @@ import { clone, isArray, isEmpty, isObject } from '@antv/util'; import Combo from '../../item/combo'; import Edge from '../../item/edge'; import Node from '../../item/node'; -import { registry } from '../../plugin'; -import { ComboModel, ComboUserModel, GraphData, IGraph } from '../../types'; +import { ComboModel, ComboUserModel, Graph, GraphData } from '../../types'; import { ComboUserModelData } from '../../types/combo'; import { DataChangeType, @@ -40,7 +39,7 @@ import { EdgeCollisionChecker, QuadTree } from '../../utils/polyline'; * Storages user data and inner data. */ export class DataController { - public graph: IGraph; + public graph: Graph; public extensions = []; /** * Inner data stored in graphCore structure. @@ -57,7 +56,7 @@ export class DataController { */ private dataType: 'treeData' | 'graphData' | 'fetch'; - constructor(graph: IGraph) { + constructor(graph: Graph) { this.graph = graph; this.tap(); } @@ -197,7 +196,7 @@ export class DataController { return [...transforms, ...requiredTransformers] .map((config) => ({ config, - func: getExtension(config, registry.useLib, 'transform'), + func: getExtension(config, 'transform'), })) .filter((ext) => !!ext.func); } diff --git a/packages/g6/src/runtime/controller/interaction.ts b/packages/g6/src/runtime/controller/interaction.ts index 3d2470c4c4..5764aae3aa 100644 --- a/packages/g6/src/runtime/controller/interaction.ts +++ b/packages/g6/src/runtime/controller/interaction.ts @@ -1,6 +1,5 @@ import { FederatedPointerEvent, IElement } from '@antv/g'; -import { registry } from '../../plugin'; -import { IGraph } from '../../types'; +import { Graph } from '../../types'; import { Behavior } from '../../types/behavior'; import { CANVAS_EVENT_TYPE, DOM_EVENT_TYPE, IG6GraphEvent } from '../../types/event'; import { ItemInfo, getContextMenuEventProps, getItemInfoFromElement } from '../../utils/event'; @@ -31,7 +30,7 @@ const wrapListener = (type: string, eventName: string, listener: Listener): List * Storage related data. */ export class InteractionController { - private graph: IGraph; + private graph: Graph; private mode: string; /** @@ -52,7 +51,7 @@ export class InteractionController { private prevItemInfo: ItemInfo; - constructor(graph: IGraph) { + constructor(graph: Graph) { this.graph = graph; this.initEvents(); this.tap(); @@ -82,8 +81,9 @@ export class InteractionController { } try { // Get behavior extensions from useLib. - const BehaviorClass = getExtension(config, registry.useLib, 'behavior'); + const BehaviorClass = getExtension(config, 'behavior'); const options = typeof config === 'string' ? {} : config; + // @ts-ignore const behavior = new BehaviorClass(options); behavior.graph = this.graph; if (behavior) { diff --git a/packages/g6/src/runtime/controller/item.ts b/packages/g6/src/runtime/controller/item.ts index c36a0f5fe0..8a2542438c 100644 --- a/packages/g6/src/runtime/controller/item.ts +++ b/packages/g6/src/runtime/controller/item.ts @@ -5,12 +5,9 @@ import { debounce, isArray, isNumber, isObject, uniq, uniqueId } from '@antv/uti import Combo from '../../item/combo'; import Edge from '../../item/edge'; import Node from '../../item/node'; -import registry from '../../plugin'; -import { BaseEdge } from '../../plugin/item/edge/base'; -import { BaseNode } from '../../plugin/item/node/base'; import { ComboModel, - IGraph, + Graph, NodeDisplayModel, NodeEncode, NodeModel, @@ -19,9 +16,17 @@ import { } from '../../types'; import { ComboDisplayModel, ComboEncode, ComboShapesEncode } from '../../types/combo'; import { GraphCore } from '../../types/data'; -import { EdgeDisplayModel, EdgeEncode, EdgeModel, EdgeModelData, EdgeShapesEncode } from '../../types/edge'; +import { + EdgeDisplayModel, + EdgeEncode, + EdgeModel, + EdgeModelData, + EdgeRegistry, + EdgeShapesEncode, +} from '../../types/edge'; import { ViewportChangeHookParams } from '../../types/hook'; import { DisplayMapper, ITEM_TYPE, LodLevelRanges, SHAPE_TYPE, ShapeStyle } from '../../types/item'; +import { NodeRegistry } from '../../types/node'; import { ComboStyleSet, ComboThemeSpecifications, @@ -41,7 +46,7 @@ import { traverseGraphAncestors, } from '../../utils/data'; import { getGroupedChanges } from '../../utils/event'; -import { getExtension } from '../../utils/extension'; +import { getExtensionsByCategory } from '../../utils/extension'; import { upsertTransientItem } from '../../utils/item'; import { isPointPreventPolylineOverlap, isPolylineWithObstacleAvoidance } from '../../utils/polyline'; import { getCombinedBoundsByData, intersectBBox, upsertShape } from '../../utils/shape'; @@ -80,10 +85,10 @@ const getWarnMsg = { * Manages and stores the node / edge / combo items. */ export class ItemController { - public graph: IGraph; - public nodeExtensions: BaseNode[] = []; - public edgeExtensions: BaseEdge[] = []; - public comboExtensions: BaseNode[] = []; + public graph: Graph; + public nodeExtensions: NodeRegistry[string][] = []; + public edgeExtensions: EdgeRegistry[string][] = []; + public comboExtensions: NodeRegistry[string][] = []; public zoom: number; @@ -138,7 +143,7 @@ export class ItemController { private cacheWarnMsg = {}; - constructor(graph: IGraph) { + constructor(graph: Graph) { this.graph = graph; // get mapper for node / edge / combo const { node, edge, combo, nodeState = {}, edgeState = {}, comboState = {} } = graph.getSpecification(); @@ -157,10 +162,9 @@ export class ItemController { */ private tap() { // item extensions are node / edge / combo type registrations - const extensions = this.getExtensions(); - this.nodeExtensions = extensions.node; - this.edgeExtensions = extensions.edge; - this.comboExtensions = extensions.combo; + this.nodeExtensions = getExtensionsByCategory('node'); + this.edgeExtensions = getExtensionsByCategory('edge'); + this.comboExtensions = getExtensionsByCategory('combo'); this.graph.hooks.render.tap(this.onRender.bind(this)); this.graph.hooks.itemchange.tap(this.onChange.bind(this)); this.graph.hooks.itemstatechange.tap(this.onItemStateChange.bind(this)); @@ -175,23 +179,6 @@ export class ItemController { this.graph.hooks.destroy.tap(this.onDestroy.bind(this)); } - /** - * Get the extensions from useLib, stdLib is a subset of useLib. - */ - private getExtensions() { - // TODO: user need to config using node/edge/combo types from useLib to spec? - const { node, edge, combo } = this.graph.getSpecification(); - - const nodeTypes = Object.keys(registry.useLib.nodes || {}); - const edgeTypes = Object.keys(registry.useLib.edges || {}); - const comboTypes = Object.keys(registry.useLib.combos || {}); - return { - node: nodeTypes.map((config) => getExtension(config, registry.useLib, 'node')).filter(Boolean), - edge: edgeTypes.map((config) => getExtension(config, registry.useLib, 'edge')).filter(Boolean), - combo: comboTypes.map((config) => getExtension(config, registry.useLib, 'combo')).filter(Boolean), - }; - } - /** * Listener of runtime's render hook. * @param param contains inner data stored in graphCore structure @@ -558,9 +545,7 @@ export class ItemController { const parentItem = this.itemMap.get(current.parentId); if (current.parentId && parentItem?.model.data.collapsed) { - this.graph.executeWithNoStack(() => { - this.graph.hideItem(innerModel.id, { disableAnimate: false }); - }); + this.graph.hideItem(innerModel.id, { disableAnimate: false }); } }); debounceUpdateAllRelates(); @@ -802,6 +787,7 @@ export class ItemController { const { keyShape } = item.shapeMap; if (!keyShape) return; const renderBounds = keyShape.getRenderBounds(); + // @ts-expect-error TODO: Need to fix the type if (containFunc(renderBounds, range, 0.4)) itemsInView.push(item); else itemsOutView.push(item); }); @@ -811,6 +797,7 @@ export class ItemController { const { keyShape } = item.shapeMap; if (!keyShape) return; const renderBounds = keyShape.getRenderBounds(); + // @ts-expect-error TODO: Need to fix the type if (containFunc(renderBounds, range, 0.4)) { itemsInView.push(item); } @@ -821,6 +808,7 @@ export class ItemController { const { keyShape } = item.shapeMap; if (!keyShape) return; const renderBounds = keyShape.getRenderBounds(); + // @ts-expect-error TODO: Need to fix the type if (!containFunc(renderBounds, range, 0.4)) { itemsOutView.push(item); } @@ -1147,6 +1135,7 @@ export class ItemController { this.itemMap.set(node.id, nodeItem); const { x, y } = nodeItem.model.data; + // @ts-expect-error TODO: Need to fix the type if (delayFirstDraw && isPointInBBox({ x: convertToNumber(x), y: convertToNumber(y) }, viewRange)) { itemsInView.push(nodeItem); } else { @@ -1451,9 +1440,7 @@ export class ItemController { // find the succeeds in collapsed graphComboTreeDfs(this.graph, [comboModel], (child) => { if (child.id !== comboModel.id) { - this.graph.executeWithNoStack(() => { - this.graph.hideItem(child.id, { disableAnimate: false }); - }); + this.graph.hideItem(child.id, { disableAnimate: false }); } relatedEdges = relatedEdges.concat(graphCore.getRelatedEdges(child.id)); succeedIds.push(child.id); @@ -1471,9 +1458,7 @@ export class ItemController { pairs.push({ source, target }); }); // each item in groupedEdges is a virtual edge - this.graph.executeWithNoStack(() => { - this.graph.addData('edge', groupVirtualEdges(pairs)); - }); + this.graph.addData('edge', groupVirtualEdges(pairs)); } private expandCombo(graphCore: GraphCore, comboModel: ComboModel) { @@ -1542,12 +1527,10 @@ export class ItemController { ); // remove related virtual edges - this.graph.executeWithNoStack(() => { - this.graph.removeData('edge', uniq(relatedVirtualEdgeIds)); - this.graph.showItem(edgesToShow.concat(nodesToShow)); - // add virtual edges by grouping visible ancestor edges - this.graph.addData('edge', groupVirtualEdges(virtualPairs)); - }); + this.graph.removeData('edge', uniq(relatedVirtualEdgeIds)); + this.graph.showItem(edgesToShow.concat(nodesToShow)); + // add virtual edges by grouping visible ancestor edges + this.graph.addData('edge', groupVirtualEdges(virtualPairs)); } /** diff --git a/packages/g6/src/runtime/controller/layout.ts b/packages/g6/src/runtime/controller/layout.ts index e8892d71f5..a113cf4349 100644 --- a/packages/g6/src/runtime/controller/layout.ts +++ b/packages/g6/src/runtime/controller/layout.ts @@ -1,9 +1,9 @@ import { Animation, DisplayObject, IAnimationEffectTiming } from '@antv/g'; import { Graph as GraphLib, ID } from '@antv/graphlib'; import { Layout, LayoutMapping, OutNode, Supervisor, isLayoutWithIterations } from '@antv/layout'; -import { Extensions, registry, stdLib } from '../../plugin'; +import { Extensions } from '../../plugin'; import { - IGraph, + Graph, LayoutOptions, NodeModelData, isImmediatelyInvokedLayoutOptions, @@ -11,6 +11,7 @@ import { } from '../../types'; import { GraphCore } from '../../types/data'; import { EdgeModelData } from '../../types/edge'; +import { getExtension } from '../../utils/extension'; import { getNodeSizeFn, isComboLayout, isTreeLayout, layoutOneTree, radialLayout } from '../../utils/layout'; /** @@ -19,7 +20,7 @@ import { getNodeSizeFn, isComboLayout, isTreeLayout, layoutOneTree, radialLayout */ export class LayoutController { public extensions = {}; - public graph: IGraph; + public graph: Graph; private currentLayout: Layout | null; private currentSupervisor: Supervisor | null; @@ -27,7 +28,7 @@ export class LayoutController { private animatedDisplayObject: DisplayObject; private previousNodes: Map; - constructor(graph: IGraph) { + constructor(graph: Graph) { this.graph = graph; this.animatedDisplayObject = new DisplayObject({}); this.tap(); @@ -189,7 +190,7 @@ export class LayoutController { let { workerEnabled = false } = options; // Find built-in layout algorithms. - const layoutCtor = stdLib.layouts[type] || registry.useLib.layouts[type]; + const layoutCtor = getExtension(type, 'layout'); if (!layoutCtor) { throw new Error(`Unknown layout algorithm: ${type}`); } @@ -214,7 +215,9 @@ export class LayoutController { } // Initialize layout. + // @ts-expect-error TODO: Need to fix the type const useCache = layoutCtor === Extensions.DagreLayout; + // @ts-expect-error TODO: Need to fix the type const layout = new layoutCtor({ nodeSize, width, diff --git a/packages/g6/src/runtime/controller/plugin.ts b/packages/g6/src/runtime/controller/plugin.ts index 1504195f70..e031a71861 100644 --- a/packages/g6/src/runtime/controller/plugin.ts +++ b/packages/g6/src/runtime/controller/plugin.ts @@ -1,7 +1,6 @@ import { uniqueId } from '@antv/util'; -import registry from '../../plugin'; import { LodController } from '../../plugin/widget'; -import { IGraph } from '../../types'; +import { Graph } from '../../types'; import { IG6GraphEvent } from '../../types/event'; import { Plugin as PluginBase } from '../../types/plugin'; import { getExtension } from '../../utils/extension'; @@ -39,7 +38,7 @@ const wrapListener = (type: string, eventName: string, listener: Listener): List */ export class PluginController { public extensions: any = []; - public graph: IGraph; + public graph: Graph; /** * Plugins on graph. @@ -57,7 +56,7 @@ export class PluginController { */ private listenersMap: Record> = {}; - constructor(graph: IGraph) { + constructor(graph: Graph) { this.graph = graph; this.tap(); } @@ -88,9 +87,12 @@ export class PluginController { ) { plugins.push(required.type); + // @ts-expect-error TODO: Need to fix the type if (!this.graph.specification.plugins) { + // @ts-expect-error TODO: Need to fix the type this.graph.specification.plugins = []; } + // @ts-expect-error TODO: Need to fix the type this.graph.specification.plugins.push(required); } }); @@ -113,7 +115,7 @@ export class PluginController { this.pluginMap.set(key, { type: key, plugin: config }); return { key, plugin: config }; } - const Plugin = getExtension(config, registry.useLib, 'plugin'); + const Plugin = getExtension(config, 'widget'); const options = typeof config === 'string' ? {} : config; const type = typeof config === 'string' ? config : config.type; @@ -121,6 +123,7 @@ export class PluginController { if (!Plugin) { throw new Error(`Plugin ${type} not found, please make sure you have registered it first`); } + // @ts-expect-error TODO: Need to fix the type const plugin = new Plugin({ ...options, key }); plugin.init(graph); this.pluginMap.set(key, { type, plugin }); @@ -131,7 +134,7 @@ export class PluginController { if (typeof config.init === 'function' && config.options) { return config.required; } - const Plugin = getExtension(config, registry.useLib, 'plugin'); + const Plugin = getExtension(config, 'widget'); return Plugin?.required; } diff --git a/packages/g6/src/runtime/controller/theme.ts b/packages/g6/src/runtime/controller/theme.ts index ab6292e00f..206b9cb870 100644 --- a/packages/g6/src/runtime/controller/theme.ts +++ b/packages/g6/src/runtime/controller/theme.ts @@ -1,7 +1,6 @@ -import registry from '../../plugin'; -import { IGraph } from '../../types'; -import { ThemeSpecification } from '../../types/theme'; -import { getCatExtensions, getExtension } from '../../utils/extension'; +import { Graph } from '../../types'; +import { ThemeRegistry, ThemeSpecification } from '../../types/theme'; +import { getExtension, getExtensionsByCategory } from '../../utils/extension'; /** * Manages theme extensions for graph. @@ -9,7 +8,7 @@ import { getCatExtensions, getExtension } from '../../utils/extension'; */ export class ThemeController { public extension; - public graph: IGraph; + public graph: Graph; private themeConfig; private solver; @@ -18,7 +17,7 @@ export class ThemeController { [themeName: string]: ThemeSpecification; }; - constructor(graph: IGraph) { + constructor(graph: Graph) { this.graph = graph; this.tap(); } @@ -38,11 +37,14 @@ export class ThemeController { private getExtension() { const { theme = {} } = this.graph.getSpecification(); this.themeConfig = theme; - return theme ? getExtension(theme, registry.useLib, 'themeSolver') : undefined; + return theme ? getExtension(theme, 'themeSolver') : undefined; } - private getThemes() { - return getCatExtensions(registry.useLib, 'theme'); + private getThemes(): ThemeRegistry { + return getExtensionsByCategory('theme').reduce((res, acc) => { + res[acc.type] = acc; + return res; + }, {}) as ThemeRegistry; } /** diff --git a/packages/g6/src/runtime/controller/viewport.ts b/packages/g6/src/runtime/controller/viewport.ts index a95c433243..f609278d51 100644 --- a/packages/g6/src/runtime/controller/viewport.ts +++ b/packages/g6/src/runtime/controller/viewport.ts @@ -1,12 +1,12 @@ -import { IGraph } from '../../types'; +import { Graph } from '../../types'; import { ViewportChangeHookParams } from '../../types/hook'; let landmarkCounter = 0; export class ViewportController { - public graph: IGraph; + public graph: Graph; - constructor(graph: IGraph) { + constructor(graph: Graph) { this.graph = graph; this.tap(); } diff --git a/packages/g6/src/runtime/graph.ts b/packages/g6/src/runtime/graph.ts index 57a425f7bd..af0bc0bd27 100644 --- a/packages/g6/src/runtime/graph.ts +++ b/packages/g6/src/runtime/graph.ts @@ -1,18 +1,16 @@ +// @ts-nocheck import EventEmitter from '@antv/event-emitter'; import { AABB, Canvas, Cursor, DataURLType, DisplayObject, PointLike, Rect } from '@antv/g'; import { GraphChange, ID } from '@antv/graphlib'; import { clone, groupBy, isArray, isEmpty, isEqual, isNil, isNumber, isObject, isString, map } from '@antv/util'; import Node from '../item/node'; -import { History } from '../plugin/widget/history'; -import { Command } from '../plugin/widget/history/command'; -import type { ComboUserModel, EdgeUserModel, GraphData, IGraph, NodeUserModel, Specification } from '../types'; +import type { ComboUserModel, EdgeUserModel, GraphData, NodeUserModel, Specification } from '../types'; import type { CameraAnimationOptions } from '../types/animate'; import type { BehaviorOptionsOf, BehaviorRegistry } from '../types/behavior'; import type { ComboDisplayModel, ComboModel, ComboShapesEncode } from '../types/combo'; import type { Bounds, Padding, Point } from '../types/common'; import type { DataChangeType, DataConfig, GraphCore } from '../types/data'; import type { EdgeDisplayModel, EdgeModel, EdgeModelData, EdgeShapesEncode } from '../types/edge'; -import type { StackType } from '../types/history'; import type { Hooks, ViewportChangeHookParams } from '../types/hook'; import type { ITEM_TYPE, SHAPE_TYPE, ShapeStyle } from '../types/item'; import type { ImmediatelyInvokedLayoutOptions, LayoutOptions, StandardLayoutOptions } from '../types/layout'; @@ -20,7 +18,7 @@ import type { NodeDisplayModel, NodeModel, NodeModelData, NodeShapesEncode } fro import { Plugin as PluginBase } from '../types/plugin'; import type { RendererName } from '../types/render'; import { ComboMapper, EdgeMapper, NodeMapper } from '../types/spec'; -import type { ThemeOptionsOf, ThemeRegistry, ThemeSpecification } from '../types/theme'; +import type { ThemeOptionsOf, ThemeSolverRegistry, ThemeSpecification } from '../types/theme'; import { FitViewRules, GraphTransformOptions } from '../types/view'; import { getCombinedCanvasesBounds } from '../utils/bbox'; import { changeRenderer, createCanvas } from '../utils/canvas'; @@ -38,8 +36,7 @@ import { ViewportController, } from './controller'; import Hook from './hooks'; - -export class Graph extends EventEmitter implements IGraph { +export class Graph extends EventEmitter { public hooks: Hooks; // for nodes and edges excluding their labels, which will be separate into groups public canvas: Canvas; @@ -79,12 +76,10 @@ export class Graph extends constructor(spec: Specification) { super(); - this.specification = Object.assign({}, this.defaultSpecification, this.formatSpecification(spec)); this.initHooks(); this.initCanvas(); this.initControllers(); - this.initHistory(); this.hooks.init.emit({ canvases: { @@ -185,22 +180,6 @@ export class Graph extends }); } - private initHistory() { - const { enableStack, stackCfg } = this.specification; - if (enableStack) { - const history = { - type: 'history', - key: 'history', - enableStack, - stackCfg, - }; - if (!this.specification.plugins) { - this.specification.plugins = []; - } - this.specification.plugins.push(history); - } - } - /** * Change the renderer at runtime. * @param type renderer name @@ -545,7 +524,6 @@ export class Graph extends * Clear the graph, means remove all the items on the graph. */ public clear() { - this.startHistoryBatch(); this.removeData( 'edge', this.getAllEdgesData().map((edge) => edge.id), @@ -558,7 +536,6 @@ export class Graph extends 'combo', this.getAllCombosData().map((combo) => combo.id), ); - this.stopHistoryBatch(); } public getViewportCenter(): PointLike { @@ -1298,17 +1275,6 @@ export class Graph extends return this.updatePosition('combo', models, upsertAncestors, disableAnimate, callback); } - /** - * Get history plugin instance - */ - private getHistoryPlugin(): History { - if (!this.specification.enableStack || !this.pluginController.hasPlugin('history')) { - console.error('The history plugin is not loaded or initialized.'); - return; - } - return this.pluginController.getPlugin('history') as History; - } - private updatePosition( type: 'node' | 'combo', models: Partial | Partial[] | Partial[]>, @@ -1721,12 +1687,10 @@ export class Graph extends */ public collapseCombo(comboIds: ID | ID[]) { const ids = isArray(comboIds) ? comboIds : [comboIds]; - this.executeWithNoStack(() => { - this.updateData( - 'combo', - ids.map((id) => ({ id, data: { collapsed: true } })), - ); - }); + this.updateData( + 'combo', + ids.map((id) => ({ id, data: { collapsed: true } })), + ); this.emit('aftercollapsecombo', { type: 'combo', action: 'collapseCombo', @@ -1742,12 +1706,10 @@ export class Graph extends */ public expandCombo(comboIds: ID | ID[]) { const ids = isArray(comboIds) ? comboIds : [comboIds]; - this.executeWithNoStack(() => { - this.updateData( - 'combo', - ids.map((id) => ({ id, data: { collapsed: false } })), - ); - }); + this.updateData( + 'combo', + ids.map((id) => ({ id, data: { collapsed: false } })), + ); this.emit('afterexpandcombo', { type: 'combo', action: 'expandCombo', @@ -2496,156 +2458,6 @@ export class Graph extends }, 16); } - // ===== history operations ===== - - /** - * Determine if history (redo/undo) is enabled. - */ - public isHistoryEnabled() { - const history = this.getHistoryPlugin(); - return history?.isEnable(); - } - - /** - * Push the operation(s) onto the specified stack - * @param cmd commands to be pushed - * @param stackType undo/redo stack - * @param isNew - */ - public pushStack(cmd: Command[], stackType: StackType, isNew?: boolean) { - const history = this.getHistoryPlugin(); - return history?.push(cmd, stackType, isNew); - } - - /** - * Pause stacking operation. - */ - public pauseStack(): void { - const history = this.getHistoryPlugin(); - return history?.pauseStack(); - } - - /** - * Resume stacking operation. - */ - public resumeStack(): void { - const history = this.getHistoryPlugin(); - return history?.resumeStack(); - } - - /** - * Execute a callback without allowing any stacking operations. - * @param callback - */ - public executeWithNoStack = (callback: () => void): void => { - const history = this.getHistoryPlugin(); - history?.pauseStack(); - try { - callback(); - } finally { - history?.resumeStack(); - } - }; - - /** - * Retrieve the current redo stack which consists of operations that could be undone - */ - public getUndoStack() { - const history = this.getHistoryPlugin(); - return history?.getUndoStack(); - } - - /** - * Retrieve the current undo stack which consists of operations that were undone - */ - public getRedoStack() { - const history = this.getHistoryPlugin(); - return history?.getRedoStack(); - } - - /** - * Retrieve the complete history stack - */ - public getStack() { - const history = this.getHistoryPlugin(); - return history?.getStack(); - } - - /** - * Restore n operations that were last n reverted on the graph. - * @param steps The number of operations to undo. Default to 1. - */ - public undo() { - const history = this.getHistoryPlugin(); - history?.undo(); - } - - /** - * Revert recent n operation(s) performed on the graph. - * @param steps The number of operations to redo. Default to 1. - */ - public redo() { - const history = this.getHistoryPlugin(); - history?.redo(); - } - - /** - * Indicate whether there are any actions available in the undo stack. - */ - public canUndo() { - const history = this.getHistoryPlugin(); - return history?.canUndo(); - } - - /** - * Indicate whether there are any actions available in the redo stack. - */ - public canRedo() { - const history = this.getHistoryPlugin(); - return history?.canRedo(); - } - - /** - * Begin a historyBatch operation. - * Any operations performed between `startHistoryBatch` and `stopHistoryBatch` are grouped together. - * treated as a single operation when undoing or redoing. - */ - public startHistoryBatch() { - const history = this.getHistoryPlugin(); - history?.startHistoryBatch(); - } - - /** - * End a historyBatch operation. - * Any operations performed between `startHistoryBatch` and `stopHistoryBatch` are grouped together. - * treated as a single operation when undoing or redoing. - */ - public stopHistoryBatch() { - const history = this.getHistoryPlugin(); - history?.stopHistoryBatch(); - } - - /** - * Execute a provided function within a batched context - * All operations performed inside callback will be treated as a composite operation - * more convenient way without manually invoking `startHistoryBatch` and `stopHistoryBatch`. - * @param callback The func containing operations to be batched together. - */ - public historyBatch(callback: () => void) { - const history = this.getHistoryPlugin(); - history?.historyBatch(callback); - } - - /** - * Clear history stack - * @param {StackType} stackType undo/redo stack - */ - public cleanHistory(stackType?: StackType) { - const history = this.getHistoryPlugin(); - if (!stackType) return history?.clear(); - return stackType === 'undo' ? history?.clearUndoStack() : history?.clearRedoStack(); - } - /** * Collapse sub tree(s). * @param ids Root id(s) of the sub trees. @@ -2698,9 +2510,6 @@ export class Graph extends this.transientCanvas.destroy(); this.transientLabelCanvas.destroy(); - // clear history stack - this.cleanHistory(); - callback?.(); this.hooks.destroy.emit({}); diff --git a/packages/g6/src/runtime/layered-canvas/types.ts b/packages/g6/src/runtime/layered-canvas/types.ts new file mode 100644 index 0000000000..917d48b435 --- /dev/null +++ b/packages/g6/src/runtime/layered-canvas/types.ts @@ -0,0 +1 @@ +export type Layer = 'background' | 'main' | 'label' | 'transient' | 'transientLabel'; diff --git a/packages/g6/src/spec/canvas/index.ts b/packages/g6/src/spec/canvas/index.ts new file mode 100644 index 0000000000..b1cd77fa16 --- /dev/null +++ b/packages/g6/src/spec/canvas/index.ts @@ -0,0 +1,35 @@ +import type { CanvasConfig, IRenderer } from '@antv/g'; +import type { Layer } from '../../runtime/layered-canvas/types'; + +/** + * 画布配置项 + * + * Canvas spec + * @public + */ +export type CanvasOption = Pick & { + /** + * 画布宽度 + * + * canvas width + */ + width?: number; + /** + * 画布高度 + * + * canvas height + */ + height?: number; + /** + * 获取渲染器 + * + * get renderer + */ + renderer?: (layer: Layer) => IRenderer; + /** + * 是否自动调整画布大小 + * + * whether to auto resize canvas + */ + autoResize?: boolean; +}; diff --git a/packages/g6/src/spec/canvas/io.ts b/packages/g6/src/spec/canvas/io.ts new file mode 100644 index 0000000000..f332ddce4f --- /dev/null +++ b/packages/g6/src/spec/canvas/io.ts @@ -0,0 +1,13 @@ +/** + * 设置画布配置项 + * + * set canvas spec + */ +export function setter() {} + +/** + * 获取画布配置项 + * + * get canvas spec + */ +export function getter() {} diff --git a/packages/g6/src/spec/data/index.ts b/packages/g6/src/spec/data/index.ts new file mode 100644 index 0000000000..04463e99b9 --- /dev/null +++ b/packages/g6/src/spec/data/index.ts @@ -0,0 +1,57 @@ +import type { BaseStyleProps } from '@antv/g'; +import type { ID } from '@antv/graphlib'; +import type { EdgeStyle } from '../element/edge'; + +export type DataOption = { + /** + * 节点数据 + * + * node data + */ + nodes?: NodeData[]; + /** + * 边数据 + * + * edge data + */ + edges?: EdgeData[]; + /** + * Combo 数据 + * + * combo data + */ + combos?: ComboData[]; +}; + +export type NodeData = { + id: ID; + data?: Record; + style?: NodeLikeStyle; +}; + +export type ComboData = { + id: ID; + data?: Record; + style?: NodeLikeStyle; +}; + +export type EdgeData = { + id: ID; + source: ID; + target: ID; + data?: Record; + style?: EdgeStyle; +}; + +/** + * Can be a node or combo. + */ +export type NodeLikeStyle = Pick & { + parentId?: ID; + collapsed?: boolean; + type?: string; + x?: number; + y?: number; + z?: number; + [keys: string]: any; +}; diff --git a/packages/g6/src/spec/data/io.ts b/packages/g6/src/spec/data/io.ts new file mode 100644 index 0000000000..feb2c54d63 --- /dev/null +++ b/packages/g6/src/spec/data/io.ts @@ -0,0 +1,13 @@ +/** + * 设置数据配置项 + * + * set data spec + */ +export function setter() {} + +/** + * 获取数据配置项 + * + * get data spec + */ +export function getter() {} diff --git a/packages/g6/src/spec/element/combo/index.ts b/packages/g6/src/spec/element/combo/index.ts new file mode 100644 index 0000000000..685e9d668b --- /dev/null +++ b/packages/g6/src/spec/element/combo/index.ts @@ -0,0 +1,45 @@ +import type { AnimationOption } from '../../../types/animate'; +import type { CallableObject } from '../../../types/callable'; +import type { NodeData, NodeLikeStyle } from '../../data'; +import type { Palette } from '../types'; + +/** + * Combo 配置项 + * + * Combo spec + */ +export type ComboOption = { + /** + * Combo 样式 + * + * Combo style + */ + style?: CallableComboStyle; + /** + * Combo 状态样式 + * + * Combo state style + */ + state?: { + [keys: string]: CallableComboStyle; + }; + /** + * Combo 动画 + * + * Combo animation + */ + animate?: AnimationOption; + /** + * 色板 + * + * Palette + */ + palette?: Palette; +}; + +/** + * Combo 样式 + * + * Combo style + */ +type CallableComboStyle = CallableObject; diff --git a/packages/g6/src/spec/element/combo/io.ts b/packages/g6/src/spec/element/combo/io.ts new file mode 100644 index 0000000000..8be22107ca --- /dev/null +++ b/packages/g6/src/spec/element/combo/io.ts @@ -0,0 +1,13 @@ +/** + * 设置 Combo 配置项 + * + * set Combo spec + */ +export function setter() {} + +/** + * 获取 Combo 配置项 + * + * get Combo spec + */ +export function getter() {} diff --git a/packages/g6/src/spec/element/edge/index.ts b/packages/g6/src/spec/element/edge/index.ts new file mode 100644 index 0000000000..1b63fbcc9e --- /dev/null +++ b/packages/g6/src/spec/element/edge/index.ts @@ -0,0 +1,63 @@ +import type { BaseStyleProps } from '@antv/g'; +import type { AnimationOption } from '../../../types/animate'; +import type { CallableObject } from '../../../types/callable'; +import type { EdgeData } from '../../data'; +import type { Palette } from '../types'; + +/** + * 边配置项 + * + * Edge spec + */ +export type EdgeOption = { + /** + * 边样式 + * + * Edge style + */ + style?: CallableEdgeStyle; + /** + * 边状态样式 + * + * Edge state style + */ + state?: { + [keys: string]: CallableEdgeStyle; + }; + /** + * 边动画 + * + * Edge animation + */ + animate?: AnimationOption; + /** + * 色板 + * + * Palette + */ + palette?: Palette; +}; + +/** + * 边样式 + * + * Edge style + */ +type CallableEdgeStyle = CallableObject; + +export type EdgeStyle = Pick & { + type?: string; + /** + * 起点连接桩 id + * + * source port id + */ + sourcePort?: string; + /** + * 终点连接桩 id + * + * target port id + */ + targetPort?: string; + [keys: string]: any; +}; diff --git a/packages/g6/src/spec/element/edge/io.ts b/packages/g6/src/spec/element/edge/io.ts new file mode 100644 index 0000000000..2fa4865e05 --- /dev/null +++ b/packages/g6/src/spec/element/edge/io.ts @@ -0,0 +1,13 @@ +/** + * 设置 Edge 配置项 + * + * set Edge spec + */ +export function setter() {} + +/** + * 获取 Edge 配置项 + * + * get Edge spec + */ +export function getter() {} diff --git a/packages/g6/src/spec/element/index.ts b/packages/g6/src/spec/element/index.ts new file mode 100644 index 0000000000..2114537cbf --- /dev/null +++ b/packages/g6/src/spec/element/index.ts @@ -0,0 +1,3 @@ +export type { ComboOption } from './combo'; +export type { EdgeOption } from './edge'; +export type { NodeOption } from './node'; diff --git a/packages/g6/src/spec/element/node/index.ts b/packages/g6/src/spec/element/node/index.ts new file mode 100644 index 0000000000..79dc6f08f7 --- /dev/null +++ b/packages/g6/src/spec/element/node/index.ts @@ -0,0 +1,45 @@ +import type { AnimationOption } from '../../../types/animate'; +import type { CallableObject } from '../../../types/callable'; +import type { NodeData, NodeLikeStyle } from '../../data'; +import type { Palette } from '../types'; + +/** + * 节点配置项 + * + * Node spec + */ +export type NodeOption = { + /** + * 节点样式 + * + * Node style + */ + style?: CallableNodeStyle; + /** + * 节点状态样式 + * + * Node state style + */ + state?: { + [keys: string]: CallableNodeStyle; + }; + /** + * 节点动画 + * + * Node animation + */ + animate?: AnimationOption; + /** + * 色板 + * + * Palette + */ + palette?: Palette; +}; + +/** + * 节点样式 + * + * Node style + */ +type CallableNodeStyle = CallableObject; diff --git a/packages/g6/src/spec/element/types.ts b/packages/g6/src/spec/element/types.ts new file mode 100644 index 0000000000..ac50b4f230 --- /dev/null +++ b/packages/g6/src/spec/element/types.ts @@ -0,0 +1,56 @@ +import type { PaletteColor } from '../../types/palette'; + +/** + * 色板配置项 + * + * Palette options + * @public + */ +export type Palette = PaletteColor | GroupPalette | FieldPalette; + +export type STDPalette = GroupPalette | FieldPalette; + +interface BasePalette { + /** + * 色板颜色 + * + * Palette color + */ + color: PaletteColor; + /** + * 倒序取色 + * + * Color in reverse order + */ + invert?: boolean; +} + +interface GroupPalette extends BasePalette { + /** + * 分组取色 + * + * Coloring by group + */ + type: 'group'; + /** + * 分组字段,未指定时基于节点 id 分组 + * + * Group field, when not specified, group by node id + */ + field?: string; +} + +interface FieldPalette extends BasePalette { + /** + * 基于字段值取色 + * + * Coloring based on field value + */ + type: 'value'; + /** + * 取值字段 + * + * Value field + */ + field: string; +} diff --git a/packages/g6/src/spec/index.ts b/packages/g6/src/spec/index.ts new file mode 100644 index 0000000000..d5904b36b4 --- /dev/null +++ b/packages/g6/src/spec/index.ts @@ -0,0 +1,73 @@ +import type { CanvasOption } from './canvas'; +import type { DataOption } from './data'; +import type { ComboOption, EdgeOption, NodeOption } from './element'; +import type { LayoutOption } from './layout'; +import type { ModeOption } from './mode'; +import type { OptimizeOption } from './optimize'; +import type { ThemeOption } from './theme'; +import type { ViewportOption } from './viewport'; +import type { WidgetOption } from './widget'; + +/** + * G6 规范 + * + * G6 Specification + * @public + */ +export type G6Spec = CanvasOption & + ViewportOption & { + /** + * 数据 + * + * Data + */ + data?: DataOption; + /** + * 布局 + * + * Layout + */ + layout?: LayoutOption; + /** + * 节点 + * + * Node + */ + node?: NodeOption; + /** + * 边 + * + * Edge + */ + edge?: EdgeOption; + /** + * Combo + * + * Combo + */ + combo?: ComboOption; + /** + * 主题 + * + * Theme + */ + theme?: ThemeOption; + /** + * 模式 + * + * Mode + */ + mode?: ModeOption; + /** + * 画布插件 + * + * Canvas widget + */ + widget?: WidgetOption; + /** + * 优化选项 + * + * Optimize options + */ + optimize?: OptimizeOption; + }; diff --git a/packages/g6/src/spec/layout/index.ts b/packages/g6/src/spec/layout/index.ts new file mode 100644 index 0000000000..a046ff920b --- /dev/null +++ b/packages/g6/src/spec/layout/index.ts @@ -0,0 +1,26 @@ +import type { STDLayoutOptions } from '../../types/layout'; +import type { NodeData } from '../data'; + +export type LayoutOption = CustomLayout | STDLayoutOptions | PipeLayout[]; + +// see: https://g6.antv.antgroup.com/api/graph#graphoptionslayoutpipes +/** + * 流水线子图布局 + * + * Pipeline layout options + */ +export type PipeLayout = (STDLayoutOptions | CustomLayout) & { + /** + * 参与该布局的节点 + * + * Nodes involved in the layout + * @param node - 节点数据 | node data + * @returns 是否参与布局 | Whether to participate in the layout + */ + nodesFilter: (node: NodeData) => boolean; +}; + +export type CustomLayout = { + type: string; + [key: string]: any; +}; diff --git a/packages/g6/src/spec/layout/io.ts b/packages/g6/src/spec/layout/io.ts new file mode 100644 index 0000000000..87c4ebede3 --- /dev/null +++ b/packages/g6/src/spec/layout/io.ts @@ -0,0 +1,13 @@ +/** + * 设置布局配置项 + * + * set layout spec + */ +export function setter() {} + +/** + * 获取布局配置项 + * + * get layout spec + */ +export function getter() {} diff --git a/packages/g6/src/spec/mode/index.ts b/packages/g6/src/spec/mode/index.ts new file mode 100644 index 0000000000..8de46ffdde --- /dev/null +++ b/packages/g6/src/spec/mode/index.ts @@ -0,0 +1,24 @@ +export type ModeOption = (BuiltInBehavior | CustomBehavior)[]; + +// TODO import from built in behavior +declare type BuiltInBehavior = + | 'activate-relations' + | 'brush-select' + | 'click-select' + | 'collapse-expand-combo' + | 'collapse-expand-tree' + | 'create-edge' + | 'drag-canvas' + | 'drag-combo' + | 'drag-node' + | 'hover-activate' + | 'lasso-select' + | 'orbit-canvas-3d' + | 'rotate-canvas-3d' + | 'scroll-canvas' + | 'shortcuts-call' + | 'track-canvas-3d' + | 'zoom-canvas-3d' + | 'zoom-canvas'; + +type CustomBehavior = string; diff --git a/packages/g6/src/spec/mode/io.ts b/packages/g6/src/spec/mode/io.ts new file mode 100644 index 0000000000..4d1b84d541 --- /dev/null +++ b/packages/g6/src/spec/mode/io.ts @@ -0,0 +1,13 @@ +/** + * 设置交互模式配置项 + * + * set mode spec + */ +export function setter() {} + +/** + * 获取交互模式配置项 + * + * get mode spec + */ +export function getter() {} diff --git a/packages/g6/src/spec/optimize/index.ts b/packages/g6/src/spec/optimize/index.ts new file mode 100644 index 0000000000..0d84471fc9 --- /dev/null +++ b/packages/g6/src/spec/optimize/index.ts @@ -0,0 +1,35 @@ +/** + * TODO: option should adjust + */ +export type OptimizeOption = { + /** + * 是否开启首次渲染时的分片渲染,若为 number,则表示开启分片渲染的元素数量上限 + * + * Whether enable tile rendering for first time. If it is a number, it means the maximum number of elements for tile rendering. + */ + tileFirstRender?: boolean | number; + /** + * 首次渲染时的分片渲染的元素数量上限 + * + * Tile size for first rendering. + */ + tileFirstRenderSize?: number; + /** + * 是否在 drag-canvas, zoom-canvas 显示/隐藏图形过程中,启用分片渲染。若指定 number,则表示开启分片渲染的元素数量上限。 + * + * Whether enable tile hiding / showing for behaviors, e.g. hiding shapes while drag-canvas, zoom-canvas. + */ + tileBehavior?: boolean | number; + /** + * 交互的分片渲染单片/一帧渲染的元素数量 + * + * Tile size for shape optimizing by behaviors, e.g. hiding shapes while drag-canvas, zoom-canvas. The enableOptimize in behavior configuration has higher priority. + */ + tileBehaviorSize?: number; + /** + * 层级渲染的分片渲染单片/一帧渲染的元素数量 + * + * Tile size for level of detail changing. + */ + tileLodSize?: number; +}; diff --git a/packages/g6/src/spec/optimize/io.ts b/packages/g6/src/spec/optimize/io.ts new file mode 100644 index 0000000000..932317f3c2 --- /dev/null +++ b/packages/g6/src/spec/optimize/io.ts @@ -0,0 +1,13 @@ +/** + * 设置优化配置项 + * + * set optimize spec + */ +export function setter() {} + +/** + * 获取优化配置项 + * + * get optimize spec + */ +export function getter() {} diff --git a/packages/g6/src/spec/theme/index.ts b/packages/g6/src/spec/theme/index.ts new file mode 100644 index 0000000000..439e4f3bdb --- /dev/null +++ b/packages/g6/src/spec/theme/index.ts @@ -0,0 +1,6 @@ +export type ThemeOption = BuiltInTheme | CustomTheme; + +// TODO import from built in theme +declare type BuiltInTheme = 'light' | 'dark'; + +type CustomTheme = string; diff --git a/packages/g6/src/spec/theme/io.ts b/packages/g6/src/spec/theme/io.ts new file mode 100644 index 0000000000..54a80f98f6 --- /dev/null +++ b/packages/g6/src/spec/theme/io.ts @@ -0,0 +1,13 @@ +/** + * 设置主题配置项 + * + * set theme spec + */ +export function setter() {} + +/** + * 获取主题配置项 + * + * get theme spec + */ +export function getter() {} diff --git a/packages/g6/src/spec/viewport/index.ts b/packages/g6/src/spec/viewport/index.ts new file mode 100644 index 0000000000..b3149000f2 --- /dev/null +++ b/packages/g6/src/spec/viewport/index.ts @@ -0,0 +1,66 @@ +import type { CameraAnimationOptions } from '../../types/animate'; +import type { Padding, Point, STDPadding } from '../../types/common'; +import type { Position } from '../../types/position'; +import type { FitViewRules } from '../../types/view'; + +/** + * 视口配置项 + * + * Viewport + * @public + */ +export type ViewportOption = { + /** + * 是否自动适应 + * + * whether to auto fit + */ + autoFit?: AutoFit; + /** + * 画布内边距 + * + * canvas padding + */ + padding?: Padding; + /** + * 缩放比例 + * + * zoom ratio + */ + zoom?: number; + /** + * 缩放范围 + * + * zoom range + */ + zoomRange?: [number, number]; +}; + +/** + * @internal + */ +export type STDViewportOption = { + autoFit: STDAutoFit; + padding: STDPadding; + zoom: number; + zoomRange: [number, number]; +}; + +/** + * 视口自适应规则(标准属性) + * + * Viewport auto fit rules(STD) + * @public + */ +export type STDAutoFit = + | { type: 'view'; padding?: Padding; rules?: FitViewRules; effectTiming?: CameraAnimationOptions } + | { type: 'center'; effectTiming?: CameraAnimationOptions } + | { type: 'position'; position: Point; alignment?: Position }; + +/** + * 视口自适应规则 + * + * Viewport auto fit rules + * @public + */ +export type AutoFit = STDAutoFit | 'view' | 'center'; diff --git a/packages/g6/src/spec/viewport/io.ts b/packages/g6/src/spec/viewport/io.ts new file mode 100644 index 0000000000..3b42539b18 --- /dev/null +++ b/packages/g6/src/spec/viewport/io.ts @@ -0,0 +1,13 @@ +/** + * 设置视口配置项 + * + * set viewport spec + */ +export function setter() {} + +/** + * 获取视口配置项 + * + * get viewport spec + */ +export function getter() {} diff --git a/packages/g6/src/spec/widget/index.ts b/packages/g6/src/spec/widget/index.ts new file mode 100644 index 0000000000..17cae83ba2 --- /dev/null +++ b/packages/g6/src/spec/widget/index.ts @@ -0,0 +1,27 @@ +export type WidgetOption = Abbr[]; + +// TODO needs to fill the options +declare type BuiltInWidget = + | { type: 'edge-bundling' } + | { type: 'edge-filter-lens' } + | { type: 'fisheye' } + | { type: 'grid' } + | { type: 'hull' } + | { type: 'legend' } + | { type: 'lod-controller' } + | { type: 'menu' } + | { type: 'minimap' } + | { type: 'snapline' } + | { type: 'timebar' } + | { type: 'toolbar' } + | { type: 'tooltip' } + | { type: 'watermarker' }; + +type CustomWidget = BaseWidget; + +export interface BaseWidget { + type: string; + [key: string]: any; +} + +type Abbr = (R & { key?: string }) | R['type']; diff --git a/packages/g6/src/spec/widget/io.ts b/packages/g6/src/spec/widget/io.ts new file mode 100644 index 0000000000..7325b791a5 --- /dev/null +++ b/packages/g6/src/spec/widget/io.ts @@ -0,0 +1,13 @@ +/** + * 设置组件配置项 + * + * set widget spec + */ +export function setter() {} + +/** + * 获取组件配置项 + * + * get widget spec + */ +export function getter() {} diff --git a/packages/g6/src/types/animate.ts b/packages/g6/src/types/animate.ts index b0943b09a0..64c70e809d 100644 --- a/packages/g6/src/types/animate.ts +++ b/packages/g6/src/types/animate.ts @@ -1,4 +1,4 @@ -import { IAnimationEffectTiming } from '@antv/g'; +import { IAnimation, IAnimationEffectTiming } from '@antv/g'; export interface AnimateCfg { /** @@ -61,3 +61,43 @@ export interface IAnimates { } export type CameraAnimationOptions = Partial>; + +/** + * 动画结果 + * + * Animation result + */ +export type AnimationResult = IAnimation; + +/** + * 动画阶段 + * + * Animation stage + */ +export type AnimationStage = 'enter' | 'exit' | 'update' | 'show' | 'hide'; + +/** + * 元素动画配置项 + * + * Element animation configuration + */ +export type AnimationOption = { + [K in string]?: { + [G in AnimationStage]?: AnimationEffectTiming; + }; +}; + +// TODO update to built-in type +export type AnimationType = R; + +/** + * 动画配置项 + * + * Animation configuration + * @public + */ +export type AnimationEffectTiming = Pick & { + type: AnimationType; + onFinish?: () => void; + onCancel?: () => void; +}; diff --git a/packages/g6/src/types/behavior.ts b/packages/g6/src/types/behavior.ts index 9c4b1c41a9..d04b7aff7c 100644 --- a/packages/g6/src/types/behavior.ts +++ b/packages/g6/src/types/behavior.ts @@ -1,5 +1,5 @@ import { IG6GraphEvent } from './event'; -import { IGraph } from './graph'; +import { Graph } from './graph'; export interface BehaviorOption { key?: string; @@ -9,7 +9,8 @@ export interface BehaviorOption { * TODO: Support spec mode. */ export abstract class Behavior { - graph: IGraph; + static type: string; + graph: Graph; options: any; constructor(options: any) { this.options = options; diff --git a/packages/g6/src/types/callable.ts b/packages/g6/src/types/callable.ts new file mode 100644 index 0000000000..a0391a14ea --- /dev/null +++ b/packages/g6/src/types/callable.ts @@ -0,0 +1,31 @@ +/** + * 可回调值 + * + * Callable value + * @example + * type Prop = number; + * type CallableProp = Callable; + * const prop1: CallableProp = 1; + * const prop2: CallableProp = (value) => value; + */ +export type CallableValue = R | ((args: P) => R); + +/** + * 可回调对象 + * + * Callable object + * @example + * type Style = { + * fill?: string; + * } + * type CallableObjectStyle = CallableObject; + * const style1: CallableObjectStyle = { + * fill: 'red', + * } + * const style2: CallableObjectStyle = { + * fill: ({ model }) => model.value, + * } + */ +export type CallableObject, P = never> = { + [K in keyof O]: CallableValue; +}; diff --git a/packages/g6/src/types/common.ts b/packages/g6/src/types/common.ts index 2997599769..550d32c5c9 100644 --- a/packages/g6/src/types/common.ts +++ b/packages/g6/src/types/common.ts @@ -1,7 +1,7 @@ import { ID } from 'types'; export type Padding = number | number[]; -export type StandardPadding = [number, number, number, number]; +export type STDPadding = [number, number, number, number]; export type Point = { x: number; diff --git a/packages/g6/src/types/edge.ts b/packages/g6/src/types/edge.ts index fdbea6b7fd..8c2b25249d 100644 --- a/packages/g6/src/types/edge.ts +++ b/packages/g6/src/types/edge.ts @@ -1,4 +1,4 @@ -import { DisplayObject, PathStyleProps } from '@antv/g'; +import type { DisplayObject, PathStyleProps } from '@antv/g'; import { Edge as GEdge, PlainObject } from '@antv/graphlib'; import { BaseEdge } from '../plugin/item/edge/base'; import { IAnimates } from './animate'; @@ -133,3 +133,7 @@ export type ArrowStyle = PathStyleProps & { export interface EdgeRegistry { [key: string]: typeof BaseEdge; } + +/** --------------------- V5.1 --------------------- */ + +export type EdgeDirection = 'in' | 'out' | 'both'; diff --git a/packages/g6/src/types/event.ts b/packages/g6/src/types/event.ts index b792e47a0f..d01a2eefd5 100644 --- a/packages/g6/src/types/event.ts +++ b/packages/g6/src/types/event.ts @@ -1,6 +1,6 @@ import { FederatedPointerEvent } from '@antv/g'; import { ID } from '@antv/graphlib'; -import { IGraph } from './graph'; +import { Graph } from './graph'; /** Event type enum */ export enum CANVAS_EVENT_TYPE { @@ -38,7 +38,7 @@ export enum DOM_EVENT_TYPE { export type ICanvasEventType = `${CANVAS_EVENT_TYPE}`; export interface IG6GraphEvent extends Omit { - currentTarget: IGraph; + currentTarget: Graph; itemType: 'node' | 'edge' | 'combo' | 'canvas'; itemId: ID; key?: string; diff --git a/packages/g6/src/types/graph.ts b/packages/g6/src/types/graph.ts index e5f697af8e..197d01ae01 100644 --- a/packages/g6/src/types/graph.ts +++ b/packages/g6/src/types/graph.ts @@ -1,788 +1 @@ -import EventEmitter from '@antv/event-emitter'; -import { AABB, Canvas, Cursor, DisplayObject, PointLike } from '@antv/g'; -import { ID } from '@antv/graphlib'; -import { Command } from '../plugin/widget/history/command'; -import { Hooks } from '../types/hook'; -import { CameraAnimationOptions } from './animate'; -import { BehaviorOptionsOf, BehaviorRegistry } from './behavior'; -import { ComboDisplayModel, ComboModel, ComboShapesEncode, ComboUserModel } from './combo'; -import { Padding, Point } from './common'; -import { GraphData } from './data'; -import { EdgeDisplayModel, EdgeModel, EdgeShapesEncode, EdgeUserModel } from './edge'; -import type { StackType } from './history'; -import { ITEM_TYPE, SHAPE_TYPE, ShapeStyle } from './item'; -import { LayoutOptions } from './layout'; -import { NodeDisplayModel, NodeModel, NodeShapesEncode, NodeUserModel } from './node'; -import { RendererName } from './render'; -import { ComboMapper, EdgeMapper, NodeMapper, Specification } from './spec'; -import { ThemeOptionsOf, ThemeRegistry } from './theme'; -import { FitViewRules, GraphTransformOptions } from './view'; - -export interface IGraph - extends EventEmitter { - [x: string]: any; - hooks: Hooks; - canvas: Canvas; - labelCanvas: Canvas; - transientCanvas: Canvas; - destroyed: boolean; - container: HTMLElement; - rendererType: RendererName; - - // ===== graph instance === - /** - * Destroy the graph instance and remove the related canvases. - * @returns - * @group Graph Instance - */ - destroy: (callback?: () => void) => void; - /** - * Update the specs (configurations). - */ - updateSpecification: (spec: Specification) => Specification; - /** - * Update the theme specs (configurations). - */ - updateTheme: (theme: ThemeOptionsOf) => void; - /** - * Update the item display mapper for a specific item type. - * @param type - The type of item (node, edge, or combo). - * @param mapper - The mapper to be updated. - */ - updateMapper: (type: ITEM_TYPE, mapper: NodeMapper | EdgeMapper | ComboMapper) => void; - /** - * Updates the state configuration for the specified item type, corresponds to the nodeState, edgeState, or comboState on the graph spec. - * @param itemType - The type of item (node, edge, or combo). - * @param stateConfig - The state configuration to update. - * @param updateType - The type of update ('mergeReplace' or 'replace'). Default is 'mergeReplace'. - */ - updateStateConfig: ( - itemType: ITEM_TYPE, - stateConfig: - | { - [stateName: string]: ((data: NodeModel) => NodeDisplayModel) | NodeShapesEncode; - } - | { - [stateName: string]: ((data: EdgeModel) => EdgeDisplayModel) | EdgeShapesEncode; - } - | { - [stateName: string]: ((data: ComboModel) => ComboDisplayModel) | ComboShapesEncode; - }, - updateType?: 'mergeReplace' | 'replace', - ) => void; - /** - * Get the copy of specs(configurations). - * @returns graph specs - */ - getSpecification: () => Specification; - /** - * Change the renderer at runtime. - * @param type renderer name - * @returns - */ - changeRenderer: (type: RendererName) => void; - - // ====== data operations ==== - /** - * Find a node's inner data according to id or function. - * @param { ID | Function} condition id or condition function - * @returns result node's inner data - * @group Data - */ - getNodeData: (condition: ID | Function) => NodeModel | undefined; - /** - * Find an edge's inner data according to id or function. - * @param { ID | Function} condition id or condition function - * @returns result edge's inner data - * @group Data - */ - getEdgeData: (condition: ID | Function) => EdgeModel | undefined; - /** - * Find a combo's inner data according to id or function. - * @param { ID | Function} condition id or condition function - * @returns result combo's inner data - * @group Data - */ - getComboData: (condition: ID | Function) => ComboModel | undefined; - /** - * Get all the nodes' inner data - * @returns all nodes' inner data on the graph - * @group Data - */ - getAllNodesData: () => NodeModel[]; - /** - * Get all the edges' inner data - * @returns all edges' inner data on the graph - * @group Data - */ - getAllEdgesData: () => EdgeModel[]; - /** - * Get all the combos' inner data - * @returns all combos' inner data on the graph - * @group Data - */ - getAllCombosData: () => ComboModel[]; - /** - * Get one-hop edge ids from a start node. - * @param nodeId id of the start node - * @returns one-hop edge ids - * @group Data - */ - getRelatedEdgesData: (nodeId: ID, direction?: 'in' | 'out' | 'both') => EdgeModel[]; - /** - * Get nearby edges from a start node using quad-tree collision detection. - * @param nodeId id of the start node - * @returns nearby edges' data array - * @group Data - */ - getNearEdgesData: (nodeId: ID, shouldBegin?: (edge: EdgeDisplayModel) => boolean) => EdgeModel[]; - /** - * Get one-hop node ids from a start node. - * @param nodeId id of the start node - * @returns one-hop node ids - * @group Data - */ - getNeighborNodesData: (nodeId: ID, direction?: 'in' | 'out' | 'both') => NodeModel[]; - /* - * Get the children's data of a combo. - * @param comboId combo id - * @returns children's data array - * @group Data - */ - getComboChildrenData: (comboId: ID) => (ComboModel | NodeModel)[]; - /** - * Get item type by id. - * @param id - * @returns 'node' | 'edge' | 'combo' - */ - getTypeById: (id: ID) => ITEM_TYPE; - /** - * Input data and render the graph. - * If there is old data, diffs and changes it. - * @param data - * @returns - * @group Data - */ - read: (data: GraphData) => void; - /** - * Change graph data. - * @param data new data - * @param type the way to change data, 'replace' means discard the old data and use the new one; 'mergeReplace' means merge the common part, remove (old - new), add (new - old) - * @param re-layout whether re-layout the nodes after data changing - * @returns - * @group Data - */ - changeData: (data: GraphData, type?: 'replace' | 'mergeReplace', relayout?: boolean) => void; - /** - * Clear the graph, means remove all the items on the graph. - * @returns - * @group Data - */ - clear: () => void; - /** - * Find items which has the state. - * @param itemType item type - * @param state state name - * @param value state value, true by default - * @param additionalFilter additional filter function - * @returns items that is the type and has the state - * @group Item - */ - findIdByState: ( - itemType: ITEM_TYPE, - state: string, - value?: string | boolean, - additionalFilter?: (model: NodeModel | EdgeModel | ComboModel) => boolean, - ) => ID[]; - /** - * Add one or more node/edge/combo data to the graph. - * @param itemType item type - * @param model user data - * @returns whether success - * @group Data - */ - addData: ( - itemType: ITEM_TYPE, - model: NodeUserModel | EdgeUserModel | ComboUserModel | NodeUserModel[] | EdgeUserModel[] | ComboUserModel[], - ) => NodeModel | EdgeModel | ComboModel | NodeModel[] | EdgeModel[] | ComboModel[]; - /** - * Remove one or more node/edge/combo data from the graph. - * @param itemType the type the item(s) to be removed. - * @param id the id or the ids' array of the items to be removed. - * @returns whether success - * @group Data - */ - removeData: (itemType: ITEM_TYPE, id: ID | ID[]) => void; - /** - * Update one or more node/edge/combo data on the graph. - * @param itemType the type the item(s) to be udated. - * @param models update configs. - * @group Data - */ - updateData: ( - itemType: ITEM_TYPE, - model: - | Partial - | Partial - | Partial[] | Partial[] | Partial[]>, - ) => NodeModel | EdgeModel | ComboModel | NodeModel[] | EdgeModel[] | ComboModel[]; - - /** - * Update one or more nodes' positions, - * do not update other styles which leads to better performance than updating positions by updateData. - * @param models new configurations with x and y for every node, which has id field to indicate the specific item. - * @param upsertAncestors whether update the ancestors in combo tree. - * @param disableAnimate whether disable the animation for this call. - * @param callback callback function after update nodes done. - * @group Data - */ - updateNodePosition: ( - models: Partial | Partial[] | Partial[]>, - upsertAncestors?: boolean, - disableAnimate?: boolean, - callback?: (model: NodeModel | EdgeModel | ComboModel, canceled?: boolean) => void, - ) => NodeModel | ComboModel | NodeModel[] | ComboModel[]; - - /** - * Update one or more combos' positions, it is achieved by move the succeed nodes. - * Do not update other styles which leads to better performance than updating positions by updateData. - * @param models new configurations with x and y for every combo, which has id field to indicate the specific item. - * @param upsertAncestors whether update the ancestors in combo tree. - * @param disableAnimate whether disable the animation for this call. - * @param callback callback function after update combos done. - * @group Data - */ - updateComboPosition: ( - models: Partial | Partial[] | Partial[]>, - upsertAncestors?: boolean, - disableAnimate?: boolean, - callback?: (model: NodeModel | EdgeModel | ComboModel) => void, - ) => NodeModel | ComboModel | NodeModel[] | ComboModel[]; - - /** - * Move one or more combos a distance (dx, dy) relatively, - * do not update other styles which leads to better performance than updating positions by updateData. - * In fact, it changes the succeed nodes positions to affect the combo's position, but not modify the combo's position directly. - * @param models new configurations with x and y for every combo, which has id field to indicate the specific item. - * @param dx the distance alone x-axis to move the combo. - * @param dy the distance alone y-axis to move the combo. - * @param upsertAncestors whether update the ancestors in the combo tree. - * @param callback callback function after move combo done. - * @group Combo - */ - moveCombo: ( - ids: ID[], - dx: number, - dy: number, - upsertAncestors?: boolean, - callback?: (model: NodeModel | EdgeModel | ComboModel, canceled?: boolean) => void, - ) => ComboModel[]; - - // ===== view operations ===== - - /** - * Move the graph with a relative vector. - * @param dx x of the relative vector - * @param dy y of the relative vector - * @param effectTiming animation configurations - * @group View - */ - translate: ( - distance: Partial<{ - dx: number; - dy: number; - dz: number; - }>, - effectTiming?: CameraAnimationOptions, - ) => Promise; - /** - * Move the graph and align to a point. - * @param point position on the canvas to align - * @param effectTiming animation configurations - * @group View - */ - translateTo: (point: PointLike, effectTiming?: CameraAnimationOptions) => Promise; - /** - * Return the current zoom level of camera. - * @returns current zoom - * @group View - */ - getZoom: () => number; - /** - * Zoom the graph with a relative ratio. - * @param ratio relative ratio to zoom - * @param center zoom center - * @param effectTiming animation configurations - * @group View - */ - zoom: (ratio: number, center?: Point, effectTiming?: CameraAnimationOptions) => Promise; - /** - * Zoom the graph to a specified ratio. - * @param toRatio specified ratio - * @param center zoom center - * @param effectTiming animation configurations - * @group View - */ - zoomTo: (toRatio: number, center?: Point, effectTiming?: CameraAnimationOptions) => Promise; - /** - * Rotate the graph with a relative angle in clockwise. - * @param angle - * @param center - * @param effectTiming - * @group View - */ - rotate: (angle: number, center?: Point, effectTiming?: CameraAnimationOptions) => Promise; - /** - * Rotate the graph to an absolute angle in clockwise. - * @param toAngle - * @param center - * @param effectTiming - * @group View - */ - rotateTo: (toAngle: number, center?: Point, effectTiming?: CameraAnimationOptions) => Promise; - - /** - * Transform the graph with a CSS-Transform-like syntax. - * @param options - * @param effectTiming - * @group View - */ - transform: (options: GraphTransformOptions, effectTiming?: CameraAnimationOptions) => Promise; - /** - * Stop the current transition of transform immediately. - * @group View - */ - stopTransformTransition: () => void; - /** - * Return the center of viewport, e.g. for a 500 * 500 canvas, its center is [250, 250]. - * @group View - */ - getViewportCenter: () => PointLike; - /** - * Fit the graph content to the view. - * @param options.padding padding while fitting - * @param options.rules rules for fitting - * @param effectTiming animation configurations - * @returns - * @group View - */ - fitView: ( - options?: { - padding?: Padding; - rules?: FitViewRules; - }, - effectTiming?: CameraAnimationOptions, - ) => Promise; - /** - * Fit the graph center to the view center. - * @param effectTiming animation configurations - * @returns - * @group View - */ - fitCenter: (boundsType?: 'render' | 'layout', effectTiming?: CameraAnimationOptions) => Promise; - /** - * Move the graph to make the item align the view center. - * @param item node/edge/combo item or its id - * @param effectTiming animation configurations - * @group View - */ - focusItem: (id: ID | ID[], effectTiming?: CameraAnimationOptions) => Promise; - /** - * Get the size of the graph canvas. - * @returns [width, height] - * @group View - */ - getSize: () => number[]; - /** - * Set the size for the graph canvas. - * @param number[] [width, height] - * @group View - */ - setSize: (size: number[]) => void; - - /** - * Get the rendering coordinate according to the canvas dom (viewport) coordinate. - * @param Point rendering coordinate - * @returns canvas dom (viewport) coordinate - * @group View - */ - getCanvasByViewport: (viewportPoint: Point) => Point; - - /** - * Get the canvas dom (viewport) coordinate according to the rendering coordinate. - * @param Point canvas dom (viewport) coordinate - * @returns rendering coordinate - * @group View - */ - getViewportByCanvas: (canvasPoint: Point) => Point; - - /** - * Get the browser coordinate according to the rendering coordinate. - * @param Point rendering coordinate - * @returns browser coordinate - * @group View - */ - getClientByCanvas: (canvasPoint: Point) => Point; - - /** - * Get the rendering coordinate according to the browser coordinate. - * @param Point browser coordinate - * @returns rendering coordinate - * @group View - */ - getCanvasByClient: (ClientPoint: Point) => Point; - - // ===== item operations ===== - /** - * Show the item(s). - * @param ids the item id(s) to be shown - * @returns - * @group Data - */ - showItem: (ids: ID | ID[], options?: { disableAnimate?: boolean; shapeIds?: string[] }) => void; - /** - * Hide the item(s). - * @param ids the item id(s) to be hidden - * @returns - * @group Item - */ - hideItem: ( - ids: ID | ID[], - options?: { - disableAnimate?: boolean; - keepKeyShape?: boolean; - keepRelated?: boolean; - shapeIds?: string[]; - }, - ) => void; - /** - * Make the item(s) to the front. - * @param ids the item id(s) to front - * @returns - * @group Item - */ - frontItem: (ids: ID | ID[]) => void; - /** - * Make the item(s) to the back. - * @param ids the item id(s) to back - * @returns - * @group Item - */ - backItem: (ids: ID | ID[]) => void; - /** - * Set state for the item(s). - * @param ids the id(s) for the item(s) to be set - * @param state the state name - * @param value state value - * @returns - * @group Item - */ - setItemState: (ids: ID | ID[], state: string, value: boolean) => void; - /** - * Get the state value for an item. - * @param id the id for the item - * @param states the state name - * @returns {boolean | string} the state value - * @group Item - */ - getItemState: (id: ID, state: string) => boolean | string; - /** - * Get all the state names with value true for an item. - * @param id the id for the item - * @returns {string[]} the state names with value true - * @group Item - */ - getItemAllStates: (id: ID) => string[]; - /** - * Clear all the states for item(s). - * @param ids the id(s) for the item(s) to be clear - * @param states the states' names, all the states wil be cleared if states is not assigned - * @returns - * @group Item - */ - clearItemState: (ids: ID | ID[], states?: string[]) => void; - - /** - * Get the rendering bbox for a node / edge / combo, or the graph (when the id is not assigned). - * @param id the id for the node / edge / combo, undefined for the whole graph - * @returns rendering bounding box. returns false if the item is not exist - */ - getRenderBBox: (id: ID | undefined, onlyKeyShape?: boolean, isTransient?: boolean) => AABB | false; - - /** - * Get the visibility for a node / edge / combo. - * @param id the id for the node / edge / combo - * @returns visibility for the item, false for invisible or un-existence for the item - */ - getItemVisible: (id: ID) => boolean; - - /** - * Get the visible shape ids in a node / edge / combo. - * @param id the id for the node / edge / combo - * @returns ids of the visible shapes - */ - getItemVisibleShapeIds: (id: ID) => string[]; - - // ===== combo operations ===== - - /** - * Add a new combo to the graph, and update the structure of the existed child in childrenIds to be the children of the new combo. - * Different from addData with combo type, this API update the succeeds' combo tree structures in the same time. - * @param model combo user data. - * @param childrenIds the ids of the children nodes / combos to move into the new combo. - * @returns whether success - * @group Combo - */ - addCombo: (model: ComboUserModel, childrenIds: ID[]) => ComboModel; - /** - * Collapse a combo. - * @param comboId combo id or ids' array. - * @group Combo - */ - collapseCombo: (comboIds: ID | ID[]) => void; - /** - * Expand a combo. - * @group Combo - * @param comboId combo id or ids' array. - * @group Combo - */ - expandCombo: (comboIds: ID | ID[]) => void; - - // ===== layout ===== - /** - * Layout the graph (with current configurations if cfg is not assigned). - * @group Layout - */ - layout: (options?: LayoutOptions, disableAnimate?: boolean) => Promise; - stopLayout: () => void; - - // ===== interaction ===== - /** - * Switch mode. - * @param mode mode name - * @returns - * @group Interaction - */ - setMode: (mode: string) => void; - /** - * Get current mode. - * @returns mode name - * @group Interaction - */ - getMode: () => string; - /** - * Set the cursor. But the cursor in item's style has higher priority. - * @param cursor - */ - setCursor: (cursor: Cursor) => void; - /** - * Add behavior(s) to mode(s). - * @param behaviors behavior names or configs - * @param modes mode names - * @returns - * @group Interaction - */ - addBehaviors: (behaviors: BehaviorOptionsOf | BehaviorOptionsOf[], modes: string | string[]) => void; - /** - * Remove behavior(s) from mode(s). - * @param behaviors behavior names or configs - * @param modes mode names - * @returns - * @group Interaction - */ - removeBehaviors: (behaviorKeys: string[], modes: string | string[]) => void; - /** - * Update a behavior on a mode. - * @param behavior behavior configs, whose name indicates the behavior to be updated - * @param mode mode name - * @returns - * @group Interaction - */ - updateBehavior: (behavior: BehaviorOptionsOf, mode?: string) => void; - - /** - * Draw or update a G shape or group to the transient canvas. - * @param type shape type or item type - * @param id new shape id or updated shape id for a interaction shape, node/edge/combo id for item interaction group drawing - * @returns upserted shape or group - * @group Interaction - */ - drawTransient: ( - type: ITEM_TYPE | SHAPE_TYPE, - id: ID, - config: { - action?: 'remove' | 'add' | 'update' | undefined; - /** Data to be merged into the transient item. */ - data?: Record; - /** Style to be merged into the transient shape. */ - style?: ShapeStyle; - /** For type: 'edge' */ - drawSource?: boolean; - /** For type: 'edge' */ - drawTarget?: boolean; - /** Only shape with id in shapeIds will be cloned while type is ITEM_TYPE. If shapeIds is not assigned, the whole item will be cloned. */ - shapeIds?: string[]; - /** Whether show the shapes in shapeIds. True by default. */ - visible?: boolean; - upsertAncestors?: boolean; - }, - canvas?: Canvas, - ) => DisplayObject; - - /** - * Add plugin(s) to graph. - * @param pluginCfgs - * @returns - * @group Plugin - */ - addPlugins: ( - pluginCfgs: { - key: string; - type: string; - [cfgName: string]: unknown; - }[], - ) => void; - - /** - * Remove plugin(s) from graph. - * @param pluginCfgs - * @returns - * @group Plugin - */ - removePlugins: (pluginKeys: string[]) => void; - - /** - * Update one plugin of the graph. - * @param pluginCfgs - * @returns - * @group Plugin - */ - updatePlugin: (pluginCfg: { key: string; type: string; [cfgName: string]: unknown }) => void; - - // ===== history operations ===== - - /** - * Determine if history (redo/undo) is enabled. - * @group History - */ - isHistoryEnabled: () => void; - - /** - * Push the operation(s) onto the specified stack - * @param cmd commands to be pushed - * @param stackType undo/redo stack - * @group History - */ - pushStack: (cmd: Command[], stackType: StackType) => void; - /** - * Pause stacking operation. - * @group History - */ - pauseStack: () => void; - /** - * Resume stacking operation. - * @group History - */ - resumeStack: () => void; - /** - * Execute a callback without allowing any stacking operations. - * @param callback - * @group History - */ - executeWithNoStack: (callback: () => void) => void; - /** - * Retrieve the current redo stack which consists of operations that could be undone - * @group History - */ - getUndoStack: () => void; - - /** - * Retrieve the current undo stack which consists of operations that were undone - * @group History - */ - getRedoStack: () => void; - - /** - * Retrieve the complete history stack - * @returns - * @group History - */ - getStack: () => void; - - /** - * Revert the last n operation(s) on the graph. - * @returns - * @group History - */ - undo: () => void; - - /** - * Restore the operation that was last n reverted on the graph. - * @returns - * @group History - */ - redo: () => void; - - /** - * Indicate whether there are any actions available in the undo stack. - * @group History - */ - canUndo: () => void; - - /** - * Indicate whether there are any actions available in the redo stack. - * @group History - */ - canRedo: () => void; - - /** - * Begin a historyBatch operation. - * Any operations performed between `startHistoryBatch` and `stopHistoryBatch` are grouped together. - * treated as a single operation when undoing or redoing. - * @group History - */ - startHistoryBatch: () => void; - - /** - * End a historyBatch operation. - * Any operations performed between `startHistoryBatch` and `stopHistoryBatch` are grouped together. - * treated as a single operation when undoing or redoing. - * @group History - */ - stopHistoryBatch: () => void; - - /** - * Execute a provided function within a batched context - * All operations performed inside callback will be treated as a composite operation - * more convenient way without manually invoking `startHistoryBatch` and `stopHistoryBatch`. - * @param callback The func containing operations to be batched together. - * @group History - */ - historyBatch: (callback: () => void) => void; - - /** - * Execute a provided function within a batched context - * All operations performed inside callback will be treated as a composite operation - * more convenient way without manually invoking `startHistoryBatch` and `stopHistoryBatch`. - * @param callback The func containing operations to be batched together. - * @group History - */ - cleanHistory: (stackType?: StackType) => void; - // ===== tree operations ===== - /** - * Collapse sub tree(s). - * @param ids Root id(s) of the sub trees. - * @param disableAnimate Whether disable the animations for this operation. - * @returns - * @group Tree - */ - collapse: (ids: ID | ID[], disableAnimate?: boolean) => void; - /** - * Expand sub tree(s). - * @param ids Root id(s) of the sub trees. - * @param disableAnimate Whether disable the animations for this operation. - * @returns - * @group Tree - */ - expand: (ids: ID | ID[], disableAnimate?: boolean) => void; -} +export type { Graph } from '../runtime/graph'; diff --git a/packages/g6/src/types/history.ts b/packages/g6/src/types/history.ts deleted file mode 100644 index 62c8d353e2..0000000000 --- a/packages/g6/src/types/history.ts +++ /dev/null @@ -1,31 +0,0 @@ -export type StackCfg = { - /** A number representing the size of the stack. */ - stackSize?: number; - /** Indicate whether the stack is active. If active, operations can be pushed onto the stack; otherwise, cannot. */ - stackActive?: boolean; - /** - * Allows finer-grained control over the ignore option. - * If an API is in excludes, even if its operation type is not ignored, it will not be put on the stack - */ - excludes?: string[]; - includes?: string[]; - /** ignore* is a global setting that indicates whether to ignore a certain type of operation */ - ignoreAdd?: boolean; - /** A boolean indicating whether to ignore remove operations. */ - ignoreRemove?: boolean; - /** A boolean indicating whether to ignore update operations. */ - ignoreUpdate?: boolean; - /** A boolean indicating whether to ignore state change operations.*/ - ignoreStateChange?: boolean; - /** A boolean indicating whether to ignore layer change operations. */ - ignoreLayerChange?: boolean; - /** A boolean indicating whether to ignore display change operations. */ - ignoreDisplayChange?: boolean; -}; - -export enum STACK_TYPE { - 'redo' = 'redo', - 'undo' = 'undo', -} - -export type StackType = `${STACK_TYPE}`; diff --git a/packages/g6/src/types/index.ts b/packages/g6/src/types/index.ts index 429ad135b6..693d221534 100644 --- a/packages/g6/src/types/index.ts +++ b/packages/g6/src/types/index.ts @@ -23,10 +23,9 @@ export type { EdgeUserModel, } from './edge'; export type { ICanvasEventType, IG6GraphEvent } from './event'; -export type { IGraph } from './graph'; -export type { StackCfg } from './history'; +export type { Graph } from './graph'; export { isImmediatelyInvokedLayoutOptions, isLayoutWorkerized } from './layout'; // function 不应该放在 types 文件下面 -export type { ImmediatelyInvokedLayoutOptions, LayoutOptions, StandardLayoutOptions } from './layout'; +export type { ImmediatelyInvokedLayoutOptions, LayoutOptions, STDLayoutOptions } from './layout'; export type { NodeDisplayModel, NodeEncode, diff --git a/packages/g6/src/types/layout.ts b/packages/g6/src/types/layout.ts index 144b45b285..80881f71d2 100644 --- a/packages/g6/src/types/layout.ts +++ b/packages/g6/src/types/layout.ts @@ -1,5 +1,5 @@ -import { IAnimationEffectTiming } from '@antv/g'; -import { +import type { IAnimationEffectTiming } from '@antv/g'; +import type { CircularLayoutOptions, ConcentricLayoutOptions, D3ForceLayoutOptions, @@ -13,34 +13,9 @@ import { RadialLayoutOptions, RandomLayoutOptions, } from '@antv/layout'; -import { GraphCore } from './data'; +import type { GraphCore } from './data'; -type Animatable = { - /** - * Make layout animated. For layouts with iterations, transitions will happen between ticks. - */ - animated?: boolean; - - /** - * Effect timing of animation for layouts without iterations. - * @see https://g.antv.antgroup.com/api/animation/waapi#effecttiming - */ - animationEffectTiming?: Partial; -}; - -type Workerized = { - /** - * Make layout running in WebWorker. - */ - workerEnabled?: boolean; - - /** - * Iterations for iterable layouts such as Force. - */ - iterations?: number; -}; - -type PureLayoutOptions = +type BuiltInLayoutOptions = | CircularLayout | RandomLayout | ConcentricLayout @@ -50,30 +25,20 @@ type PureLayoutOptions = | FruchtermanLayout | D3ForceLayout | ForceLayout - | ForceAtlas2 - | CustomLayout; + | ForceAtlas2; +// TODO 后面可能不需要,如果手动布局直接更新数据中位置即可 export type ImmediatelyInvokedLayoutOptions = { /** * like an IIFE. */ execute: (graph: GraphCore, options?: any) => Promise; -} & Animatable & { - presetLayout?: Partial; - }; +} & Animatable & + PresetLayoutOptions; -type CustomLayout = { - type: string; - [option: string]: any; -}; +export type STDLayoutOptions = BuiltInLayoutOptions & Animatable & Workerized & PresetLayoutOptions; -export type StandardLayoutOptions = PureLayoutOptions & - Animatable & - Workerized & { - presetLayout?: Partial; - }; - -export type LayoutOptions = StandardLayoutOptions | ImmediatelyInvokedLayoutOptions; +export type LayoutOptions = STDLayoutOptions | ImmediatelyInvokedLayoutOptions; /** * @@ -87,7 +52,7 @@ export function isImmediatelyInvokedLayoutOptions(options: any): options is Imme * * @param options */ -export function isLayoutWorkerized(options: StandardLayoutOptions) { +export function isLayoutWorkerized(options: STDLayoutOptions) { return ( [ 'circular', @@ -146,6 +111,37 @@ interface ForceAtlas2 extends ForceAtlas2LayoutOptions { type: 'forceAtlas2'; } -export interface LayoutRegistry { - [key: string]: Layout; +type Animatable = { + /** + * Make layout animated. For layouts with iterations, transitions will happen between ticks. + */ + animated?: boolean; + + /** + * Effect timing of animation for layouts without iterations. + * @see https://g.antv.antgroup.com/api/animation/waapi#effecttiming + */ + animationEffectTiming?: Partial; +}; + +type Workerized = { + /** + * Make layout running in WebWorker. + */ + workerEnabled?: boolean; + + /** + * Iterations for iterable layouts such as Force. + */ + iterations?: number; +}; + +interface PresetLayoutOptions { + presetLayout?: Partial; +} + +export interface LayoutRegistry { + [key: string]: Layout & { + type?: string; + }; } diff --git a/packages/g6/src/types/palette.ts b/packages/g6/src/types/palette.ts new file mode 100644 index 0000000000..41b29e8856 --- /dev/null +++ b/packages/g6/src/types/palette.ts @@ -0,0 +1,43 @@ +// TODO +declare type BuiltInPalette = + | 'blues' + | 'brBG' + | 'buGn' + | 'buPu' + | 'gnBu' + | 'greens' + | 'greys' + | 'oranges' + | 'orRd' + | 'piYG' + | 'pRGn' + | 'puBu' + | 'puBuGn' + | 'puOr' + | 'puRd' + | 'purples' + | 'rdBu' + | 'rdGy' + | 'rdPu' + | 'rdYlBu' + | 'rdYlGn' + | 'reds' + | 'spectral' + | 'ylGn' + | 'ylGnBu' + | 'ylOrBr' + | 'ylOrRd' + // Only for continuous palette + | 'rainbow' + | 'sinebow' + | 'spectral' + | 'turbo'; + +/** + * 色板,可以是色板名或者颜色数组,也可以是一个生成颜色的函数 + * + * Palette, can be palette name or color array or a function to generate color + */ +export type PaletteColor = BasePaletteColor; + +type BasePaletteColor = BuiltInPalette | string | string[] | ((value: number) => string); diff --git a/packages/g6/src/types/plugin.ts b/packages/g6/src/types/plugin.ts index dd1a6cd1aa..4318cd3eb6 100644 --- a/packages/g6/src/types/plugin.ts +++ b/packages/g6/src/types/plugin.ts @@ -1,10 +1,10 @@ import { deepMix, each } from '@antv/util'; -import { IGraph } from './graph'; +import { Graph } from './graph'; export interface IPluginBaseConfig { container?: HTMLElement | string | null; className?: string; - graph?: IGraph; + graph?: Graph; [key: string]: any; } @@ -13,6 +13,8 @@ interface EventMapType { } export abstract class Plugin { + static type: string; + public key: string; static required: boolean = false; @@ -23,7 +25,7 @@ export abstract class Plugin { public destroyed: boolean; - public graph: IGraph; + public graph: Graph; /** * Constructor for the Plugin Base Class. @@ -53,8 +55,9 @@ export abstract class Plugin { /** * Init. + * @param graph */ - public init(graph: IGraph) { + public init(graph: Graph) { this.graph = graph; } diff --git a/packages/g6/src/types/position.ts b/packages/g6/src/types/position.ts new file mode 100644 index 0000000000..592bcde235 --- /dev/null +++ b/packages/g6/src/types/position.ts @@ -0,0 +1,10 @@ +export type Position = + | 'top' + | 'bottom' + | 'left' + | 'right' + | 'center' + | 'top-left' + | 'top-right' + | 'bottom-left' + | 'bottom-right'; diff --git a/packages/g6/src/types/spec.ts b/packages/g6/src/types/spec.ts index 5baecb8bb3..8bca2158b7 100644 --- a/packages/g6/src/types/spec.ts +++ b/packages/g6/src/types/spec.ts @@ -7,10 +7,9 @@ import { DataConfig, DataLifecycleType, TransformerFn } from './data'; import { EdgeDisplayModel, EdgeEncode, EdgeModel, EdgeShapesEncode } from './edge'; import { LayoutOptions } from './layout'; import { NodeDisplayModel, NodeEncode, NodeModel, NodeShapesEncode } from './node'; -import { ThemeOptionsOf, ThemeRegistry } from './theme'; +import { ThemeOptionsOf, ThemeSolverRegistry } from './theme'; import { FitViewRules, GraphAlignment } from './view'; -import { StackCfg } from './history'; import { Plugin } from './plugin'; import { RendererName } from './render'; @@ -18,7 +17,7 @@ export type NodeMapper = ((data: NodeModel) => NodeDisplayModel) | NodeEncode; export type EdgeMapper = ((data: EdgeModel) => EdgeDisplayModel) | EdgeEncode; export type ComboMapper = ((data: ComboModel) => ComboDisplayModel) | ComboEncode; -export interface Specification { +export interface Specification { container?: string | HTMLElement; backgroundCanvas?: Canvas; canvas?: Canvas; @@ -121,8 +120,4 @@ export interface Specification; - - enableStack?: boolean; - - stackCfg?: StackCfg; } diff --git a/packages/g6/src/types/stdlib.ts b/packages/g6/src/types/stdlib.ts deleted file mode 100644 index b74b216ed5..0000000000 --- a/packages/g6/src/types/stdlib.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { BehaviorRegistry } from './behavior'; -import { ThemeRegistry } from './theme'; - -export type StdLibCategory = - | 'transform' - | 'behavior' - | 'layout' - | 'node' - | 'edge' - | 'combo' - | 'theme' - | 'themeSolver' - | 'plugin'; - -export interface Lib { - behaviors?: BehaviorRegistry; - themes?: ThemeRegistry; - // TODO: type templates - transforms?: Record; - layouts?: Record; - nodes?: Record; - edges?: Record; - combos?: Record; - plugins?: Record; -} diff --git a/packages/g6/src/types/theme.ts b/packages/g6/src/types/theme.ts index af0806c4d8..adc6cf4c15 100644 --- a/packages/g6/src/types/theme.ts +++ b/packages/g6/src/types/theme.ts @@ -24,6 +24,9 @@ export abstract class Theme { * @example { 'drag-node': DragNodeBehavior, 'my-drag-node': MyDragNodeBehavior } */ export interface ThemeRegistry { + [type: string]: ThemeSpecification; +} +export interface ThemeSolverRegistry { [type: string]: typeof BaseThemeSolver; } @@ -31,13 +34,13 @@ export interface ThemeRegistry { * Type templates, input registry table, output configure type. * @example ThemeOptionsOf<{ 'drag-node': typeof DragNodeBehavior }> // 'drag-node' | { type: 'drag-node', key?: 'ctrl' | 'shift' } */ -export type ThemeOptionsOf = +export type ThemeOptionsOf = | Extract | { [K in keyof T]: T[K] extends { new (options: infer O): any } ? O & { type: K } : { type: K }; }[Extract]; -export type ThemeObjectOptionsOf = { +export type ThemeObjectOptionsOf = { [K in keyof T]: T[K] extends { new (options: infer O): any } ? O & { type: K; key: string } : never; }[Extract]; @@ -156,6 +159,7 @@ export interface ComboThemeSpecifications { * Theme specification with node / edge / combo palette and style mappers. And also canvas DOM CSS settings. */ export interface ThemeSpecification { + type?: string; node?: NodeThemeSpecifications; edge?: EdgeThemeSpecifications; combo?: ComboThemeSpecifications; diff --git a/packages/g6/src/utils/data.ts b/packages/g6/src/utils/data.ts index b111c4dfe5..514a417918 100644 --- a/packages/g6/src/utils/data.ts +++ b/packages/g6/src/utils/data.ts @@ -3,7 +3,7 @@ import { ID, TreeData } from '@antv/graphlib'; import { isArray } from '@antv/util'; import { NodeModel, NodeUserModel } from '../types'; import { DataLifecycleType, GraphCore, GraphData } from '../types/data'; -import { IGraph } from '../types/graph'; +import { Graph } from '../types/graph'; import { NodeUserModelData } from '../types/node'; /** @@ -68,7 +68,7 @@ export const graphCoreTreeDfs = ( * @param fn will be called while visiting each node * @param mode 'TB' - visit from top to bottom; 'BT' - visit from bottom to top; */ -export const graphComboTreeDfs = (graph: IGraph, nodes: NodeUserModel[], fn, mode: 'TB' | 'BT' = 'TB') => { +export const graphComboTreeDfs = (graph: Graph, nodes: NodeUserModel[], fn, mode: 'TB' | 'BT' = 'TB') => { if (!nodes?.length) return; nodes.forEach((node) => { if (mode === 'TB') fn(node); // Traverse from top to bottom @@ -86,7 +86,7 @@ export const graphComboTreeDfs = (graph: IGraph, nodes: NodeUserModel[], fn, mod * @param mode 'TB' - visit from top to bottom; 'BT' - visit from bottom to top; */ export const traverseAncestorsAndSucceeds = ( - graph: IGraph, + graph: Graph, graphCore: GraphCore, nodes: NodeUserModel[], fn, @@ -98,7 +98,7 @@ export const traverseAncestorsAndSucceeds = ( return; }; -export const traverseGraphAncestors = (graph: IGraph, nodes: NodeUserModel[], fn) => { +export const traverseGraphAncestors = (graph: Graph, nodes: NodeUserModel[], fn) => { if (!nodes?.length) return; nodes.forEach((node) => { if (!node.data.parentId) return; diff --git a/packages/g6/src/utils/event.ts b/packages/g6/src/utils/event.ts index 4855fbcab5..27e191eaeb 100644 --- a/packages/g6/src/utils/event.ts +++ b/packages/g6/src/utils/event.ts @@ -12,7 +12,7 @@ import { TreeStructureChanged, TreeStructureDetached, } from '@antv/graphlib'; -import { IG6GraphEvent, IGraph, NodeModelData } from '../types'; +import { Graph, IG6GraphEvent, NodeModelData } from '../types'; import { GraphCore } from '../types/data'; import { EdgeModelData } from '../types/edge'; @@ -55,7 +55,7 @@ export const getItemInfoFromElement = (element: IElement): ItemInfo | null => { * @param graph Graph instance. * @returns Contextmenu event props. */ -export const getContextMenuEventProps = (event: IG6GraphEvent, graph: IGraph): IG6GraphEvent => { +export const getContextMenuEventProps = (event: IG6GraphEvent, graph: Graph): IG6GraphEvent => { return { ...event, type: 'contextmenu', diff --git a/packages/g6/src/utils/extend.ts b/packages/g6/src/utils/extend.ts deleted file mode 100644 index a1fcf0e6c4..0000000000 --- a/packages/g6/src/utils/extend.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { registry } from '../plugin'; -import { Graph } from '../runtime/graph'; -import { BehaviorRegistry } from '../types/behavior'; -import { EdgeRegistry } from '../types/edge'; -import { LayoutRegistry } from '../types/layout'; -import { NodeRegistry } from '../types/node'; -import { PluginRegistry } from '../types/plugin'; -import { ThemeRegistry } from '../types/theme'; - -/** - * Extend graph class with custom libs (extendLibrary), and extendLibrary will be merged into useLib. - * B1 is the Behavior lib from user, B2 is the Behavior lib of the graph to be extended(built-in graph) - * TODO: more templates, and might be merged to be two templates for the whole extendLibrary - * @param GraphClass - * @param extendLibrary - * @param extendLibrary.behaviors - * @param extendLibrary.themeSolvers - * @param extendLibrary.nodes - * @param extendLibrary.edges - * @param extendLibrary.layouts - * @param extendLibrary.plugins - */ -export const extend = < - B1 extends BehaviorRegistry, - B2 extends BehaviorRegistry, - T1 extends ThemeRegistry, - T2 extends ThemeRegistry, ->( - GraphClass: typeof Graph, - extendLibrary: { - behaviors?: B1; - themeSolvers?: T1; - nodes?: NodeRegistry; - edges?: EdgeRegistry; - layouts?: LayoutRegistry; - plugins?: PluginRegistry; - }, -): typeof Graph => { - // merged the extendLibrary to useLib for global usage - Object.keys(extendLibrary).forEach((cat) => { - registry.useLib[cat] = Object.assign({}, registry.useLib[cat], extendLibrary[cat] || {}); - Object.keys(registry.useLib[cat]).forEach((type) => { - const extension = registry.useLib[cat][type]; - extension.type = type; - }); - }); - return GraphClass as any; -}; diff --git a/packages/g6/src/utils/extension.ts b/packages/g6/src/utils/extension.ts index c8dc569cc3..35e8c1d892 100644 --- a/packages/g6/src/utils/extension.ts +++ b/packages/g6/src/utils/extension.ts @@ -1,25 +1,28 @@ -import { isFunction } from '@antv/util'; -import { StdLibCategory } from '../types/stdlib'; +import { PluginEntry, STDPluginCategory, getRegisterPlugin, getRegisterPlugins } from '../plugin/register'; /** - * Get one extension from a (std)lib. - * @param config extension's config - * @param lib any lib - * @param {StdLibCategory} cat category of the extension - * @returns + * 获取指定类型的指定插件类 + * + * Get a specific plugin class of a specific category. + * @param config - 插件配置 | Plugin configuration. + * @param category - 插件类型 | Plugin category. + * @returns - 插件类 | A plugin class. */ -export const getExtension = (config: string | Function | object, lib, cat: StdLibCategory) => { - const catKey = `${cat}s`; - // TODO: whether keep function type config? - if (isFunction(config)) { - return config; - } +export const getExtension = ( + config: string | object, + category: T, +): PluginEntry['plugin'] => { const type = typeof config === 'string' ? config : (config as any).type; - const ext = lib[catKey]?.[type]; - return ext; + return getRegisterPlugin(category, type)?.plugin; }; -export const getCatExtensions = (lib, cat: StdLibCategory) => { - const catKey = `${cat}s`; - return lib[catKey]; +/** + * 获取指定类型的插件类集合 + * + * Get a collection of plugin classes of a specific category. + * @param category - 插件类型 | Plugin category to retrieve. + * @returns - 插件类集合 | A collection of plugin classes. + */ +export const getExtensionsByCategory = (category: T): PluginEntry['plugin'][] => { + return getRegisterPlugins()?.[`${category}s`]?.map((item) => item.plugin); }; diff --git a/packages/g6/src/utils/index.ts b/packages/g6/src/utils/index.ts index ec1e8514ef..5e13645f48 100644 --- a/packages/g6/src/utils/index.ts +++ b/packages/g6/src/utils/index.ts @@ -10,7 +10,6 @@ export { traverseGraphAncestors, treeData2GraphData, } from './data'; -export { extend } from './extend'; export { getEdgesBetween } from './item'; export { transform } from './matrix'; export { mock } from './mock'; diff --git a/packages/g6/src/utils/item.ts b/packages/g6/src/utils/item.ts index 0df5a4dacd..df56e0d5a0 100644 --- a/packages/g6/src/utils/item.ts +++ b/packages/g6/src/utils/item.ts @@ -4,7 +4,7 @@ import { uniqueId } from '@antv/util'; import Combo from '../item/combo'; import Edge from '../item/edge'; import Node from '../item/node'; -import { IGraph } from '../types'; +import { Graph } from '../types'; import { GraphCore } from '../types/data'; import { getCombinedBoundsByItem } from './shape'; @@ -14,7 +14,7 @@ import { getCombinedBoundsByItem } from './shape'; * @param ids the end nodes/combos id list * @returns id list of the edges meet the condition */ -export const getEdgesBetween = (graph: IGraph, ids: ID[]): ID[] => { +export const getEdgesBetween = (graph: Graph, ids: ID[]): ID[] => { const edgeIdSet = new Set(); ids.forEach((endId) => { const edgesData = graph.getRelatedEdgesData(endId); diff --git a/packages/g6/src/utils/shape.ts b/packages/g6/src/utils/shape.ts index 9a424e4f49..3fe9ec1eb4 100644 --- a/packages/g6/src/utils/shape.ts +++ b/packages/g6/src/utils/shape.ts @@ -20,8 +20,8 @@ import { DEFAULT_LABEL_BG_PADDING } from '../constant'; import Combo from '../item/combo'; import Edge from '../item/edge'; import Node from '../item/node'; -import { AnimateTiming, ComboDisplayModel, ComboModelData, IAnimates, IGraph } from '../types'; -import { Padding, Point, StandardPadding } from '../types/common'; +import { AnimateTiming, ComboDisplayModel, ComboModelData, Graph, IAnimates } from '../types'; +import { Padding, Point, STDPadding } from '../types/common'; import { EdgeDisplayModel, EdgeModelData, EdgeShapeMap } from '../types/edge'; import { GShapeStyle, ItemShapeStyles, SHAPE_TYPE, SHAPE_TYPE_3D, ShapeStyle, State } from '../types/item'; import { NodeDisplayModel, NodeModelData, NodeShapeMap } from '../types/node'; @@ -273,7 +273,7 @@ export const updateShapes = ( */ export const formatPadding = ( value: Padding, - defaultArr: StandardPadding = DEFAULT_LABEL_BG_PADDING, + defaultArr: STDPadding = DEFAULT_LABEL_BG_PADDING, ): [number, number, number, number] => { if (isArray(value)) { switch (value.length) { @@ -681,7 +681,7 @@ export const combineBounds = ( * @returns combined bounds */ export const getCombinedBoundsByData = ( - graph: IGraph, + graph: Graph, models: (Node | Combo)[], ): | { diff --git a/packages/g6/tests/demo/behaviors/activate-relations.ts b/packages/g6/tests/demo/behaviors/activate-relations.ts index 8c79d42025..e5665db419 100644 --- a/packages/g6/tests/demo/behaviors/activate-relations.ts +++ b/packages/g6/tests/demo/behaviors/activate-relations.ts @@ -1,14 +1,10 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; -export default (context: TestCaseContext) => { - const ExtGraph = extend(Graph, { - behaviors: { - 'activate-relations': Extensions.ActivateRelations, - }, - }); +register('behavior', 'activate-relations', Extensions.ActivateRelations); - return new ExtGraph({ +export default (context: TestCaseContext) => { + return new Graph({ ...context, layout: { type: 'grid', diff --git a/packages/g6/tests/demo/behaviors/brush-select.ts b/packages/g6/tests/demo/behaviors/brush-select.ts index d710162f04..323382211d 100644 --- a/packages/g6/tests/demo/behaviors/brush-select.ts +++ b/packages/g6/tests/demo/behaviors/brush-select.ts @@ -1,16 +1,11 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; -export default (context: TestCaseContext) => { - const ExtGraph = extend(Graph, { - behaviors: { - 'brush-select': Extensions.BrushSelect, - }, - plugins: { - grid: Extensions.Grid, - }, - }); - return new ExtGraph({ +register('behavior', 'brush-select', Extensions.BrushSelect); +register('widget', 'grid', Extensions.Grid); + +export default (context: TestCaseContext) => { + return new Graph({ ...context, // plugins: ['grid'], layout: { diff --git a/packages/g6/tests/demo/behaviors/create-edge.ts b/packages/g6/tests/demo/behaviors/create-edge.ts index 53fdcf03ed..a816a128ba 100644 --- a/packages/g6/tests/demo/behaviors/create-edge.ts +++ b/packages/g6/tests/demo/behaviors/create-edge.ts @@ -1,6 +1,9 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; +register('behavior', 'create-edge', Extensions.CreateEdge); +register('behavior', 'brush-select', Extensions.BrushSelect); + export default (context: TestCaseContext, options) => { const createEdgeOptions = options || { trigger: 'click', @@ -9,13 +12,7 @@ export default (context: TestCaseContext, options) => { createActualEventName: 'aftercreate', cancelCreateEventName: 'cancelcreate', }; - const ExtGraph = extend(Graph, { - behaviors: { - 'create-edge': Extensions.CreateEdge, - 'brush-select': Extensions.BrushSelect, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ ...context, layout: { type: 'grid', diff --git a/packages/g6/tests/demo/behaviors/scroll-canvas.ts b/packages/g6/tests/demo/behaviors/scroll-canvas.ts index a90aa9eaa0..bfe5c07326 100644 --- a/packages/g6/tests/demo/behaviors/scroll-canvas.ts +++ b/packages/g6/tests/demo/behaviors/scroll-canvas.ts @@ -1,13 +1,10 @@ -import { extend, Extensions, Graph } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; +register('behavior', 'scroll-canvas', Extensions.ScrollCanvas); + export default (context: TestCaseContext) => { - const ExtGraph = extend(Graph, { - behaviors: { - 'scroll-canvas': Extensions.ScrollCanvas, - }, - }); - return new ExtGraph({ + return new Graph({ ...context, type: 'graph', layout: { diff --git a/packages/g6/tests/demo/behaviors/shortcuts-call.ts b/packages/g6/tests/demo/behaviors/shortcuts-call.ts index 0b6266b11f..32e9622e71 100644 --- a/packages/g6/tests/demo/behaviors/shortcuts-call.ts +++ b/packages/g6/tests/demo/behaviors/shortcuts-call.ts @@ -1,13 +1,10 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; +register('behavior', 'shortcuts-call', Extensions.ShortcutsCall); + export default (context: TestCaseContext, options = {}) => { - const ExtGraph = extend(Graph, { - behaviors: { - 'shortcuts-call': Extensions.ShortcutsCall, - }, - }); - return new ExtGraph({ + return new Graph({ width: 500, height: 500, layout: { diff --git a/packages/g6/tests/demo/behaviors/zoom-canvas.ts b/packages/g6/tests/demo/behaviors/zoom-canvas.ts index b6d04e48e5..1ba602d1c8 100644 --- a/packages/g6/tests/demo/behaviors/zoom-canvas.ts +++ b/packages/g6/tests/demo/behaviors/zoom-canvas.ts @@ -1,6 +1,9 @@ -import { extend, Extensions, Graph } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; +register('behavior', 'zoom-canvas', Extensions.ZoomCanvas); +register('transform', 'transform-v4-data', Extensions.TransformV4Data); + export default (context: TestCaseContext) => { const data = { nodes: [ @@ -42,15 +45,7 @@ export default (context: TestCaseContext) => { ], }; - const ExtGraph = extend(Graph, { - transforms: { - 'transform-v4-data': Extensions.TransformV4Data, - }, - behaviors: { - 'zoom-canvas': Extensions.ZoomCanvas, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ ...context, node: { lodStrategy: {}, diff --git a/packages/g6/tests/demo/combo/combo-basic.ts b/packages/g6/tests/demo/combo/combo-basic.ts index b5a58ede5e..6cc62e3f62 100644 --- a/packages/g6/tests/demo/combo/combo-basic.ts +++ b/packages/g6/tests/demo/combo/combo-basic.ts @@ -1,4 +1,6 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; + +register('behavior', 'hover-activate', Extensions.HoverActivate); export default ( context, @@ -8,12 +10,7 @@ export default ( } = {}, ) => { const { disableAnimate = false, comboType = 'circle-combo' } = options; - const ExtGraph = extend(Graph, { - behaviors: { - 'hover-activate': Extensions.HoverActivate, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ ...context, layout: { type: 'grid', diff --git a/packages/g6/tests/demo/combo/combo-rect.ts b/packages/g6/tests/demo/combo/combo-rect.ts index 315f2b08b3..f90fa49a0d 100644 --- a/packages/g6/tests/demo/combo/combo-rect.ts +++ b/packages/g6/tests/demo/combo/combo-rect.ts @@ -1,18 +1,15 @@ -import { Extensions, Graph, extend, stdLib } from '../../../src/index'; +import { Extensions, Graph, getRegisterPlugin, register } from '../../../src/index'; import { data as comboData } from '../../datasets/combo-data'; import { container, height, width } from '../../datasets/const'; +register('behavior', 'hover-activate', Extensions.HoverActivate); +register('layout', 'concentric', Extensions.ConcentricLayout); +register('layout', 'comboCombined', Extensions.ComboCombinedLayout); + +const layoutClass = getRegisterPlugin('layout', 'concentric').plugin; + export default () => { - const ExtGraph = extend(Graph, { - behaviors: { - 'hover-activate': Extensions.HoverActivate, - }, - layouts: { - concentric: Extensions.ConcentricLayout, - comboCombined: Extensions.ComboCombinedLayout, - }, - }); const graph = new Graph({ container, width, @@ -20,8 +17,7 @@ export default () => { type: 'graph', layout: { type: 'comboCombined', - // innerLayout: 'concentric', - innerLayout: new stdLib.layouts['concentric'](), + innerLayout: layoutClass, }, node: { labelShape: { diff --git a/packages/g6/tests/demo/data/data-from-v4.ts b/packages/g6/tests/demo/data/data-from-v4.ts index b52a3fed59..6a70861766 100644 --- a/packages/g6/tests/demo/data/data-from-v4.ts +++ b/packages/g6/tests/demo/data/data-from-v4.ts @@ -1,5 +1,5 @@ import { Layout, LayoutMapping } from '@antv/layout'; -import { Extensions, Graph, GraphCore, extend } from '../../../src/index'; +import { Extensions, Graph, GraphCore, register } from '../../../src/index'; import { GraphDataChanges } from '../../../src/types/data'; import { TestCaseContext } from '../interface'; @@ -1409,23 +1409,15 @@ const data2 = { ], }; -export default (context: TestCaseContext, options?: {}) => { - const CustomGraph = extend(Graph, { - transforms: { - 'edge-cluster': edgeClusterTransform, - 'transform-v4-data': Extensions.TransformV4Data, - 'map-node-size': Extensions.MapNodeSize, - }, - edges: { - 'quadratic-edge': Extensions.QuadraticEdge, - }, - layouts: { - 'line-layout': LineLayout, - }, - }); +register('transform', 'edge-cluster', edgeClusterTransform); +register('transform', 'transform-v4-data', Extensions.TransformV4Data); +register('transform', 'map-node-size', Extensions.MapNodeSize); +register('edge', 'quadratic-edge', Extensions.QuadraticEdge); +register('layout', 'line-layout', LineLayout); +export default (context: TestCaseContext, options?: {}) => { const { width, height } = context; - const graph = new CustomGraph({ + const graph = new Graph({ ...context, transforms: [ 'transform-v4-data', diff --git a/packages/g6/tests/demo/data/process-parallel-edges.ts b/packages/g6/tests/demo/data/process-parallel-edges.ts index 4b0ab91139..b6a8114fe9 100644 --- a/packages/g6/tests/demo/data/process-parallel-edges.ts +++ b/packages/g6/tests/demo/data/process-parallel-edges.ts @@ -1,4 +1,4 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; const data = { @@ -83,18 +83,12 @@ for (let i = 0; i < 5; i++) { }); } -export default (context: TestCaseContext) => { - const ExtGraph = extend(Graph, { - transforms: { - 'process-parallel-edges': Extensions.ProcessParallelEdges, - }, - edges: { - 'quadratic-edge': Extensions.QuadraticEdge, - 'loop-edge': Extensions.LoopEdge, - }, - }); +register('transform', 'process-parallel-edges', Extensions.ProcessParallelEdges); +register('edge', 'quadratic-edge', Extensions.QuadraticEdge); +register('edge', 'loop-edge', Extensions.LoopEdge); - const graph = new ExtGraph({ +export default (context: TestCaseContext) => { + const graph = new Graph({ ...context, data, transforms: [ diff --git a/packages/g6/tests/demo/demo/demo.ts b/packages/g6/tests/demo/demo/demo.ts index 63a3b1d5a0..b9a125219b 100644 --- a/packages/g6/tests/demo/demo/demo.ts +++ b/packages/g6/tests/demo/demo/demo.ts @@ -1,6 +1,6 @@ import { initThreads, supportsThreads } from '@antv/layout-wasm'; import Stats from 'stats.js'; -import { Extensions, Graph, GraphData, extend } from '../../../src/index'; +import { Extensions, Graph, GraphData, register } from '../../../src/index'; import { RendererName } from '../../../src/types/render'; import { container, width } from '../../datasets/const'; @@ -159,26 +159,18 @@ const defaultTheme = { }; let currentTheme = defaultTheme; +register('behavior', 'brush-select', Extensions.BrushSelect); +register('behavior', 'hover-activate', Extensions.HoverActivate); +register('layout', 'force-wasm', Extensions.ForceLayout); +register('transform', 'data-format', dataFormat); + const create2DGraph = ( getNodeAnimates = getDefaultNodeAnimates, getEdgeAnimates = getDefaultEdgeAnimates, theme = defaultTheme, rendererType: RendererName = 'canvas', ) => { - const ExtGraph = extend(Graph, { - behaviors: { - 'brush-select': Extensions.BrushSelect, - 'hover-activate': Extensions.HoverActivate, - }, - layouts: { - 'force-wasm': Extensions.ForceLayout, - }, - transforms: { - 'data-format': dataFormat, - }, - }); - console.log('theme', { ...defaultTheme, ...theme }); - const graph = new ExtGraph({ + const graph = new Graph({ container: container as HTMLElement, // width, // height: 1400, @@ -298,23 +290,17 @@ const create2DGraph = ( return graph; }; +register('behavior', 'brush-select', Extensions.BrushSelect); +register('behavior', 'hover-activate', Extensions.HoverActivate); +register('layout', 'force-wasm', Extensions.ForceLayout); + const create3DGraph = async () => { const supported = await supportsThreads(); const threads = await initThreads(supported); - const ExtGraph = extend(Graph, { - behaviors: { - 'brush-select': Extensions.BrushSelect, - 'hover-active': Extensions.HoverActivate, - }, - layouts: { - 'force-wasm': Extensions.ForceLayout, - }, - }); - console.log('create3DGraph', dataFor3D); - const newGraph = new ExtGraph({ + const newGraph = new Graph({ container: container as HTMLDivElement, width, height: 1400, diff --git a/packages/g6/tests/demo/demo/demoForPolyline.ts b/packages/g6/tests/demo/demo/demoForPolyline.ts index 42dc15e79c..9366be626e 100644 --- a/packages/g6/tests/demo/demo/demoForPolyline.ts +++ b/packages/g6/tests/demo/demo/demoForPolyline.ts @@ -1,8 +1,9 @@ import Stats from 'stats.js'; -import { Extensions, Graph, extend } from '../../../src/index'; - +import { Extensions, Graph, register } from '../../../src/index'; import { container, height, width } from '../../datasets/const'; +register('edge', 'polyline-edge', Extensions.PolylineEdge); + export default () => { const data = { nodes: [], @@ -73,12 +74,7 @@ export default () => { }; }; - const ExtGraph = extend(Graph, { - edges: { - 'polyline-edge': Extensions.PolylineEdge, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ container, width, height, diff --git a/packages/g6/tests/demo/demo/diamond.ts b/packages/g6/tests/demo/demo/diamond.ts index 84c8e2ec0b..5b87d8e31f 100644 --- a/packages/g6/tests/demo/demo/diamond.ts +++ b/packages/g6/tests/demo/demo/diamond.ts @@ -1,6 +1,8 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; +register('node', 'diamond-node', Extensions.DiamondNode); + let graph: any; const createCtrlContainer = (container: HTMLElement) => { @@ -77,12 +79,7 @@ export default (context: TestCaseContext) => { createCtrlContainer(container!); createCtrl(); - const ExtGraph = extend(Graph, { - nodes: { - 'diamond-node': Extensions.DiamondNode, - }, - }); - graph = new ExtGraph({ + graph = new Graph({ ...context, type: 'graph', data, diff --git a/packages/g6/tests/demo/demo/ellipse.ts b/packages/g6/tests/demo/demo/ellipse.ts index 0c6cf38838..68a26adfab 100644 --- a/packages/g6/tests/demo/demo/ellipse.ts +++ b/packages/g6/tests/demo/demo/ellipse.ts @@ -1,4 +1,4 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; let graph: any; @@ -72,16 +72,14 @@ const data = { ], }; +register('node', 'ellipse-node', Extensions.EllipseNode); + export default (context: TestCaseContext) => { const { width, height, container } = context; createCtrlContainer(container!); createCtrl(); - const ExtGraph = extend(Graph, { - nodes: { - 'ellipse-node': Extensions.EllipseNode, - }, - }); - graph = new ExtGraph({ + + graph = new Graph({ ...context, data, modes: { diff --git a/packages/g6/tests/demo/demo/hexagon.ts b/packages/g6/tests/demo/demo/hexagon.ts index 475fd349e3..21b108b651 100644 --- a/packages/g6/tests/demo/demo/hexagon.ts +++ b/packages/g6/tests/demo/demo/hexagon.ts @@ -1,4 +1,4 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; let graph: any; @@ -72,16 +72,14 @@ const data = { ], }; +register('node', 'hexagon-node', Extensions.HexagonNode); + export default (context: TestCaseContext) => { const { width, height, container } = context; createCtrlContainer(container!); createCtrl(); - const ExtGraph = extend(Graph, { - nodes: { - 'hexagon-node': Extensions.HexagonNode, - }, - }); - graph = new ExtGraph({ + + graph = new Graph({ ...context, type: 'graph', data, diff --git a/packages/g6/tests/demo/demo/menu.ts b/packages/g6/tests/demo/demo/menu.ts index 67e29804aa..7828d2eff5 100644 --- a/packages/g6/tests/demo/demo/menu.ts +++ b/packages/g6/tests/demo/demo/menu.ts @@ -1,7 +1,9 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { container, height, width } from '../../datasets/const'; +register('widget', 'menu', Extensions.Menu); + export default () => { const data = { nodes: [ @@ -39,13 +41,7 @@ export default () => { }, ], }; - - const ExtGraph = extend(Graph, { - plugins: { - menu: Extensions.Menu, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ container, width, height, diff --git a/packages/g6/tests/demo/demo/modelRect.ts b/packages/g6/tests/demo/demo/modelRect.ts index 7b14e36405..8d98f39717 100644 --- a/packages/g6/tests/demo/demo/modelRect.ts +++ b/packages/g6/tests/demo/demo/modelRect.ts @@ -1,4 +1,4 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; let graph: any; @@ -72,17 +72,14 @@ const data = { ], }; +register('node', 'modelRect-node', Extensions.ModelRectNode); + export default (context: TestCaseContext) => { const { width, height, container } = context; createCtrlContainer(container!); createCtrl(); - const ExtGraph = extend(Graph, { - nodes: { - 'modelRect-node': Extensions.ModelRectNode, - }, - }); - graph = new ExtGraph({ + graph = new Graph({ ...context, data, modes: { diff --git a/packages/g6/tests/demo/demo/quadratic.ts b/packages/g6/tests/demo/demo/quadratic.ts index 05c690b77a..bbb0819bc8 100644 --- a/packages/g6/tests/demo/demo/quadratic.ts +++ b/packages/g6/tests/demo/demo/quadratic.ts @@ -1,6 +1,8 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { container, height, width } from '../../datasets/const'; +register('edge', 'quadratic-edge', Extensions.QuadraticEdge); + export default () => { const data = { nodes: [ @@ -57,12 +59,7 @@ export default () => { }; }; - const ExtGraph = extend(Graph, { - edges: { - 'quadratic-edge': Extensions.QuadraticEdge, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ container, width, height, diff --git a/packages/g6/tests/demo/demo/star.ts b/packages/g6/tests/demo/demo/star.ts index 73cbd8efdc..7cbb073f06 100644 --- a/packages/g6/tests/demo/demo/star.ts +++ b/packages/g6/tests/demo/demo/star.ts @@ -1,9 +1,11 @@ // 这是从外部引入的功能 -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; let graph: any; +register('node', 'star-node', Extensions.StarNode); + const createCtrlContainer = (container: HTMLElement) => { const ctrlContainer = document.createElement('div'); ctrlContainer.id = 'ctrl-container'; @@ -78,13 +80,7 @@ export default (context: TestCaseContext) => { createCtrlContainer(container!); createCtrl(); - const ExtGraph = extend(Graph, { - nodes: { - 'star-node': Extensions.StarNode, - }, - }); - - graph = new ExtGraph({ + graph = new Graph({ ...context, type: 'graph', data, diff --git a/packages/g6/tests/demo/demo/tooltip.ts b/packages/g6/tests/demo/demo/tooltip.ts index 7ab3f39c21..3a10b26c5a 100644 --- a/packages/g6/tests/demo/demo/tooltip.ts +++ b/packages/g6/tests/demo/demo/tooltip.ts @@ -1,6 +1,8 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph } from '../../../src/index'; import { container, height, width } from '../../datasets/const'; +register('widget', 'tooltip', Extensions.Tooltip); + export default () => { const data = { nodes: [ @@ -39,12 +41,7 @@ export default () => { ], }; - const ExtGraph = extend(Graph, { - plugins: { - tooltip: Extensions.Tooltip, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ container, width, height, @@ -65,10 +62,10 @@ export default () => { getContent: (e) => { return new Promise((resolve) => { const data = ` -
+

类型: ${e.itemType}

ID: ${e.itemId} -
+
`; setTimeout(() => { resolve(data); diff --git a/packages/g6/tests/demo/demo/triangle.ts b/packages/g6/tests/demo/demo/triangle.ts index 35a0d72f4d..743a9c5267 100644 --- a/packages/g6/tests/demo/demo/triangle.ts +++ b/packages/g6/tests/demo/demo/triangle.ts @@ -1,6 +1,8 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; +register('node', 'triangle-node', Extensions.TriangleNode); + let graph: any; const createCtrlContainer = (container: HTMLElement) => { @@ -77,11 +79,6 @@ export default (context: TestCaseContext) => { createCtrlContainer(container!); createCtrl(); - const ExtGraph = extend(Graph, { - nodes: { - 'triangle-node': Extensions.TriangleNode, - }, - }); graph = new Graph({ ...context, data, diff --git a/packages/g6/tests/demo/index.ts b/packages/g6/tests/demo/index.ts index 32062a70e6..a413afbaa9 100644 --- a/packages/g6/tests/demo/index.ts +++ b/packages/g6/tests/demo/index.ts @@ -25,8 +25,6 @@ import modelRect from './demo/modelRect'; import quadratic from './demo/quadratic'; import rect from './demo/rect'; import star from './demo/star'; -import tooltip from './demo/tooltip'; -import triangle from './demo/triangle'; import anchor from './item/anchor'; import arrow from './item/edge/arrow'; import cubic_edge from './item/edge/cubic-edge'; @@ -63,18 +61,11 @@ import performance from './performance/performance'; import edgeBundling from './plugins/edgeBundling'; import edgeFilterLens from './plugins/edgeFilterLens'; import fisheye from './plugins/fisheye'; -import history from './plugins/history'; -import history_combo from './plugins/history-combo'; import hull from './plugins/hull'; import legend from './plugins/legend'; import minimap from './plugins/minimap'; import snapline from './plugins/snapline'; -import toolbar from './plugins/toolbar'; -import watermarker from './plugins/watermarker'; -import treeGraph from './tree/treeGraph'; -import user_defined_canvas from './user-defined-canvas/circular'; import mapper from './visual/mapper'; -import visual from './visual/visual'; export { default as timebar_chart } from './plugins/timebar-chart'; export { default as timebar_time } from './plugins/timebar-time'; @@ -114,8 +105,6 @@ export { fps_test, graphCore, hexagon, - history, - history_combo, hull, image_clip_node, image_node, @@ -150,11 +139,4 @@ export { rect, snapline, star, - toolbar, - tooltip, - treeGraph, - triangle, - user_defined_canvas, - visual, - watermarker, }; diff --git a/packages/g6/tests/demo/item/edge/arrow.ts b/packages/g6/tests/demo/item/edge/arrow.ts index 64b491d065..d3e1d37c6c 100644 --- a/packages/g6/tests/demo/item/edge/arrow.ts +++ b/packages/g6/tests/demo/item/edge/arrow.ts @@ -1,5 +1,5 @@ import { ArrowConfig } from '@antv/g6'; -import { Extensions, Graph, extend } from '../../../../src/index'; +import { Extensions, Graph, register } from '../../../../src/index'; import { TestCaseContext } from '../../interface'; const defaultData = { @@ -37,6 +37,8 @@ const defaultData = { ], }; +register('edge', 'cubic-edge', Extensions.CubicEdge); + export default ( context: TestCaseContext, options: { @@ -46,11 +48,7 @@ export default ( ) => { const { startArrow = true, endArrow = true } = options; - const ExtGraph = extend(Graph, { - edges: { 'cubic-edge': Extensions.CubicEdge }, - }); - - const graph = new ExtGraph({ + const graph = new Graph({ ...context, type: 'graph', data: JSON.parse(JSON.stringify(defaultData)), diff --git a/packages/g6/tests/demo/item/edge/cubic-edge.ts b/packages/g6/tests/demo/item/edge/cubic-edge.ts index f7388cdb04..3736d3a996 100644 --- a/packages/g6/tests/demo/item/edge/cubic-edge.ts +++ b/packages/g6/tests/demo/item/edge/cubic-edge.ts @@ -1,4 +1,4 @@ -import { Extensions, Graph, extend } from '../../../../src/index'; +import { Extensions, IGraph, register } from '../../../../src/index'; // @ts-nocheck @@ -220,6 +220,9 @@ const createControls = () => { parentEle.appendChild(highlightStyleCb); }; +register('edge', 'cubic-edge', Extensions.CubicEdge); +register('behavior', 'activate-relations', Extensions.ActivateRelations); + export default () => { // 1.create control container (for control buttons, etc.) createCtrlContainer(); @@ -227,14 +230,8 @@ export default () => { // 2.create graph container = document.getElementById('container')!; - const ExtGraph = extend(Graph, { - behaviors: { - 'activate-relations': Extensions.ActivateRelations, - }, - edges: { 'cubic-edge': Extensions.CubicEdge }, - }); - graph = new ExtGraph({ + graph = new Graph({ container, width: 500, height: 500, diff --git a/packages/g6/tests/demo/item/edge/cubic-horizontal-edge.ts b/packages/g6/tests/demo/item/edge/cubic-horizontal-edge.ts index 5346329855..d76c4b397e 100644 --- a/packages/g6/tests/demo/item/edge/cubic-horizontal-edge.ts +++ b/packages/g6/tests/demo/item/edge/cubic-horizontal-edge.ts @@ -1,6 +1,7 @@ -import { Extensions, Graph, extend } from '../../../../src/index'; +import { Extensions, Graph, IGraph, register } from '../../../../src/index'; -// @ts-nocheck +register('edge', 'cubic-horizontal-edge', Extensions.CubicHorizontalEdge); +register('behavior', 'activate-relations', Extensions.ActivateRelations); let graph: IGraph; let container: HTMLElement; @@ -230,12 +231,6 @@ export default () => { // 2.create graph container = document.getElementById('container')!; - const ExtGraph = extend(Graph, { - behaviors: { - 'activate-relations': Extensions.ActivateRelations, - }, - edges: { 'cubic-horizontal-edge': Extensions.CubicHorizontalEdge }, - }); graph = new Graph({ container, diff --git a/packages/g6/tests/demo/item/edge/cubic-vertical-edge.ts b/packages/g6/tests/demo/item/edge/cubic-vertical-edge.ts index 94804af671..bab416994d 100644 --- a/packages/g6/tests/demo/item/edge/cubic-vertical-edge.ts +++ b/packages/g6/tests/demo/item/edge/cubic-vertical-edge.ts @@ -1,4 +1,4 @@ -import { Extensions, Graph, extend } from '../../../../src/index'; +import { Extensions, Graph, IGraph, register } from '../../../../src/index'; // @ts-nocheck let graph: IGraph; @@ -219,6 +219,9 @@ const createControls = () => { parentEle.appendChild(highlightStyleCb); }; +register('edge', 'cubic-vertical-edge', Extensions.CubicVerticalEdge); +register('behavior', 'activate-relations', Extensions.ActivateRelations); + export default () => { // 1.create control container (for control buttons, etc.) createCtrlContainer(); @@ -226,12 +229,6 @@ export default () => { // 2.create graph container = document.getElementById('container')!; - const ExtGraph = extend(Graph, { - behaviors: { - 'activate-relations': Extensions.ActivateRelations, - }, - edges: { 'cubic-vertical-edge': Extensions.CubicVerticalEdge }, - }); graph = new Graph({ container, diff --git a/packages/g6/tests/demo/item/edge/line-edge.ts b/packages/g6/tests/demo/item/edge/line-edge.ts index a1024e1197..6518cd84a1 100644 --- a/packages/g6/tests/demo/item/edge/line-edge.ts +++ b/packages/g6/tests/demo/item/edge/line-edge.ts @@ -1,6 +1,8 @@ -import { Graph } from '../../../../src/index'; +import { Extensions, Graph, register } from '../../../../src/index'; import { TestCaseContext } from '../../interface'; +register('behavior', 'activate-relations', Extensions.ActivateRelations); + let graph: Graph; const defaultData = { diff --git a/packages/g6/tests/demo/item/edge/loop-edge.ts b/packages/g6/tests/demo/item/edge/loop-edge.ts index 8848a38836..103851ec28 100644 --- a/packages/g6/tests/demo/item/edge/loop-edge.ts +++ b/packages/g6/tests/demo/item/edge/loop-edge.ts @@ -1,5 +1,5 @@ import { deepMix } from '@antv/util'; -import { EdgeUserModel, Extensions, Graph, extend } from '../../../../src/index'; +import { EdgeUserModel, Extensions, Graph, IGraph, register } from '../../../../src/index'; import { TestCaseContext } from '../../interface'; // @ts-nocheck @@ -221,24 +221,18 @@ const createControls = () => { parentEle.appendChild(changeLoopPositionBtn); }; +register('node', 'ellipse-node', Extensions.EllipseNode); +register('behavior', 'activate-relations', Extensions.ActivateRelations); +register('edge', 'loop-edge', Extensions.LoopEdge); + export default (context: TestCaseContext) => { const { container } = context; // 1.create control container (for control buttons, etc.) createCtrlContainer(container!); createControls(); - const ExtGraph = extend(Graph, { - nodes: { - 'ellipse-node': Extensions.EllipseNode, - }, - behaviors: { - 'activate-relations': Extensions.ActivateRelations, - }, - edges: { - 'loop-edge': Extensions.LoopEdge, - }, - }); - graph = new ExtGraph({ + + graph = new Graph({ ...context, data: defaultData, modes: { diff --git a/packages/g6/tests/demo/item/edge/polyline-edge.ts b/packages/g6/tests/demo/item/edge/polyline-edge.ts index 43912026c4..9d72286097 100644 --- a/packages/g6/tests/demo/item/edge/polyline-edge.ts +++ b/packages/g6/tests/demo/item/edge/polyline-edge.ts @@ -1,5 +1,5 @@ // @ts-nocheck -import { Extensions, Graph, IGraph, extend } from '../../../../src/index'; +import { Extensions, Graph, IGraph, register } from '../../../../src/index'; import { TestCaseContext } from '../../interface'; let graph: IGraph; let container: HTMLElement; @@ -300,22 +300,18 @@ const createControls = () => { ); }; +register('edge', 'polyline-edge', Extensions.PolylineEdge); +register('behavior', 'activate-relations', Extensions.ActivateRelations); + export default (context: TestCaseContext) => { const { container } = context; // 1.create control container (for control buttons, etc.) createCtrlContainer(container!); createControls(); - const ExtGraph = extend(Graph, { - edges: { - 'polyline-edge': Extensions.PolylineEdge, - }, - behaviors: { - 'activate-relations': Extensions.ActivateRelations, - }, - }); + // 2.create graph - graph = new ExtGraph({ + graph = new Graph({ ...context, type: 'graph', data: defaultData, diff --git a/packages/g6/tests/demo/item/label.ts b/packages/g6/tests/demo/item/label.ts index 2c7e60c73f..5b47e38ee4 100644 --- a/packages/g6/tests/demo/item/label.ts +++ b/packages/g6/tests/demo/item/label.ts @@ -1,11 +1,7 @@ -import { Graph as BaseGraph, extend, Extensions } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; -const Graph = extend(BaseGraph, { - edges: { - 'cubic-edge': Extensions.CubicEdge, - }, -}); +register('edge', 'cubic-edge', Extensions.CubicEdge); const defaultData = { nodes: [ diff --git a/packages/g6/tests/demo/item/node/cube.ts b/packages/g6/tests/demo/item/node/cube.ts index 865c23016b..851df88207 100644 --- a/packages/g6/tests/demo/item/node/cube.ts +++ b/packages/g6/tests/demo/item/node/cube.ts @@ -1,13 +1,10 @@ -import { Extensions, Graph, extend } from '../../../../src/index'; +import { Extensions, Graph, register } from '../../../../src/index'; import { TestCaseContext } from '../../interface'; +register('node', 'cube-node', Extensions.CubeNode); + export default (context: TestCaseContext) => { - const ExtGraph = extend(Graph, { - nodes: { - 'cube-node': Extensions.CubeNode, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ ...context, type: 'graph', renderer: 'webgl-3d', diff --git a/packages/g6/tests/demo/item/node/donut-node.ts b/packages/g6/tests/demo/item/node/donut-node.ts index 9069a28eb2..a3edf9cd67 100644 --- a/packages/g6/tests/demo/item/node/donut-node.ts +++ b/packages/g6/tests/demo/item/node/donut-node.ts @@ -1,8 +1,11 @@ -import { Extensions, Graph, extend } from '../../../../src/index'; +import { Extensions, Graph, IGraph, register } from '../../../../src/index'; let outerTop = 0; let graph: IGraph; +register('node', 'donut-node', Extensions.DonutNode); +register('behavior', 'hover-activate', Extensions.HoverActivate); + const createLabelCheckbox = ( container: HTMLElement, labelText: string, @@ -182,16 +185,8 @@ export default (context) => { ], }; - const ExtGraph = extend(Graph, { - nodes: { - 'donut-node': Extensions.DonutNode, - }, - behaviors: { - 'hover-activate': Extensions.HoverActivate, - }, - }); // @ts-ignore - graph = new ExtGraph({ + graph = new Graph({ ...context, data, type: 'graph', diff --git a/packages/g6/tests/demo/layouts/combo-combined.ts b/packages/g6/tests/demo/layouts/combo-combined.ts index 652cd5ee16..6b74fde7bf 100644 --- a/packages/g6/tests/demo/layouts/combo-combined.ts +++ b/packages/g6/tests/demo/layouts/combo-combined.ts @@ -1,4 +1,4 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; const data = { @@ -608,13 +608,11 @@ const data = { }, ], }; + +register('layout', 'comboCombined', Extensions.ComboCombinedLayout); + export default (context: TestCaseContext) => { - const ExtGraph = extend(Graph, { - layouts: { - comboCombined: Extensions.ComboCombinedLayout, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ ...context, layout: { type: 'comboCombined', diff --git a/packages/g6/tests/demo/layouts/custom.ts b/packages/g6/tests/demo/layouts/custom.ts index a1fddbc585..7850fe4c18 100644 --- a/packages/g6/tests/demo/layouts/custom.ts +++ b/packages/g6/tests/demo/layouts/custom.ts @@ -1,5 +1,5 @@ import { Layout, LayoutMapping } from '@antv/layout'; -import { Graph, extend } from '../../../src/index'; +import { Graph, register } from '../../../src/index'; import { data } from '../../datasets/dataset1'; import { TestCaseContext } from '../interface'; @@ -25,15 +25,10 @@ class MyCustomLayout implements Layout<{}> { id: 'myCustomLayout'; } -export default (context: TestCaseContext) => { - // Register custom layout - const ExtGraph = extend(Graph, { - layouts: { - 'my-custom-layout': MyCustomLayout, - }, - }); +register('layout', 'my-custom-layout', MyCustomLayout); - return new ExtGraph({ +export default (context: TestCaseContext) => { + return new Graph({ ...context, type: 'graph', data: JSON.parse(JSON.stringify(data)), diff --git a/packages/g6/tests/demo/layouts/d3force.ts b/packages/g6/tests/demo/layouts/d3force.ts index 4c6ee07c25..776e0bcb27 100644 --- a/packages/g6/tests/demo/layouts/d3force.ts +++ b/packages/g6/tests/demo/layouts/d3force.ts @@ -1,15 +1,13 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { data } from '../../datasets/dataset1'; import { TestCaseContext } from '../interface'; +register('layout', 'd3force', Extensions.D3ForceLayout); + export default (context: TestCaseContext) => { const { width, height } = context; - const ExtGraph = extend(Graph, { - layouts: { - d3force: Extensions.D3ForceLayout, - }, - }); - return new ExtGraph({ + + return new Graph({ ...context, data: JSON.parse(JSON.stringify(data)), layout: { diff --git a/packages/g6/tests/demo/layouts/dagre-combo.ts b/packages/g6/tests/demo/layouts/dagre-combo.ts index c1cfaf9922..aab5abd41a 100644 --- a/packages/g6/tests/demo/layouts/dagre-combo.ts +++ b/packages/g6/tests/demo/layouts/dagre-combo.ts @@ -1,4 +1,4 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; @@ -169,13 +169,10 @@ const data = { ], }; +register('layout', 'dagre', Extensions.DagreLayout); + export default (context: TestCaseContext) => { - const ExtGraph = extend(Graph, { - layouts: { - dagre: Extensions.DagreLayout, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ ...context, autoFit: 'view', modes: { diff --git a/packages/g6/tests/demo/layouts/dagre-update.ts b/packages/g6/tests/demo/layouts/dagre-update.ts index 717406b73e..8f16f181b5 100644 --- a/packages/g6/tests/demo/layouts/dagre-update.ts +++ b/packages/g6/tests/demo/layouts/dagre-update.ts @@ -1,18 +1,12 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; -export default (context: TestCaseContext) => { - const ExtGraph = extend(Graph, { - layouts: { - dagre: Extensions.DagreLayout, - }, - edges: { - 'cubic-edge': Extensions.CubicEdge, - 'quadratic-edge': Extensions.QuadraticEdge, - 'polyline-edge': Extensions.PolylineEdge, - }, - }); +register('layout', 'dagre', Extensions.DagreLayout); +register('edge', 'cubic-edge', Extensions.CubicEdge); +register('edge', 'quadratic-edge', Extensions.QuadraticEdge); +register('edge', 'polyline-edge', Extensions.PolylineEdge); +export default (context: TestCaseContext) => { const data = { nodes: [ { @@ -65,7 +59,7 @@ export default (context: TestCaseContext) => { }; const container = context.container; - const graph = new ExtGraph({ + const graph = new Graph({ ...context, layout: layoutConfigs.Default, node: (node) => { diff --git a/packages/g6/tests/demo/layouts/dagre.ts b/packages/g6/tests/demo/layouts/dagre.ts index 4646dee109..0b0c22bd9d 100644 --- a/packages/g6/tests/demo/layouts/dagre.ts +++ b/packages/g6/tests/demo/layouts/dagre.ts @@ -1,7 +1,9 @@ -import { Extensions, Graph, extend } from '../../../src/index'; - +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; +register('edge', 'polyline-edge', Extensions.PolylineEdge); +register('layout', 'dagre', Extensions.DagreLayout); + export default (context: TestCaseContext) => { const data = { nodes: [ @@ -244,15 +246,8 @@ export default (context: TestCaseContext) => { }, ], }; - const ExtGraph = extend(Graph, { - layouts: { - dagre: Extensions.DagreLayout, - }, - edges: { - 'polyline-edge': Extensions.PolylineEdge, - }, - }); - const graph = new ExtGraph({ + + const graph = new Graph({ ...context, data: JSON.parse(JSON.stringify(data2)), layout: { diff --git a/packages/g6/tests/demo/layouts/force-3d.ts b/packages/g6/tests/demo/layouts/force-3d.ts index a1c85b1dbf..da862186d2 100644 --- a/packages/g6/tests/demo/layouts/force-3d.ts +++ b/packages/g6/tests/demo/layouts/force-3d.ts @@ -1,15 +1,13 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { data } from '../../datasets/dataset1'; import { TestCaseContext } from '../interface'; +register('node', 'sphere-node', Extensions.SphereNode); + export default (context: TestCaseContext) => { const { width, height } = context; - const ExtGraph = extend(Graph, { - nodes: { - 'sphere-node': Extensions.SphereNode, - }, - }); - const graph = new ExtGraph({ + + const graph = new Graph({ ...context, type: 'graph', renderer: 'webgl-3d', diff --git a/packages/g6/tests/demo/layouts/force-wasm-3d.ts b/packages/g6/tests/demo/layouts/force-wasm-3d.ts index 69b9b17957..1ba83d7cba 100644 --- a/packages/g6/tests/demo/layouts/force-wasm-3d.ts +++ b/packages/g6/tests/demo/layouts/force-wasm-3d.ts @@ -1,8 +1,13 @@ import { ForceLayout, initThreads, supportsThreads } from '@antv/layout-wasm'; -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { loadDataset } from '../../datasets/legacy-format'; import { TestCaseContext } from '../interface'; +register('layout', 'force-wasm', ForceLayout); +register('node', 'sphere-node', Extensions.SphereNode); +register('behavior', 'orbit-canvas-3d', Extensions.OrbitCanvas3D); +register('behavior', 'zoom-canvas-3d', Extensions.ZoomCanvas3D); + export default async (context: TestCaseContext) => { const { width, height } = context; @@ -12,20 +17,7 @@ export default async (context: TestCaseContext) => { const supported = await supportsThreads(); const threads = await initThreads(supported); - // Register custom layout - const ExtGraph = extend(Graph, { - layouts: { - 'force-wasm': ForceLayout, - }, - nodes: { - 'sphere-node': Extensions.SphereNode, - }, - behaviors: { - 'orbit-canvas-3d': Extensions.OrbitCanvas3D, - 'zoom-canvas-3d': Extensions.ZoomCanvas3D, - }, - }); - return new ExtGraph({ + return new Graph({ ...context, data: JSON.parse(JSON.stringify(data)), renderer: 'webgl-3d', diff --git a/packages/g6/tests/demo/layouts/force-wasm.ts b/packages/g6/tests/demo/layouts/force-wasm.ts index eeab54d85f..ca67edc03e 100644 --- a/packages/g6/tests/demo/layouts/force-wasm.ts +++ b/packages/g6/tests/demo/layouts/force-wasm.ts @@ -1,22 +1,18 @@ import { ForceLayout, initThreads, supportsThreads } from '@antv/layout-wasm'; -import { Graph, extend } from '../../../src/index'; +import { Graph, register } from '../../../src/index'; import { data } from '../../datasets/dataset1'; import { TestCaseContext } from '../interface'; +// Register custom layout +register('layout', 'force-wasm', ForceLayout); + export default async (context: TestCaseContext) => { const { width, height } = context; const supported = await supportsThreads(); const threads = await initThreads(supported); - // Register custom layout - const ExtGraph = extend(Graph, { - layouts: { - 'force-wasm': ForceLayout, - }, - }); - - return new ExtGraph({ + return new Graph({ ...context, data: JSON.parse(JSON.stringify(data)), layout: { diff --git a/packages/g6/tests/demo/layouts/forceatlas2-wasm.ts b/packages/g6/tests/demo/layouts/forceatlas2-wasm.ts index 288d30b3d8..f096c16bf1 100644 --- a/packages/g6/tests/demo/layouts/forceatlas2-wasm.ts +++ b/packages/g6/tests/demo/layouts/forceatlas2-wasm.ts @@ -1,22 +1,18 @@ import { ForceAtlas2Layout, initThreads, supportsThreads } from '@antv/layout-wasm'; -import { Graph, extend } from '../../../src/index'; +import { Graph, register } from '../../../src/index'; import { data } from '../../datasets/dataset1'; import { TestCaseContext } from '../interface'; +// Register custom layout +register('layout', 'forceatlas2-wasm', ForceAtlas2Layout); + export default async (context: TestCaseContext) => { const { width, height } = context; const supported = await supportsThreads(); const threads = await initThreads(supported); - // Register custom layout - const ExtGraph = extend(Graph, { - layouts: { - 'forceatlas2-wasm': ForceAtlas2Layout, - }, - }); - - return new ExtGraph({ + return new Graph({ ...context, data: JSON.parse(JSON.stringify(data)), layout: { diff --git a/packages/g6/tests/demo/layouts/fruchterman-gpu.ts b/packages/g6/tests/demo/layouts/fruchterman-gpu.ts index 46f1f0b78f..c12c2e152c 100644 --- a/packages/g6/tests/demo/layouts/fruchterman-gpu.ts +++ b/packages/g6/tests/demo/layouts/fruchterman-gpu.ts @@ -1,19 +1,15 @@ import { FruchtermanLayout } from '@antv/layout-gpu'; -import { Graph, extend } from '../../../src/index'; +import { Graph, register } from '../../../src/index'; import { data } from '../../datasets/dataset1'; import { TestCaseContext } from '../interface'; +// Register custom layout +register('layout', 'fruchterman-gpu', FruchtermanLayout); + export default async (context: TestCaseContext) => { const { width, height } = context; - // Register custom layout - const ExtGraph = extend(Graph, { - layouts: { - 'fruchterman-gpu': FruchtermanLayout, - }, - }); - - return new ExtGraph({ + return new Graph({ ...context, data: JSON.parse(JSON.stringify(data)), layout: { diff --git a/packages/g6/tests/demo/layouts/fruchterman-wasm.ts b/packages/g6/tests/demo/layouts/fruchterman-wasm.ts index 7dd7c53f69..065e3ff617 100644 --- a/packages/g6/tests/demo/layouts/fruchterman-wasm.ts +++ b/packages/g6/tests/demo/layouts/fruchterman-wasm.ts @@ -1,22 +1,17 @@ import { FruchtermanLayout, initThreads, supportsThreads } from '@antv/layout-wasm'; -import { Graph, extend } from '../../../src/index'; +import { Graph, register } from '../../../src/index'; import { data } from '../../datasets/dataset1'; import { TestCaseContext } from '../interface'; +register('layout', 'fruchterman-wasm', FruchtermanLayout); + export default async (context: TestCaseContext) => { const { width, height } = context; const supported = await supportsThreads(); const threads = await initThreads(supported); - // Register custom layout - const ExtGraph = extend(Graph, { - layouts: { - 'fruchterman-wasm': FruchtermanLayout, - }, - }); - - return new ExtGraph({ + return new Graph({ ...context, data: JSON.parse(JSON.stringify(data)), layout: { diff --git a/packages/g6/tests/demo/performance/fps.ts b/packages/g6/tests/demo/performance/fps.ts index cf5b1eb0f1..8c1118da45 100644 --- a/packages/g6/tests/demo/performance/fps.ts +++ b/packages/g6/tests/demo/performance/fps.ts @@ -1,17 +1,13 @@ import Stats from 'stats.js'; -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { container, width } from '../../datasets/const'; import data from '../../datasets/eva-3d-data.json'; -const createGraph = async () => { - const ExtGraph = extend(Graph, { - behaviors: { - 'brush-select': Extensions.BrushSelect, - 'hover-activate': Extensions.HoverActivate, - }, - }); +register('behavior', 'brush-select', Extensions.BrushSelect); +register('behavior', 'hover-activate', Extensions.HoverActivate); - const graph = new ExtGraph({ +const createGraph = async () => { + const graph = new Graph({ container: container as HTMLElement, width, height: 1200, diff --git a/packages/g6/tests/demo/performance/layout-3d.ts b/packages/g6/tests/demo/performance/layout-3d.ts index 4db4031e36..5ec00ebbe5 100644 --- a/packages/g6/tests/demo/performance/layout-3d.ts +++ b/packages/g6/tests/demo/performance/layout-3d.ts @@ -1,18 +1,12 @@ import { initThreads, supportsThreads } from '@antv/layout-wasm'; -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { loadDataset } from '../../datasets/legacy-format'; -const ExtGraph = extend(Graph, { - layouts: { - 'force-wasm': Extensions.ForceLayout, - }, - nodes: { - 'sphere-node': Extensions.SphereNode, - }, - behaviors: { - 'orbit-canvas-3d': Extensions.OrbitCanvas3D, - 'zoom-canvas-3d': Extensions.ZoomCanvas3D, - }, -}); + +register('layout', 'force-wasm', Extensions.ForceLayout); +register('node', 'sphere-node', Extensions.SphereNode); +register('behavior', 'orbit-canvas-3d', Extensions.OrbitCanvas3D); +register('behavior', 'zoom-canvas-3d', Extensions.ZoomCanvas3D); + export default async () => { const $container = document.getElementById('container')!; $container.style.display = 'none'; @@ -83,7 +77,7 @@ export default async () => { // Register custom layout - const graph = new ExtGraph({ + const graph = new Graph({ container: $container1, width: WIDTH, height: HEIGHT, diff --git a/packages/g6/tests/demo/performance/performance.ts b/packages/g6/tests/demo/performance/performance.ts index cf4c657828..b1b7fbabb0 100644 --- a/packages/g6/tests/demo/performance/performance.ts +++ b/packages/g6/tests/demo/performance/performance.ts @@ -1,7 +1,13 @@ import { initThreads, supportsThreads } from '@antv/layout-wasm'; -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { IBadgePosition } from '../../../src/types/item'; import { container, width } from '../../datasets/const'; + +register('layout', 'force-wasm', Extensions.ForceLayout); +register('layout', 'fruchterman-wasm', Extensions.FruchtermanLayout); +register('behavior', 'brush-select', Extensions.BrushSelect); +register('behavior', 'hover-activate', Extensions.HoverActivate); + const data = { nodes: [ { id: 'Myriel', data: { x: 122.619579008568, y: -121.31805520154471 } }, @@ -1914,17 +1920,7 @@ const createGraph = async () => { const supported = await supportsThreads(); const threads = await initThreads(supported); - const ExtGraph = extend(Graph, { - layouts: { - 'force-wasm': Extensions.ForceLayout, - 'fruchterman-wasm': Extensions.FruchtermanLayout, - }, - behaviors: { - 'brush-select': Extensions.BrushSelect, - 'hover-activate': Extensions.HoverActivate, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ container: container as HTMLElement, width, height: 1200, diff --git a/packages/g6/tests/demo/plugins/edgeBundling.ts b/packages/g6/tests/demo/plugins/edgeBundling.ts index 9b6cd5e7ac..7655d17a77 100644 --- a/packages/g6/tests/demo/plugins/edgeBundling.ts +++ b/packages/g6/tests/demo/plugins/edgeBundling.ts @@ -1,16 +1,10 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; -export default (context: TestCaseContext, options = {}) => { - const ExtGraph = extend(Graph, { - edges: { - 'polyline-edge': Extensions.PolylineEdge, - }, - plugins: { - edgeBundling: Extensions.EdgeBundling, - }, - }); +register('edge', 'polyline-edge', Extensions.PolylineEdge); +register('widget', 'edgeBundling', Extensions.EdgeBundling); +export default (context: TestCaseContext, options = {}) => { const data = { nodes: [ { @@ -466,7 +460,7 @@ export default (context: TestCaseContext, options = {}) => { const width = container.scrollWidth; const height = container.scrollHeight || 500; - const graph = new ExtGraph({ + const graph = new Graph({ ...context, data, width, diff --git a/packages/g6/tests/demo/plugins/edgeFilterLens.ts b/packages/g6/tests/demo/plugins/edgeFilterLens.ts index bb97efb34d..eed9e7b17d 100644 --- a/packages/g6/tests/demo/plugins/edgeFilterLens.ts +++ b/packages/g6/tests/demo/plugins/edgeFilterLens.ts @@ -1,8 +1,10 @@ import { clone } from '@antv/util'; -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import data from '../../datasets/force-data.json'; import { TestCaseContext } from '../interface'; +register('widget', 'filterLens', Extensions.EdgeFilterLens); + export default (context: TestCaseContext, options = {}) => { const trigger = 'mousemove'; let filterLens = { @@ -94,12 +96,7 @@ export default (context: TestCaseContext, options = {}) => { // ========================================================= // - const ExtGraph = extend(Graph, { - plugins: { - filterLens: Extensions.EdgeFilterLens, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ ...context, layout: { type: 'grid', diff --git a/packages/g6/tests/demo/plugins/fisheye.ts b/packages/g6/tests/demo/plugins/fisheye.ts index e1e4ce0733..c5a9c6732a 100644 --- a/packages/g6/tests/demo/plugins/fisheye.ts +++ b/packages/g6/tests/demo/plugins/fisheye.ts @@ -1,4 +1,7 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; + +register('widget', 'fisheye', Extensions.Fisheye); +register('widget', 'hover-active', Extensions.HoverActivate); export default async () => { let fisheye = { @@ -124,14 +127,9 @@ export default async () => { height = container.scrollHeight || 500; } let graph; + const createGraph = (customData) => { - const ExtGraph = extend(Graph, { - plugins: { - fisheye: Extensions.Fisheye, - 'hover-active': Extensions.HoverActivate, - }, - }); - graph = new ExtGraph({ + graph = new Graph({ container: 'container', width, height, diff --git a/packages/g6/tests/demo/plugins/history-combo.ts b/packages/g6/tests/demo/plugins/history-combo.ts deleted file mode 100644 index eef0d45a69..0000000000 --- a/packages/g6/tests/demo/plugins/history-combo.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { Extensions, Graph, extend } from '../../../src/index'; - -const createOperationContainer = (container: HTMLElement) => { - const operationContainer = document.createElement('div'); - operationContainer.id = 'ctrl-container'; - operationContainer.style.width = '100%'; - operationContainer.style.height = '50px'; - operationContainer.style.lineHeight = '50px'; - operationContainer.style.backgroundColor = '#eee'; - - container.appendChild(operationContainer); -}; - -const createOperations = (graph): any => { - const parentEle = document.getElementById('ctrl-container'); - if (!parentEle) return; - - // undo/redo - const undoButton = document.createElement('button'); - undoButton.innerText = 'undo'; - undoButton.addEventListener('click', () => { - graph.undo(); - }); - const redoButton = document.createElement('button'); - redoButton.innerText = 'redo'; - redoButton.addEventListener('click', () => { - graph.redo(); - }); - - undoButton.disabled = graph.canUndo(); - redoButton.disabled = graph.canRedo(); - - parentEle.appendChild(undoButton); - parentEle.appendChild(redoButton); - - // add combo - const addComboButton = document.createElement('button'); - addComboButton.innerText = 'add combo'; - addComboButton.addEventListener('click', () => { - graph.addCombo( - { - id: 'combo2', - data: { - x: 200, - y: 100, - keyShape: { - padding: [10, 20, 30, 40], - r: 50, - fill: '#0f0', - }, - }, - }, - [], - ); - }); - parentEle.appendChild(addComboButton); - - // update combo position - const updateComboButton = document.createElement('button'); - updateComboButton.innerText = 'move combo'; - updateComboButton.addEventListener('click', () => { - graph.updateComboPosition( - { - id: 'combo1', - data: { - x: 300, - y: 100, - }, - }, - [], - ); - }); - parentEle.appendChild(updateComboButton); - - // collapse combo - const collapseComboButton = document.createElement('button'); - collapseComboButton.innerText = 'collapse combo'; - collapseComboButton.addEventListener('click', () => { - graph.collapseCombo('combo1'); - }); - parentEle.appendChild(collapseComboButton); - - // expand combo - const expandComboButton = document.createElement('button'); - expandComboButton.innerText = 'expand combo'; - expandComboButton.addEventListener('click', () => { - graph.expandCombo('combo1'); - }); - parentEle.appendChild(expandComboButton); - - return { undoButton, redoButton }; -}; - -export default (context) => { - const { container } = context; - - // 1.create operation container - createOperationContainer(container!); - - const data = { - nodes: [], - edges: [], - combos: [{ id: 'combo1', data: { x: 150, y: 100 } }], - }; - - const ExtGraph = extend(Graph, { - behaviors: { - 'hover-activate': Extensions.HoverActivate, - }, - }); - const graph = new ExtGraph({ - ...context, - data, - type: 'graph', - modes: { - default: [ - 'collapse-expand-combo', - 'drag-canvas', - 'drag-node', - { - type: 'click-select', - itemTypes: ['node', 'edge', 'combo'], - }, - { - type: 'hover-activate', - itemTypes: ['node', 'edge', 'combo'], - }, - 'drag-combo', - ], - }, - combo: (model) => { - return { - id: model.id, - data: { - keyShape: { - padding: [10, 20, 30, 40], - r: 50, - fill: '#f00', - }, - labelShape: { - text: model.id, - }, - ...model.data, - }, - }; - }, - stackCfg: { - stackSize: 0, - ignoreStateChange: true, - }, - }); - - const { undoButton, redoButton } = createOperations(graph); - - const updateButtonStatus = () => { - undoButton.disabled = !graph.canUndo(); - redoButton.disabled = !graph.canRedo(); - }; - - updateButtonStatus(); - - graph.on('history:change', () => { - updateButtonStatus(); - }); - - return graph; -}; diff --git a/packages/g6/tests/demo/plugins/history.ts b/packages/g6/tests/demo/plugins/history.ts deleted file mode 100644 index 69e880478c..0000000000 --- a/packages/g6/tests/demo/plugins/history.ts +++ /dev/null @@ -1,268 +0,0 @@ -import G6 from '../../../src/index'; - -const createOperationContainer = (container: HTMLElement) => { - const operationContainer = document.createElement('div'); - operationContainer.id = 'ctrl-container'; - operationContainer.style.width = '100%'; - operationContainer.style.height = '50px'; - operationContainer.style.lineHeight = '50px'; - operationContainer.style.backgroundColor = '#eee'; - - container.appendChild(operationContainer); -}; - -const createOperations = (graph): any => { - const parentEle = document.getElementById('ctrl-container'); - if (!parentEle) return; - - // undo/redo - const undoButton = document.createElement('button'); - undoButton.innerText = 'undo'; - undoButton.addEventListener('click', () => { - graph.undo(); - }); - const redoButton = document.createElement('button'); - redoButton.innerText = 'redo'; - redoButton.addEventListener('click', () => { - graph.redo(); - }); - - undoButton.disabled = graph.canUndo(); - redoButton.disabled = graph.canRedo(); - - parentEle.appendChild(undoButton); - parentEle.appendChild(redoButton); - - // set item's state - const setStateButton = document.createElement('button'); - setStateButton.innerText = 'set node 1 selected state'; - setStateButton.addEventListener('click', () => { - graph.setItemState('node1', 'selected', true); - }); - parentEle.appendChild(setStateButton); - - // clear item's state - const clearStateButton = document.createElement('button'); - clearStateButton.innerText = 'clear node 1 selected state'; - clearStateButton.addEventListener('click', () => { - graph.clearItemState('node1', 'selected'); - }); - parentEle.appendChild(clearStateButton); - - // add new node/edge on the map - const addNodeButton = document.createElement('button'); - addNodeButton.innerText = 'add data'; - addNodeButton.addEventListener('click', () => { - graph.startHistoryBatch(); - graph.addData('node', { - id: 'node3', - data: { - x: 300, - y: 100, - }, - }); - graph.addData('edge', { - id: 'edge2', - source: 'node2', - target: 'node3', - data: { - type: 'line-edge', - }, - }); - graph.stopHistoryBatch(); - }); - parentEle.appendChild(addNodeButton); - - // remove new node/edge on the map - const removeButton = document.createElement('button'); - removeButton.innerText = 'remove data'; - removeButton.addEventListener('click', () => { - graph.startHistoryBatch(); - graph.removeData('edge', 'edge2'); - graph.removeData('node', 'node3'); - graph.stopHistoryBatch(); - }); - parentEle.appendChild(removeButton); - - // update node/edge - const updateButton = document.createElement('button'); - updateButton.innerText = 'update data'; - updateButton.addEventListener('click', () => { - graph.historyBatch(() => { - graph.updateData('node', [ - { - id: 'node1', - data: { - x: 350, - y: 200, - }, - }, - { - id: 'node4', - data: { - x: 200, - y: 110, - }, - }, - ]); - graph.updateData('edge', { - id: 'edge1', - data: { - labelShape: { - text: '', - }, - }, - }); - }); - }); - parentEle.appendChild(updateButton); - - // show/hide node - const visibilityButton = document.createElement('button'); - visibilityButton.innerText = 'show/hide node'; - visibilityButton.addEventListener('click', () => { - const visible = graph.getItemVisible('node4'); - if (visible) { - graph.hideItem('node4'); - } else { - graph.showItem('node4'); - } - }); - parentEle.appendChild(visibilityButton); - - // to front/back - const frontButton = document.createElement('button'); - frontButton.innerText = 'front node 4'; - frontButton.addEventListener('click', () => { - graph.frontItem('node4'); - }); - parentEle.appendChild(frontButton); - - const backButton = document.createElement('button'); - backButton.innerText = 'back node 4'; - backButton.addEventListener('click', () => { - graph.backItem('node4'); - }); - parentEle.appendChild(backButton); - - return { undoButton, redoButton }; -}; - -export default (context) => { - const { container } = context; - - // 1.create operation container - createOperationContainer(container!); - - const data = { - nodes: [ - { - id: 'node1', - data: { - x: 100, - y: 100, - type: 'circle-node', - }, - }, - { - id: 'node2', - data: { - x: 200, - y: 100, - type: 'circle-node', - }, - }, - { - id: 'node4', - data: { - x: 200, - y: 200, - type: 'circle-node', - keyShape: { - fill: 'orange', - }, - }, - }, - ], - edges: [ - { - id: 'edge1', - source: 'node1', - target: 'node2', - data: { - type: 'line-edge', - }, - }, - ], - // combos: [{ id: 'combo1', data: { x: 400, y: 100 } }], - }; - - const edge: (data: any) => any = (edgeInnerModel: any) => { - const { id, data } = edgeInnerModel; - return { - id, - data: { - keyShape: { - stroke: 'blue', - }, - // iconShape: { - // // img: 'https://gw.alipayobjects.com/zos/basement_prod/012bcf4f-423b-4922-8c24-32a89f8c41ce.svg', - // text: 'label', - // fill: 'blue' - // }, - labelShape: { - text: 'label', - position: 'middle', - fill: 'blue', - }, - labelBackgroundShape: { - fill: 'white', - }, - ...data, - }, - }; - }; - - const graph = new G6.Graph({ - ...context, - data, - type: 'graph', - modes: { - default: ['drag-canvas', 'drag-node', 'click-select'], - }, - node: (nodeInnerModel: any) => { - const { id, data } = nodeInnerModel; - return { - id, - data: { - keyShape: { - r: 16, - }, - ...data, - }, - }; - }, - edge, - // enableStack: false, - // stackCfg: { - // stackSize: 0, - // stackActive: true, - // ignoreStateChange: true, - // }, - }); - - const { undoButton, redoButton } = createOperations(graph); - - const updateButtonStatus = () => { - undoButton.disabled = !graph.canUndo(); - redoButton.disabled = !graph.canRedo(); - }; - - updateButtonStatus(); - - graph.on('history:change', () => { - updateButtonStatus(); - }); - - return graph; -}; diff --git a/packages/g6/tests/demo/plugins/legend.ts b/packages/g6/tests/demo/plugins/legend.ts index 7ede73a580..6711938bac 100644 --- a/packages/g6/tests/demo/plugins/legend.ts +++ b/packages/g6/tests/demo/plugins/legend.ts @@ -1,16 +1,12 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; +register('widget', 'legend', Extensions.Legend); + export default (context: TestCaseContext) => { const { renderer, legendCanvas } = context; - const ExtGraph = extend(Graph, { - plugins: { - legend: Extensions.Legend, - }, - }); - - return new ExtGraph({ + return new Graph({ ...context, type: 'graph', data: { diff --git a/packages/g6/tests/demo/plugins/map.ts b/packages/g6/tests/demo/plugins/map.ts index deac3021ac..c2a68f7939 100644 --- a/packages/g6/tests/demo/plugins/map.ts +++ b/packages/g6/tests/demo/plugins/map.ts @@ -1,18 +1,12 @@ import { MapView } from '@antv/g6-plugin-map-view'; -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; -export default (context: TestCaseContext) => { - const ExtGraph = extend(Graph, { - plugins: { - 'map-view': MapView, - }, - behaviors: { - 'hover-activate': Extensions.HoverActivate, - }, - }); +register('widget', 'map-view', MapView); +register('behavior', 'hover-activate', Extensions.HoverActivate); - const graph = new ExtGraph({ +export default (context: TestCaseContext) => { + const graph = new Graph({ ...context, data: { nodes: [ diff --git a/packages/g6/tests/demo/plugins/minimap.ts b/packages/g6/tests/demo/plugins/minimap.ts index b06925f4d7..5f638ddbf9 100644 --- a/packages/g6/tests/demo/plugins/minimap.ts +++ b/packages/g6/tests/demo/plugins/minimap.ts @@ -1,14 +1,10 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; -export default (context: TestCaseContext) => { - const ExtGraph = extend(Graph, { - plugins: { - minimap: Extensions.Minimap, - }, - }); +register('widget', 'minimap', Extensions.Minimap); - return new ExtGraph({ +export default (context: TestCaseContext) => { + return new Graph({ ...context, data: { nodes: [ diff --git a/packages/g6/tests/demo/plugins/snapline.ts b/packages/g6/tests/demo/plugins/snapline.ts index 579b4e52e5..b30b6c6888 100644 --- a/packages/g6/tests/demo/plugins/snapline.ts +++ b/packages/g6/tests/demo/plugins/snapline.ts @@ -1,5 +1,7 @@ import { AABB } from '@antv/g'; -import { Graph as BaseGraph, Extensions, GraphData, IGraph, extend } from '../../../src/index'; +import { Extensions, Graph, GraphData, IGraph, register } from '../../../src/index'; + +register('widget', 'snapline', Extensions.Snapline); let graph: IGraph; @@ -194,15 +196,8 @@ const createTestComboButton = () => { parentEle.appendChild(labelLabel); parentEle.appendChild(labelCb); }; - const createGraph = () => { - const ExtGraph = extend(BaseGraph, { - plugins: { - snapline: Extensions.Snapline, - }, - }); - - const graph = new ExtGraph({ + const graph = new Graph({ container: 'container', width: 500, height: 500, diff --git a/packages/g6/tests/demo/plugins/timebar-chart.ts b/packages/g6/tests/demo/plugins/timebar-chart.ts index 92ef15d98e..8586d80e71 100644 --- a/packages/g6/tests/demo/plugins/timebar-chart.ts +++ b/packages/g6/tests/demo/plugins/timebar-chart.ts @@ -1,11 +1,7 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import type { TestCaseContext } from '../interface'; -const ExtGraph = extend(Graph, { - plugins: { - timebar: Extensions.Timebar, - }, -}); +register('widget', 'timebar', Extensions.Timebar); export default (context: TestCaseContext) => { const startTime = new Date('2023-08-01').getTime(); @@ -34,7 +30,7 @@ export default (context: TestCaseContext) => { })), }; - const graph = new ExtGraph({ + const graph = new Graph({ ...context, layout: { type: 'grid', diff --git a/packages/g6/tests/demo/plugins/timebar-time.ts b/packages/g6/tests/demo/plugins/timebar-time.ts index cc567211c7..495435a9b4 100644 --- a/packages/g6/tests/demo/plugins/timebar-time.ts +++ b/packages/g6/tests/demo/plugins/timebar-time.ts @@ -1,11 +1,7 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import type { TestCaseContext } from '../interface'; -const ExtGraph = extend(Graph, { - plugins: { - timebar: Extensions.Timebar, - }, -}); +register('widget', 'timebar', Extensions.Timebar); export default (context: TestCaseContext) => { const startTime = new Date('2023-08-01').getTime(); @@ -34,7 +30,7 @@ export default (context: TestCaseContext) => { })), }; - const graph = new ExtGraph({ + const graph = new Graph({ ...context, layout: { type: 'grid', diff --git a/packages/g6/tests/demo/plugins/toolbar.ts b/packages/g6/tests/demo/plugins/toolbar.ts index 8f03d7bc93..10f4e1c0be 100644 --- a/packages/g6/tests/demo/plugins/toolbar.ts +++ b/packages/g6/tests/demo/plugins/toolbar.ts @@ -1,6 +1,8 @@ -import { Extensions, Graph, extend } from '../../../src/index'; - +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; + +register('widget', 'toolbar', Extensions.Toolbar); + export default (context: TestCaseContext) => { const data = { nodes: [ @@ -37,12 +39,7 @@ export default (context: TestCaseContext) => { ], }; - const ExtGraph = extend(Graph, { - plugins: { - toolbar: Extensions.Toolbar, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ ...context, type: 'graph', layout: { diff --git a/packages/g6/tests/demo/plugins/watermarker.ts b/packages/g6/tests/demo/plugins/watermarker.ts index d8053e95f2..a9a438b025 100644 --- a/packages/g6/tests/demo/plugins/watermarker.ts +++ b/packages/g6/tests/demo/plugins/watermarker.ts @@ -1,6 +1,8 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { TestCaseContext } from '../interface'; +register('widget', 'watermarker', Extensions.WaterMarker); + export default (context: TestCaseContext, options = {}) => { const { watermarkerCanvas, ...pluginConfigs } = options; const data = { @@ -38,13 +40,8 @@ export default (context: TestCaseContext, options = {}) => { ], }; - const ExtGraph = extend(Graph, { - plugins: { - watermarker: Extensions.WaterMarker, - }, - }); // const testCanvas = createNodeGCanvas('canvas', 500, 500); - const graph = new ExtGraph({ + const graph = new Graph({ ...context, type: 'graph', layout: { diff --git a/packages/g6/tests/demo/visual/visual.ts b/packages/g6/tests/demo/visual/visual.ts index 6f5b37eea1..d13a1314ef 100644 --- a/packages/g6/tests/demo/visual/visual.ts +++ b/packages/g6/tests/demo/visual/visual.ts @@ -1,19 +1,14 @@ -import { Extensions, Graph, extend } from '../../../src/index'; +import { Extensions, Graph, register } from '../../../src/index'; import { IBadgePosition } from '../../../src/types/item'; import { container, width } from '../../datasets/const'; +register('layout', 'force-wasm', Extensions.ForceLayout); +register('layout', 'fruchterman-wasm', Extensions.FruchtermanLayout); +register('behavior', 'brush-select', Extensions.BrushSelect); +register('behavior', 'hover-activate', Extensions.HoverActivate); + const createGraph = () => { - const ExtGraph = extend(Graph, { - layouts: { - 'force-wasm': Extensions.ForceLayout, - 'fruchterman-wasm': Extensions.FruchtermanLayout, - }, - behaviors: { - 'brush-select': Extensions.BrushSelect, - 'hover-activate': Extensions.HoverActivate, - }, - }); - const graph = new ExtGraph({ + const graph = new Graph({ container: container as HTMLElement, width, height: 1200, diff --git a/packages/g6/tests/integration/plugins-history-combo.spec.ts b/packages/g6/tests/integration/plugins-history-combo.spec.ts deleted file mode 100644 index aa541d938c..0000000000 --- a/packages/g6/tests/integration/plugins-history-combo.spec.ts +++ /dev/null @@ -1,119 +0,0 @@ -import historyCombo from '../demo/plugins/history-combo'; -import { createContext } from './utils'; -import './utils/useSnapshotMatchers'; - -const dir = `${__dirname}/snapshots/plugins/history`; - -describe('Plugins history combo', () => { - it('should be rendered correctly', (done) => { - const { backgroundCanvas, canvas, container, labelCanvas, transientCanvas, transientLabelCanvas } = createContext( - 500, - 500, - ); - - const graph = historyCombo({ - backgroundCanvas, - canvas, - container, - labelCanvas, - transientCanvas, - transientLabelCanvas, - width: 500, - height: 500, - }); - - graph.on('afterlayout', async () => { - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-combo-init'); - - const $undo = document.querySelectorAll('button')[0]; - const $redo = document.querySelectorAll('button')[1]; - - /** - * Click button to add combo 2. - * Verify that the API `addCombo` supports history. - */ - const $addCombo = document.querySelectorAll('button')[2] as HTMLInputElement; - $addCombo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-add-combo'); - $undo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-add-combo-undo'); - $redo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-add-combo-redo'); - $undo.click(); - - /** - * Click button to move combo 1. - * Verify that the API `addCombo` supports history. - */ - // const $moveCombo = document.querySelectorAll( - // 'button', - // )[3] as HTMLInputElement; - // $moveCombo.click(); - // await expect(canvas).toMatchSVGSnapshot( - // dir, - // 'plugins-history-move-combo', - // ); - // $undo.click(); - // await expect(canvas).toMatchSVGSnapshot( - // dir, - // 'plugins-history-move-combo-undo', - // ); - // $redo.click(); - // await expect(canvas).toMatchSVGSnapshot( - // dir, - // 'plugins-history-move-combo-redo', - // ); - - /** - * Click button to collapse combo 1. - * Verify that the API `collapseCombo` supports history. - */ - // const $collapseCombo = document.querySelectorAll( - // 'button', - // )[4] as HTMLInputElement; - // $collapseCombo.click(); - // await expect(canvas).toMatchSVGSnapshot( - // dir, - // 'plugins-history-collapse-combo', - // ); - // $undo.click(); - // await expect(canvas).toMatchSVGSnapshot( - // dir, - // 'plugins-history-collapse-combo-undo', - // ); - // $redo.click(); - // await expect(canvas).toMatchSVGSnapshot( - // dir, - // 'plugins-history-collapse-combo-redo', - // ); - // $undo.click(); - - /** - * Click button to collapse combo 1. - * Verify that the API `collapseCombo` supports history. - */ - // const $expandCombo = document.querySelectorAll( - // 'button', - // )[5] as HTMLInputElement; - // $expandCombo.click(); - // await expect(canvas).toMatchSVGSnapshot( - // dir, - // 'plugins-history-expand-combo', - // ); - // $undo.click(); - // await expect(canvas).toMatchSVGSnapshot( - // dir, - // 'plugins-history-expand-combo-undo', - // ); - // $redo.click(); - // await expect(canvas).toMatchSVGSnapshot( - // dir, - // 'plugins-history-expand-combo-redo', - // ); - // $undo.click(); - - graph.destroy(); - done(); - }); - }); -}); diff --git a/packages/g6/tests/integration/plugins-history.spec.ts b/packages/g6/tests/integration/plugins-history.spec.ts deleted file mode 100644 index e61602db64..0000000000 --- a/packages/g6/tests/integration/plugins-history.spec.ts +++ /dev/null @@ -1,146 +0,0 @@ -import history from '../demo/plugins/history'; -import { createContext } from './utils'; -import './utils/useSnapshotMatchers'; - -const dir = `${__dirname}/snapshots/plugins/history`; - -describe('Plugins history', () => { - it('should be rendered correctly', (done) => { - const { backgroundCanvas, canvas, container, labelCanvas, transientCanvas, transientLabelCanvas } = createContext( - 500, - 500, - ); - - const graph = history({ - backgroundCanvas, - canvas, - container, - labelCanvas, - transientCanvas, - transientLabelCanvas, - width: 500, - height: 500, - }); - - graph.on('afterlayout', async () => { - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-init'); - - const $undo = document.querySelectorAll('button')[0]; - const $redo = document.querySelectorAll('button')[1]; - - /** - * Click button to set node 1 state selected. - * Verify that the API `setItemSate` supports history. - */ - const $setState = document.querySelectorAll('button')[2] as HTMLInputElement; - $setState.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-set-item-state'); - $undo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-set-item-state-undo'); - $redo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-set-item-state-redo'); - - /** - * Click button to clear node 1 selected. - * Verify that the API `clearItemState` supports history. - */ - const $clearState = document.querySelectorAll('button')[3] as HTMLInputElement; - $clearState.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-clear-item-state'); - $undo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-clear-item-state-undo'); - $redo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-clear-item-state-redo'); - $undo.click(); - - /** - * Click button to add node 3 and edge 2. - * Verify that the API `addData` supports history. - */ - const $addData = document.querySelectorAll('button')[4] as HTMLInputElement; - $addData.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-add-data'); - $undo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-add-data-undo'); - $redo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-add-data-redo'); - - /** - * Click button to delete node 3 and edge 2. - * Verify that the API `deleteData` supports history. - */ - const $deleteData = document.querySelectorAll('button')[5] as HTMLInputElement; - $deleteData.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-delete-data'); - $undo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-delete-data-undo'); - $redo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-delete-data-redo'); - $undo.click(); - - /** - * Click button to update node 1. - * Verify that the API `updateData` supports history. - */ - const $updateData = document.querySelectorAll('button')[6] as HTMLInputElement; - $updateData.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-update-data'); - $undo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-update-data-undo'); - $redo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-update-data-redo'); - $undo.click(); - - /** - * Click button to hide node 3. - * Verify that the API `hideItem` supports history. - */ - const $showHideItem = document.querySelectorAll('button')[7] as HTMLInputElement; - $showHideItem.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-hide-item'); - $undo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-hide-item-undo'); - $redo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-hide-item-redo'); - - /** - * Click button to show node 3. - * Verify that the API `showItem` supports history. - */ - $showHideItem.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-show-item'); - $undo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-show-item-undo'); - $redo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-show-item-redo'); - - /** - * Click button to back node 3. - * Verify that the API `backItem` supports history. - */ - const $backItem = document.querySelectorAll('button')[9] as HTMLInputElement; - $updateData.click(); - $backItem.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-back-item'); - $undo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-back-item-undo'); - $redo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-back-item-redo'); - - /** - * Click button to front node 3. - * Verify that the API `frontItem` supports history. - */ - const $frontItem = document.querySelectorAll('button')[8] as HTMLInputElement; - $frontItem.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-front-item'); - $undo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-front-item-undo'); - $redo.click(); - await expect(canvas).toMatchSVGSnapshot(dir, 'plugins-history-front-item-redo'); - - graph.destroy(); - done(); - }); - }); -}); diff --git a/packages/g6/tests/unit/spec.spec.ts b/packages/g6/tests/unit/spec.spec.ts new file mode 100644 index 0000000000..b14d2c6338 --- /dev/null +++ b/packages/g6/tests/unit/spec.spec.ts @@ -0,0 +1,295 @@ +import { Renderer } from '@antv/g-canvas'; +import type { G6Spec } from '../../src/spec'; +import type { DataOption } from '../../src/spec/data'; +import type { ComboOption, EdgeOption, NodeOption } from '../../src/spec/element'; +import type { LayoutOption } from '../../src/spec/layout'; +import type { ModeOption } from '../../src/spec/mode'; +import type { OptimizeOption } from '../../src/spec/optimize'; +import type { ThemeOption } from '../../src/spec/theme'; +import type { WidgetOption } from '../../src/spec/widget'; + +// for type check +describe('spec', () => { + it('spec', () => { + const spec: G6Spec = { + width: 800, + height: 600, + renderer: () => { + return new Renderer(); + }, + devicePixelRatio: 2, + autoResize: true, + autoFit: { + type: 'view', + rules: {}, + }, + padding: [10, 10], + zoom: 1.2, + zoomRange: [0.5, 2], + data: { + nodes: [ + { + id: 'node-1', + data: { + value: 1, + }, + style: { + nodeStyle: 'red', + }, + }, + ], + edges: [], + combos: [], + }, + node: { + style: { + nodeStyle: 'blue', + }, + state: { + state1: { + nodeStyle: 'green', + }, + }, + animate: { + default: { + enter: { + type: 'fade-in', + }, + }, + }, + palette: { + type: 'group', + field: 'field', + color: 'brBG', + }, + }, + theme: 'light', + mode: ['drag-canvas', 'my-behavior'], + widget: ['my-widget', { type: 'another-widget', text: 'text', value: 1 }], + optimize: { + tileFirstRender: true, + }, + }; + + expect(spec).toBeTruthy(); + }); + + it('infer', () => { + class Graph { + #spec: G6Spec; + + constructor(spec: G6Spec) { + this.#spec = spec; + } + + public getData(): NonNullable { + return this.#spec.data!; + } + + public setData(data: G6Spec['data']) { + this.#spec.data = data; + } + } + + const anySpec = { + data: { + nodes: [ + { + id: 'node-1', + data: { value: 1 }, + style: { fill: 'red' }, + }, + ], + }, + }; + + const graph = new Graph(anySpec); + const data = graph.getData(); + + expect(data.nodes?.[0].data?.value).toBeTruthy(); + }); + + it('data', () => { + const data: DataOption = { + nodes: [ + { id: 'node-1' }, + { id: 'node-2', data: { value: 1, field: 'A' } }, + { id: 'node-3', data: { value: 2 }, style: { x: 1, fill: 'red', y: 1, opacity: 0.1 } }, + ], + edges: [ + { + id: 'edge-1', + source: 'node-1', + target: 'node-2', + data: { value: 1, field: 'A' }, + style: { stroke: 'red' }, + }, + { id: 'edge-2', source: 'node-1', target: 'node-3' }, + ], + combos: [ + { id: 'combo-1' }, + { id: 'combo-2', data: { value: 1, field: 'A' } }, + { id: 'combo-3', data: { value: 2 }, style: { x: 1, fill: 'red' } }, + ], + }; + + expect(data).toBeTruthy(); + }); + + it('theme', () => { + const builtInTheme: ThemeOption = 'light'; + expect(builtInTheme).toBeTruthy(); + + const registerTheme: ThemeOption = 'ghost'; + expect(registerTheme).toBeTruthy(); + }); + + it('behavior', () => { + const builtInBehavior: ModeOption = ['orbit-canvas-3d']; + expect(builtInBehavior).toBeTruthy(); + + const registerBehavior: ModeOption = ['drag-canvas', 'my-behavior']; + expect(registerBehavior).toBeTruthy(); + }); + + it('layout', () => { + const builtInLayout: LayoutOption = { + type: 'concentric', + clockwise: true, + height: 100, + }; + expect(builtInLayout).toBeTruthy(); + + type RegisterLayout = LayoutOption; + + const registerLayout1: RegisterLayout = { + type: 'layout1', + param: 1, + }; + expect(registerLayout1).toBeTruthy(); + + const registerLayout2: RegisterLayout = { + type: 'layout2', + args: true, + }; + expect(registerLayout2).toBeTruthy(); + + const pipeLayout: LayoutOption = [ + { + type: 'force', + nodesFilter: (node) => node.data!.value > 1, + }, + ]; + expect(pipeLayout).toBeTruthy(); + }); + + it('node', () => { + const registerNode: NodeOption = { + style: { + nodeStyle: (model) => model.style?.nodeStyle || 'white', + }, + state: { + state1: { + nodeStyle: (data) => data.style?.nodeStyle || 'white', + }, + }, + animate: { + default: { + enter: { + type: 'fade-in', + delay: 100, + }, + }, + state1: { + show: { + type: 'wave-in', + duration: 100, + }, + }, + }, + palette: 'spectral', + }; + + expect(registerNode).toBeTruthy(); + }); + + it('edge', () => { + const registerEdge: EdgeOption = { + style: { + edgeStyle: (model) => model.style?.edgeStyle || 'white', + }, + state: { + state1: { + edgeStyle: 'red', + }, + }, + animate: { + default: { + enter: { + type: 'fade-in', + delay: 100, + }, + }, + state1: { + show: { + type: 'wave-in', + duration: 100, + }, + }, + }, + palette: { + type: 'group', + color: 'my-palette', + invert: true, + }, + }; + + expect(registerEdge).toBeTruthy(); + }); + + it('combo', () => { + const registerCombo: ComboOption = { + style: { + comboStyle: (model) => model.style?.comboStyle || 'white', + }, + state: { + state1: { + comboStyle: 'red', + }, + }, + animate: { + default: { + enter: { + type: 'fade-in', + delay: 100, + }, + }, + state1: { + show: { + type: 'wave-in', + duration: 100, + }, + }, + }, + }; + + expect(registerCombo).toBeTruthy(); + }); + + it('widget', () => { + const builtInWidget: WidgetOption = ['hull', { type: 'grid' }]; + expect(builtInWidget).toBeTruthy(); + + const registerWidget: WidgetOption = ['widget1', { type: 'widget2', option2: 1 }, 'grid', { type: 'tooltip' }]; + + expect(registerWidget).toBeTruthy(); + }); + + it('optimize', () => { + const optimize: OptimizeOption = { + tileFirstRender: true, + }; + + expect(optimize).toBeTruthy(); + }); +}); diff --git a/packages/site/docs/apis/graph/Graph.en.md b/packages/site/docs/apis/graph/Graph.en.md index 0ef07e637b..fa96e158be 100644 --- a/packages/site/docs/apis/graph/Graph.en.md +++ b/packages/site/docs/apis/graph/Graph.en.md @@ -784,89 +784,6 @@ Collapse one or multiple subtrees Expand one or multiple subtrees -## History Stack - -### isHistoryEnabled - -**Type**: `() => void` - -Determine if history (redo/undo) is enabled - -### getRedoStack - -**Type**: `() => void` - -Retrieve the current undo stack which consists of operations that were undone - -### getUndoStack - -**Type**: `() => void` - -Retrieve the current redo stack which consists of operations that could be undone - -### getStack - -**Type**: `() => void` - -Retrieve the complete history stack - -### pushStack - -**Type**: `(cmd: Command[], stackType: 'redo' | 'undo') => void` - -Push the operation(s) onto the specified stack - -### pauseStack - -**Type**: `() => void` - -Pause stacking operation - -### resumeStack - -**Type**: `() => void` - -Resume stacking operation - -### startHistoryBatch - -**Type**: `() => void` - -Begin a historyBatch operation - -Any operations performed between `startHistoryBatch` and `stopHistoryBatch` are grouped together. -treated as a single operation when undoing or redoing - -### stopHistoryBatch - -**Type**: `() => void` - -Stop a historyBatch operation. - -### executeWithNoStack - -**Type**: `(callback: () => void) => void` - -Execute a callback without allowing any stacking operations - -### undo - -**Type**: `() => void` - -Revert the last operation on the graph - -### redo - -**Type**: `() => void` - -Restore the last operation on the graph - -### cleanHistory - -**Type**: `(stackType?: 'redo' | 'undo') => void` - -Clear history stack - ## Free Plugins ### addPlugins diff --git a/packages/site/docs/apis/graph/Graph.zh.md b/packages/site/docs/apis/graph/Graph.zh.md index 50244fe3a0..50264ccbcc 100644 --- a/packages/site/docs/apis/graph/Graph.zh.md +++ b/packages/site/docs/apis/graph/Graph.zh.md @@ -788,88 +788,6 @@ false | AABB; 展开一个或多个子树 -## 历史栈 - -### isHistoryEnabled - -**类型**:`() => void` - -获取历史栈是否启用 - -### getRedoStack - -**类型**:`() => void` - -获取重做栈 - -### getUndoStack - -**类型**:`() => void` - -获取撤销栈 - -### getStack - -**类型**:`() => void` - -获取历史栈 - -### pushStack - -**类型**:`(cmd: Command[], stackType: 'redo' | 'undo') => void` - -添加操作到历史栈 - -### pauseStack - -**类型**:`() => void` - -暂停入栈操作 - -### resumeStack - -**类型**:`() => void` - -恢复入栈操作 - -### startHistoryBatch - -**类型**:`() => void` - -开始批处理历史操作 - -`startHistoryBatch` 到 `stopHistoryBatch` 过程中的操作会被认为是原子操作 - -### stopHistoryBatch - -**类型**:`() => void` - -停止批处理历史操作 - -### executeWithNoStack - -**类型**: `(callback: () => void) => void` - -执行一个回调,该过程中不允许历史栈操作 - -### undo - -**类型**: `() => void` - -撤销 - -### redo - -**类型**: `() => void` - -重做 - -### cleanHistory - -**类型**:`(stackType?: 'redo' | 'undo') => void` - -清除历史记录 - ## 自由插件 ### addPlugins diff --git a/packages/site/docs/apis/graph/Specification.en.md b/packages/site/docs/apis/graph/Specification.en.md index 1e396e57e9..86c32b67cd 100644 --- a/packages/site/docs/apis/graph/Specification.en.md +++ b/packages/site/docs/apis/graph/Specification.en.md @@ -470,18 +470,6 @@ Free plugins' configurations. **TODO**: 链接各个插件的配置文档 -## enableStack - -**Type**: `boolean` - -Whether to enable the history stack. - -## stackCfg - -**Type**: `StackCfg` - - - ## optimize **Type**: `OptimizeCfg` diff --git a/packages/site/docs/apis/plugins/HistoryConfig.en.md b/packages/site/docs/apis/plugins/HistoryConfig.en.md deleted file mode 100644 index 45c8de2525..0000000000 --- a/packages/site/docs/apis/plugins/HistoryConfig.en.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: History -order: 1 ---- - -- [History](/en/examples/tool/history/#history) - -## Configurations - -### enableStack - -**Type**: `boolean` - -**Default**: `false` - -Whether to enable stack - -### stackCfg Required - -**Type**: `StackCfg` - - - -**Default**: `{}` - -Stack configuration - -## API - -### canRedo - -**Type**: `() => boolean;` - -**Description**: Can redo - -### canUndo - -**Type**: `() => boolean;` - -**Description**: Can undo - -### clear - -**Type**: `() => void;` - -**Description**: Clear stack - -### clearRedoStack - -**Type**: `() => void;` - -**Description**: Clear redo stack - -### clearUndoStack - -**Type**: `() => void;` - -**Description**: Clear undo stack - -### isEnable - -**Type**: `() => boolean;` - -**Description**: Is stack enabled - -### getStack - -**Type**: `() => Record;` - - - -**Description**: Get stack - -### getRedoStack - -**Type**: `() => Command[][];` - - - -**Description**: Get redo stack - -### getUndoStack - -**Type**: `() => Command[][];` - - - -**Description**: Get undo stack - -### historyBatch - -**Type**: `(callback: () => void) => void;` - -**Description**: Execute the provided function in a historyBatch mode - -### notify - -**Type**: `(graph: IGraph, eventName: string, ...data: any[]) => void;` - -### push - -**Type**: `(commands: Command[], stackType: StackType = 'undo', isNew = true) => void;` - - - -
- - StackType - - -```ts -type StackType = 'redo' | 'undo'; -``` - -
- -**Description**: Push stack - -**Description**: Notify event - -### redo - -**Type**: `() => void;` - -**Description**: Redo - -### undo - -**Type**: `() => void;` - -**Description**: Undo - -### startHistoryBatch - -**Type**: `() => void;` - -**Description**: Start history batch - -### stopHistoryBatch - -**Type**: `() => void;` - -**Description**: Stop history batch - - diff --git a/packages/site/docs/apis/plugins/HistoryConfig.zh.md b/packages/site/docs/apis/plugins/HistoryConfig.zh.md deleted file mode 100644 index 84b97ca576..0000000000 --- a/packages/site/docs/apis/plugins/HistoryConfig.zh.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: History 历史记录 -order: 1 ---- - -- [撤销重做](/examples/tool/history/#history) - -## 配置项 - -### enableStack - -**类型**:`boolean` - -**默认值**:`false` - -是否启用堆栈 - -### stackCfg 必须 - -**类型**:`StackCfg` - - - -**默认值**:`{}` - -堆栈配置 - -## API - -### canRedo - -**类型**:`() => boolean;` - -**说明**:是否可以重做 - -### canUndo - -**类型**:`() => boolean;` - -**说明**:是否可以撤销 - -### clear - -**类型**:`() => void;` - -**说明**:清空堆栈 - -### clearRedoStack - -**类型**:`() => void;` - -**说明**:清空重做堆栈 - -### clearUndoStack - -**类型**:`() => void;` - -**说明**:清空撤销堆栈 - -### isEnable - -**类型**:`() => boolean;` - -**说明**:是否启用堆栈 - -### getStack - -**类型**:`() => Record;` - - - -**说明**:获取堆栈 - -### getRedoStack - -**类型**:`() => Command[][];` - - - -**说明**:获取重做堆栈 - -### getUndoStack - -**类型**:`() => Command[][];` - - - -**说明**:获取撤销堆栈 - -### historyBatch - -**类型**:`(callback: () => void) => void;` - -**说明**:以 historyBatch 模式执行所提供的函数 - -### notify - -**类型**:`(graph: IGraph, eventName: string, ...data: any[]) => void;` - -**说明**:事件通知 - -### push - -**类型**:`(commands: Command[], stackType: StackType = 'undo', isNew = true) => void;` - - - -
- - StackType - - -```ts -type StackType = 'redo' | 'undo'; -``` - -
- -**说明**:推入堆栈 - -### redo - -**类型**:`() => void;` - -**说明**:重做 - -### undo - -**类型**:`() => void;` - -**说明**:撤销 - -### startHistoryBatch - -**类型**:`() => void;` - -**说明**:开始历史批处理 - -### stopHistoryBatch - -**类型**:`() => void;` - -**说明**:结束历史批处理 - - diff --git a/packages/site/docs/apis/plugins/TimeBar.en.md b/packages/site/docs/apis/plugins/TimeBar.en.md index 840696f238..3a0441ea88 100644 --- a/packages/site/docs/apis/plugins/TimeBar.en.md +++ b/packages/site/docs/apis/plugins/TimeBar.en.md @@ -48,7 +48,7 @@ Time bar data ### filter -**Type**: `type filter = (graph: IGraph, values: Values) => void;` +**Type**: `type filter = (graph: Graph, values: Values) => void;` **Default**: `undefined` diff --git a/packages/site/docs/apis/plugins/TimeBar.zh.md b/packages/site/docs/apis/plugins/TimeBar.zh.md index afe0d32c3a..7b9e6da86b 100644 --- a/packages/site/docs/apis/plugins/TimeBar.zh.md +++ b/packages/site/docs/apis/plugins/TimeBar.zh.md @@ -48,7 +48,7 @@ order: 8 ### filter -**类型**:`type filter = (graph: IGraph, values: Values) => void;` +**类型**:`type filter = (graph: Graph, values: Values) => void;` **默认值**:`undefined` diff --git a/packages/site/docs/common/IPluginBaseConfig.en.md b/packages/site/docs/common/IPluginBaseConfig.en.md index 054da84162..b3f21f1f47 100644 --- a/packages/site/docs/common/IPluginBaseConfig.en.md +++ b/packages/site/docs/common/IPluginBaseConfig.en.md @@ -18,7 +18,7 @@ The class name of the plugin container ### graph -**Type**: `IGraph` +**Type**: `Graph` **Default**: Current graph instance diff --git a/packages/site/docs/common/IPluginBaseConfig.zh.md b/packages/site/docs/common/IPluginBaseConfig.zh.md index 46c0c78696..21bb7ed3a4 100644 --- a/packages/site/docs/common/IPluginBaseConfig.zh.md +++ b/packages/site/docs/common/IPluginBaseConfig.zh.md @@ -18,7 +18,7 @@ ### graph -**类型**:`IGraph` +**类型**:`Graph` **默认值**:当前图实例 diff --git a/packages/site/docs/common/PluginHistoryCommand.en.md b/packages/site/docs/common/PluginHistoryCommand.en.md deleted file mode 100644 index 31764e4ded..0000000000 --- a/packages/site/docs/common/PluginHistoryCommand.en.md +++ /dev/null @@ -1,13 +0,0 @@ -
- - Command - - -```ts -type Command = { - redo: (graph: IGraph) => void; - undo: (graph: IGraph) => void; -}; -``` - -
diff --git a/packages/site/docs/common/PluginHistoryCommand.zh.md b/packages/site/docs/common/PluginHistoryCommand.zh.md deleted file mode 100644 index 31764e4ded..0000000000 --- a/packages/site/docs/common/PluginHistoryCommand.zh.md +++ /dev/null @@ -1,13 +0,0 @@ -
- - Command - - -```ts -type Command = { - redo: (graph: IGraph) => void; - undo: (graph: IGraph) => void; -}; -``` - -
diff --git a/packages/site/docs/common/StackCfg.en.md b/packages/site/docs/common/StackCfg.en.md deleted file mode 100644 index 300b4bab00..0000000000 --- a/packages/site/docs/common/StackCfg.en.md +++ /dev/null @@ -1,31 +0,0 @@ -
- - StackCfg - - -```ts -type StackCfg = { - /** The maximum number of steps allowed in the history stack. */ - stackSize?: number; - /** Whether to allow pushing actions to the history stack by default. */ - stackActive?: boolean; - /** API names to be excluded from being pushed to the history stack. This configuration takes the highest priority. */ - excludes?: string[]; - /** API names to be included in the history stack. This configuration takes the highest priority. */ - includes?: string[]; - /** Whether to ignore all add data operations. */ - ignoreAdd?: boolean; - /** Whether to ignore all remove data operations. */ - ignoreRemove?: boolean; - /** Whether to ignore all update data operations. */ - ignoreUpdate?: boolean; - /** Whether to ignore all element state change operations. */ - ignoreStateChange?: boolean; - /** Whether to ignore all layer change operations. */ - ignoreLayerChange?: boolean; - /** Whether to ignore all display change operations. */ - ignoreDisplayChange?: boolean; -}; -``` - -
diff --git a/packages/site/docs/common/StackCfg.zh.md b/packages/site/docs/common/StackCfg.zh.md deleted file mode 100644 index f5a15387e2..0000000000 --- a/packages/site/docs/common/StackCfg.zh.md +++ /dev/null @@ -1,31 +0,0 @@ -
- - StackCfg - - -```ts -type StackCfg = { - /** 历史栈允许存储的最大步数。*/ - stackSize?: number; - /** 默认是否允许入栈。*/ - stackActive?: boolean; - /** 需要排除入栈的 API 名称,此处配置的优先级最高。*/ - excludes?: string[]; - /** 需要入栈的 API 名称,此处配置的优先级最高。*/ - includes?: string[]; - /** 是否忽略所有的新增数据操作。*/ - ignoreAdd?: boolean; - /** 是否忽略所有的删除数据操作。*/ - ignoreRemove?: boolean; - /** 是否忽略所有的更新数据操作。*/ - ignoreUpdate?: boolean; - /** 是否忽略所有的元素状态变更操作。*/ - ignoreStateChange?: boolean; - /** 是否忽略所有的层级变更操作。*/ - ignoreLayerChange?: boolean; - /** 是否忽略所有的渲染变更操作。*/ - ignoreDisplayChange?: boolean; -}; -``` - -
diff --git a/packages/site/docs/manual/customize/overview.en.md b/packages/site/docs/manual/customize/overview.en.md index db33099d4f..2ad60ebed2 100644 --- a/packages/site/docs/manual/customize/overview.en.md +++ b/packages/site/docs/manual/customize/overview.en.md @@ -141,7 +141,6 @@ All built-in and custom plugins should inherit from Extensions.BasePlugin or oth | type | Import from | Registered by Default | Demo | API | Note | | :------------ | :--------------------- | :-------------------- | :----------------------------------------------------- | :-------------------------------------- | :-------------------------------- | -| 'history' | Extensions.History | ✅ Yes | [DEMO](/en/examples/tool/history/#history) | [API](/en/apis/plugins/history-config) | | | 'toolbar' | Extensions.Toolbar | No | [DEMO](/en/examples/tool/toolbar/#toolbar) | [API](/en/apis/plugins/toolbar-config) | | | 'tooltip' | Extensions.Tooltip | No | [DEMO](/en/examples/tool/tooltip/#tooltipPlugin) | [API](/en/apis/plugins/tooltip-config) | | | 'minimap' | Extensions.Minimap | No | [DEMO](/en/examples/tool/minimap/#minimap) | [API](/en/apis/plugins/mini-map-config) | | diff --git a/packages/site/docs/manual/customize/overview.zh.md b/packages/site/docs/manual/customize/overview.zh.md index 89a8c6604b..b9b2716086 100644 --- a/packages/site/docs/manual/customize/overview.zh.md +++ b/packages/site/docs/manual/customize/overview.zh.md @@ -138,7 +138,6 @@ const graph = new Graph({ | type 名称 | 引入方式 | 是否默认注册 | Demo | API | 注释 | | :------------ | :--------------------- | :----------- | :----------------------------------------------------- | :-------------------------------------- | :--------------- | -| 'history' | Extensions.History | ✅ 是 | [DEMO](/zh/examples/tool/history/#history) | [API](/zh/apis/plugins/history-config) | | | 'toolbar' | Extensions.Toolbar | 否 | [DEMO](/zh/examples/tool/toolbar/#toolbar) | [API](/zh/apis/plugins/toolbar-config) | | | 'tooltip' | Extensions.Tooltip | 否 | [DEMO](/zh/examples/tool/tooltip/#tooltipPlugin) | [API](/zh/apis/plugins/tooltip-config) | | | 'minimap' | Extensions.Minimap | 否 | [DEMO](/zh/examples/tool/minimap/#minimap) | [API](/zh/apis/plugins/mini-map-config) | | diff --git a/packages/site/docs/manual/new-features.en.md b/packages/site/docs/manual/new-features.en.md index 4efd21b7a7..92b85f851f 100644 --- a/packages/site/docs/manual/new-features.en.md +++ b/packages/site/docs/manual/new-features.en.md @@ -542,9 +542,7 @@ const stdLib = { 'collapse-expand-tree': CollapseExpandTree, // Collapse/expand subtree 'click-select': ClickSelect, // Click to select }, - plugins: { - history: History, // History stack - }, + plugins: {}, nodes: { 'circle-node': CircleNode, // Circle node 'rect-node': RectNode, // Rectangular node diff --git a/packages/site/docs/manual/new-features.zh.md b/packages/site/docs/manual/new-features.zh.md index d91e631c25..9ff387949e 100644 --- a/packages/site/docs/manual/new-features.zh.md +++ b/packages/site/docs/manual/new-features.zh.md @@ -549,9 +549,7 @@ const stdLib = { 'collapse-expand-tree': CollapseExpandTree, // 展开/收起子树 'click-select': ClickSelect, // 点击选择 }, - plugins: { - history: History, // 历史栈 - }, + plugins: {}, nodes: { 'circle-node': CircleNode, // 圆形节点 'rect-node': RectNode, // 矩形边 diff --git a/packages/site/examples/tool/history/demo/history.ts b/packages/site/examples/tool/history/demo/history.ts deleted file mode 100644 index c6cf26d713..0000000000 --- a/packages/site/examples/tool/history/demo/history.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { Graph } from '@antv/g6'; - -const container = document.getElementById('container'); -const width = container.scrollWidth; -const height = container.scrollHeight || 500; - -const graph = new Graph({ - container: 'container', - width, - height, - theme: { - type: 'spec', - specification: { - node: { - dataTypeField: 'cluster', - }, - }, - }, - node: { - animates: { - update: [ - { - fields: ['opacity'], - shapeId: 'haloShape', - }, - ], - }, - }, - combo: (model) => { - return { - id: model.id, - data: { - type: 'circle-combo', - ...model.data, - keyShape: { - padding: [10, 20, 30, 40], - r: 50, - }, - labelShape: { - text: model.id, - }, - }, - }; - }, - data: { - nodes: [ - { id: '1', data: { x: 250, y: 300, parentId: 'combo1' } }, - { id: '2', data: { x: 350, y: 300, parentId: 'combo1' } }, - { id: '3', data: { x: 250, y: 450, parentId: 'combo2' } }, - ], - edges: [ - { id: 'edge1', source: '1', target: '2', data: {} }, - ], - combos: [ - { id: 'combo1', data: { parentId: 'combo2' } }, // collapsed: true - { id: 'combo2', data: {} }, - ], - }, - modes: { - default: [ - 'collapse-expand-combo', - { - type: 'drag-node', - // enableTransient: false, - // updateComboStructure: false, - }, - 'drag-canvas', - { - type: 'click-select', - itemTypes: ['node', 'edge', 'combo'], - }, - { - type: 'drag-combo', - enableTransient: true, - // updateComboStructure: true, - }, - ], - }, -}); - -const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); -const simulate = () => { - // Add elements - // Batch update, also supports `historyBatch` - graph.startHistoryBatch(); // start batch - graph.addData('node', { - id: '4', - data: { - x: 300, - y: 370, - parentId: 'combo1', - }, - }); - graph.addData('edge', { - id: 'edge3', - source: '1', - target: '4', - }); - graph.stopHistoryBatch(); // end batch - // Update Node Color (no stack) - delay(300).then(() => { - // Method 1: No stack - graph.executeWithNoStack(() => { - graph.updateData( - 'node', - { - id: '1', - data: { - cluster: Math.random(), - }, - } - ); - }); - // Method 2: No stack - graph.pauseStack(); - graph.updateData( - 'node', - { - id: '2', - data: { - cluster: Math.random(), - }, - } - ); - graph.resumeStack(); - }); - // set states - delay(600).then(() => { - graph.historyBatch(() => { - graph.setItemState(['1', '2', '3', '4'], 'selected', true); - }); - }); - // move - delay(1200).then(() => { - graph.moveCombo('combo2', 50, 0); - }); - // collpase combo - delay(1800).then(() => { - graph.collapseCombo('combo1'); - }); -}; - -/** Create operations and tips */ -const btnContainer = document.createElement('div'); -btnContainer.style.position = 'absolute'; -container.appendChild(btnContainer); -const tipButton = document.createElement('a'); -tipButton.innerText = 'Simulate interaction'; -tipButton.addEventListener('click', simulate); -btnContainer.appendChild(tipButton); -const tip = document.createElement('span'); -tip.innerHTML = `:
Add Elements (🌟 batch processing) 👉 Update Node Color (⛳️ No stack) 👉 Update States 👉 Move Combo 👉 Collapse Combo
`; -btnContainer.appendChild(tip); -const undoButton = document.createElement('button'); -undoButton.innerText = '⬅️ undo'; -undoButton.addEventListener('click', () => { - graph.undo(); -}); -btnContainer.appendChild(undoButton); -const redoButton = document.createElement('button'); -redoButton.innerText = '➡️ redo'; -redoButton.style.margin = '10px 5px'; -redoButton.addEventListener('click', () => { - graph.redo(); -}); -btnContainer.appendChild(redoButton); - -/** Update redo/undo status */ -const updateButtonStatus = () => { - undoButton.disabled = !graph.canUndo(); - redoButton.disabled = !graph.canRedo(); -}; - -updateButtonStatus(); - -graph.on('history:change', () => { - updateButtonStatus(); -}); - -window.graph = graph; \ No newline at end of file diff --git a/packages/site/examples/tool/history/demo/meta.json b/packages/site/examples/tool/history/demo/meta.json index 99300fde92..da29408db2 100644 --- a/packages/site/examples/tool/history/demo/meta.json +++ b/packages/site/examples/tool/history/demo/meta.json @@ -3,14 +3,5 @@ "zh": "中文分类", "en": "Category" }, - "demos": [ - { - "filename": "history.ts", - "title": { - "zh": "撤销重做", - "en": "History" - }, - "screenshot": "" - } - ] + "demos": [] } diff --git a/packages/site/examples/tool/history/index.en.md b/packages/site/examples/tool/history/index.en.md index a95bbf4874..4c4173485d 100644 --- a/packages/site/examples/tool/history/index.en.md +++ b/packages/site/examples/tool/history/index.en.md @@ -1,151 +1,3 @@ --- title: History --- - -History is a built-in components in G6, but not reigstered by default. It needs to be imported into the code and registered with the `extend` method, and then you could configured it to the graph instance. - -## Usage - -### API - -#### isHistoryEnabled - -Determine if history (redo/undo) is enabled. - -```ts -isHistoryEnabled: () => void; -``` - -#### pushStack - -Push the operation(s) onto the specified stack. - -```ts -pushStack: (cmd: Command[], stackType: StackType) => void; -``` - -**Parameters:** - -`cmd`: An array of commands to be pushed onto the stack. -`stackType`: The type of stack (undo/redo) to push the commands onto. - -#### pauseStack - -Pause stacking operation. - -```ts -pauseStack: () => void; -``` - -#### resumeStack - -Resume stacking operation. - -```ts -resumeStack: () => void; -``` - -#### executeWithNoStack - -Execute a callback without allowing any stacking operations. - -```ts -executeWithNoStack: (callback: () => void) => void; -``` - -Parameters: -callback: The callback function to be executed without stacking operations. - -#### getUndoStack - -Retrieve the current undo stack which consists of operations that could be undone. - -```ts -getUndoStack: () => void; -``` - -#### getRedoStack - -Retrieve the current redo stack which consists of operations that were undone. - -```ts -getRedoStack: () => void; -``` - -#### getStack - -Retrieve the complete history stack. - -```ts -getStack: () => void; -``` - -#### undo - -Revert the last n operation(s) on the graph. - -```ts -undo: () => void; -``` - -#### redo - -Restore the operation that was last n reverted on the graph. - -```ts -redo: () => void; -``` - -#### canUndo - -Indicate whether there are any actions available in the undo stack. - -```ts -canUndo: () => void; -``` - -#### canRedo - -Indicate whether there are any actions available in the redo stack. - -```ts -canRedo: () => void; -``` - -#### startHistoryBatch - -Begin a historyBatch operation. Any operations performed between startHistoryBatch and stopHistoryBatch are grouped together and treated as a single operation when undoing or redoing. - -```ts -startHistoryBatch: () => void; -``` - -#### stopHistoryBatch - -End a historyBatch operation. Any operations performed between startHistoryBatch and stopHistoryBatch are grouped together and treated as a single operation when undoing or redoing. - -```ts -stopHistoryBatch: () => void; -``` - -#### historyBatch - -Execute a provided function within a batched context. All operations performed inside the callback will be treated as a composite operation, providing a more convenient way without manually invoking startHistoryBatch and stopHistoryBatch. - -```ts -historyBatch: (callback: () => void) => void; -``` - -**Parameters:** -_callback_: The function containing operations to be batched together. - -#### cleanHistory - -Execute a provided function within a batched context. All operations performed inside the callback will be treated as a composite operation, providing a more convenient way without manually invoking startHistoryBatch and stopHistoryBatch. - -```ts -cleanHistory: (stackType?: StackType) => void; -``` - -**Parameters:** -_stackType (optional)_: The type of stack (undo/redo) to be cleaned. If not provided, all stacks will be cleaned. diff --git a/packages/site/examples/tool/history/index.zh.md b/packages/site/examples/tool/history/index.zh.md index b5f52facbd..c9e55a3103 100644 --- a/packages/site/examples/tool/history/index.zh.md +++ b/packages/site/examples/tool/history/index.zh.md @@ -1,7 +1,3 @@ --- title: 撤销重做 --- - -G6 中内置的 History 组件,但未默认注册。需要将其引入到代码中,并使用 `extend` 方法注册后,方可在图实例上配置和使用。 - -## 使用指南 diff --git a/packages/site/examples/tool/toolbar/demo/self-toolbar.ts b/packages/site/examples/tool/toolbar/demo/self-toolbar.ts index 2df1edeb4b..f2d34af7b1 100644 --- a/packages/site/examples/tool/toolbar/demo/self-toolbar.ts +++ b/packages/site/examples/tool/toolbar/demo/self-toolbar.ts @@ -3,7 +3,6 @@ import insertCss from 'insert-css'; const Graph = extend(BaseGraph, { plugins: { toolbar: Extensions.Toolbar, - history: Extensions.History, }, }); @@ -45,8 +44,6 @@ const toolbar = {
  • alert
  • add node
  • random remove node
  • -
  • redo
  • -
  • undo
  • `; }, @@ -55,7 +52,6 @@ const toolbar = { alert('hello world'); } if (code === 'add') { - graph.startHistoryBatch(); graph.addData('node', { id: 'node2', data: { @@ -78,25 +74,10 @@ const toolbar = { type: 'line-edge', }, }); - graph.stopHistoryBatch(); } if (code === 'remove') { graph.removeData('node', 'node2'); } - if (code === 'redo') { - if (graph.canRedo()) { - graph.redo(); - } else { - alert('can not redo'); - } - } - if (code === 'undo') { - if (graph.canUndo()) { - graph.undo(); - } else { - alert('can not undo'); - } - } }, };