@marimo-team/frontend 0.18.5-dev183 → 0.18.5-dev186
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/dependency-graph-panel-B6oPfRTp.js +4 -0
- package/dist/assets/edit-page-BNwlX8qM.js +12 -0
- package/dist/assets/index-BIeqDcea.css +2 -0
- package/dist/assets/{index-3FOfqUYt.js → index-CBtg35hI.js} +2 -2
- package/dist/assets/useDependencyPanelTab-DgtlzfpF.js +1 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/components/dependency-graph/dependency-graph.tsx +5 -22
- package/src/components/{editor/chrome/wrapper/minimap.tsx → dependency-graph/minimap-content.tsx} +49 -76
- package/src/components/dependency-graph/panels.tsx +4 -15
- package/src/components/dependency-graph/types.ts +0 -1
- package/src/components/editor/chrome/panels/dependency-graph-panel.tsx +12 -5
- package/src/components/editor/chrome/wrapper/app-chrome.tsx +32 -3
- package/src/components/editor/chrome/wrapper/footer.tsx +17 -4
- package/src/components/editor/chrome/wrapper/minimap-state.ts +0 -2
- package/src/components/editor/chrome/wrapper/useDependencyPanelTab.ts +16 -0
- package/dist/assets/cell-actions-By11JcES.js +0 -1
- package/dist/assets/dependency-graph-panel-Xl6gHQbe.js +0 -4
- package/dist/assets/edit-page-Dkay6iPX.js +0 -13
- package/dist/assets/index-G6ss-VDT.css +0 -2
- package/src/components/dependency-graph/dependency-graph-minimap.tsx +0 -197
- package/src/components/editor/chrome/wrapper/footer-items/minimap-status.tsx +0 -21
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
|
|
3
|
-
import type { Atom } from "jotai";
|
|
4
|
-
|
|
5
|
-
import React, {
|
|
6
|
-
type PropsWithChildren,
|
|
7
|
-
useEffect,
|
|
8
|
-
useMemo,
|
|
9
|
-
useRef,
|
|
10
|
-
useState,
|
|
11
|
-
} from "react";
|
|
12
|
-
import useEvent from "react-use-event-hook";
|
|
13
|
-
import ReactFlow, {
|
|
14
|
-
type CoordinateExtent,
|
|
15
|
-
type Edge,
|
|
16
|
-
type Node,
|
|
17
|
-
PanOnScrollMode,
|
|
18
|
-
useEdgesState,
|
|
19
|
-
useNodesState,
|
|
20
|
-
useStore,
|
|
21
|
-
} from "reactflow";
|
|
22
|
-
import { nodeTypes } from "@/components/dependency-graph/custom-node";
|
|
23
|
-
import type { CellId } from "@/core/cells/ids";
|
|
24
|
-
import type { CellData } from "@/core/cells/types";
|
|
25
|
-
import type { Variables } from "@/core/variables/types";
|
|
26
|
-
import { scrollAndHighlightCell } from "../editor/links/cell-link";
|
|
27
|
-
import { type NodeData, VerticalElementsBuilder } from "./elements";
|
|
28
|
-
import { GraphSelectionPanel } from "./panels";
|
|
29
|
-
import { useFitToViewOnDimensionChange } from "./utils/useFitToViewOnDimensionChange";
|
|
30
|
-
|
|
31
|
-
interface Props {
|
|
32
|
-
cellIds: CellId[];
|
|
33
|
-
variables: Variables;
|
|
34
|
-
cellAtoms: Atom<CellData>[];
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const elementsBuilder = new VerticalElementsBuilder();
|
|
38
|
-
|
|
39
|
-
export const DependencyGraphMinimap: React.FC<PropsWithChildren<Props>> = ({
|
|
40
|
-
cellIds,
|
|
41
|
-
variables,
|
|
42
|
-
cellAtoms,
|
|
43
|
-
children,
|
|
44
|
-
}) => {
|
|
45
|
-
// State
|
|
46
|
-
const { nodes: initialNodes, edges: allEdges } =
|
|
47
|
-
elementsBuilder.createElements(cellIds, cellAtoms, variables, false);
|
|
48
|
-
const [edges, setEdges] = useEdgesState([]);
|
|
49
|
-
const [nodes, setNodes] = useNodesState(initialNodes);
|
|
50
|
-
const [selectedNodeId, setSelectedNodeId] = useState<CellId>();
|
|
51
|
-
const [selectedEdge, setSelectedEdge] = useState<Edge>();
|
|
52
|
-
const hasRenderer = useRef(false);
|
|
53
|
-
|
|
54
|
-
// Subscriptions
|
|
55
|
-
useFitToViewOnDimensionChange();
|
|
56
|
-
const height = useStore(({ height }) => height);
|
|
57
|
-
|
|
58
|
-
// If the cellIds change, update the nodes.
|
|
59
|
-
const syncChanges = useEvent(
|
|
60
|
-
(elements: { nodes: Node<NodeData>[]; edges: Edge[] }) => {
|
|
61
|
-
setNodes(elements.nodes);
|
|
62
|
-
setEdges([]);
|
|
63
|
-
},
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
// If the cellIds change, update the nodes.
|
|
67
|
-
// Only on the second render, because the first render is the initial render.
|
|
68
|
-
useEffect(() => {
|
|
69
|
-
if (!hasRenderer.current) {
|
|
70
|
-
hasRenderer.current = true;
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
syncChanges(
|
|
74
|
-
elementsBuilder.createElements(cellIds, cellAtoms, variables, false),
|
|
75
|
-
);
|
|
76
|
-
}, [cellIds, variables, cellAtoms, syncChanges]);
|
|
77
|
-
|
|
78
|
-
// If the selected node changes, update the edges.
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
if (selectedNodeId) {
|
|
81
|
-
const selectedEdges = allEdges.filter((edge) => {
|
|
82
|
-
const { source, target, data } = edge;
|
|
83
|
-
|
|
84
|
-
return (
|
|
85
|
-
(source === selectedNodeId && data.direction === "outputs") ||
|
|
86
|
-
(target === selectedNodeId && data.direction === "inputs")
|
|
87
|
-
);
|
|
88
|
-
});
|
|
89
|
-
setEdges(selectedEdges);
|
|
90
|
-
}
|
|
91
|
-
}, [selectedNodeId, setEdges, allEdges]);
|
|
92
|
-
|
|
93
|
-
const translateExtent = useTranslateExtent(nodes, height);
|
|
94
|
-
|
|
95
|
-
const handleClearSelection = () => {
|
|
96
|
-
setSelectedNodeId(undefined);
|
|
97
|
-
setSelectedEdge(undefined);
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const renderGraphSelectionPanel = () => {
|
|
101
|
-
if (selectedEdge) {
|
|
102
|
-
return (
|
|
103
|
-
<GraphSelectionPanel
|
|
104
|
-
selection={{
|
|
105
|
-
type: "edge",
|
|
106
|
-
source: selectedEdge.source as CellId,
|
|
107
|
-
target: selectedEdge.target as CellId,
|
|
108
|
-
}}
|
|
109
|
-
onClearSelection={handleClearSelection}
|
|
110
|
-
variables={variables}
|
|
111
|
-
edges={edges}
|
|
112
|
-
/>
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
if (selectedNodeId) {
|
|
116
|
-
return (
|
|
117
|
-
<GraphSelectionPanel
|
|
118
|
-
selection={{ type: "node", id: selectedNodeId }}
|
|
119
|
-
variables={variables}
|
|
120
|
-
edges={edges}
|
|
121
|
-
onClearSelection={handleClearSelection}
|
|
122
|
-
/>
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return null;
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
return (
|
|
130
|
-
<ReactFlow
|
|
131
|
-
nodes={nodes}
|
|
132
|
-
edges={edges}
|
|
133
|
-
nodeTypes={nodeTypes}
|
|
134
|
-
translateExtent={translateExtent}
|
|
135
|
-
onNodeClick={(_event, node) => {
|
|
136
|
-
const id = node.id;
|
|
137
|
-
setSelectedNodeId(id as CellId);
|
|
138
|
-
setSelectedEdge(undefined);
|
|
139
|
-
setEdges([]);
|
|
140
|
-
}}
|
|
141
|
-
onNodeDoubleClick={(_event, node) => {
|
|
142
|
-
scrollAndHighlightCell(node.id as CellId, "focus");
|
|
143
|
-
}}
|
|
144
|
-
onEdgeClick={(_event, edge) => {
|
|
145
|
-
setSelectedEdge(edge);
|
|
146
|
-
}}
|
|
147
|
-
// On
|
|
148
|
-
snapToGrid={true}
|
|
149
|
-
fitView={true}
|
|
150
|
-
elementsSelectable={true}
|
|
151
|
-
// Off
|
|
152
|
-
minZoom={1}
|
|
153
|
-
maxZoom={1}
|
|
154
|
-
draggable={false}
|
|
155
|
-
panOnScrollMode={PanOnScrollMode.Vertical}
|
|
156
|
-
zoomOnDoubleClick={false}
|
|
157
|
-
nodesDraggable={false}
|
|
158
|
-
nodesConnectable={false}
|
|
159
|
-
nodesFocusable={false}
|
|
160
|
-
edgesFocusable={false}
|
|
161
|
-
selectNodesOnDrag={false}
|
|
162
|
-
panOnDrag={false}
|
|
163
|
-
preventScrolling={false}
|
|
164
|
-
zoomOnPinch={false}
|
|
165
|
-
panOnScroll={true}
|
|
166
|
-
autoPanOnNodeDrag={false}
|
|
167
|
-
autoPanOnConnect={false}
|
|
168
|
-
>
|
|
169
|
-
{renderGraphSelectionPanel()}
|
|
170
|
-
{children}
|
|
171
|
-
</ReactFlow>
|
|
172
|
-
);
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
// Limit the extent of the graph to just the visible nodes.
|
|
176
|
-
// The top node and bottom node can be scrolled to the middle of the graph.
|
|
177
|
-
function useTranslateExtent(nodes: Node[], height: number): CoordinateExtent {
|
|
178
|
-
const PADDING_Y = 10;
|
|
179
|
-
|
|
180
|
-
return useMemo<CoordinateExtent>(() => {
|
|
181
|
-
const top = nodes.reduce(
|
|
182
|
-
(top, { position }) => Math.min(top, position.y - height / 2 - PADDING_Y),
|
|
183
|
-
Number.POSITIVE_INFINITY,
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
const bottom = nodes.reduce(
|
|
187
|
-
(bottom, { position }) =>
|
|
188
|
-
Math.max(bottom, position.y + height / 2 + PADDING_Y),
|
|
189
|
-
Number.NEGATIVE_INFINITY,
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
return [
|
|
193
|
-
[Number.NEGATIVE_INFINITY, top],
|
|
194
|
-
[Number.POSITIVE_INFINITY, bottom],
|
|
195
|
-
];
|
|
196
|
-
}, [nodes, height]);
|
|
197
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
|
|
3
|
-
import { useAtom } from "jotai";
|
|
4
|
-
import { MapIcon } from "lucide-react";
|
|
5
|
-
import { FooterItem } from "../footer-item";
|
|
6
|
-
import { minimapOpenAtom } from "../minimap-state";
|
|
7
|
-
|
|
8
|
-
export const MinimapStatusIcon: React.FC = () => {
|
|
9
|
-
const [open, setOpen] = useAtom(minimapOpenAtom);
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<FooterItem
|
|
13
|
-
tooltip="Toggle Minimap"
|
|
14
|
-
selected={open}
|
|
15
|
-
onClick={() => setOpen((prev) => !prev)}
|
|
16
|
-
data-testid="footer-minimap"
|
|
17
|
-
>
|
|
18
|
-
<MapIcon className="h-4 w-4" />
|
|
19
|
-
</FooterItem>
|
|
20
|
-
);
|
|
21
|
-
};
|