From 37913595b1fb81f83257ef673920cbb898ffac71 Mon Sep 17 00:00:00 2001 From: bcg-john-nguyen Date: Fri, 12 May 2023 14:11:47 -0700 Subject: [PATCH 1/3] config without build file --- src/Node/index.tsx | 22 +++++++++++++++++++--- src/Tree/index.tsx | 38 +++++++++++++++++++++++++++++++++++--- src/types/common.ts | 13 +++++++++++-- 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/src/Node/index.tsx b/src/Node/index.tsx index 11be7955..35232768 100644 --- a/src/Node/index.tsx +++ b/src/Node/index.tsx @@ -7,7 +7,6 @@ import { TreeNodeDatum, RawNodeDatum, RenderCustomNodeElementFn, - AddChildrenFunction, } from '../types/common.js'; import DefaultNodeElement from './DefaultNodeElement.js'; @@ -36,7 +35,9 @@ type NodeProps = { onNodeMouseOut: NodeEventHandler; subscriptions: object; centerNode: (hierarchyPointNode: HierarchyPointNode) => void; - handleAddChildrenToNode: (nodeId: string, children: RawNodeDatum[]) => void; + handleAddChildrenToNode: (nodeId: string, children: RawNodeDatum[], replace?: boolean) => void; + handleRemoveNode: (nodeId: string, parentNodeId: string) => void; + handleUpdateNodeAttributes: (nodeId: string, attributes: Omit) => void; }; type NodeState = { @@ -149,6 +150,9 @@ export default class Node extends React.Component { onNodeMouseOver: this.handleOnMouseOver, onNodeMouseOut: this.handleOnMouseOut, addChildren: this.handleAddChildren, + removeNode: this.handleRemoveNode, + replaceChildren: this.handleReplaceChildren, + updateNodeAttributes: this.handleUpdateNodeAttributes, }; return renderNode(nodeProps); @@ -172,10 +176,22 @@ export default class Node extends React.Component { this.props.onNodeMouseOut(this.props.hierarchyPointNode, evt); }; - handleAddChildren: AddChildrenFunction = childrenData => { + handleAddChildren = childrenData => { this.props.handleAddChildrenToNode(this.props.data.__rd3t.id, childrenData); }; + handleReplaceChildren = childrenData => { + this.props.handleAddChildrenToNode(this.props.data.__rd3t.id, childrenData, true); + }; + + handleUpdateNodeAttributes = attributes => { + this.props.handleUpdateNodeAttributes(this.props.data.__rd3t.id, attributes); + }; + + handleRemoveNode = () => { + this.props.handleRemoveNode(this.props.data.__rd3t.id, this.props.parent.data.__rd3t.id); + }; + componentWillLeave(done) { const { orientation, transitionDuration, position, parent } = this.props; const transform = this.setTransform(position, parent, orientation, true); diff --git a/src/Tree/index.tsx b/src/Tree/index.tsx index cc36898a..d5f64d25 100644 --- a/src/Tree/index.tsx +++ b/src/Tree/index.tsx @@ -328,7 +328,33 @@ class Tree extends React.Component { } }; - handleAddChildrenToNode = (nodeId: string, childrenData: RawNodeDatum[]) => { + handleRemoveNode = (nodeId: string, parentNodeId: string) => { + const data = clone(this.state.data); + const parentMatches = this.findNodesById(parentNodeId, data, []); + if (parentMatches.length > 0) { + const targetNodeDatum = parentMatches[0]; + if (targetNodeDatum.children && targetNodeDatum.children.length > 0) { + const removeNodeIndex = targetNodeDatum.children.findIndex(c => c.__rd3t.id === nodeId); + if (removeNodeIndex > -1) { + targetNodeDatum.children.splice(removeNodeIndex, 1); + this.setState({ data }); + } + } + } + }; + + handleUpdateNodeAttributes = (nodeId: string, node: Omit) => { + const data = clone(this.state.data); + const matches = this.findNodesById(nodeId, data, []); + if (matches.length > 0) { + const targetNodeDatum = matches[0]; + targetNodeDatum.name = node.name; + targetNodeDatum.attributes = node.attributes; + this.setState({ data }); + } + }; + + handleAddChildrenToNode = (nodeId: string, childrenData: RawNodeDatum[], replace?: boolean) => { const data = clone(this.state.data); const matches = this.findNodesById(nodeId, data, []); @@ -339,8 +365,12 @@ class Tree extends React.Component { const formattedChildren = clone(childrenData).map((node: RawNodeDatum) => Tree.assignInternalProperties([node], depth + 1) ); - targetNodeDatum.children.push(...formattedChildren.flat()); + if (replace) { + targetNodeDatum.children = formattedChildren.flat(); + } else { + targetNodeDatum.children.push(...formattedChildren.flat()); + } this.setState({ data }); } }; @@ -584,7 +614,7 @@ class Tree extends React.Component { const { data, x, y, parent } = hierarchyPointNode; return ( { handleAddChildrenToNode={this.handleAddChildrenToNode} subscriptions={subscriptions} centerNode={this.centerNode} + handleRemoveNode={this.handleRemoveNode} + handleUpdateNodeAttributes={this.handleUpdateNodeAttributes} /> ); })} diff --git a/src/types/common.ts b/src/types/common.ts index 3e77dec7..df2e491b 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -33,7 +33,8 @@ export type PathFunction = (link: TreeLinkDatum, orientation: Orientation) => st export type PathClassFunction = PathFunction; export type SyntheticEventHandler = (evt: SyntheticEvent) => void; -export type AddChildrenFunction = (children: RawNodeDatum[]) => void; +export type UpdateChildren = (children: RawNodeDatum[]) => void; +export type UpdateNodeAttributes = (attributes: Omit) => void; /** * The properties that are passed to the user-defined `renderCustomNodeElement` render function. @@ -70,7 +71,15 @@ export interface CustomNodeElementProps { /** * The `Node` class's internal `addChildren` handler. */ - addChildren: AddChildrenFunction; + addChildren: UpdateChildren; + /** + * The `Node` class's internal `replaceChildren` handler. + */ + replaceChildren: UpdateChildren; + /** + * The `Node` class's internal `updateNodeAttributes` handler. + */ + updateNodeAttributes: UpdateNodeAttributes; } export type RenderCustomNodeElementFn = (rd3tNodeProps: CustomNodeElementProps) => JSX.Element; From c2e2af285766d424f0c63b5864d5e753356c2861 Mon Sep 17 00:00:00 2001 From: bcg-john-nguyen Date: Sat, 13 May 2023 12:39:51 -0700 Subject: [PATCH 2/3] Updat types --- src/Node/index.tsx | 8 +++++--- src/types/common.ts | 10 +++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Node/index.tsx b/src/Node/index.tsx index 35232768..9d9f81a2 100644 --- a/src/Node/index.tsx +++ b/src/Node/index.tsx @@ -7,6 +7,8 @@ import { TreeNodeDatum, RawNodeDatum, RenderCustomNodeElementFn, + UpdateChildrenFunction, + UpdateNodeAttributesFunction, } from '../types/common.js'; import DefaultNodeElement from './DefaultNodeElement.js'; @@ -176,15 +178,15 @@ export default class Node extends React.Component { this.props.onNodeMouseOut(this.props.hierarchyPointNode, evt); }; - handleAddChildren = childrenData => { + handleAddChildren: UpdateChildrenFunction = childrenData => { this.props.handleAddChildrenToNode(this.props.data.__rd3t.id, childrenData); }; - handleReplaceChildren = childrenData => { + handleReplaceChildren: UpdateChildrenFunction = childrenData => { this.props.handleAddChildrenToNode(this.props.data.__rd3t.id, childrenData, true); }; - handleUpdateNodeAttributes = attributes => { + handleUpdateNodeAttributes: UpdateNodeAttributesFunction = attributes => { this.props.handleUpdateNodeAttributes(this.props.data.__rd3t.id, attributes); }; diff --git a/src/types/common.ts b/src/types/common.ts index df2e491b..c93cfc8e 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -33,8 +33,8 @@ export type PathFunction = (link: TreeLinkDatum, orientation: Orientation) => st export type PathClassFunction = PathFunction; export type SyntheticEventHandler = (evt: SyntheticEvent) => void; -export type UpdateChildren = (children: RawNodeDatum[]) => void; -export type UpdateNodeAttributes = (attributes: Omit) => void; +export type UpdateChildrenFunction = (children: RawNodeDatum[]) => void; +export type UpdateNodeAttributesFunction = (attributes: Omit) => void; /** * The properties that are passed to the user-defined `renderCustomNodeElement` render function. @@ -71,15 +71,15 @@ export interface CustomNodeElementProps { /** * The `Node` class's internal `addChildren` handler. */ - addChildren: UpdateChildren; + addChildren: UpdateChildrenFunction; /** * The `Node` class's internal `replaceChildren` handler. */ - replaceChildren: UpdateChildren; + replaceChildren: UpdateChildrenFunction; /** * The `Node` class's internal `updateNodeAttributes` handler. */ - updateNodeAttributes: UpdateNodeAttributes; + updateNodeAttributes: UpdateNodeAttributesFunction; } export type RenderCustomNodeElementFn = (rd3tNodeProps: CustomNodeElementProps) => JSX.Element; From 5c260b37418a61bfebf168f4b898439adb46489e Mon Sep 17 00:00:00 2001 From: bcg-john-nguyen Date: Thu, 1 Jun 2023 12:19:45 -0700 Subject: [PATCH 3/3] callback to methods --- src/Node/index.tsx | 37 ++++++++++++++++++++++++------------- src/Tree/index.tsx | 21 +++++++++++++++------ src/types/common.ts | 7 +++++-- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/Node/index.tsx b/src/Node/index.tsx index 9d9f81a2..226fd6df 100644 --- a/src/Node/index.tsx +++ b/src/Node/index.tsx @@ -7,8 +7,6 @@ import { TreeNodeDatum, RawNodeDatum, RenderCustomNodeElementFn, - UpdateChildrenFunction, - UpdateNodeAttributesFunction, } from '../types/common.js'; import DefaultNodeElement from './DefaultNodeElement.js'; @@ -37,9 +35,18 @@ type NodeProps = { onNodeMouseOut: NodeEventHandler; subscriptions: object; centerNode: (hierarchyPointNode: HierarchyPointNode) => void; - handleAddChildrenToNode: (nodeId: string, children: RawNodeDatum[], replace?: boolean) => void; - handleRemoveNode: (nodeId: string, parentNodeId: string) => void; - handleUpdateNodeAttributes: (nodeId: string, attributes: Omit) => void; + handleAddChildrenToNode: ( + nodeId: string, + children: RawNodeDatum[], + replace?: boolean, + callback?: () => void + ) => void; + handleRemoveNode: (nodeId: string, parentNodeId: string, callback?: () => void) => void; + handleUpdateNodeAttributes: ( + nodeId: string, + attributes: Omit, + callback?: () => void + ) => void; }; type NodeState = { @@ -178,20 +185,24 @@ export default class Node extends React.Component { this.props.onNodeMouseOut(this.props.hierarchyPointNode, evt); }; - handleAddChildren: UpdateChildrenFunction = childrenData => { - this.props.handleAddChildrenToNode(this.props.data.__rd3t.id, childrenData); + handleAddChildren = (childrenData, callback?: () => void) => { + this.props.handleAddChildrenToNode(this.props.data.__rd3t.id, childrenData, false, callback); }; - handleReplaceChildren: UpdateChildrenFunction = childrenData => { - this.props.handleAddChildrenToNode(this.props.data.__rd3t.id, childrenData, true); + handleReplaceChildren = (childrenData, callback?: () => void) => { + this.props.handleAddChildrenToNode(this.props.data.__rd3t.id, childrenData, true, callback); }; - handleUpdateNodeAttributes: UpdateNodeAttributesFunction = attributes => { - this.props.handleUpdateNodeAttributes(this.props.data.__rd3t.id, attributes); + handleUpdateNodeAttributes = (attributes, callback?: () => void) => { + this.props.handleUpdateNodeAttributes(this.props.data.__rd3t.id, attributes, callback); }; - handleRemoveNode = () => { - this.props.handleRemoveNode(this.props.data.__rd3t.id, this.props.parent.data.__rd3t.id); + handleRemoveNode = (callback?: () => void) => { + this.props.handleRemoveNode( + this.props.data.__rd3t.id, + this.props.parent.data.__rd3t.id, + callback + ); }; componentWillLeave(done) { diff --git a/src/Tree/index.tsx b/src/Tree/index.tsx index d5f64d25..4a6542b2 100644 --- a/src/Tree/index.tsx +++ b/src/Tree/index.tsx @@ -328,7 +328,7 @@ class Tree extends React.Component { } }; - handleRemoveNode = (nodeId: string, parentNodeId: string) => { + handleRemoveNode = (nodeId: string, parentNodeId: string, callback?: () => void) => { const data = clone(this.state.data); const parentMatches = this.findNodesById(parentNodeId, data, []); if (parentMatches.length > 0) { @@ -337,24 +337,33 @@ class Tree extends React.Component { const removeNodeIndex = targetNodeDatum.children.findIndex(c => c.__rd3t.id === nodeId); if (removeNodeIndex > -1) { targetNodeDatum.children.splice(removeNodeIndex, 1); - this.setState({ data }); + this.setState({ data }, callback); } } } }; - handleUpdateNodeAttributes = (nodeId: string, node: Omit) => { + handleUpdateNodeAttributes = ( + nodeId: string, + node: Omit, + callback?: () => void + ) => { const data = clone(this.state.data); const matches = this.findNodesById(nodeId, data, []); if (matches.length > 0) { const targetNodeDatum = matches[0]; targetNodeDatum.name = node.name; targetNodeDatum.attributes = node.attributes; - this.setState({ data }); + this.setState({ data }, callback); } }; - handleAddChildrenToNode = (nodeId: string, childrenData: RawNodeDatum[], replace?: boolean) => { + handleAddChildrenToNode = ( + nodeId: string, + childrenData: RawNodeDatum[], + replace?: boolean, + callback?: () => void + ) => { const data = clone(this.state.data); const matches = this.findNodesById(nodeId, data, []); @@ -371,7 +380,7 @@ class Tree extends React.Component { } else { targetNodeDatum.children.push(...formattedChildren.flat()); } - this.setState({ data }); + this.setState({ data }, callback); } }; diff --git a/src/types/common.ts b/src/types/common.ts index c93cfc8e..bb09becf 100644 --- a/src/types/common.ts +++ b/src/types/common.ts @@ -33,8 +33,11 @@ export type PathFunction = (link: TreeLinkDatum, orientation: Orientation) => st export type PathClassFunction = PathFunction; export type SyntheticEventHandler = (evt: SyntheticEvent) => void; -export type UpdateChildrenFunction = (children: RawNodeDatum[]) => void; -export type UpdateNodeAttributesFunction = (attributes: Omit) => void; +export type UpdateChildrenFunction = (children: RawNodeDatum[], callback?: () => void) => void; +export type UpdateNodeAttributesFunction = ( + attributes: Omit, + callback?: () => void +) => void; /** * The properties that are passed to the user-defined `renderCustomNodeElement` render function.