@marimo-team/frontend 0.18.5-dev168 → 0.18.5-dev171
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/{CellStatus-C5QfWAQj.js → CellStatus-ClrYbUob.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-B0tKPs5t.js → ConnectedDataExplorerComponent-KlUs_Sz3.js} +1 -1
- package/dist/assets/{ErrorBoundary-BYCO3_zw.js → ErrorBoundary-Drf1manw.js} +1 -1
- package/dist/assets/{ImperativeModal-7Thr73Oo.js → ImperativeModal-q6QlC2aZ.js} +1 -1
- package/dist/assets/{JsonOutput-NOfbbuUx.js → JsonOutput-CkeISXrs.js} +9 -9
- package/dist/assets/{LazyAnyLanguageCodeMirror-DIbHWNF6.js → LazyAnyLanguageCodeMirror-jpEDlD0M.js} +2 -2
- package/dist/assets/{MarimoErrorOutput-usFICLUe.js → MarimoErrorOutput-CO8cm8-0.js} +2 -2
- package/dist/assets/{RenderHTML-LxV1eecf.js → RenderHTML-D6fh5YLC.js} +1 -1
- package/dist/assets/{VisuallyHidden-BLp5kXtE.js → VisuallyHidden-BodIky8L.js} +1 -1
- package/dist/assets/{add-cell-with-ai-CEKGThxQ.js → add-cell-with-ai-B3V6Mgb9.js} +12 -12
- package/dist/assets/{add-database-form-DQyrphh9.js → add-database-form-C-K88iSC.js} +1 -1
- package/dist/assets/{agent-panel-CnTn12AW.js → agent-panel-BvLqBe3U.js} +6 -6
- package/dist/assets/{ai-model-dropdown-CxRols0L.js → ai-model-dropdown-D1nEKS8b.js} +1 -1
- package/dist/assets/{alert-dialog-B3T1GCoD.js → alert-dialog-k5KxevGr.js} +1 -1
- package/dist/assets/any-language-editor-DQu1Tt2N.js +3 -0
- package/dist/assets/{app-config-button-DtMP2_j5.js → app-config-button-BD5l-v4I.js} +1 -1
- package/dist/assets/{button-C9TEIJJh.js → button-DuYGqRtX.js} +1 -1
- package/dist/assets/{cache-panel-C-YLXsti.js → cache-panel-C1So4Zu3.js} +1 -1
- package/dist/assets/{capabilities-h9_pyvFv.js → capabilities-BmAOeMOK.js} +1 -1
- package/dist/assets/{capitalize-D4JsDDXI.js → capitalize-DQeWKRGx.js} +1 -1
- package/dist/assets/{cell-actions-DCZqhhwF.js → cell-actions-CJiaF9Tu.js} +1 -1
- package/dist/assets/cell-link-Hwo1QbqQ.js +1 -0
- package/dist/assets/{cells-DAR6V-0d.js → cells-rr1jjvJk.js} +33 -33
- package/dist/assets/{chat-components-CyY2c7cG.js → chat-components-DXJsXOD8.js} +1 -1
- package/dist/assets/{chat-display-BgCCmGdz.js → chat-display-C08N0rx5.js} +1 -1
- package/dist/assets/{chat-panel-ByuXM3gc.js → chat-panel-CNL6ANh8.js} +2 -2
- package/dist/assets/client-SMzMTiO_.js +4 -0
- package/dist/assets/{column-preview-DBqi4KCj.js → column-preview-BzvHnhPG.js} +1 -1
- package/dist/assets/command-palette-B_md1fzh.js +1 -0
- package/dist/assets/{command-BXWdrTY9.js → command-xU8ykulh.js} +1 -1
- package/dist/assets/{common-D10A9aix.js → common-_RAkDTpe.js} +1 -1
- package/dist/assets/{config-D3ojpe3F.js → config-cCkBQ_ER.js} +1 -1
- package/dist/assets/{copy-Bmkr29w4.js → copy-DRhpWiOq.js} +1 -1
- package/dist/assets/{copy-icon-qVgCqhII.js → copy-icon-B69c-352.js} +1 -1
- package/dist/assets/{createReducer-CaezzNVH.js → createReducer-DDa-hVe3.js} +1 -1
- package/dist/assets/{datasource-CW2RMV2e.js → datasource-DHbNHnua.js} +2 -2
- package/dist/assets/{dates-B2_O0-if.js → dates-CdsE1R40.js} +1 -1
- package/dist/assets/{dependency-graph-panel-CtlDdK0s.js → dependency-graph-panel-BGp5UzmZ.js} +3 -3
- package/dist/assets/{dialog-DIUTtzeB.js → dialog-DUEuLcT2.js} +1 -1
- package/dist/assets/{dist-vrNOUnFF.js → dist-DOFFh6Ii.js} +1 -1
- package/dist/assets/{documentation-panel-Cup0ghBs.js → documentation-panel-CuPlvIjJ.js} +1 -1
- package/dist/assets/{download-D3Uujsn_.js → download-DKRxBkYD.js} +1 -1
- package/dist/assets/edit-page-DAFshpgY.js +13 -0
- package/dist/assets/{error-banner-D2-5vgE4.js → error-banner-DU5Qb8a8.js} +1 -1
- package/dist/assets/{error-panel-DcRvXIwA.js → error-panel-CoYFpNUd.js} +1 -1
- package/dist/assets/{es-DCqUUmrq.js → es-YVwBDiDw.js} +1 -1
- package/dist/assets/{field-D2_0r7wT.js → field-DDKGFzpC.js} +1 -1
- package/dist/assets/{file-explorer-panel-9Bt20tRi.js → file-explorer-panel-BcpntT7Q.js} +1 -1
- package/dist/assets/{floating-outline-BTc4L5BF.js → floating-outline-CHprSkP6.js} +1 -1
- package/dist/assets/{focus-6-St0ai2.js → focus-D3ygI6Sy.js} +1 -1
- package/dist/assets/{form-1WOcPtE8.js → form-B_zRT4QS.js} +2 -2
- package/dist/assets/{formats-nh-sPUUZ.js → formats-B9CrBoaO.js} +1 -1
- package/dist/assets/{glide-data-editor-EdMWe-iv.js → glide-data-editor-Brckuic5.js} +1 -1
- package/dist/assets/{globals-CJb4gcmW.js → globals-D46Vbo5D.js} +1 -1
- package/dist/assets/{home-page-Lqy9A89-.js → home-page-DuPzZzUf.js} +2 -2
- package/dist/assets/hotkeys-uKX61F1_.js +1 -0
- package/dist/assets/{index-CIoUDThG.js → index-CQBtzy-J.js} +9 -9
- package/dist/assets/index-G6ss-VDT.css +2 -0
- package/dist/assets/{input-DP44ewsS.js → input-CaEtLL8p.js} +1 -1
- package/dist/assets/{kiosk-mode-C3lS9kUL.js → kiosk-mode-CTjr_Jn4.js} +1 -1
- package/dist/assets/{label-DJo0Eeb3.js → label-qwandMoh.js} +1 -1
- package/dist/assets/{layout-F63rlsGg.js → layout-CprHgyfx.js} +4 -4
- package/dist/assets/links-Cw9RjHIY.js +1 -0
- package/dist/assets/{logs-panel-fnMYUf4-.js → logs-panel-CFM-1lMP.js} +1 -1
- package/dist/assets/{maps-DELIOfTw.js → maps-s2pQkyf5.js} +1 -1
- package/dist/assets/{markdown-renderer-B9gYLzJX.js → markdown-renderer-DecoaRsV.js} +1 -1
- package/dist/assets/{mermaid-BUMgiGGr.js → mermaid-BPkO79lo.js} +1 -1
- package/dist/assets/{mode-D4GlAyEq.js → mode-BYulXE3t.js} +1 -1
- package/dist/assets/{multi-map-TecGBFLS.js → multi-map-fjX9ImVF.js} +1 -1
- package/dist/assets/{name-cell-input-BMtblyo6.js → name-cell-input-BGJDnv5Z.js} +1 -1
- package/dist/assets/{numbers-Ckcn6C-H.js → numbers-C9_R_vlY.js} +1 -1
- package/dist/assets/outline-panel-C-__7mIh.js +1 -0
- package/dist/assets/{packages-panel-DyC7zUxG.js → packages-panel-B4bQCG8Y.js} +1 -1
- package/dist/assets/{cell-editor-DJ1tY3mU.js → panel-context-Bee798AZ.js} +13 -13
- package/dist/assets/{panels-wYHy1fpG.js → panels-CuLZ4Xjj.js} +1 -1
- package/dist/assets/{process-output-D1GR6Ero.js → process-output-2gz8Uri2.js} +1 -1
- package/dist/assets/{readonly-python-code-CGnOB_RP.js → readonly-python-code-ihKi3Mrq.js} +1 -1
- package/dist/assets/{renderShortcut-CV_tqoEI.js → renderShortcut-D0Pei-OA.js} +1 -1
- package/dist/assets/{run-page-BLnJcKtg.js → run-page-Q1ifcEUY.js} +1 -1
- package/dist/assets/{runs-BbV5uZz6.js → runs-yuOchwkU.js} +1 -1
- package/dist/assets/scratchpad-panel-B75Qsjwz.js +1 -0
- package/dist/assets/{secrets-panel-K7EccfRa.js → secrets-panel-CDWmmmBS.js} +1 -1
- package/dist/assets/{select-BJ18Dxpd.js → select-D0g5GnIs.js} +1 -1
- package/dist/assets/{session-panel-C3rDPyig.js → session-panel-Bn5_JmbT.js} +1 -1
- package/dist/assets/{share-0dWXMs9M.js → share-CXQVxivL.js} +1 -1
- package/dist/assets/{slides-component-CZ76zal6.js → slides-component-DUIqQih1.js} +1 -1
- package/dist/assets/{snippets-panel-s0p4CCoa.js → snippets-panel-CVBBnX9H.js} +1 -1
- package/dist/assets/{spec-D9TFI5I_.js → spec-qp_XZeSS.js} +1 -1
- package/dist/assets/{state-DwSzcmzL.js → state-BHFBtWym.js} +1 -1
- package/dist/assets/{state-CGq6kn1k.js → state-CIznbe1J.js} +1 -1
- package/dist/assets/{state-BK5o1KAL.js → state-DNwec0Uj.js} +1 -1
- package/dist/assets/{switch-C8yab1pC.js → switch-iJj-D3dz.js} +1 -1
- package/dist/assets/{terminal-CA6CqpuO.js → terminal-CRIGvHBN.js} +1 -1
- package/dist/assets/{textarea-DBFtOima.js → textarea-DmNrZcLR.js} +1 -1
- package/dist/assets/{tooltip-BNPhCMFo.js → tooltip-CrRUCOBw.js} +1 -1
- package/dist/assets/tracing-D9h130fg.js +1 -0
- package/dist/assets/{tracing-panel-C-o1Db4W.js → tracing-panel-DaDvGMEN.js} +2 -2
- package/dist/assets/{type-drzC-SxF.js → type-BdyvjzTI.js} +1 -1
- package/dist/assets/{types-Bt3U-XJV.js → types-4-l_7Ws2.js} +1 -1
- package/dist/assets/{useAddCell-CNI3pgez.js → useAddCell-BpMe5DB-.js} +1 -1
- package/dist/assets/{useBoolean-C_vQizET.js → useBoolean-BDG41CyP.js} +1 -1
- package/dist/assets/{useCellActionButton-BbfiHu5s.js → useCellActionButton-Dh4wbVPA.js} +1 -1
- package/dist/assets/{useDeleteCell-B_jFiS1Y.js → useDeleteCell-DBzN8QcP.js} +1 -1
- package/dist/assets/{useIframeCapabilities-ZISlVepl.js → useIframeCapabilities-CU-WWxnz.js} +1 -1
- package/dist/assets/{useInstallPackage-CBvG269f.js → useInstallPackage-RldLPyJs.js} +1 -1
- package/dist/assets/{useLifecycle-BX7GmOQ5.js → useLifecycle-CmDXEyIC.js} +1 -1
- package/dist/assets/{useNotebookActions-BeM5fet2.js → useNotebookActions-DKyQBNlS.js} +1 -1
- package/dist/assets/useRunCells-BGzo-QMk.js +1 -0
- package/dist/assets/{useSplitCell-COPg5dJw.js → useSplitCell-CvKAuKQ_.js} +1 -1
- package/dist/assets/{useTheme-CuOCKnyR.js → useTheme-DfP1CWaW.js} +1 -1
- package/dist/assets/{utilities.esm-B7XtzwiJ.js → utilities.esm-CT3NbLA9.js} +2 -2
- package/dist/assets/{utils-Cxqw03y3.js → utils-CJJIceVn.js} +1 -1
- package/dist/assets/{vega-component-arPQXQS8.js → vega-component-CLrcy81y.js} +1 -1
- package/dist/assets/{write-secret-modal-CIbhcoWF.js → write-secret-modal-CLm48gMe.js} +1 -1
- package/dist/index.html +68 -68
- package/package.json +1 -1
- package/src/components/editor/actions/useNotebookActions.tsx +1 -1
- package/src/components/editor/chrome/panels/panel-context.tsx +34 -0
- package/src/components/editor/chrome/state.ts +30 -15
- package/src/components/editor/chrome/types.ts +67 -77
- package/src/components/editor/chrome/wrapper/app-chrome.tsx +216 -139
- package/src/components/editor/chrome/wrapper/sidebar.tsx +76 -43
- package/src/components/scratchpad/scratchpad.tsx +17 -4
- package/src/components/ui/reorderable-list.tsx +190 -31
- package/src/core/codemirror/cells/extensions.ts +7 -4
- package/src/core/hotkeys/__tests__/shortcuts.test.ts +61 -4
- package/src/core/hotkeys/shortcuts.ts +34 -2
- package/dist/assets/any-language-editor-CTAS1EXW.js +0 -3
- package/dist/assets/cell-link-DjST51KF.js +0 -1
- package/dist/assets/client-BQowSjqE.js +0 -4
- package/dist/assets/command-palette-CjFiCjws.js +0 -1
- package/dist/assets/edit-page-fJ4hHm67.js +0 -13
- package/dist/assets/hotkeys-D3ICc8RW.js +0 -1
- package/dist/assets/index-D-BWugLn.css +0 -2
- package/dist/assets/links-ZVVAwqm7.js +0 -1
- package/dist/assets/outline-panel-Blq76m9b.js +0 -1
- package/dist/assets/scratchpad-panel-CTJDEy90.js +0 -1
- package/dist/assets/tracing-VZVj-gEo.js +0 -1
- package/dist/assets/useRunCells-oeY0TrS1.js +0 -1
- /package/dist/assets/{cell-editor-Iey559K_.css → panel-context-Iey559K_.css} +0 -0
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
import React, {
|
|
2
|
+
import React, {
|
|
3
|
+
type PropsWithChildren,
|
|
4
|
+
Suspense,
|
|
5
|
+
useEffect,
|
|
6
|
+
useMemo,
|
|
7
|
+
} from "react";
|
|
3
8
|
import {
|
|
4
9
|
type ImperativePanelHandle,
|
|
5
10
|
Panel,
|
|
@@ -10,9 +15,10 @@ import { Footer } from "./footer";
|
|
|
10
15
|
import { Sidebar } from "./sidebar";
|
|
11
16
|
import "./app-chrome.css";
|
|
12
17
|
import { TooltipProvider } from "@radix-ui/react-tooltip";
|
|
13
|
-
import { useAtomValue } from "jotai";
|
|
18
|
+
import { useAtom, useAtomValue } from "jotai";
|
|
14
19
|
import { XIcon } from "lucide-react";
|
|
15
20
|
import { Button } from "@/components/ui/button";
|
|
21
|
+
import { ReorderableList } from "@/components/ui/reorderable-list";
|
|
16
22
|
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
17
23
|
import { LazyMount } from "@/components/utils/lazy-mount";
|
|
18
24
|
import { cellErrorCount } from "@/core/cells/cells";
|
|
@@ -20,8 +26,9 @@ import { getFeatureFlag } from "@/core/config/feature-flag";
|
|
|
20
26
|
import { cn } from "@/utils/cn";
|
|
21
27
|
import { ErrorBoundary } from "../../boundary/ErrorBoundary";
|
|
22
28
|
import { ContextAwarePanel } from "../panels/context-aware-panel/context-aware-panel";
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
29
|
+
import { PanelSectionProvider } from "../panels/panel-context";
|
|
30
|
+
import { panelLayoutAtom, useChromeActions, useChromeState } from "../state";
|
|
31
|
+
import { PANEL_MAP, PANELS, type PanelDescriptor } from "../types";
|
|
25
32
|
import { BackendConnectionStatus } from "./footer-items/backend-status";
|
|
26
33
|
import { Minimap } from "./minimap";
|
|
27
34
|
import { PanelsWrapper } from "./panels";
|
|
@@ -67,11 +74,67 @@ export const AppChrome: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
67
74
|
setIsSidebarOpen,
|
|
68
75
|
setIsDeveloperPanelOpen,
|
|
69
76
|
setSelectedDeveloperPanelTab,
|
|
77
|
+
openApplication,
|
|
70
78
|
} = useChromeActions();
|
|
71
79
|
const sidebarRef = React.useRef<ImperativePanelHandle>(null);
|
|
72
80
|
const developerPanelRef = React.useRef<ImperativePanelHandle>(null);
|
|
73
81
|
const { aiPanelTab, setAiPanelTab } = useAiPanelTab();
|
|
74
82
|
const errorCount = useAtomValue(cellErrorCount);
|
|
83
|
+
const [panelLayout, setPanelLayout] = useAtom(panelLayoutAtom);
|
|
84
|
+
|
|
85
|
+
// Convert current developer panel items to PanelDescriptors
|
|
86
|
+
const devPanelItems = useMemo(() => {
|
|
87
|
+
return panelLayout.developerPanel.flatMap((id) => {
|
|
88
|
+
const panel = PANEL_MAP.get(id);
|
|
89
|
+
return panel ? [panel] : [];
|
|
90
|
+
});
|
|
91
|
+
}, [panelLayout.developerPanel]);
|
|
92
|
+
|
|
93
|
+
const handleSetDevPanelItems = (items: PanelDescriptor[]) => {
|
|
94
|
+
setPanelLayout((prev) => ({
|
|
95
|
+
...prev,
|
|
96
|
+
developerPanel: items.map((item) => item.type),
|
|
97
|
+
}));
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const handleDevPanelReceive = (item: PanelDescriptor, fromListId: string) => {
|
|
101
|
+
// Remove from the source list
|
|
102
|
+
if (fromListId === "sidebar") {
|
|
103
|
+
setPanelLayout((prev) => ({
|
|
104
|
+
...prev,
|
|
105
|
+
sidebar: prev.sidebar.filter((id) => id !== item.type),
|
|
106
|
+
}));
|
|
107
|
+
|
|
108
|
+
// If the moved item was selected in sidebar, select the first remaining item
|
|
109
|
+
if (selectedPanel === item.type) {
|
|
110
|
+
const remainingSidebar = panelLayout.sidebar.filter(
|
|
111
|
+
(id) => id !== item.type,
|
|
112
|
+
);
|
|
113
|
+
if (remainingSidebar.length > 0) {
|
|
114
|
+
openApplication(remainingSidebar[0]);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Select the dropped item in developer panel
|
|
120
|
+
setSelectedDeveloperPanelTab(item.type);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// Get panels available for developer panel context menu
|
|
124
|
+
// Only show panels that are NOT in the sidebar
|
|
125
|
+
const availableDevPanels = useMemo(() => {
|
|
126
|
+
const sidebarIds = new Set(panelLayout.sidebar);
|
|
127
|
+
return PANELS.filter((p) => {
|
|
128
|
+
if (p.hidden) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
// Exclude panels that are in the sidebar
|
|
132
|
+
if (sidebarIds.has(p.type)) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
});
|
|
137
|
+
}, [panelLayout.sidebar]);
|
|
75
138
|
|
|
76
139
|
// sync sidebar
|
|
77
140
|
useEffect(() => {
|
|
@@ -160,60 +223,74 @@ export const AppChrome: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
160
223
|
|
|
161
224
|
const helpPaneBody = (
|
|
162
225
|
<ErrorBoundary>
|
|
163
|
-
<
|
|
164
|
-
<div className="
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
226
|
+
<PanelSectionProvider value="sidebar">
|
|
227
|
+
<div className="flex flex-col h-full flex-1 overflow-hidden mr-[-4px]">
|
|
228
|
+
<div className="p-3 border-b flex justify-between items-center">
|
|
229
|
+
{selectedPanel === "ai" && agentsEnabled ? (
|
|
230
|
+
<Tabs
|
|
231
|
+
value={aiPanelTab}
|
|
232
|
+
onValueChange={(value) => {
|
|
233
|
+
if (value === "chat" || value === "agents") {
|
|
234
|
+
setAiPanelTab(value);
|
|
235
|
+
}
|
|
236
|
+
}}
|
|
237
|
+
>
|
|
238
|
+
<TabsList>
|
|
239
|
+
<TabsTrigger
|
|
240
|
+
value="chat"
|
|
241
|
+
className="py-0.5 text-xs uppercase tracking-wide font-bold"
|
|
242
|
+
>
|
|
243
|
+
Chat
|
|
244
|
+
</TabsTrigger>
|
|
245
|
+
<TabsTrigger
|
|
246
|
+
value="agents"
|
|
247
|
+
className="py-0.5 text-xs uppercase tracking-wide font-bold"
|
|
248
|
+
>
|
|
249
|
+
Agents
|
|
250
|
+
</TabsTrigger>
|
|
251
|
+
</TabsList>
|
|
252
|
+
</Tabs>
|
|
253
|
+
) : (
|
|
254
|
+
<span className="text-sm text-(--slate-11) uppercase tracking-wide font-semibold flex-1">
|
|
255
|
+
{selectedPanel}
|
|
256
|
+
</span>
|
|
257
|
+
)}
|
|
258
|
+
<Button
|
|
259
|
+
data-testid="close-helper-pane"
|
|
260
|
+
className="m-0"
|
|
261
|
+
size="xs"
|
|
262
|
+
variant="text"
|
|
263
|
+
onClick={() => setIsSidebarOpen(false)}
|
|
173
264
|
>
|
|
174
|
-
<
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
{selectedPanel}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
>
|
|
201
|
-
<XIcon className="w-4 h-4" />
|
|
202
|
-
</Button>
|
|
265
|
+
<XIcon className="w-4 h-4" />
|
|
266
|
+
</Button>
|
|
267
|
+
</div>
|
|
268
|
+
<Suspense>
|
|
269
|
+
<TooltipProvider>
|
|
270
|
+
{selectedPanel === "files" && <LazyFileExplorerPanel />}
|
|
271
|
+
{selectedPanel === "variables" && <LazySessionPanel />}
|
|
272
|
+
{selectedPanel === "dependencies" && <LazyDependencyGraphPanel />}
|
|
273
|
+
{selectedPanel === "packages" && <LazyPackagesPanel />}
|
|
274
|
+
{selectedPanel === "outline" && <LazyOutlinePanel />}
|
|
275
|
+
{selectedPanel === "documentation" && <LazyDocumentationPanel />}
|
|
276
|
+
{selectedPanel === "snippets" && <LazySnippetsPanel />}
|
|
277
|
+
{selectedPanel === "ai" && renderAiPanel()}
|
|
278
|
+
{selectedPanel === "errors" && <LazyErrorsPanel />}
|
|
279
|
+
{selectedPanel === "scratchpad" && <LazyScratchpadPanel />}
|
|
280
|
+
{selectedPanel === "tracing" && <LazyTracingPanel />}
|
|
281
|
+
{selectedPanel === "secrets" && <LazySecretsPanel />}
|
|
282
|
+
{selectedPanel === "logs" && <LazyLogsPanel />}
|
|
283
|
+
{selectedPanel === "terminal" && (
|
|
284
|
+
<LazyTerminal
|
|
285
|
+
visible={isSidebarOpen}
|
|
286
|
+
onClose={() => setIsSidebarOpen(false)}
|
|
287
|
+
/>
|
|
288
|
+
)}
|
|
289
|
+
{selectedPanel === "cache" && <LazyCachePanel />}
|
|
290
|
+
</TooltipProvider>
|
|
291
|
+
</Suspense>
|
|
203
292
|
</div>
|
|
204
|
-
|
|
205
|
-
<TooltipProvider>
|
|
206
|
-
{selectedPanel === "files" && <LazyFileExplorerPanel />}
|
|
207
|
-
{selectedPanel === "variables" && <LazySessionPanel />}
|
|
208
|
-
{selectedPanel === "dependencies" && <LazyDependencyGraphPanel />}
|
|
209
|
-
{selectedPanel === "packages" && <LazyPackagesPanel />}
|
|
210
|
-
{selectedPanel === "outline" && <LazyOutlinePanel />}
|
|
211
|
-
{selectedPanel === "documentation" && <LazyDocumentationPanel />}
|
|
212
|
-
{selectedPanel === "snippets" && <LazySnippetsPanel />}
|
|
213
|
-
{selectedPanel === "ai" && renderAiPanel()}
|
|
214
|
-
</TooltipProvider>
|
|
215
|
-
</Suspense>
|
|
216
|
-
</div>
|
|
293
|
+
</PanelSectionProvider>
|
|
217
294
|
</ErrorBoundary>
|
|
218
295
|
);
|
|
219
296
|
|
|
@@ -281,36 +358,47 @@ export const AppChrome: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
281
358
|
<div className="flex flex-col h-full">
|
|
282
359
|
{/* Panel header with tabs */}
|
|
283
360
|
<div className="flex items-center justify-between border-b px-2 h-8 bg-background shrink-0">
|
|
284
|
-
<
|
|
285
|
-
value={
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
361
|
+
<ReorderableList<PanelDescriptor>
|
|
362
|
+
value={devPanelItems}
|
|
363
|
+
setValue={handleSetDevPanelItems}
|
|
364
|
+
getKey={(p) => p.type}
|
|
365
|
+
availableItems={availableDevPanels}
|
|
366
|
+
crossListDrag={{
|
|
367
|
+
dragType: "panels",
|
|
368
|
+
listId: "developer-panel",
|
|
369
|
+
onReceive: handleDevPanelReceive,
|
|
370
|
+
}}
|
|
371
|
+
getItemLabel={(panel) => (
|
|
372
|
+
<span className="flex items-center gap-2">
|
|
373
|
+
<panel.Icon className="w-4 h-4 text-muted-foreground" />
|
|
374
|
+
{panel.label}
|
|
375
|
+
</span>
|
|
376
|
+
)}
|
|
377
|
+
ariaLabel="Developer panel tabs"
|
|
378
|
+
className="flex flex-row gap-1"
|
|
379
|
+
minItems={0}
|
|
380
|
+
onAction={(panel) => setSelectedDeveloperPanelTab(panel.type)}
|
|
381
|
+
renderItem={(panel) => (
|
|
382
|
+
<div
|
|
383
|
+
className={cn(
|
|
384
|
+
"text-sm flex gap-2 px-2 pt-1 pb-0.5 items-center leading-none rounded-sm cursor-pointer",
|
|
385
|
+
selectedDeveloperPanelTab === panel.type
|
|
386
|
+
? "bg-muted"
|
|
387
|
+
: "hover:bg-muted/50",
|
|
388
|
+
)}
|
|
389
|
+
>
|
|
390
|
+
<panel.Icon
|
|
391
|
+
className={cn(
|
|
392
|
+
"w-4 h-4",
|
|
393
|
+
panel.type === "errors" &&
|
|
394
|
+
errorCount > 0 &&
|
|
395
|
+
"text-destructive",
|
|
396
|
+
)}
|
|
397
|
+
/>
|
|
398
|
+
{panel.label}
|
|
399
|
+
</div>
|
|
400
|
+
)}
|
|
401
|
+
/>
|
|
314
402
|
<div className="border-l border-border h-4 mx-1" />
|
|
315
403
|
<BackendConnectionStatus />
|
|
316
404
|
<div className="flex-1" />
|
|
@@ -323,60 +411,49 @@ export const AppChrome: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
323
411
|
</Button>
|
|
324
412
|
</div>
|
|
325
413
|
{/* Panel content */}
|
|
326
|
-
<
|
|
327
|
-
|
|
328
|
-
<
|
|
329
|
-
|
|
330
|
-
<
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
414
|
+
<Suspense fallback={<div />}>
|
|
415
|
+
<PanelSectionProvider value="developer-panel">
|
|
416
|
+
<div className="flex-1 overflow-hidden">
|
|
417
|
+
{selectedDeveloperPanelTab === "files" && (
|
|
418
|
+
<LazyFileExplorerPanel />
|
|
419
|
+
)}
|
|
420
|
+
{selectedDeveloperPanelTab === "variables" && (
|
|
421
|
+
<LazySessionPanel />
|
|
422
|
+
)}
|
|
423
|
+
{selectedDeveloperPanelTab === "dependencies" && (
|
|
424
|
+
<LazyDependencyGraphPanel />
|
|
425
|
+
)}
|
|
426
|
+
{selectedDeveloperPanelTab === "packages" && (
|
|
427
|
+
<LazyPackagesPanel />
|
|
428
|
+
)}
|
|
429
|
+
{selectedDeveloperPanelTab === "outline" && <LazyOutlinePanel />}
|
|
430
|
+
{selectedDeveloperPanelTab === "documentation" && (
|
|
431
|
+
<LazyDocumentationPanel />
|
|
432
|
+
)}
|
|
433
|
+
{selectedDeveloperPanelTab === "snippets" && (
|
|
434
|
+
<LazySnippetsPanel />
|
|
435
|
+
)}
|
|
436
|
+
{selectedDeveloperPanelTab === "ai" && renderAiPanel()}
|
|
437
|
+
{selectedDeveloperPanelTab === "errors" && <LazyErrorsPanel />}
|
|
438
|
+
{selectedDeveloperPanelTab === "scratchpad" && (
|
|
337
439
|
<LazyScratchpadPanel />
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
<
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
{selectedDeveloperPanelTab === "logs" && (
|
|
356
|
-
<LazyMount isOpen={isDeveloperPanelOpen}>
|
|
357
|
-
<Suspense fallback={<div />}>
|
|
358
|
-
<LazyLogsPanel />
|
|
359
|
-
</Suspense>
|
|
360
|
-
</LazyMount>
|
|
361
|
-
)}
|
|
362
|
-
{selectedDeveloperPanelTab === "terminal" && (
|
|
363
|
-
<LazyMount isOpen={isDeveloperPanelOpen}>
|
|
364
|
-
<Suspense fallback={<div />}>
|
|
365
|
-
<LazyTerminal
|
|
366
|
-
visible={isDeveloperPanelOpen}
|
|
367
|
-
onClose={() => setIsDeveloperPanelOpen(false)}
|
|
368
|
-
/>
|
|
369
|
-
</Suspense>
|
|
370
|
-
</LazyMount>
|
|
371
|
-
)}
|
|
372
|
-
{selectedDeveloperPanelTab === "cache" && (
|
|
373
|
-
<LazyMount isOpen={isDeveloperPanelOpen}>
|
|
374
|
-
<Suspense fallback={<div />}>
|
|
375
|
-
<LazyCachePanel />
|
|
376
|
-
</Suspense>
|
|
377
|
-
</LazyMount>
|
|
378
|
-
)}
|
|
379
|
-
</div>
|
|
440
|
+
)}
|
|
441
|
+
{selectedDeveloperPanelTab === "tracing" && <LazyTracingPanel />}
|
|
442
|
+
{selectedDeveloperPanelTab === "secrets" && <LazySecretsPanel />}
|
|
443
|
+
{selectedDeveloperPanelTab === "logs" && <LazyLogsPanel />}
|
|
444
|
+
{/* LazyMount needed for Terminal to avoid spurious connection */}
|
|
445
|
+
{selectedDeveloperPanelTab === "terminal" && (
|
|
446
|
+
<LazyMount isOpen={isDeveloperPanelOpen}>
|
|
447
|
+
<LazyTerminal
|
|
448
|
+
visible={isDeveloperPanelOpen}
|
|
449
|
+
onClose={() => setIsDeveloperPanelOpen(false)}
|
|
450
|
+
/>
|
|
451
|
+
</LazyMount>
|
|
452
|
+
)}
|
|
453
|
+
{selectedDeveloperPanelTab === "cache" && <LazyCachePanel />}
|
|
454
|
+
</div>
|
|
455
|
+
</PanelSectionProvider>
|
|
456
|
+
</Suspense>
|
|
380
457
|
</div>
|
|
381
458
|
</Panel>
|
|
382
459
|
);
|
|
@@ -8,72 +8,105 @@ import { useMemo } from "react";
|
|
|
8
8
|
import { ReorderableList } from "@/components/ui/reorderable-list";
|
|
9
9
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
10
10
|
import { notebookQueuedOrRunningCountAtom } from "@/core/cells/cells";
|
|
11
|
-
import { snippetsEnabledAtom } from "@/core/config/config";
|
|
12
11
|
import { cn } from "@/utils/cn";
|
|
13
12
|
import { FeedbackButton } from "../components/feedback-button";
|
|
14
|
-
import {
|
|
13
|
+
import { panelLayoutAtom, useChromeActions, useChromeState } from "../state";
|
|
15
14
|
import { PANEL_MAP, PANELS, type PanelDescriptor } from "../types";
|
|
16
15
|
|
|
17
16
|
export const Sidebar: React.FC = () => {
|
|
18
|
-
const { selectedPanel } = useChromeState();
|
|
19
|
-
const { toggleApplication } =
|
|
20
|
-
|
|
21
|
-
const
|
|
17
|
+
const { selectedPanel, selectedDeveloperPanelTab } = useChromeState();
|
|
18
|
+
const { toggleApplication, setSelectedDeveloperPanelTab } =
|
|
19
|
+
useChromeActions();
|
|
20
|
+
const [panelLayout, setPanelLayout] = useAtom(panelLayoutAtom);
|
|
22
21
|
|
|
23
22
|
const renderIcon = ({ Icon }: PanelDescriptor, className?: string) => {
|
|
24
23
|
return <Icon className={cn("h-5 w-5", className)} />;
|
|
25
24
|
};
|
|
26
25
|
|
|
27
|
-
// Get
|
|
28
|
-
//
|
|
29
|
-
const availableSidebarPanels = useMemo(
|
|
30
|
-
()
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
26
|
+
// Get panels available for sidebar context menu
|
|
27
|
+
// Only show panels that are NOT in the developer panel
|
|
28
|
+
const availableSidebarPanels = useMemo(() => {
|
|
29
|
+
const devPanelIds = new Set(panelLayout.developerPanel);
|
|
30
|
+
return PANELS.filter((p) => {
|
|
31
|
+
if (p.hidden) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
// Exclude panels that are in the developer panel
|
|
35
|
+
if (devPanelIds.has(p.type)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
});
|
|
40
|
+
}, [panelLayout.developerPanel]);
|
|
41
|
+
|
|
42
|
+
// Convert current sidebar items to PanelDescriptors
|
|
43
|
+
const sidebarItems = useMemo(() => {
|
|
44
|
+
return panelLayout.sidebar.flatMap((id) => {
|
|
45
|
+
const panel = PANEL_MAP.get(id);
|
|
46
|
+
return panel ? [panel] : [];
|
|
47
|
+
});
|
|
48
|
+
}, [panelLayout.sidebar]);
|
|
49
|
+
|
|
50
|
+
const handleSetSidebarItems = (items: PanelDescriptor[]) => {
|
|
51
|
+
setPanelLayout((prev) => ({
|
|
52
|
+
...prev,
|
|
53
|
+
sidebar: items.map((item) => item.type),
|
|
54
|
+
}));
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const handleReceive = (item: PanelDescriptor, fromListId: string) => {
|
|
58
|
+
// Remove from the source list
|
|
59
|
+
if (fromListId === "developer-panel") {
|
|
60
|
+
setPanelLayout((prev) => ({
|
|
61
|
+
...prev,
|
|
62
|
+
developerPanel: prev.developerPanel.filter((id) => id !== item.type),
|
|
63
|
+
}));
|
|
43
64
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
// If the moved item was selected in dev panel, select the first remaining item
|
|
66
|
+
if (selectedDeveloperPanelTab === item.type) {
|
|
67
|
+
const remainingDevPanels = panelLayout.developerPanel.filter(
|
|
68
|
+
(id) => id !== item.type,
|
|
69
|
+
);
|
|
70
|
+
if (remainingDevPanels.length > 0) {
|
|
71
|
+
setSelectedDeveloperPanelTab(remainingDevPanels[0]);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
47
75
|
|
|
48
|
-
|
|
49
|
-
|
|
76
|
+
// Select the dropped item in sidebar
|
|
77
|
+
toggleApplication(item.type);
|
|
50
78
|
};
|
|
51
79
|
|
|
52
80
|
return (
|
|
53
81
|
<div className="h-full pt-4 pb-1 px-1 flex flex-col items-start text-muted-foreground text-md select-none no-print text-sm z-50 dark:bg-background print:hidden hide-on-fullscreen">
|
|
54
82
|
<ReorderableList<PanelDescriptor>
|
|
55
|
-
value={
|
|
56
|
-
setValue={
|
|
83
|
+
value={sidebarItems}
|
|
84
|
+
setValue={handleSetSidebarItems}
|
|
85
|
+
getKey={(p) => p.type}
|
|
57
86
|
availableItems={availableSidebarPanels}
|
|
87
|
+
crossListDrag={{
|
|
88
|
+
dragType: "panels",
|
|
89
|
+
listId: "sidebar",
|
|
90
|
+
onReceive: handleReceive,
|
|
91
|
+
}}
|
|
58
92
|
getItemLabel={(panel) => (
|
|
59
|
-
<span className="flex items-center gap-2
|
|
93
|
+
<span className="flex items-center gap-2">
|
|
60
94
|
{renderIcon(panel, "h-4 w-4 text-muted-foreground")}
|
|
61
|
-
{panel.
|
|
95
|
+
{panel.label}
|
|
62
96
|
</span>
|
|
63
97
|
)}
|
|
64
|
-
ariaLabel="
|
|
98
|
+
ariaLabel="Sidebar panels"
|
|
65
99
|
className="flex flex-col gap-0"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}}
|
|
100
|
+
minItems={0}
|
|
101
|
+
onAction={(panel) => toggleApplication(panel.type)}
|
|
102
|
+
renderItem={(panel) => (
|
|
103
|
+
<SidebarItem
|
|
104
|
+
tooltip={panel.tooltip}
|
|
105
|
+
selected={selectedPanel === panel.type}
|
|
106
|
+
>
|
|
107
|
+
{renderIcon(panel)}
|
|
108
|
+
</SidebarItem>
|
|
109
|
+
)}
|
|
77
110
|
/>
|
|
78
111
|
<FeedbackButton>
|
|
79
112
|
<SidebarItem tooltip="Send feedback!" selected={false}>
|
|
@@ -27,6 +27,10 @@ import { useTheme } from "@/theme/useTheme";
|
|
|
27
27
|
import { cn } from "@/utils/cn";
|
|
28
28
|
import { Functions } from "@/utils/functions";
|
|
29
29
|
import { CellEditor } from "../editor/cell/code/cell-editor";
|
|
30
|
+
import {
|
|
31
|
+
usePanelOrientation,
|
|
32
|
+
usePanelSection,
|
|
33
|
+
} from "../editor/chrome/panels/panel-context";
|
|
30
34
|
import { HideInKioskMode } from "../editor/kiosk-mode";
|
|
31
35
|
import { OutputArea } from "../editor/Output";
|
|
32
36
|
import { ConsoleOutput } from "../editor/output/console/ConsoleOutput";
|
|
@@ -53,6 +57,8 @@ export const ScratchPad: React.FC = () => {
|
|
|
53
57
|
const lastFocusedCellId = useLastFocusedCellId();
|
|
54
58
|
const { createNewCell, updateCellCode } = useCellActions();
|
|
55
59
|
const { sendRunScratchpad } = useRequestClient();
|
|
60
|
+
const orientation = usePanelOrientation();
|
|
61
|
+
const section = usePanelSection();
|
|
56
62
|
|
|
57
63
|
const cellId = SCRATCH_CELL_ID;
|
|
58
64
|
const cellRuntime = notebookState.cellRuntime[cellId];
|
|
@@ -223,13 +229,15 @@ export const ScratchPad: React.FC = () => {
|
|
|
223
229
|
</div>
|
|
224
230
|
);
|
|
225
231
|
|
|
232
|
+
const isVertical = orientation === "vertical";
|
|
233
|
+
|
|
226
234
|
return (
|
|
227
235
|
<div
|
|
228
236
|
className="flex flex-col h-full overflow-hidden"
|
|
229
237
|
id={HTMLCellId.create(cellId)}
|
|
230
238
|
>
|
|
231
|
-
<PanelGroup direction=
|
|
232
|
-
{/*
|
|
239
|
+
<PanelGroup key={section} direction={orientation} className="h-full">
|
|
240
|
+
{/* Editor panel */}
|
|
233
241
|
<Panel defaultSize={40} minSize={20} maxSize={70}>
|
|
234
242
|
<div className="h-full flex flex-col overflow-hidden relative">
|
|
235
243
|
{renderToolbar()}
|
|
@@ -257,8 +265,13 @@ export const ScratchPad: React.FC = () => {
|
|
|
257
265
|
{renderHistory()}
|
|
258
266
|
</div>
|
|
259
267
|
</Panel>
|
|
260
|
-
<PanelResizeHandle
|
|
261
|
-
|
|
268
|
+
<PanelResizeHandle
|
|
269
|
+
className={cn(
|
|
270
|
+
"bg-border hover:bg-primary/50 transition-colors",
|
|
271
|
+
isVertical ? "h-1" : "w-1",
|
|
272
|
+
)}
|
|
273
|
+
/>
|
|
274
|
+
{/* Output panel */}
|
|
262
275
|
<Panel defaultSize={60} minSize={20}>
|
|
263
276
|
<div className="h-full flex flex-col divide-y overflow-hidden">
|
|
264
277
|
<div className="flex-1 overflow-auto">
|