mirror of
https://gitee.com/antv/g6.git
synced 2024-12-02 03:38:20 +08:00
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 <banxuan.zyx@antgroup.com> * 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 <banxuan.zyx@antgroup.com>
This commit is contained in:
parent
951114dd4e
commit
4058ba5344
26
.github/workflows/build.yml
vendored
26
.github/workflows/build.yml
vendored
@ -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.
|
||||
<!-- Created by actions-cool/maintain-one-comment -->
|
||||
emojis: 'eyes'
|
||||
body-include: '<!-- Created by actions-cool/maintain-one-comment -->'
|
||||
|
||||
- name: Upload blob report to GitHub Actions Artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
|
@ -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": [
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 = [];
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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: {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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 = [];
|
||||
|
@ -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);
|
||||
|
@ -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'],
|
||||
|
@ -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 };
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
240
packages/g6/src/plugin/register.ts
Normal file
240
packages/g6/src/plugin/register.ts
Normal file
@ -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';
|
||||
|
||||
/**
|
||||
* <zh/> 转换对象类型 T 的复数 key 为其单数形式
|
||||
* <en/> Converts plural keys of an object type T to their singular form.
|
||||
* @example -- `{ nodes: MyType }` becomes `{ node: MyType }`
|
||||
*/
|
||||
type SingularKeys<T> = {
|
||||
[K in keyof T as K extends `${infer R}s` ? R : never]: T[K];
|
||||
};
|
||||
|
||||
/**
|
||||
* <zh/> 将对象类型 T 中的 Record<string, U> 类型的值转换为 U 类型
|
||||
* <en/> Converts the values of type Record<string, U> in object type T to type U.
|
||||
* @example - `{ key: { [key: string]: MyType } }` becomes `{ key: MyType }`
|
||||
*/
|
||||
type UnwrapRecordValues<T> = {
|
||||
[K in keyof T]: T[K] extends Record<string, infer U> ? U : T[K];
|
||||
};
|
||||
|
||||
/**
|
||||
* <zh/> 用于将一个对象类型的 key 转换为其单数形式,并将对应的值类型转换为其子类型
|
||||
* <en/> 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<T> = UnwrapRecordValues<SingularKeys<T>>;
|
||||
|
||||
type Plugins = {
|
||||
nodes: NodeRegistry;
|
||||
edges: EdgeRegistry;
|
||||
combos: NodeRegistry;
|
||||
layouts: LayoutRegistry;
|
||||
widgets: WidgetRegistry;
|
||||
behaviors: BehaviorRegistry;
|
||||
themeSolvers: ThemeSolverRegistry;
|
||||
themes: ThemeRegistry;
|
||||
transforms: any; //TODO: 待数据处理移除后删除
|
||||
};
|
||||
|
||||
/**
|
||||
* <zh/> 插件类型映射
|
||||
*
|
||||
* <en/> Plugin type mapping
|
||||
*/
|
||||
type STDPlugins = Singular<Plugins>;
|
||||
|
||||
/**
|
||||
* <zh/> 插件类型,即复数形式,例如 nodes
|
||||
*
|
||||
* <en/> Plugin category, i.e. plural form, e.g. nodes.
|
||||
*/
|
||||
type PluginCategory = keyof Plugins;
|
||||
|
||||
/**
|
||||
* <zh/> 标准插件类型,即单数形式,例如 node
|
||||
*
|
||||
* <en/> Standard plugin category, i.e. singular form, e.g. node.
|
||||
*/
|
||||
type STDPluginCategory = keyof STDPlugins;
|
||||
|
||||
/**
|
||||
* <zh/> 插件条目,包含插件名称和插件类,例如 { name: 'node', plugin: BaseNode }
|
||||
*
|
||||
* <en/> Plugin entry, including plugin name and plugin class, e.g. { name: 'node', plugin: BaseNode }
|
||||
*/
|
||||
type PluginEntry<T extends STDPluginCategory> = {
|
||||
name: string;
|
||||
plugin: STDPlugins[T];
|
||||
};
|
||||
|
||||
/**
|
||||
* <zh/> 转换后的插件集合,例如 { nodes: [{ name: 'node', plugin: BaseNode }] }
|
||||
*
|
||||
* <en/> Transformed plugin collection, e.g. { nodes: [{ name: 'node', plugin: BaseNode }] }
|
||||
*/
|
||||
type TransformedPlugins = {
|
||||
[category: string]: PluginEntry<STDPluginCategory>[];
|
||||
};
|
||||
|
||||
const pluginCategoryList: PluginCategory[] = [
|
||||
'nodes',
|
||||
'edges',
|
||||
'combos',
|
||||
'behaviors',
|
||||
'layouts',
|
||||
'widgets',
|
||||
'themes',
|
||||
'themeSolvers',
|
||||
'transforms',
|
||||
];
|
||||
|
||||
class PluginRegistry {
|
||||
private nodes: Map<string, NodeRegistry[string]> = new Map();
|
||||
|
||||
private edges: Map<string, EdgeRegistry[string]> = new Map();
|
||||
|
||||
private combos: Map<string, NodeRegistry[string]> = new Map();
|
||||
|
||||
private layouts: Map<string, LayoutRegistry[string]> = new Map();
|
||||
|
||||
private widgets: Map<string, WidgetRegistry[string]> = new Map();
|
||||
|
||||
private behaviors: Map<string, BehaviorRegistry[string]> = new Map();
|
||||
|
||||
private themeSolvers: Map<string, ThemeSolverRegistry[string]> = new Map();
|
||||
|
||||
private themes: Map<string, ThemeRegistry[string]> = new Map();
|
||||
|
||||
private transforms: Map<string, any> = new Map(); //TODO: 待数据处理移除后删除
|
||||
|
||||
constructor() {
|
||||
// Initialize the registry with built-in plugins.
|
||||
this.registerBuiltInPlugins();
|
||||
}
|
||||
|
||||
/**
|
||||
* <zh/> 注册内置插件
|
||||
*
|
||||
* <en/> 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]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* <zh/> 根据 type 获取插件类型
|
||||
*
|
||||
* <en/> Get the plugin category by type.
|
||||
* @param type - <zh/> 插件类型 | <en/> The plugin type.
|
||||
* @returns - <zh/> 插件类型 | <en/> The plugin category.
|
||||
* @example getPluginCategory('node') => 'nodes'
|
||||
* @private
|
||||
*/
|
||||
private getPluginCategory<T extends STDPluginCategory>(type: T): PluginCategory {
|
||||
return `${type}s` as PluginCategory;
|
||||
}
|
||||
|
||||
/**
|
||||
* <zh/> 注册插件
|
||||
*
|
||||
* <en/> Register a plugin.
|
||||
* @param type <zh/> 插件类型 | <en/> The type of the plugin.
|
||||
* @param key <zh/> 插件的唯一标识 | <en/> The unique identifier of the plugin.
|
||||
* @param pluginClass <zh/> 插件类 | <en/> The plugin class.
|
||||
* @public
|
||||
*/
|
||||
public register<T extends STDPluginCategory>(
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <zh/> 获取已注册的插件集合
|
||||
*
|
||||
* <en/> Get registered plugins.
|
||||
* @returns - <zh/> 已注册的插件 | <en/> 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* <zh/> 获取指定插件
|
||||
*
|
||||
* <en/> Get a specific plugin.
|
||||
* @param type - <zh/> 插件类型 | <en/> The type of the plugin to retrieve.
|
||||
* @param key - <zh/> 插件的唯一标识 | <en/> The key of the specific plugin to retrieve.
|
||||
* @returns - <zh/> 已注册的插件 | <en/> The registered plugin.
|
||||
* @public
|
||||
*/
|
||||
public getRegisterPlugin<T extends STDPluginCategory>(type: T, key: string): PluginEntry<T> {
|
||||
const category = this.getPluginCategory(type);
|
||||
return {
|
||||
name: key,
|
||||
plugin: this[category].get(key) as STDPlugins[T],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* <zh/> 注销插件
|
||||
*
|
||||
* <en/> Unregister a plugin.
|
||||
* @param type - <zh/> 插件类型 | <en/> The type of the plugin to unregister.
|
||||
* @param key - <zh/> 插件的唯一标识 | <en/> The key of the plugin to unregister.
|
||||
* @public
|
||||
*/
|
||||
public unregister<T extends STDPluginCategory>(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 };
|
@ -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') {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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 = {};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<T> {
|
||||
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<Command[]>;
|
||||
protected redoStack: HistoryStack<Command[]>;
|
||||
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<string, Command[][]> {
|
||||
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);
|
||||
}
|
||||
}
|
@ -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');
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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];
|
||||
});
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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';
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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(`
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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<TimebarStyleProps['onChange']>) => void;
|
||||
filter?: (graph: Graph, values: Parameters<TimebarStyleProps['onChange']>) => void;
|
||||
axisStyle?: SubStyleProps<TimebarStyleProps, 'axis'>;
|
||||
chartStyle?: SubStyleProps<TimebarStyleProps, 'chart'>;
|
||||
controllerStyle?: SubStyleProps<TimebarStyleProps, 'controller'>;
|
||||
@ -175,7 +175,7 @@ export class Timebar extends Base {
|
||||
};
|
||||
}
|
||||
|
||||
public init(graph: IGraph) {
|
||||
public init(graph: Graph) {
|
||||
super.init(graph);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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(`<div class='${className || 'g6-component-tooltip'}'></div>`);
|
||||
@ -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;
|
||||
|
@ -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';
|
||||
|
@ -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(() => {
|
||||
|
@ -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<any, any>) {
|
||||
constructor(graph: Graph<any, any>) {
|
||||
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);
|
||||
}
|
||||
|
@ -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<any, any>) {
|
||||
constructor(graph: Graph<any, any>) {
|
||||
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) {
|
||||
|
@ -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<any, any>) {
|
||||
constructor(graph: Graph<any, any>) {
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<any> | null;
|
||||
private currentSupervisor: Supervisor | null;
|
||||
@ -27,7 +28,7 @@ export class LayoutController {
|
||||
private animatedDisplayObject: DisplayObject;
|
||||
private previousNodes: Map<ID, object>;
|
||||
|
||||
constructor(graph: IGraph<any, any>) {
|
||||
constructor(graph: Graph<any, any>) {
|
||||
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,
|
||||
|
@ -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<string, Record<string, Listener>> = {};
|
||||
|
||||
constructor(graph: IGraph<any, any>) {
|
||||
constructor(graph: Graph<any, any>) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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<any, any>) {
|
||||
constructor(graph: Graph<any, any>) {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<any, any>) {
|
||||
constructor(graph: Graph<any, any>) {
|
||||
this.graph = graph;
|
||||
this.tap();
|
||||
}
|
||||
|
@ -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<B extends BehaviorRegistry, T extends ThemeRegistry> extends EventEmitter implements IGraph<B, T> {
|
||||
export class Graph<B extends BehaviorRegistry = any, T extends ThemeSolverRegistry = any> 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<B extends BehaviorRegistry, T extends ThemeRegistry> extends
|
||||
|
||||
constructor(spec: Specification<B, T>) {
|
||||
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<B extends BehaviorRegistry, T extends ThemeRegistry> 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<B extends BehaviorRegistry, T extends ThemeRegistry> 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<B extends BehaviorRegistry, T extends ThemeRegistry> extends
|
||||
'combo',
|
||||
this.getAllCombosData().map((combo) => combo.id),
|
||||
);
|
||||
this.stopHistoryBatch();
|
||||
}
|
||||
|
||||
public getViewportCenter(): PointLike {
|
||||
@ -1298,17 +1275,6 @@ export class Graph<B extends BehaviorRegistry, T extends ThemeRegistry> 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<NodeUserModel> | Partial<ComboUserModel | Partial<NodeUserModel>[] | Partial<ComboUserModel>[]>,
|
||||
@ -1721,12 +1687,10 @@ export class Graph<B extends BehaviorRegistry, T extends ThemeRegistry> 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<B extends BehaviorRegistry, T extends ThemeRegistry> 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<B extends BehaviorRegistry, T extends ThemeRegistry> 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<B extends BehaviorRegistry, T extends ThemeRegistry> extends
|
||||
this.transientCanvas.destroy();
|
||||
this.transientLabelCanvas.destroy();
|
||||
|
||||
// clear history stack
|
||||
this.cleanHistory();
|
||||
|
||||
callback?.();
|
||||
|
||||
this.hooks.destroy.emit({});
|
||||
|
1
packages/g6/src/runtime/layered-canvas/types.ts
Normal file
1
packages/g6/src/runtime/layered-canvas/types.ts
Normal file
@ -0,0 +1 @@
|
||||
export type Layer = 'background' | 'main' | 'label' | 'transient' | 'transientLabel';
|
35
packages/g6/src/spec/canvas/index.ts
Normal file
35
packages/g6/src/spec/canvas/index.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import type { CanvasConfig, IRenderer } from '@antv/g';
|
||||
import type { Layer } from '../../runtime/layered-canvas/types';
|
||||
|
||||
/**
|
||||
* <zh/> 画布配置项
|
||||
*
|
||||
* <en/> Canvas spec
|
||||
* @public
|
||||
*/
|
||||
export type CanvasOption = Pick<CanvasConfig, 'container' | 'devicePixelRatio'> & {
|
||||
/**
|
||||
* <zh/> 画布宽度
|
||||
*
|
||||
* <en/> canvas width
|
||||
*/
|
||||
width?: number;
|
||||
/**
|
||||
* <zh/> 画布高度
|
||||
*
|
||||
* <en/> canvas height
|
||||
*/
|
||||
height?: number;
|
||||
/**
|
||||
* <zh/> 获取渲染器
|
||||
*
|
||||
* <en/> get renderer
|
||||
*/
|
||||
renderer?: (layer: Layer) => IRenderer;
|
||||
/**
|
||||
* <zh/> 是否自动调整画布大小
|
||||
*
|
||||
* <en/> whether to auto resize canvas
|
||||
*/
|
||||
autoResize?: boolean;
|
||||
};
|
13
packages/g6/src/spec/canvas/io.ts
Normal file
13
packages/g6/src/spec/canvas/io.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* <zh/> 设置画布配置项
|
||||
*
|
||||
* <en/> set canvas spec
|
||||
*/
|
||||
export function setter() {}
|
||||
|
||||
/**
|
||||
* <zh/> 获取画布配置项
|
||||
*
|
||||
* <en/> get canvas spec
|
||||
*/
|
||||
export function getter() {}
|
57
packages/g6/src/spec/data/index.ts
Normal file
57
packages/g6/src/spec/data/index.ts
Normal file
@ -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 = {
|
||||
/**
|
||||
* <zh/> 节点数据
|
||||
*
|
||||
* <en/> node data
|
||||
*/
|
||||
nodes?: NodeData[];
|
||||
/**
|
||||
* <zh/> 边数据
|
||||
*
|
||||
* <en/> edge data
|
||||
*/
|
||||
edges?: EdgeData[];
|
||||
/**
|
||||
* <zh/> Combo 数据
|
||||
*
|
||||
* <en/> combo data
|
||||
*/
|
||||
combos?: ComboData[];
|
||||
};
|
||||
|
||||
export type NodeData = {
|
||||
id: ID;
|
||||
data?: Record<string, any>;
|
||||
style?: NodeLikeStyle;
|
||||
};
|
||||
|
||||
export type ComboData = {
|
||||
id: ID;
|
||||
data?: Record<string, any>;
|
||||
style?: NodeLikeStyle;
|
||||
};
|
||||
|
||||
export type EdgeData = {
|
||||
id: ID;
|
||||
source: ID;
|
||||
target: ID;
|
||||
data?: Record<string, any>;
|
||||
style?: EdgeStyle;
|
||||
};
|
||||
|
||||
/**
|
||||
* Can be a node or combo.
|
||||
*/
|
||||
export type NodeLikeStyle = Pick<BaseStyleProps, 'cursor' | 'opacity' | 'pointerEvents' | 'visibility' | 'zIndex'> & {
|
||||
parentId?: ID;
|
||||
collapsed?: boolean;
|
||||
type?: string;
|
||||
x?: number;
|
||||
y?: number;
|
||||
z?: number;
|
||||
[keys: string]: any;
|
||||
};
|
13
packages/g6/src/spec/data/io.ts
Normal file
13
packages/g6/src/spec/data/io.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* <zh/> 设置数据配置项
|
||||
*
|
||||
* <en/> set data spec
|
||||
*/
|
||||
export function setter() {}
|
||||
|
||||
/**
|
||||
* <zh/> 获取数据配置项
|
||||
*
|
||||
* <en/> get data spec
|
||||
*/
|
||||
export function getter() {}
|
45
packages/g6/src/spec/element/combo/index.ts
Normal file
45
packages/g6/src/spec/element/combo/index.ts
Normal file
@ -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';
|
||||
|
||||
/**
|
||||
* <zh/> Combo 配置项
|
||||
*
|
||||
* <en/> Combo spec
|
||||
*/
|
||||
export type ComboOption = {
|
||||
/**
|
||||
* <zh/> Combo 样式
|
||||
*
|
||||
* <en/> Combo style
|
||||
*/
|
||||
style?: CallableComboStyle;
|
||||
/**
|
||||
* <zh/> Combo 状态样式
|
||||
*
|
||||
* <en/> Combo state style
|
||||
*/
|
||||
state?: {
|
||||
[keys: string]: CallableComboStyle;
|
||||
};
|
||||
/**
|
||||
* <zh/> Combo 动画
|
||||
*
|
||||
* <en/> Combo animation
|
||||
*/
|
||||
animate?: AnimationOption;
|
||||
/**
|
||||
* <zh/> 色板
|
||||
*
|
||||
* <en/> Palette
|
||||
*/
|
||||
palette?: Palette;
|
||||
};
|
||||
|
||||
/**
|
||||
* <zh/> Combo 样式
|
||||
*
|
||||
* <en/> Combo style
|
||||
*/
|
||||
type CallableComboStyle = CallableObject<NodeLikeStyle, NodeData>;
|
13
packages/g6/src/spec/element/combo/io.ts
Normal file
13
packages/g6/src/spec/element/combo/io.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* <zh/> 设置 Combo 配置项
|
||||
*
|
||||
* <en/> set Combo spec
|
||||
*/
|
||||
export function setter() {}
|
||||
|
||||
/**
|
||||
* <zh/> 获取 Combo 配置项
|
||||
*
|
||||
* <en/> get Combo spec
|
||||
*/
|
||||
export function getter() {}
|
63
packages/g6/src/spec/element/edge/index.ts
Normal file
63
packages/g6/src/spec/element/edge/index.ts
Normal file
@ -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';
|
||||
|
||||
/**
|
||||
* <zh/> 边配置项
|
||||
*
|
||||
* <en/> Edge spec
|
||||
*/
|
||||
export type EdgeOption = {
|
||||
/**
|
||||
* <zh/> 边样式
|
||||
*
|
||||
* <en/> Edge style
|
||||
*/
|
||||
style?: CallableEdgeStyle;
|
||||
/**
|
||||
* <zh/> 边状态样式
|
||||
*
|
||||
* <en/> Edge state style
|
||||
*/
|
||||
state?: {
|
||||
[keys: string]: CallableEdgeStyle;
|
||||
};
|
||||
/**
|
||||
* <zh/> 边动画
|
||||
*
|
||||
* <en/> Edge animation
|
||||
*/
|
||||
animate?: AnimationOption;
|
||||
/**
|
||||
* <zh/> 色板
|
||||
*
|
||||
* <en/> Palette
|
||||
*/
|
||||
palette?: Palette;
|
||||
};
|
||||
|
||||
/**
|
||||
* <zh/> 边样式
|
||||
*
|
||||
* <en/> Edge style
|
||||
*/
|
||||
type CallableEdgeStyle = CallableObject<EdgeStyle, EdgeData>;
|
||||
|
||||
export type EdgeStyle = Pick<BaseStyleProps, 'cursor' | 'opacity' | 'pointerEvents' | 'visibility' | 'zIndex'> & {
|
||||
type?: string;
|
||||
/**
|
||||
* <zh/> 起点连接桩 id
|
||||
*
|
||||
* <en/> source port id
|
||||
*/
|
||||
sourcePort?: string;
|
||||
/**
|
||||
* <zh/> 终点连接桩 id
|
||||
*
|
||||
* <en/> target port id
|
||||
*/
|
||||
targetPort?: string;
|
||||
[keys: string]: any;
|
||||
};
|
13
packages/g6/src/spec/element/edge/io.ts
Normal file
13
packages/g6/src/spec/element/edge/io.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* <zh/> 设置 Edge 配置项
|
||||
*
|
||||
* <en/> set Edge spec
|
||||
*/
|
||||
export function setter() {}
|
||||
|
||||
/**
|
||||
* <zh/> 获取 Edge 配置项
|
||||
*
|
||||
* <en/> get Edge spec
|
||||
*/
|
||||
export function getter() {}
|
3
packages/g6/src/spec/element/index.ts
Normal file
3
packages/g6/src/spec/element/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export type { ComboOption } from './combo';
|
||||
export type { EdgeOption } from './edge';
|
||||
export type { NodeOption } from './node';
|
45
packages/g6/src/spec/element/node/index.ts
Normal file
45
packages/g6/src/spec/element/node/index.ts
Normal file
@ -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';
|
||||
|
||||
/**
|
||||
* <zh/> 节点配置项
|
||||
*
|
||||
* <en/> Node spec
|
||||
*/
|
||||
export type NodeOption = {
|
||||
/**
|
||||
* <zh/> 节点样式
|
||||
*
|
||||
* <en/> Node style
|
||||
*/
|
||||
style?: CallableNodeStyle;
|
||||
/**
|
||||
* <zh/> 节点状态样式
|
||||
*
|
||||
* <en/> Node state style
|
||||
*/
|
||||
state?: {
|
||||
[keys: string]: CallableNodeStyle;
|
||||
};
|
||||
/**
|
||||
* <zh/> 节点动画
|
||||
*
|
||||
* <en/> Node animation
|
||||
*/
|
||||
animate?: AnimationOption;
|
||||
/**
|
||||
* <zh/> 色板
|
||||
*
|
||||
* <en/> Palette
|
||||
*/
|
||||
palette?: Palette;
|
||||
};
|
||||
|
||||
/**
|
||||
* <zh/> 节点样式
|
||||
*
|
||||
* <en/> Node style
|
||||
*/
|
||||
type CallableNodeStyle = CallableObject<NodeLikeStyle, NodeData>;
|
56
packages/g6/src/spec/element/types.ts
Normal file
56
packages/g6/src/spec/element/types.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import type { PaletteColor } from '../../types/palette';
|
||||
|
||||
/**
|
||||
* <zh/> 色板配置项
|
||||
*
|
||||
* <en/> Palette options
|
||||
* @public
|
||||
*/
|
||||
export type Palette = PaletteColor | GroupPalette | FieldPalette;
|
||||
|
||||
export type STDPalette = GroupPalette | FieldPalette;
|
||||
|
||||
interface BasePalette {
|
||||
/**
|
||||
* <zh/> 色板颜色
|
||||
*
|
||||
* <en/> Palette color
|
||||
*/
|
||||
color: PaletteColor;
|
||||
/**
|
||||
* <zh/> 倒序取色
|
||||
*
|
||||
* <en/> Color in reverse order
|
||||
*/
|
||||
invert?: boolean;
|
||||
}
|
||||
|
||||
interface GroupPalette extends BasePalette {
|
||||
/**
|
||||
* <zh/> 分组取色
|
||||
*
|
||||
* <en/> Coloring by group
|
||||
*/
|
||||
type: 'group';
|
||||
/**
|
||||
* <zh/> 分组字段,未指定时基于节点 id 分组
|
||||
*
|
||||
* <en/> Group field, when not specified, group by node id
|
||||
*/
|
||||
field?: string;
|
||||
}
|
||||
|
||||
interface FieldPalette extends BasePalette {
|
||||
/**
|
||||
* <zh/> 基于字段值取色
|
||||
*
|
||||
* <en/> Coloring based on field value
|
||||
*/
|
||||
type: 'value';
|
||||
/**
|
||||
* <zh/> 取值字段
|
||||
*
|
||||
* <en/> Value field
|
||||
*/
|
||||
field: string;
|
||||
}
|
73
packages/g6/src/spec/index.ts
Normal file
73
packages/g6/src/spec/index.ts
Normal file
@ -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';
|
||||
|
||||
/**
|
||||
* <zh/> G6 规范
|
||||
*
|
||||
* <en/> G6 Specification
|
||||
* @public
|
||||
*/
|
||||
export type G6Spec = CanvasOption &
|
||||
ViewportOption & {
|
||||
/**
|
||||
* <zh/> 数据
|
||||
*
|
||||
* <en/> Data
|
||||
*/
|
||||
data?: DataOption;
|
||||
/**
|
||||
* <zh/> 布局
|
||||
*
|
||||
* <en/> Layout
|
||||
*/
|
||||
layout?: LayoutOption;
|
||||
/**
|
||||
* <zh/> 节点
|
||||
*
|
||||
* <en/> Node
|
||||
*/
|
||||
node?: NodeOption;
|
||||
/**
|
||||
* <zh/> 边
|
||||
*
|
||||
* <en/> Edge
|
||||
*/
|
||||
edge?: EdgeOption;
|
||||
/**
|
||||
* <zh/> Combo
|
||||
*
|
||||
* <en/> Combo
|
||||
*/
|
||||
combo?: ComboOption;
|
||||
/**
|
||||
* <zh/> 主题
|
||||
*
|
||||
* <en/> Theme
|
||||
*/
|
||||
theme?: ThemeOption;
|
||||
/**
|
||||
* <zh/> 模式
|
||||
*
|
||||
* <en/> Mode
|
||||
*/
|
||||
mode?: ModeOption;
|
||||
/**
|
||||
* <zh/> 画布插件
|
||||
*
|
||||
* <en/> Canvas widget
|
||||
*/
|
||||
widget?: WidgetOption;
|
||||
/**
|
||||
* <zh/> 优化选项
|
||||
*
|
||||
* <en/> Optimize options
|
||||
*/
|
||||
optimize?: OptimizeOption;
|
||||
};
|
26
packages/g6/src/spec/layout/index.ts
Normal file
26
packages/g6/src/spec/layout/index.ts
Normal file
@ -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
|
||||
/**
|
||||
* <zh/> 流水线子图布局
|
||||
*
|
||||
* <en/> Pipeline layout options
|
||||
*/
|
||||
export type PipeLayout = (STDLayoutOptions | CustomLayout) & {
|
||||
/**
|
||||
* <zh/> 参与该布局的节点
|
||||
*
|
||||
* <en/> Nodes involved in the layout
|
||||
* @param node - <zh/> 节点数据 | <en/> node data
|
||||
* @returns <zh/> 是否参与布局 | <en/> Whether to participate in the layout
|
||||
*/
|
||||
nodesFilter: (node: NodeData) => boolean;
|
||||
};
|
||||
|
||||
export type CustomLayout = {
|
||||
type: string;
|
||||
[key: string]: any;
|
||||
};
|
13
packages/g6/src/spec/layout/io.ts
Normal file
13
packages/g6/src/spec/layout/io.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* <zh/> 设置布局配置项
|
||||
*
|
||||
* <en/> set layout spec
|
||||
*/
|
||||
export function setter() {}
|
||||
|
||||
/**
|
||||
* <zh/> 获取布局配置项
|
||||
*
|
||||
* <en/> get layout spec
|
||||
*/
|
||||
export function getter() {}
|
24
packages/g6/src/spec/mode/index.ts
Normal file
24
packages/g6/src/spec/mode/index.ts
Normal file
@ -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;
|
13
packages/g6/src/spec/mode/io.ts
Normal file
13
packages/g6/src/spec/mode/io.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* <zh/> 设置交互模式配置项
|
||||
*
|
||||
* <en/> set mode spec
|
||||
*/
|
||||
export function setter() {}
|
||||
|
||||
/**
|
||||
* <zh/> 获取交互模式配置项
|
||||
*
|
||||
* <en/> get mode spec
|
||||
*/
|
||||
export function getter() {}
|
35
packages/g6/src/spec/optimize/index.ts
Normal file
35
packages/g6/src/spec/optimize/index.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* TODO: option should adjust
|
||||
*/
|
||||
export type OptimizeOption = {
|
||||
/**
|
||||
* <zh/> 是否开启首次渲染时的分片渲染,若为 number,则表示开启分片渲染的元素数量上限
|
||||
*
|
||||
* <en/> 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;
|
||||
/**
|
||||
* <zh/> 首次渲染时的分片渲染的元素数量上限
|
||||
*
|
||||
* <en/> Tile size for first rendering.
|
||||
*/
|
||||
tileFirstRenderSize?: number;
|
||||
/**
|
||||
* <zh/> 是否在 drag-canvas, zoom-canvas 显示/隐藏图形过程中,启用分片渲染。若指定 number,则表示开启分片渲染的元素数量上限。
|
||||
*
|
||||
* <en/> Whether enable tile hiding / showing for behaviors, e.g. hiding shapes while drag-canvas, zoom-canvas.
|
||||
*/
|
||||
tileBehavior?: boolean | number;
|
||||
/**
|
||||
* <zh/> 交互的分片渲染单片/一帧渲染的元素数量
|
||||
*
|
||||
* <en/> 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;
|
||||
/**
|
||||
* <zh/> 层级渲染的分片渲染单片/一帧渲染的元素数量
|
||||
*
|
||||
* <en/> Tile size for level of detail changing.
|
||||
*/
|
||||
tileLodSize?: number;
|
||||
};
|
13
packages/g6/src/spec/optimize/io.ts
Normal file
13
packages/g6/src/spec/optimize/io.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* <zh/> 设置优化配置项
|
||||
*
|
||||
* <en/> set optimize spec
|
||||
*/
|
||||
export function setter() {}
|
||||
|
||||
/**
|
||||
* <zh/> 获取优化配置项
|
||||
*
|
||||
* <en/> get optimize spec
|
||||
*/
|
||||
export function getter() {}
|
6
packages/g6/src/spec/theme/index.ts
Normal file
6
packages/g6/src/spec/theme/index.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export type ThemeOption = BuiltInTheme | CustomTheme;
|
||||
|
||||
// TODO import from built in theme
|
||||
declare type BuiltInTheme = 'light' | 'dark';
|
||||
|
||||
type CustomTheme = string;
|
13
packages/g6/src/spec/theme/io.ts
Normal file
13
packages/g6/src/spec/theme/io.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* <zh/> 设置主题配置项
|
||||
*
|
||||
* <en/> set theme spec
|
||||
*/
|
||||
export function setter() {}
|
||||
|
||||
/**
|
||||
* <zh/> 获取主题配置项
|
||||
*
|
||||
* <en/> get theme spec
|
||||
*/
|
||||
export function getter() {}
|
66
packages/g6/src/spec/viewport/index.ts
Normal file
66
packages/g6/src/spec/viewport/index.ts
Normal file
@ -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';
|
||||
|
||||
/**
|
||||
* <zh/> 视口配置项
|
||||
*
|
||||
* <en/> Viewport
|
||||
* @public
|
||||
*/
|
||||
export type ViewportOption = {
|
||||
/**
|
||||
* <zh/> 是否自动适应
|
||||
*
|
||||
* <en/> whether to auto fit
|
||||
*/
|
||||
autoFit?: AutoFit;
|
||||
/**
|
||||
* <zh/> 画布内边距
|
||||
*
|
||||
* <en/> canvas padding
|
||||
*/
|
||||
padding?: Padding;
|
||||
/**
|
||||
* <zh/> 缩放比例
|
||||
*
|
||||
* <en/> zoom ratio
|
||||
*/
|
||||
zoom?: number;
|
||||
/**
|
||||
* <zh/> 缩放范围
|
||||
*
|
||||
* <en/> zoom range
|
||||
*/
|
||||
zoomRange?: [number, number];
|
||||
};
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type STDViewportOption = {
|
||||
autoFit: STDAutoFit;
|
||||
padding: STDPadding;
|
||||
zoom: number;
|
||||
zoomRange: [number, number];
|
||||
};
|
||||
|
||||
/**
|
||||
* <zh/> 视口自适应规则(标准属性)
|
||||
*
|
||||
* <en/> 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 };
|
||||
|
||||
/**
|
||||
* <zh/> 视口自适应规则
|
||||
*
|
||||
* <en/> Viewport auto fit rules
|
||||
* @public
|
||||
*/
|
||||
export type AutoFit = STDAutoFit | 'view' | 'center';
|
13
packages/g6/src/spec/viewport/io.ts
Normal file
13
packages/g6/src/spec/viewport/io.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* <zh/> 设置视口配置项
|
||||
*
|
||||
* <en/> set viewport spec
|
||||
*/
|
||||
export function setter() {}
|
||||
|
||||
/**
|
||||
* <zh/> 获取视口配置项
|
||||
*
|
||||
* <en/> get viewport spec
|
||||
*/
|
||||
export function getter() {}
|
27
packages/g6/src/spec/widget/index.ts
Normal file
27
packages/g6/src/spec/widget/index.ts
Normal file
@ -0,0 +1,27 @@
|
||||
export type WidgetOption = Abbr<BuiltInWidget | CustomWidget>[];
|
||||
|
||||
// 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 extends BaseWidget> = (R & { key?: string }) | R['type'];
|
13
packages/g6/src/spec/widget/io.ts
Normal file
13
packages/g6/src/spec/widget/io.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* <zh/> 设置组件配置项
|
||||
*
|
||||
* <en/> set widget spec
|
||||
*/
|
||||
export function setter() {}
|
||||
|
||||
/**
|
||||
* <zh/> 获取组件配置项
|
||||
*
|
||||
* <en/> get widget spec
|
||||
*/
|
||||
export function getter() {}
|
@ -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<Pick<IAnimationEffectTiming, 'duration' | 'easing' | 'easingFunction'>>;
|
||||
|
||||
/**
|
||||
* <zh/> 动画结果
|
||||
*
|
||||
* <en/> Animation result
|
||||
*/
|
||||
export type AnimationResult = IAnimation;
|
||||
|
||||
/**
|
||||
* <zh/> 动画阶段
|
||||
*
|
||||
* <en/> Animation stage
|
||||
*/
|
||||
export type AnimationStage = 'enter' | 'exit' | 'update' | 'show' | 'hide';
|
||||
|
||||
/**
|
||||
* <zh/> 元素动画配置项
|
||||
*
|
||||
* <en/> Element animation configuration
|
||||
*/
|
||||
export type AnimationOption = {
|
||||
[K in string]?: {
|
||||
[G in AnimationStage]?: AnimationEffectTiming;
|
||||
};
|
||||
};
|
||||
|
||||
// TODO update to built-in type
|
||||
export type AnimationType<R extends string> = R;
|
||||
|
||||
/**
|
||||
* <zh/> 动画配置项
|
||||
*
|
||||
* <en/> Animation configuration
|
||||
* @public
|
||||
*/
|
||||
export type AnimationEffectTiming = Pick<IAnimationEffectTiming, 'duration' | 'delay' | 'easing' | 'iterations'> & {
|
||||
type: AnimationType<string>;
|
||||
onFinish?: () => void;
|
||||
onCancel?: () => void;
|
||||
};
|
||||
|
@ -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;
|
||||
|
31
packages/g6/src/types/callable.ts
Normal file
31
packages/g6/src/types/callable.ts
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* <zh/> 可回调值
|
||||
*
|
||||
* <en/> Callable value
|
||||
* @example
|
||||
* type Prop = number;
|
||||
* type CallableProp = Callable<Prop>;
|
||||
* const prop1: CallableProp = 1;
|
||||
* const prop2: CallableProp = (value) => value;
|
||||
*/
|
||||
export type CallableValue<R, P = R> = R | ((args: P) => R);
|
||||
|
||||
/**
|
||||
* <zh/> 可回调对象
|
||||
*
|
||||
* <en/> Callable object
|
||||
* @example
|
||||
* type Style = {
|
||||
* fill?: string;
|
||||
* }
|
||||
* type CallableObjectStyle = CallableObject<Style, { model: { value: string } }>;
|
||||
* const style1: CallableObjectStyle = {
|
||||
* fill: 'red',
|
||||
* }
|
||||
* const style2: CallableObjectStyle = {
|
||||
* fill: ({ model }) => model.value,
|
||||
* }
|
||||
*/
|
||||
export type CallableObject<O extends Record<string, unknown>, P = never> = {
|
||||
[K in keyof O]: CallableValue<O[K], P>;
|
||||
};
|
@ -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;
|
||||
|
@ -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';
|
||||
|
@ -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<FederatedPointerEvent, 'currentTarget'> {
|
||||
currentTarget: IGraph;
|
||||
currentTarget: Graph;
|
||||
itemType: 'node' | 'edge' | 'combo' | 'canvas';
|
||||
itemId: ID;
|
||||
key?: string;
|
||||
|
@ -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<B extends BehaviorRegistry = BehaviorRegistry, T extends ThemeRegistry = ThemeRegistry>
|
||||
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<B, T>) => Specification<B, T>;
|
||||
/**
|
||||
* Update the theme specs (configurations).
|
||||
*/
|
||||
updateTheme: (theme: ThemeOptionsOf<T>) => 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<B, T>;
|
||||
/**
|
||||
* 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<NodeUserModel>
|
||||
| Partial<EdgeUserModel>
|
||||
| Partial<ComboUserModel | Partial<NodeUserModel>[] | Partial<EdgeUserModel>[] | Partial<ComboUserModel>[]>,
|
||||
) => 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<NodeUserModel> | Partial<ComboUserModel | Partial<NodeUserModel>[] | Partial<ComboUserModel>[]>,
|
||||
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<ComboUserModel> | Partial<ComboUserModel | Partial<NodeUserModel>[] | Partial<ComboUserModel>[]>,
|
||||
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<void>;
|
||||
/**
|
||||
* 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<void>;
|
||||
/**
|
||||
* 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<void>;
|
||||
/**
|
||||
* 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<void>;
|
||||
/**
|
||||
* 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<void>;
|
||||
/**
|
||||
* 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<void>;
|
||||
|
||||
/**
|
||||
* Transform the graph with a CSS-Transform-like syntax.
|
||||
* @param options
|
||||
* @param effectTiming
|
||||
* @group View
|
||||
*/
|
||||
transform: (options: GraphTransformOptions, effectTiming?: CameraAnimationOptions) => Promise<void>;
|
||||
/**
|
||||
* 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<void>;
|
||||
/**
|
||||
* Fit the graph center to the view center.
|
||||
* @param effectTiming animation configurations
|
||||
* @returns
|
||||
* @group View
|
||||
*/
|
||||
fitCenter: (boundsType?: 'render' | 'layout', effectTiming?: CameraAnimationOptions) => Promise<void>;
|
||||
/**
|
||||
* 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<void>;
|
||||
/**
|
||||
* 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<void>;
|
||||
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<B> | BehaviorOptionsOf<B>[], 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<B>, 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<string, any>;
|
||||
/** 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';
|
||||
|
@ -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}`;
|
@ -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,
|
||||
|
@ -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<IAnimationEffectTiming>;
|
||||
};
|
||||
|
||||
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<LayoutMapping>;
|
||||
} & Animatable & {
|
||||
presetLayout?: Partial<PureLayoutOptions>;
|
||||
};
|
||||
} & Animatable &
|
||||
PresetLayoutOptions;
|
||||
|
||||
type CustomLayout = {
|
||||
type: string;
|
||||
[option: string]: any;
|
||||
};
|
||||
export type STDLayoutOptions = BuiltInLayoutOptions & Animatable & Workerized & PresetLayoutOptions;
|
||||
|
||||
export type StandardLayoutOptions = PureLayoutOptions &
|
||||
Animatable &
|
||||
Workerized & {
|
||||
presetLayout?: Partial<PureLayoutOptions>;
|
||||
};
|
||||
|
||||
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<LayoutOptions>;
|
||||
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<IAnimationEffectTiming>;
|
||||
};
|
||||
|
||||
type Workerized = {
|
||||
/**
|
||||
* Make layout running in WebWorker.
|
||||
*/
|
||||
workerEnabled?: boolean;
|
||||
|
||||
/**
|
||||
* Iterations for iterable layouts such as Force.
|
||||
*/
|
||||
iterations?: number;
|
||||
};
|
||||
|
||||
interface PresetLayoutOptions {
|
||||
presetLayout?: Partial<BuiltInLayoutOptions>;
|
||||
}
|
||||
|
||||
export interface LayoutRegistry {
|
||||
[key: string]: Layout<LayoutOptions> & {
|
||||
type?: string;
|
||||
};
|
||||
}
|
||||
|
43
packages/g6/src/types/palette.ts
Normal file
43
packages/g6/src/types/palette.ts
Normal file
@ -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';
|
||||
|
||||
/**
|
||||
* <zh/> 色板,可以是色板名或者颜色数组,也可以是一个生成颜色的函数
|
||||
*
|
||||
* <en/> 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);
|
@ -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;
|
||||
}
|
||||
|
||||
|
10
packages/g6/src/types/position.ts
Normal file
10
packages/g6/src/types/position.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export type Position =
|
||||
| 'top'
|
||||
| 'bottom'
|
||||
| 'left'
|
||||
| 'right'
|
||||
| 'center'
|
||||
| 'top-left'
|
||||
| 'top-right'
|
||||
| 'bottom-left'
|
||||
| 'bottom-right';
|
@ -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<B extends BehaviorRegistry, T extends ThemeRegistry> {
|
||||
export interface Specification<B extends BehaviorRegistry, T extends ThemeSolverRegistry> {
|
||||
container?: string | HTMLElement;
|
||||
backgroundCanvas?: Canvas;
|
||||
canvas?: Canvas;
|
||||
@ -121,8 +120,4 @@ export interface Specification<B extends BehaviorRegistry, T extends ThemeRegist
|
||||
|
||||
/** theme */
|
||||
theme?: ThemeOptionsOf<T>;
|
||||
|
||||
enableStack?: boolean;
|
||||
|
||||
stackCfg?: StackCfg;
|
||||
}
|
||||
|
@ -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<string, unknown>;
|
||||
layouts?: Record<string, unknown>;
|
||||
nodes?: Record<string, unknown>;
|
||||
edges?: Record<string, unknown>;
|
||||
combos?: Record<string, unknown>;
|
||||
plugins?: Record<string, unknown>;
|
||||
}
|
@ -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<T extends ThemeRegistry = {}> =
|
||||
export type ThemeOptionsOf<T extends ThemeSolverRegistry = {}> =
|
||||
| Extract<keyof T, string>
|
||||
| {
|
||||
[K in keyof T]: T[K] extends { new (options: infer O): any } ? O & { type: K } : { type: K };
|
||||
}[Extract<keyof T, string>];
|
||||
|
||||
export type ThemeObjectOptionsOf<T extends ThemeRegistry = {}> = {
|
||||
export type ThemeObjectOptionsOf<T extends ThemeSolverRegistry = {}> = {
|
||||
[K in keyof T]: T[K] extends { new (options: infer O): any } ? O & { type: K; key: string } : never;
|
||||
}[Extract<keyof T, string>];
|
||||
|
||||
@ -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;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user