@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.
@@ -0,0 +1 @@
1
+ import{s as O}from"./chunk-LvLJmgfZ.js";import{d as Q,l as U,n as q,p as W,u as X}from"./useEvent-DlWF5OMa.js";import{t as Y}from"./react-BGmjiNul.js";import{H as Z}from"./cells-BLhvmrVl.js";import{t as E}from"./compiler-runtime-DeeZ7FnK.js";import{t as $}from"./jsx-runtime-DN_bIXfG.js";import{t as ee}from"./cn-C1rgT0yh.js";import{t as te}from"./createLucideIcon-CW2xpJ57.js";import{t as le}from"./useCellActionButton-COxDEyF8.js";import{a as re,n as ae,o as se,t as ne}from"./tooltip-CvjcEpZC.js";import{d as oe}from"./alert-dialog-k5KxevGr.js";import{i as L,r as ie,t as M}from"./popover-DtnzNVk-.js";import{a as ce,c as me,i as de,o as he,r as pe,t as fe,u as ue}from"./command-CDWT71Ts.js";import{n as xe}from"./focus-CgHW_IRL.js";import{a as je,i as be}from"./renderShortcut-D0Pei-OA.js";var ye=te("arrow-right",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"m12 5 7 7-7 7",key:"xquz4c"}]]),V=E(),h=O(Y(),1),t=O($(),1);const B=h.memo(h.forwardRef((n,r)=>{let e=(0,V.c)(41),l,o,i;e[0]===n?(l=e[1],o=e[2],i=e[3]):({children:l,showTooltip:i,...o}=n,e[0]=n,e[1]=l,e[2]=o,e[3]=i);let p=i===void 0?!0:i,[d,T]=(0,h.useState)(!1),g;e[4]===Symbol.for("react.memo_cache_sentinel")?(g=()=>T(!1),e[4]=g):g=e[4];let K=g,A=(0,h.useRef)(null),N;e[5]===o?N=e[6]:(N={cell:o,closePopover:K},e[5]=o,e[6]=N);let f=le(N),H=oe(),_;e[7]===Symbol.for("react.memo_cache_sentinel")?(_=()=>{Z(()=>{A.current&&A.current.scrollIntoView({behavior:"auto",block:"nearest"})})},e[7]=_):_=e[7];let R=q(_),w;e[8]===R?w=e[9]:(w=a=>{T(m=>{let v=typeof a=="function"?a(m):a;return v&&R(),v})},e[8]=R,e[9]=w);let c=q(w),S;e[10]===c?S=e[11]:(S=()=>({toggle:()=>c(ve)}),e[10]=c,e[11]=S),(0,h.useImperativeHandle)(r,S);let k;e[12]===Symbol.for("react.memo_cache_sentinel")?(k=(0,t.jsx)(ce,{placeholder:"Search actions...",className:"h-6 m-1"}),e[12]=k):k=e[12];let C;e[13]===Symbol.for("react.memo_cache_sentinel")?(C=(0,t.jsx)(pe,{children:"No results"}),e[13]=C):C=e[13];let u;if(e[14]!==f){let a;e[16]===f.length?a=e[17]:(a=(m,v)=>(0,t.jsxs)(h.Fragment,{children:[(0,t.jsx)(de,{children:m.map(s=>{if(s.redundant)return null;let F=(0,t.jsxs)("div",{className:"flex items-center flex-1",children:[s.icon&&(0,t.jsx)("div",{className:"mr-2 w-5 text-muted-foreground",children:s.icon}),(0,t.jsx)("div",{className:"flex-1",children:s.label}),(0,t.jsxs)("div",{className:"shrink-0 text-sm",children:[s.hotkey&&be(s.hotkey),s.rightElement]})]});return s.tooltip&&(F=(0,t.jsx)(ne,{content:s.tooltip,delayDuration:100,children:F})),(0,t.jsx)(he,{className:ee(s.disabled&&"opacity-50!"),onSelect:()=>{s.disableClick||s.disabled||(s.handle(),T(!1))},variant:s.variant,children:F},s.label)})},v),v<f.length-1&&(0,t.jsx)(me,{})]},v),e[16]=f.length,e[17]=a),u=f.map(a),e[14]=f,e[15]=u}else u=e[15];let x;e[18]===u?x=e[19]:(x=(0,t.jsxs)(fe,{children:[k,(0,t.jsxs)(ue,{children:[C,u]})]}),e[18]=u,e[19]=x);let D;e[20]!==H||e[21]!==x?(D=(0,t.jsx)(ie,{className:"w-[300px] p-0 pt-1 overflow-auto",scrollable:!0,...H,children:x}),e[20]=H,e[21]=x,e[22]=D):D=e[22];let j=D;if(!p){let a;e[23]===l?a=e[24]:(a=(0,t.jsx)(L,{asChild:!0,children:l}),e[23]=l,e[24]=a);let m;return e[25]!==j||e[26]!==c||e[27]!==d||e[28]!==a?(m=(0,t.jsxs)(M,{open:d,onOpenChange:c,children:[a,j]}),e[25]=j,e[26]=c,e[27]=d,e[28]=a,e[29]=m):m=e[29],m}let I;e[30]===Symbol.for("react.memo_cache_sentinel")?(I=(0,t.jsx)(ae,{tabIndex:-1,children:je("cell.cellActions")}),e[30]=I):I=e[30];let z=!d&&I,b;e[31]===l?b=e[32]:(b=(0,t.jsx)(se,{ref:A,children:(0,t.jsx)(L,{className:"flex",children:l})}),e[31]=l,e[32]=b);let y;e[33]!==z||e[34]!==b?(y=(0,t.jsxs)(re,{delayDuration:200,disableHoverableContent:!0,children:[z,b]}),e[33]=z,e[34]=b,e[35]=y):y=e[35];let P;return e[36]!==j||e[37]!==c||e[38]!==d||e[39]!==y?(P=(0,t.jsxs)(M,{open:d,onOpenChange:c,children:[y,j]}),e[36]=j,e[37]=c,e[38]=d,e[39]=y,e[40]=P):P=e[40],P})),G=h.memo(n=>{let r=(0,V.c)(5),{children:e,cellId:l}=n,o;r[0]===l?o=r[1]:(o=xe(l),r[0]=l,r[1]=o);let i=X(o);if(!i)return null;let p;return r[2]!==e||r[3]!==i?(p=(0,t.jsx)(B,{showTooltip:!1,...i,children:e}),r[2]=e,r[3]=i,r[4]=p):p=r[4],p});G.displayName="ConnectionCellActionsDropdown";function ve(n){return!n}var ge=E();const J=W("minimap");function Ne(){let n=(0,ge.c)(3),[r,e]=U(J),l;return n[0]!==r||n[1]!==e?(l={dependencyPanelTab:r,setDependencyPanelTab:e},n[0]=r,n[1]=e,n[2]=l):l=n[2],l}function _e(){return Q(J)}export{ye as a,G as i,_e as n,B as r,Ne as t};
package/dist/index.html CHANGED
@@ -66,7 +66,7 @@
66
66
  <marimo-server-token data-token="{{ server_token }}" hidden></marimo-server-token>
67
67
  <!-- /TODO -->
68
68
  <title>{{ title }}</title>
69
- <script type="module" crossorigin src="./assets/index-3FOfqUYt.js"></script>
69
+ <script type="module" crossorigin src="./assets/index-CBtg35hI.js"></script>
70
70
  <link rel="modulepreload" crossorigin href="./assets/preload-helper-BW0IMuFq.js">
71
71
  <link rel="modulepreload" crossorigin href="./assets/hotkeys-uKX61F1_.js">
72
72
  <link rel="modulepreload" crossorigin href="./assets/defaultLocale-BLUna9fQ.js">
@@ -257,7 +257,7 @@
257
257
  <link rel="stylesheet" crossorigin href="./assets/cells-jmgGt1lS.css">
258
258
  <link rel="stylesheet" crossorigin href="./assets/markdown-renderer-DdDKmWlR.css">
259
259
  <link rel="stylesheet" crossorigin href="./assets/JsonOutput-B7vuddcd.css">
260
- <link rel="stylesheet" crossorigin href="./assets/index-G6ss-VDT.css">
260
+ <link rel="stylesheet" crossorigin href="./assets/index-BIeqDcea.css">
261
261
  </head>
262
262
  <body>
263
263
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/frontend",
3
- "version": "0.18.5-dev183",
3
+ "version": "0.18.5-dev186",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -7,10 +7,9 @@ import { ReactFlowProvider } from "reactflow";
7
7
  import type { CellId } from "@/core/cells/ids";
8
8
  import type { CellData } from "@/core/cells/types";
9
9
  import type { Variables } from "@/core/variables/types";
10
- import { DependencyGraphMinimap } from "./dependency-graph-minimap";
11
10
  import { DependencyGraphTree } from "./dependency-graph-tree";
12
11
  import { GraphToolbar } from "./panels";
13
- import type { GraphLayoutView, GraphSettings } from "./types";
12
+ import type { GraphSettings, LayoutDirection } from "./types";
14
13
 
15
14
  import "reactflow/dist/style.css";
16
15
  import "./dependency-graph.css";
@@ -22,7 +21,7 @@ interface Props {
22
21
  children?: React.ReactNode;
23
22
  }
24
23
 
25
- const graphViewAtom = atom<GraphLayoutView>("_minimap_");
24
+ const graphViewAtom = atom<LayoutDirection>("TB");
26
25
  const graphViewSettings = atom<GraphSettings>({
27
26
  hidePureMarkdown: true,
28
27
  });
@@ -31,20 +30,8 @@ export const DependencyGraph: React.FC<Props> = (props) => {
31
30
  const [layoutDirection, setLayoutDirection] = useAtom(graphViewAtom);
32
31
  const [settings, setSettings] = useAtom(graphViewSettings);
33
32
 
34
- const renderGraph = () => {
35
- if (layoutDirection === "_minimap_") {
36
- return (
37
- <DependencyGraphMinimap {...props}>
38
- <GraphToolbar
39
- settings={settings}
40
- onSettingsChange={setSettings}
41
- view={layoutDirection}
42
- onChange={setLayoutDirection}
43
- />
44
- </DependencyGraphMinimap>
45
- );
46
- }
47
- return (
33
+ return (
34
+ <ReactFlowProvider key={layoutDirection}>
48
35
  <DependencyGraphTree
49
36
  {...props}
50
37
  settings={settings}
@@ -57,10 +44,6 @@ export const DependencyGraph: React.FC<Props> = (props) => {
57
44
  onChange={setLayoutDirection}
58
45
  />
59
46
  </DependencyGraphTree>
60
- );
61
- };
62
-
63
- return (
64
- <ReactFlowProvider key={layoutDirection}>{renderGraph()}</ReactFlowProvider>
47
+ </ReactFlowProvider>
65
48
  );
66
49
  };
@@ -1,9 +1,12 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import { useAtom, useAtomValue } from "jotai";
4
- import { XIcon } from "lucide-react";
3
+ import { useAtomValue } from "jotai";
5
4
  import * as React from "react";
6
- import { Button } from "@/components/ui/button";
5
+ import {
6
+ type CellGraph,
7
+ cellGraphsAtom,
8
+ isVariableAffectedBySelectedCell,
9
+ } from "@/components/editor/chrome/wrapper/minimap-state";
7
10
  import {
8
11
  useCellActions,
9
12
  useCellData,
@@ -13,14 +16,7 @@ import {
13
16
  import { cellFocusAtom, useCellFocusActions } from "@/core/cells/focus";
14
17
  import type { CellId } from "@/core/cells/ids";
15
18
  import { useVariables } from "@/core/variables/state";
16
- import { useHotkey } from "@/hooks/useHotkey";
17
19
  import { cn } from "@/utils/cn";
18
- import {
19
- type CellGraph,
20
- cellGraphsAtom,
21
- isVariableAffectedBySelectedCell,
22
- minimapOpenAtom,
23
- } from "./minimap-state";
24
20
 
25
21
  interface MinimapCellProps {
26
22
  cellId: CellId;
@@ -127,72 +123,6 @@ const MinimapCell: React.FC<MinimapCellProps> = (props) => {
127
123
  );
128
124
  };
129
125
 
130
- const MinimapInternal: React.FC<{
131
- open: boolean;
132
- setOpen: (update: boolean) => void;
133
- }> = ({ open, setOpen }) => {
134
- const cellIds = useCellIds();
135
- const cellPositions: Record<CellId, number> = Object.fromEntries(
136
- cellIds.inOrderIds.map((id, idx) => [id, idx]),
137
- );
138
- const columnBoundaries: number[] = [];
139
- let cellCount = 0;
140
- for (const [idx, column] of cellIds.getColumns().entries()) {
141
- if (idx > 0) {
142
- columnBoundaries.push(cellCount);
143
- }
144
- cellCount += column.inOrderIds.length;
145
- }
146
- return (
147
- <div
148
- className={cn(
149
- "fixed top-14 right-5 z-50 bg-background/95 backdrop-blur-sm supports-backdrop-filter:bg-background/60 rounded-lg border shadow-lg w-64 flex flex-col max-h-[58vh]",
150
- "motion-safe:transition-transform motion-safe:duration-200 motion-safe:ease-in-out",
151
- open ? "translate-x-0" : "translate-x-[calc(100%+20px)]",
152
- )}
153
- >
154
- <div className="flex items-center justify-between p-4 border-b">
155
- <span className="text-sm font-semibold">Minimap</span>
156
- <Button
157
- variant="ghost"
158
- size="icon"
159
- className="h-6 w-6"
160
- onClick={() => setOpen(false)}
161
- >
162
- <XIcon className="h-4 w-4" />
163
- </Button>
164
- </div>
165
- <div className="overflow-y-auto overflow-x-hidden flex-1 scrollbar-none">
166
- <div className="py-3 pl-3 pr-4 relative min-h-full">
167
- {cellIds.inOrderIds.map((cellId, idx) => {
168
- const isColumnBoundary = columnBoundaries.includes(idx);
169
- return (
170
- <React.Fragment key={cellId}>
171
- {/* Subtle visual divider between nodes */}
172
- {isColumnBoundary && (
173
- <div
174
- className="absolute left-5 w-[36px] h-px bg-(--gray-4) pointer-events-none"
175
- aria-hidden="true"
176
- />
177
- )}
178
- <MinimapCell cellId={cellId} cellPositions={cellPositions} />
179
- </React.Fragment>
180
- );
181
- })}
182
- </div>
183
- {/* Invisible element to prevent SVG overflow from affecting scroll */}
184
- <div className="h-0 overflow-hidden" aria-hidden="true" />
185
- </div>
186
- </div>
187
- );
188
- };
189
-
190
- export const Minimap: React.FC = () => {
191
- const [open, setOpen] = useAtom(minimapOpenAtom);
192
- useHotkey("global.toggleMinimap", () => setOpen((prev) => !prev));
193
- return <MinimapInternal open={open} setOpen={setOpen} />;
194
- };
195
-
196
126
  function codePreview(code: string): string | undefined {
197
127
  return code.split("\n")[0].trim() || undefined;
198
128
  }
@@ -443,3 +373,46 @@ function isNonReferenceableCell(graph: CellGraph): boolean {
443
373
  graph.descendants.size === 0
444
374
  );
445
375
  }
376
+
377
+ /**
378
+ * Minimap content component for display in the dependencies panel.
379
+ * Shows a scrollable list of cells with dependency visualization.
380
+ */
381
+ export const MinimapContent: React.FC = () => {
382
+ const cellIds = useCellIds();
383
+ const cellPositions: Record<CellId, number> = Object.fromEntries(
384
+ cellIds.inOrderIds.map((id, idx) => [id, idx]),
385
+ );
386
+ const columnBoundaries: number[] = [];
387
+ let cellCount = 0;
388
+ for (const [idx, column] of cellIds.getColumns().entries()) {
389
+ if (idx > 0) {
390
+ columnBoundaries.push(cellCount);
391
+ }
392
+ cellCount += column.inOrderIds.length;
393
+ }
394
+
395
+ return (
396
+ <div className="overflow-y-auto overflow-x-hidden flex-1 scrollbar-none h-full max-w-80">
397
+ <div className="py-3 pl-3 pr-4 relative min-h-full">
398
+ {cellIds.inOrderIds.map((cellId, idx) => {
399
+ const isColumnBoundary = columnBoundaries.includes(idx);
400
+ return (
401
+ <React.Fragment key={cellId}>
402
+ {/* Subtle visual divider between nodes */}
403
+ {isColumnBoundary && (
404
+ <div
405
+ className="absolute left-5 w-[36px] h-px bg-(--gray-4) pointer-events-none"
406
+ aria-hidden="true"
407
+ />
408
+ )}
409
+ <MinimapCell cellId={cellId} cellPositions={cellPositions} />
410
+ </React.Fragment>
411
+ );
412
+ })}
413
+ </div>
414
+ {/* Invisible element to prevent SVG overflow from affecting scroll */}
415
+ <div className="h-0 overflow-hidden" aria-hidden="true" />
416
+ </div>
417
+ );
418
+ };
@@ -6,7 +6,6 @@ import {
6
6
  ArrowRightToLineIcon,
7
7
  MoreVerticalIcon,
8
8
  NetworkIcon,
9
- Rows3Icon,
10
9
  SettingsIcon,
11
10
  SquareFunction,
12
11
  WorkflowIcon,
@@ -26,11 +25,11 @@ import { Checkbox } from "../ui/checkbox";
26
25
  import { Label } from "../ui/label";
27
26
  import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
28
27
  import { VariableName } from "../variables/common";
29
- import type { GraphLayoutView, GraphSelection, GraphSettings } from "./types";
28
+ import type { GraphSelection, GraphSettings, LayoutDirection } from "./types";
30
29
 
31
30
  interface Props {
32
- view: GraphLayoutView;
33
- onChange: (view: GraphLayoutView) => void;
31
+ view: LayoutDirection;
32
+ onChange: (view: LayoutDirection) => void;
34
33
  settings: GraphSettings;
35
34
  onSettingsChange: (settings: GraphSettings) => void;
36
35
  }
@@ -73,16 +72,6 @@ export const GraphToolbar: React.FC<Props> = memo(
73
72
  return (
74
73
  <Panel position="top-right" className="flex flex-col items-end gap-2">
75
74
  <div className="flex gap-2">
76
- <Button
77
- variant="outline"
78
- className="bg-background"
79
- aria-selected={view === "_minimap_"}
80
- size="xs"
81
- onClick={() => onChange("_minimap_")}
82
- >
83
- <Rows3Icon className="w-4 h-4 mr-1" />
84
- Mini Map
85
- </Button>
86
75
  <Button
87
76
  variant="outline"
88
77
  className="bg-background"
@@ -104,7 +93,7 @@ export const GraphToolbar: React.FC<Props> = memo(
104
93
  Horizontal Tree
105
94
  </Button>
106
95
  </div>
107
- {view !== "_minimap_" && settingsButton}
96
+ {settingsButton}
108
97
  </Panel>
109
98
  );
110
99
  },
@@ -2,7 +2,6 @@
2
2
  import type { CellId } from "@/core/cells/ids";
3
3
 
4
4
  export type LayoutDirection = "TB" | "LR";
5
- export type GraphLayoutView = LayoutDirection | "_minimap_";
6
5
 
7
6
  export type GraphSelection =
8
7
  | {
@@ -5,19 +5,26 @@ import { useCellDataAtoms, useCellIds } from "@/core/cells/cells";
5
5
  import { useVariables } from "@/core/variables/state";
6
6
  import { cn } from "@/utils/cn";
7
7
  import { DependencyGraph } from "../../../dependency-graph/dependency-graph";
8
+ import { MinimapContent } from "../../../dependency-graph/minimap-content";
9
+ import { useDependencyPanelTab } from "../wrapper/useDependencyPanelTab";
8
10
 
9
11
  const DependencyGraphPanel: React.FC = () => {
12
+ const { dependencyPanelTab } = useDependencyPanelTab();
10
13
  const variables = useVariables();
11
14
  const cellIds = useCellIds();
12
15
  const [cells] = useCellDataAtoms();
13
16
 
14
17
  return (
15
18
  <div className={cn("w-full h-full flex-1 mx-auto -mb-4 relative")}>
16
- <DependencyGraph
17
- cellAtoms={cells}
18
- variables={variables}
19
- cellIds={cellIds.inOrderIds}
20
- />
19
+ {dependencyPanelTab === "minimap" ? (
20
+ <MinimapContent />
21
+ ) : (
22
+ <DependencyGraph
23
+ cellAtoms={cells}
24
+ variables={variables}
25
+ cellIds={cellIds.inOrderIds}
26
+ />
27
+ )}
21
28
  </div>
22
29
  );
23
30
  };
@@ -35,10 +35,10 @@ import {
35
35
  type PanelDescriptor,
36
36
  } from "../types";
37
37
  import { BackendConnectionStatus } from "./footer-items/backend-status";
38
- import { Minimap } from "./minimap";
39
38
  import { PanelsWrapper } from "./panels";
40
39
  import { PendingAICells } from "./pending-ai-cells";
41
40
  import { useAiPanelTab } from "./useAiPanel";
41
+ import { useDependencyPanelTab } from "./useDependencyPanelTab";
42
42
  import { handleDragging } from "./utils";
43
43
 
44
44
  const LazyTerminal = React.lazy(() => import("@/components/terminal/terminal"));
@@ -84,6 +84,7 @@ export const AppChrome: React.FC<PropsWithChildren> = ({ children }) => {
84
84
  const sidebarRef = React.useRef<ImperativePanelHandle>(null);
85
85
  const developerPanelRef = React.useRef<ImperativePanelHandle>(null);
86
86
  const { aiPanelTab, setAiPanelTab } = useAiPanelTab();
87
+ const { dependencyPanelTab, setDependencyPanelTab } = useDependencyPanelTab();
87
88
  const errorCount = useAtomValue(cellErrorCount);
88
89
  const [panelLayout, setPanelLayout] = useAtom(panelLayoutAtom);
89
90
 
@@ -231,7 +232,36 @@ export const AppChrome: React.FC<PropsWithChildren> = ({ children }) => {
231
232
  <PanelSectionProvider value="sidebar">
232
233
  <div className="flex flex-col h-full flex-1 overflow-hidden mr-[-4px]">
233
234
  <div className="p-3 border-b flex justify-between items-center">
234
- {selectedPanel === "ai" && agentsEnabled ? (
235
+ {selectedPanel === "dependencies" ? (
236
+ <div className="flex items-center justify-between flex-1">
237
+ <span className="text-sm text-(--slate-11) uppercase tracking-wide font-semibold">
238
+ Dependencies
239
+ </span>
240
+ <Tabs
241
+ value={dependencyPanelTab}
242
+ onValueChange={(value) => {
243
+ if (value === "minimap" || value === "graph") {
244
+ setDependencyPanelTab(value);
245
+ }
246
+ }}
247
+ >
248
+ <TabsList>
249
+ <TabsTrigger
250
+ value="minimap"
251
+ className="py-0.5 text-xs uppercase tracking-wide font-bold"
252
+ >
253
+ Minimap
254
+ </TabsTrigger>
255
+ <TabsTrigger
256
+ value="graph"
257
+ className="py-0.5 text-xs uppercase tracking-wide font-bold"
258
+ >
259
+ Graph
260
+ </TabsTrigger>
261
+ </TabsList>
262
+ </Tabs>
263
+ </div>
264
+ ) : selectedPanel === "ai" && agentsEnabled ? (
235
265
  <Tabs
236
266
  value={aiPanelTab}
237
267
  onValueChange={(value) => {
@@ -481,7 +511,6 @@ export const AppChrome: React.FC<PropsWithChildren> = ({ children }) => {
481
511
  </Panel>
482
512
  <ContextAwarePanel />
483
513
  </PanelGroup>
484
- <Minimap />
485
514
  <PendingAICells />
486
515
  <ErrorBoundary>
487
516
  <TooltipProvider>
@@ -18,13 +18,16 @@ import {
18
18
  } from "./footer-items/backend-status";
19
19
  import { CopilotStatusIcon } from "./footer-items/copilot-status";
20
20
  import { MachineStats } from "./footer-items/machine-stats";
21
- import { MinimapStatusIcon } from "./footer-items/minimap-status";
22
21
  import { RTCStatus } from "./footer-items/rtc-status";
23
22
  import { RuntimeSettings } from "./footer-items/runtime-settings";
23
+ import { useSetDependencyPanelTab } from "./useDependencyPanelTab";
24
24
 
25
25
  export const Footer: React.FC = () => {
26
- const { isDeveloperPanelOpen } = useChromeState();
27
- const { toggleDeveloperPanel } = useChromeActions();
26
+ const { isDeveloperPanelOpen, isSidebarOpen, selectedPanel } =
27
+ useChromeState();
28
+ const { toggleDeveloperPanel, openApplication, setIsSidebarOpen } =
29
+ useChromeActions();
30
+ const setDependencyPanelTab = useSetDependencyPanelTab();
28
31
 
29
32
  const errorCount = useAtomValue(cellErrorCount);
30
33
  const connectionStatus = useAtomValue(connectionStatusAtom);
@@ -46,6 +49,17 @@ export const Footer: React.FC = () => {
46
49
  toggleDeveloperPanel();
47
50
  });
48
51
 
52
+ useHotkey("global.toggleMinimap", () => {
53
+ // If already on dependencies panel with minimap tab, close the sidebar
54
+ if (isSidebarOpen && selectedPanel === "dependencies") {
55
+ setIsSidebarOpen(false);
56
+ } else {
57
+ // Open sidebar with dependencies panel and switch to minimap tab
58
+ openApplication("dependencies");
59
+ setDependencyPanelTab("minimap");
60
+ }
61
+ });
62
+
49
63
  return (
50
64
  <footer className="h-10 py-1 gap-1 bg-background flex items-center text-muted-foreground text-md pl-2 pr-1 border-t border-border select-none no-print text-sm z-50 print:hidden hide-on-fullscreen overflow-x-auto overflow-y-hidden scrollbar-thin">
51
65
  <FooterItem
@@ -92,7 +106,6 @@ export const Footer: React.FC = () => {
92
106
 
93
107
  <div className="flex items-center shrink-0 min-w-0">
94
108
  <MachineStats />
95
- <MinimapStatusIcon />
96
109
  <AIStatusIcon />
97
110
  <CopilotStatusIcon />
98
111
  <RTCStatus />
@@ -6,8 +6,6 @@ import type { CellId } from "@/core/cells/ids";
6
6
  import { variablesAtom } from "@/core/variables/state";
7
7
  import type { Variable, VariableName, Variables } from "@/core/variables/types";
8
8
 
9
- export const minimapOpenAtom = atom(false);
10
-
11
9
  export interface CellGraph {
12
10
  variables: readonly VariableName[];
13
11
 
@@ -0,0 +1,16 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { atom, useAtom, useSetAtom } from "jotai";
4
+
5
+ export const dependencyPanelTabAtom = atom<"minimap" | "graph">("minimap");
6
+
7
+ export function useDependencyPanelTab() {
8
+ const [dependencyPanelTab, setDependencyPanelTab] = useAtom(
9
+ dependencyPanelTabAtom,
10
+ );
11
+ return { dependencyPanelTab, setDependencyPanelTab };
12
+ }
13
+
14
+ export function useSetDependencyPanelTab() {
15
+ return useSetAtom(dependencyPanelTabAtom);
16
+ }
@@ -1 +0,0 @@
1
- import{s as z}from"./chunk-LvLJmgfZ.js";import{n as F,u as K}from"./useEvent-DlWF5OMa.js";import{t as L}from"./react-BGmjiNul.js";import{H as Q}from"./cells-BLhvmrVl.js";import{t as U}from"./compiler-runtime-DeeZ7FnK.js";import{t as W}from"./jsx-runtime-DN_bIXfG.js";import{t as X}from"./cn-C1rgT0yh.js";import{t as Y}from"./createLucideIcon-CW2xpJ57.js";import{t as Z}from"./useCellActionButton-COxDEyF8.js";import{a as $,n as ee,o as te,t as le}from"./tooltip-CvjcEpZC.js";import{d as re}from"./alert-dialog-k5KxevGr.js";import{i as M,r as se,t as P}from"./popover-DtnzNVk-.js";import{a as oe,c as ae,i as ne,o as ie,r as ce,t as me,u as de}from"./command-CDWT71Ts.js";import{n as he}from"./focus-CgHW_IRL.js";import{a as pe,i as fe}from"./renderShortcut-D0Pei-OA.js";var xe=Y("arrow-right",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"m12 5 7 7-7 7",key:"xquz4c"}]]),V=U(),h=z(L(),1),t=z(W(),1);const B=h.memo(h.forwardRef((m,o)=>{let e=(0,V.c)(41),s,a,n;e[0]===m?(s=e[1],a=e[2],n=e[3]):({children:s,showTooltip:n,...a}=m,e[0]=m,e[1]=s,e[2]=a,e[3]=n);let p=n===void 0?!0:n,[d,H]=(0,h.useState)(!1),g;e[4]===Symbol.for("react.memo_cache_sentinel")?(g=()=>H(!1),e[4]=g):g=e[4];let J=g,E=(0,h.useRef)(null),N;e[5]===a?N=e[6]:(N={cell:a,closePopover:J},e[5]=a,e[6]=N);let f=Z(N),O=re(),_;e[7]===Symbol.for("react.memo_cache_sentinel")?(_=()=>{Q(()=>{E.current&&E.current.scrollIntoView({behavior:"auto",block:"nearest"})})},e[7]=_):_=e[7];let R=F(_),w;e[8]===R?w=e[9]:(w=l=>{H(c=>{let v=typeof l=="function"?l(c):l;return v&&R(),v})},e[8]=R,e[9]=w);let i=F(w),C;e[10]===i?C=e[11]:(C=()=>({toggle:()=>i(ue)}),e[10]=i,e[11]=C),(0,h.useImperativeHandle)(o,C);let S;e[12]===Symbol.for("react.memo_cache_sentinel")?(S=(0,t.jsx)(oe,{placeholder:"Search actions...",className:"h-6 m-1"}),e[12]=S):S=e[12];let k;e[13]===Symbol.for("react.memo_cache_sentinel")?(k=(0,t.jsx)(ce,{children:"No results"}),e[13]=k):k=e[13];let x;if(e[14]!==f){let l;e[16]===f.length?l=e[17]:(l=(c,v)=>(0,t.jsxs)(h.Fragment,{children:[(0,t.jsx)(ne,{children:c.map(r=>{if(r.redundant)return null;let q=(0,t.jsxs)("div",{className:"flex items-center flex-1",children:[r.icon&&(0,t.jsx)("div",{className:"mr-2 w-5 text-muted-foreground",children:r.icon}),(0,t.jsx)("div",{className:"flex-1",children:r.label}),(0,t.jsxs)("div",{className:"shrink-0 text-sm",children:[r.hotkey&&fe(r.hotkey),r.rightElement]})]});return r.tooltip&&(q=(0,t.jsx)(le,{content:r.tooltip,delayDuration:100,children:q})),(0,t.jsx)(ie,{className:X(r.disabled&&"opacity-50!"),onSelect:()=>{r.disableClick||r.disabled||(r.handle(),H(!1))},variant:r.variant,children:q},r.label)})},v),v<f.length-1&&(0,t.jsx)(ae,{})]},v),e[16]=f.length,e[17]=l),x=f.map(l),e[14]=f,e[15]=x}else x=e[15];let u;e[18]===x?u=e[19]:(u=(0,t.jsxs)(me,{children:[S,(0,t.jsxs)(de,{children:[k,x]})]}),e[18]=x,e[19]=u);let I;e[20]!==O||e[21]!==u?(I=(0,t.jsx)(se,{className:"w-[300px] p-0 pt-1 overflow-auto",scrollable:!0,...O,children:u}),e[20]=O,e[21]=u,e[22]=I):I=e[22];let j=I;if(!p){let l;e[23]===s?l=e[24]:(l=(0,t.jsx)(M,{asChild:!0,children:s}),e[23]=s,e[24]=l);let c;return e[25]!==j||e[26]!==i||e[27]!==d||e[28]!==l?(c=(0,t.jsxs)(P,{open:d,onOpenChange:i,children:[l,j]}),e[25]=j,e[26]=i,e[27]=d,e[28]=l,e[29]=c):c=e[29],c}let A;e[30]===Symbol.for("react.memo_cache_sentinel")?(A=(0,t.jsx)(ee,{tabIndex:-1,children:pe("cell.cellActions")}),e[30]=A):A=e[30];let T=!d&&A,b;e[31]===s?b=e[32]:(b=(0,t.jsx)(te,{ref:E,children:(0,t.jsx)(M,{className:"flex",children:s})}),e[31]=s,e[32]=b);let y;e[33]!==T||e[34]!==b?(y=(0,t.jsxs)($,{delayDuration:200,disableHoverableContent:!0,children:[T,b]}),e[33]=T,e[34]=b,e[35]=y):y=e[35];let D;return e[36]!==j||e[37]!==i||e[38]!==d||e[39]!==y?(D=(0,t.jsxs)(P,{open:d,onOpenChange:i,children:[y,j]}),e[36]=j,e[37]=i,e[38]=d,e[39]=y,e[40]=D):D=e[40],D})),G=h.memo(m=>{let o=(0,V.c)(5),{children:e,cellId:s}=m,a;o[0]===s?a=o[1]:(a=he(s),o[0]=s,o[1]=a);let n=K(a);if(!n)return null;let p;return o[2]!==e||o[3]!==n?(p=(0,t.jsx)(B,{showTooltip:!1,...n,children:e}),o[2]=e,o[3]=n,o[4]=p):p=o[4],p});G.displayName="ConnectionCellActionsDropdown";function ue(m){return!m}export{G as n,xe as r,B as t};