Build beautiful, interactive flow diagrams: Powered by React Flow, Simplified by Streamlit.
[!WARNING]
StreamlitFlow v1.5.0 has breaking changes. Please read on to understand how to migrate your code to the new version.
Say hello to the new and improved state management system that syncs the states between changes in the frontend and the backend. This means that you can now modify the state of the flow diagram from Python and see the changes reflected in the frontend without having to hack into the component's state.
Note: The updated state management uses a new StreamlitFlowState
class to manage the state within streamlit. Instead of taking nodes
and edges
as arguments, the streamlit_flow
function now takes a single StreamlitFlowState
object. This means that code using earlier versions of this library will need to be tweaked slightly to work with the new version.
Old
from streamlit_flow import streamlit_flow
from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
nodes = [...]
edges = [...]
streamlit_flow('flow', nodes, edges)
New
from streamlit_flow import streamlit_flow
from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
from streamlit_flow.state import StreamlitFlowState
nodes = [...]
edges = [...]
state = StreamlitFlowState(nodes, edges)
streamlit_flow('flow', state)
The benefits we get from this are significant, as the StreamlitFlowState
class makes sure that the states in the frontend and the backend are synced wth the latest changes from either side.
Example
from streamlit_flow import streamlit_flow
from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
from streamlit_flow.state import StreamlitFlowState
from uuid import uuid4
# Initialize the state if it doesn't exist
if 'flow_state' not in st.session_state:
nodes = [...]
edges = [...]
st.session_state.flow_state = StreamlitFlowState(nodes, edges)
# Use any operation that alters the state, for example add node, and then rerun
if st.button("Add node"):
new_node = StreamlitFlowNode(key=str(f"st-flow-node_{uuid4()}"),
pos=(0, 0),
data={'content': f'Node {len(st.session_state.curr_state.nodes) + 1}'},
node_type='default',
source_position='right',
target_position='left')
st.session_state.curr_state.nodes.append(new_node)
st.rerun()
# Use the state as the argument, as well as to store the return value
st.session_state.flow_state = streamlit_flow('flow', st.session_state.flow_state)
streamlit_flow
component now returns the updated state on several user interactions, such as creating/deleting/editing/moving a node or an edge, to make sure the states stay synced.arrow
or arrowclosed
to represent directed edges, as well as further styled. Check out the style options here.style
dictionary, and let Reactflow handle computing the dimensions. This means that the width
and height
attributes of the nodes are now deprecated.A demo for all these features can be found here.
pip install streamlit-flow-component
git clone https://github.com/dkapur17/streamlit-flow.git
cd streamlit-flow
npm install --prefix streamlit_flow/frontend
On the first terminal, run from the root of the repository
cd streamlit_flow/frontend
npm start
On the second terminal, run from the root of the repository
streamlit run example.py
Overhauled State Management: The component now manages the state of the flow diagram automatically. As such, it keeps track of changes to node positions, connections, and more.
Pane Context Menu: Right-clicking on the canvas now opens a context menu, allowing you to add new nodes or reset the layout.
Node Context Menu: Right-clicking on a node now opens a context menu, allowing you to edit or delete the node.
Edge Context Menu: Right-clicking on an edge now opens a context menu, allowing you to edit or delete the edge.
Way more Layouts: The layouts are now more extensive, including Tree, Layered, Force, Stress, Radial, Random and Manual. One can also make a custom layout by inheriting from the Layout
class.
Hackable Python State: The primary state management is done within the component, and the state can be read by Python. This is the intended usage. However, while not recommended, it is possible to modify the state from Python as well if the user wishes to.