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:
Aaron 2024-01-15 15:20:30 +08:00 committed by GitHub
parent 951114dd4e
commit 4058ba5344
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
193 changed files with 2047 additions and 4332 deletions

View File

@ -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

View File

@ -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": [

View File

@ -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,

View File

@ -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,
};

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 = [];
}

View File

@ -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);

View File

@ -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: {

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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 = [];

View File

@ -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);

View File

@ -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'],

View File

@ -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 };

View File

@ -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;

View File

@ -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;

View File

@ -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;

View 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 };

View File

@ -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') {

View File

@ -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;

View File

@ -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) {

View File

@ -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);
}

View File

@ -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';

View File

@ -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 = {};

View File

@ -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;

View File

@ -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);
});
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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');
}
}

View File

@ -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);
});
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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];
});

View File

@ -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);
}

View File

@ -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;

View File

@ -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';

View File

@ -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();

View File

@ -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);
}

View File

@ -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(`

View File

@ -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());

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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;

View File

@ -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';

View File

@ -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(() => {

View File

@ -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);
}

View File

@ -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) {

View File

@ -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));
}
/**

View File

@ -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,

View File

@ -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;
}

View File

@ -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;
}
/**

View File

@ -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();
}

View File

@ -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({});

View File

@ -0,0 +1 @@
export type Layer = 'background' | 'main' | 'label' | 'transient' | 'transientLabel';

View 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;
};

View File

@ -0,0 +1,13 @@
/**
* <zh/>
*
* <en/> set canvas spec
*/
export function setter() {}
/**
* <zh/>
*
* <en/> get canvas spec
*/
export function getter() {}

View 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;
};

View File

@ -0,0 +1,13 @@
/**
* <zh/>
*
* <en/> set data spec
*/
export function setter() {}
/**
* <zh/>
*
* <en/> get data spec
*/
export function getter() {}

View 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>;

View File

@ -0,0 +1,13 @@
/**
* <zh/> Combo
*
* <en/> set Combo spec
*/
export function setter() {}
/**
* <zh/> Combo
*
* <en/> get Combo spec
*/
export function getter() {}

View 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;
};

View File

@ -0,0 +1,13 @@
/**
* <zh/> Edge
*
* <en/> set Edge spec
*/
export function setter() {}
/**
* <zh/> Edge
*
* <en/> get Edge spec
*/
export function getter() {}

View File

@ -0,0 +1,3 @@
export type { ComboOption } from './combo';
export type { EdgeOption } from './edge';
export type { NodeOption } from './node';

View 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>;

View 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;
}

View 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;
};

View 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;
};

View File

@ -0,0 +1,13 @@
/**
* <zh/>
*
* <en/> set layout spec
*/
export function setter() {}
/**
* <zh/>
*
* <en/> get layout spec
*/
export function getter() {}

View 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;

View File

@ -0,0 +1,13 @@
/**
* <zh/>
*
* <en/> set mode spec
*/
export function setter() {}
/**
* <zh/>
*
* <en/> get mode spec
*/
export function getter() {}

View 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;
};

View File

@ -0,0 +1,13 @@
/**
* <zh/>
*
* <en/> set optimize spec
*/
export function setter() {}
/**
* <zh/>
*
* <en/> get optimize spec
*/
export function getter() {}

View File

@ -0,0 +1,6 @@
export type ThemeOption = BuiltInTheme | CustomTheme;
// TODO import from built in theme
declare type BuiltInTheme = 'light' | 'dark';
type CustomTheme = string;

View File

@ -0,0 +1,13 @@
/**
* <zh/>
*
* <en/> set theme spec
*/
export function setter() {}
/**
* <zh/>
*
* <en/> get theme spec
*/
export function getter() {}

View 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';

View File

@ -0,0 +1,13 @@
/**
* <zh/>
*
* <en/> set viewport spec
*/
export function setter() {}
/**
* <zh/>
*
* <en/> get viewport spec
*/
export function getter() {}

View 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'];

View File

@ -0,0 +1,13 @@
/**
* <zh/>
*
* <en/> set widget spec
*/
export function setter() {}
/**
* <zh/>
*
* <en/> get widget spec
*/
export function getter() {}

View File

@ -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;
};

View File

@ -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;

View 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>;
};

View File

@ -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;

View File

@ -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';

View File

@ -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;

View File

@ -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';

View File

@ -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}`;

View File

@ -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,

View File

@ -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;
};
}

View 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);

View File

@ -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;
}

View File

@ -0,0 +1,10 @@
export type Position =
| 'top'
| 'bottom'
| 'left'
| 'right'
| 'center'
| 'top-left'
| 'top-right'
| 'bottom-left'
| 'bottom-right';

View File

@ -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;
}

View File

@ -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>;
}

View File

@ -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