Skip to content

Commit 9cd6f28

Browse files
committed
fixes #3; redraws on shiny input change + add to example vignette
1 parent ef05c0b commit 9cd6f28

8 files changed

Lines changed: 328 additions & 194 deletions

File tree

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: reactflow
22
Title: Create beautiful, customizable, and interactive diagrams based on React Flow
3-
Version: 0.0.1
3+
Version: 0.0.2
44
Authors@R: c(
55
person("David", "Zimmermann-Kollenda", , "david_j_zimmermann@hotmail.com", role = c("aut", "cre"))
66
)

R/reactflow.R

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@
22
#' @export
33
htmlwidgets::JS
44

5-
#' A
5+
#' A ReactFlow object
66
#'
7-
#' A
8-
#' @param message a
9-
#' @param width a
7+
#' @param nodes a
8+
#' @param edges
9+
#' @param controls
10+
#' @param mini_map
11+
#' @param background
12+
#' @param allow_edge_connection
13+
#' @param use_dagre
14+
#' @param dagre_direction
15+
#' @param dagre_config
16+
#' @param ... elements passed to ReactFlow (see <https://reactflow.dev/api-reference/react-flow>)
17+
#' @param width
1018
#' @param height a
1119
#' @param elementId a
12-
#' @param ... elements passed to ReactFlow (see https://reactflow.dev/api-reference/react-flow)
1320
#'
1421
#' @import htmlwidgets
1522
#'
@@ -21,7 +28,7 @@ reactflow <- function(nodes, edges, controls = NULL, mini_map = NULL,
2128
...,
2229
width = NULL, height = NULL,
2330
elementId = NULL) {
24-
31+
2532
dagre_direction <- match.arg(dagre_direction)
2633

2734
# describe a React component to send to the browser for rendering.
@@ -32,16 +39,20 @@ reactflow <- function(nodes, edges, controls = NULL, mini_map = NULL,
3239
use_dagre = use_dagre, dagre_direction = dagre_direction,
3340
dagre_config = dagre_config, ...)
3441
)
35-
42+
3643
# create widget
3744
hw <- htmlwidgets::createWidget(
3845
name = "reactflow",
3946
reactR::reactMarkup(component),
4047
width = width,
4148
height = height,
42-
package = "reactflow"
49+
package = "reactflow",
50+
sizingPolicy = htmlwidgets::sizingPolicy(
51+
defaultWidth = "auto",
52+
defaultHeight = "auto"
53+
)
4354
)
44-
55+
4556
children <- list(controls, background, mini_map)
4657
children <- children[!sapply(children, is.null)]
4758

@@ -53,11 +64,12 @@ reactflow <- function(nodes, edges, controls = NULL, mini_map = NULL,
5364
#' Called by HTMLWidgets to produce the widget's root element.
5465
#' @noRd
5566
widget_html.reactflow <- function(id, style, class, ...) {
56-
htmltools::tagList(
67+
htmltools::tags$div(
5768
# Necessary for RStudio viewer version < 1.2
5869
reactR::html_dependency_corejs(),
5970
reactR::html_dependency_react(),
6071
reactR::html_dependency_reacttools(),
72+
6173
htmltools::tags$div(id = id, class = class, style = style)
6274
)
6375
}
@@ -79,8 +91,8 @@ widget_html.reactflow <- function(id, style, class, ...) {
7991
#' @name reactflow-shiny
8092
#'
8193
#' @export
82-
reactflowOutput <- function(outputId, width = '100%', height = '400px'){
83-
htmlwidgets::shinyWidgetOutput(outputId, 'reactflow', width, height, package = 'reactflow')
94+
reactflowOutput <- function(outputId, width = "100%", height = "400px"){
95+
htmlwidgets::shinyWidgetOutput(outputId, "reactflow", width, height, package = "reactflow")
8496
}
8597

8698
#' @rdname reactflow-shiny

README.Rmd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Layout Examples
3636

3737
## Examples
3838

39-
```r
39+
```{r}
4040
nodes <- list(
4141
list(id = "s", type = "input", data = list(label = "Start"),
4242
className = "startNode", position = list(x = 0, y = 0)),

error-redraw.R

Lines changed: 0 additions & 104 deletions
This file was deleted.

inst/htmlwidgets/reactflow.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

inst/htmlwidgets/reactflow.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

srcjs/ReactFlow.js

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { memo, Fragment, useCallback } from 'react';
1+
import React, { memo, Fragment, useCallback, useEffect, useState } from 'react';
22

33
import {
44
ReactFlow as ReactFlowOrig,
@@ -86,47 +86,34 @@ export default function ReactFlow({
8686
...props
8787
}) {
8888

89-
// if dagre is enabled, we need to layout the nodes
89+
var nodes_used = nodes;
90+
9091
if (use_dagre) {
91-
// Overwrite nodes with layouted nodes
92-
nodes = getLayoutedNodes(nodes, edges, dagre_direction, dagre_config);
92+
nodes_used = getLayoutedNodes(nodes_used, edges, dagre_direction, dagre_config);
9393
}
94-
95-
const [final_nodes, setNodes, onNodesChange] = useNodesState(nodes);
94+
95+
const [final_nodes, setNodes, onNodesChange] = useNodesState(nodes_used);
9696
const [final_edges, setEdges, onEdgesChange] = useEdgesState(edges);
9797

98-
// TODO make onNodeChange, onEdgeChange, onConnect a JS function that can be passed ??
98+
useEffect(() => {
99+
setNodes(nodes_used);
100+
setEdges(edges);
101+
}, [nodes, edges]);
99102

100103
const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)), [setEdges]);
101104

102-
// for the minimap
103-
function nodeColor(node) {
104-
switch (node.type) {
105-
case 'input':
106-
return 'lightgreen';
107-
case 'output':
108-
return 'coral';
109-
default:
110-
return 'lightblue';
111-
}
112-
}
113-
114-
// when the layout changes, recalculate the positions
115105
const onLayout = useCallback(
116106
(dagre_direction) => {
117-
nodes2 = getLayoutedNodes(nodes, edges, dagre_direction, dagre_config);
118-
119-
setNodes([...nodes2]);
120-
setEdges([...edges]);
121-
107+
const layoutedNodes = getLayoutedNodes(nodes, edges, dagre_direction, dagre_config);
108+
setNodes(layoutedNodes);
109+
setEdges(edges);
122110
window.requestAnimationFrame(() => {
123111
fitView();
124112
});
125-
126113
},
127114
[nodes, edges, dagre_direction, dagre_config],
128115
);
129-
116+
130117
return (
131118
<ReactFlowOrig
132119
nodes={final_nodes}
@@ -136,18 +123,17 @@ export default function ReactFlow({
136123
onLayout={onLayout}
137124
onConnect={allow_edge_connection ? onConnect : undefined}
138125
nodeTypes={nodeTypes}
139-
140-
onNodeDrag={(event, node, nodes) => {
126+
onNodeClick={(event, node) => {
141127
Shiny.setInputValue(elementId + "_click", {node: node.id, edge: null});
142128
}}
143-
onNodeClick={(event, node) => {
129+
// the node is selected when dragging in CSS! this makes it consistent
130+
onNodeDrag={(event, node) => {
144131
Shiny.setInputValue(elementId + "_click", {node: node.id, edge: null});
145132
}}
146133
onEdgeClick={(event, edge) => {
147134
Shiny.setInputValue(elementId + "_click", {node: null, edge: edge.id});
148135
}}
149136
{...props}
150-
>
151-
</ReactFlowOrig>
152-
)
137+
/>
138+
);
153139
}

0 commit comments

Comments
 (0)