@marimo-team/frontend 0.19.3-dev8 → 0.19.4-dev0
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-BwPGnX3z.js → CellStatus--kUu6N2K.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-KlUs_Sz3.js → ConnectedDataExplorerComponent-BKJwCHu7.js} +1 -1
- package/dist/assets/{ErrorBoundary-Drf1manw.js → ErrorBoundary-C7JBxSzd.js} +1 -1
- package/dist/assets/{ImperativeModal-q6QlC2aZ.js → ImperativeModal-DVhvP4lH.js} +1 -1
- package/dist/assets/{JsonOutput--AuyEErr.js → JsonOutput-BSGE-MRo.js} +5 -5
- package/dist/assets/{LazyAnyLanguageCodeMirror-jpEDlD0M.js → LazyAnyLanguageCodeMirror-Cp2punaU.js} +2 -2
- package/dist/assets/{MarimoErrorOutput-BZjY8e2w.js → MarimoErrorOutput-CX0SCJOZ.js} +2 -2
- package/dist/assets/{RenderHTML-BTLaM20B.js → RenderHTML-Do_PVqRy.js} +1 -1
- package/dist/assets/VisuallyHidden-B9t3FhTP.js +1 -0
- package/dist/assets/{add-cell-with-ai-BWWVs9qV.js → add-cell-with-ai-manh7kBT.js} +21 -21
- package/dist/assets/{add-database-form-Bw_YRH1r.js → add-database-form-CgkV0MRs.js} +2 -2
- package/dist/assets/agent-panel-D-OmT-rw.js +287 -0
- package/dist/assets/{ai-model-dropdown-BrUOgnWS.js → ai-model-dropdown-DzyBY5VA.js} +1 -1
- package/dist/assets/{alert-dialog-k5KxevGr.js → alert-dialog-jcHA5geR.js} +1 -1
- package/dist/assets/{any-language-editor-DQu1Tt2N.js → any-language-editor-Cm83E7D_.js} +1 -1
- package/dist/assets/{app-config-button-B8CXELx0.js → app-config-button-DC3alCuB.js} +1 -1
- package/dist/assets/button-B8cGZzP5.js +1 -0
- package/dist/assets/{cache-panel-C1So4Zu3.js → cache-panel-1FqnpB9y.js} +1 -1
- package/dist/assets/cell-editor-RHFZmO74.js +23 -0
- package/dist/assets/cell-link-Dqj_nfXA.js +1 -0
- package/dist/assets/{cells-DU3EySUd.js → cells-BNQUQiDS.js} +49 -49
- package/dist/assets/{chat-components-Bc9j9ls4.js → chat-components-CWiXtKu6.js} +1 -1
- package/dist/assets/{chat-display-BrTi6c8V.js → chat-display-CGnOamQG.js} +1 -1
- package/dist/assets/{chat-panel-8Dym5Gv3.js → chat-panel-Dh1M55c9.js} +2 -2
- package/dist/assets/client-CDjmJmVw.js +4 -0
- package/dist/assets/{column-preview-Ck6B_-sQ.js → column-preview-CKxT2s-S.js} +1 -1
- package/dist/assets/{command-B_minI8b.js → command-YPFTinLj.js} +1 -1
- package/dist/assets/{command-palette-BT3u6JBB.js → command-palette-7fVEhKGc.js} +1 -1
- package/dist/assets/common-DJkPpBxC.js +1 -0
- package/dist/assets/config-D6nhy4FA.js +1 -0
- package/dist/assets/context-DHfVoQfl.js +1 -0
- package/dist/assets/{copy-icon-B69c-352.js → copy-icon-jWsqdLn1.js} +1 -1
- package/dist/assets/{datasource-DCvPlnaJ.js → datasource-DerBLc6V.js} +2 -2
- package/dist/assets/{dependency-graph-panel-C9jYZ6pA.js → dependency-graph-panel-Vd-OsVLa.js} +4 -4
- package/dist/assets/{dialog-DUEuLcT2.js → dialog-CF5DtF1E.js} +1 -1
- package/dist/assets/{dist-DOFFh6Ii.js → dist-Dg7UO_Vw.js} +1 -1
- package/dist/assets/{documentation-panel-AsatrTfg.js → documentation-panel-xG2-zpwg.js} +1 -1
- package/dist/assets/{download-PR1bF3g_.js → download-B6EJS7Ar.js} +1 -1
- package/dist/assets/edit-page-7Hkti2j_.js +12 -0
- package/dist/assets/{error-banner-DU5Qb8a8.js → error-banner-DvT0IGDZ.js} +1 -1
- package/dist/assets/{error-panel-D_wVKV6I.js → error-panel-BxBpZYvt.js} +1 -1
- package/dist/assets/{es-CEE_7T0w.js → es-BoHEdemq.js} +1 -1
- package/dist/assets/{field-DDKGFzpC.js → field-Clr_fqUr.js} +1 -1
- package/dist/assets/{file-explorer-panel-DltK8JVp.js → file-explorer-panel-C9K0vIPl.js} +1 -1
- package/dist/assets/{floating-outline-BfdazXWm.js → floating-outline-DCrTuu2G.js} +1 -1
- package/dist/assets/{focus-CtlWIiQr.js → focus-DM53w5BH.js} +1 -1
- package/dist/assets/{form-Cy5TkLzh.js → form-BcKfhfZc.js} +2 -2
- package/dist/assets/{glide-data-editor-D_bRnWfy.js → glide-data-editor-CRb9AiCG.js} +1 -1
- package/dist/assets/{globals-BSLm1nlz.js → globals-Bf30kOQF.js} +1 -1
- package/dist/assets/{home-page-CEnaUutq.js → home-page-BRyNf7fl.js} +2 -2
- package/dist/assets/index-CBMqMxiq.js +43 -0
- package/dist/assets/index-DDc_1b-N.css +2 -0
- package/dist/assets/input-B80Yt1uu.js +1 -0
- package/dist/assets/{kiosk-mode-BnTZR6mM.js → kiosk-mode-P-NYHJID.js} +1 -1
- package/dist/assets/{label-qwandMoh.js → label-CNZLffHW.js} +1 -1
- package/dist/assets/{layout-BTiWDrbh.js → layout-DT91GUei.js} +4 -4
- package/dist/assets/links-D529u6GQ.js +1 -0
- package/dist/assets/{logs-panel-Cnp9tO_1.js → logs-panel-C2dfrRig.js} +1 -1
- package/dist/assets/{markdown-renderer-BSrbBHwX.js → markdown-renderer-BPnVa0ym.js} +2 -2
- package/dist/assets/{mermaid-BPkO79lo.js → mermaid--ZwxKP7u.js} +1 -1
- package/dist/assets/mode-Dq8MKjNR.js +1 -0
- package/dist/assets/{multi-map-fjX9ImVF.js → multi-map-CQd4MZr5.js} +1 -1
- package/dist/assets/name-cell-input-BaEPC7ON.js +1 -0
- package/dist/assets/{outline-panel-DCfj1bI-.js → outline-panel-Cca864H0.js} +1 -1
- package/dist/assets/{packages-panel-BiEckVdM.js → packages-panel-Cy_KAYmq.js} +1 -1
- package/dist/assets/{panels-BXRys72u.js → panels-BzlLZfye.js} +1 -1
- package/dist/assets/{process-output-wGlHkL-Q.js → process-output-Dn1rOp26.js} +1 -1
- package/dist/assets/{readonly-python-code-xbh7G2Y2.js → readonly-python-code-CXeF74Iq.js} +1 -1
- package/dist/assets/{renderShortcut-D0Pei-OA.js → renderShortcut-eU5Hsfml.js} +1 -1
- package/dist/assets/{run-page-BCwJRhCq.js → run-page-CM_n6pXD.js} +1 -1
- package/dist/assets/scratchpad-panel-XCkVY3Hp.js +1 -0
- package/dist/assets/{secrets-panel-CDWmmmBS.js → secrets-panel-BMY6PPth.js} +1 -1
- package/dist/assets/{select-D0g5GnIs.js → select-D9lTzMzP.js} +1 -1
- package/dist/assets/{session-panel-DuQl_oQp.js → session-panel-BDt6Y_mU.js} +1 -1
- package/dist/assets/{slides-component-MkPkpql1.js → slides-component-Dp0Yv5b0.js} +1 -1
- package/dist/assets/{snippets-panel-R_ql6HGu.js → snippets-panel-K-JKJQBf.js} +1 -1
- package/dist/assets/state-DWRZTH2y.js +1 -0
- package/dist/assets/state-JzO-Ni5T.js +1 -0
- package/dist/assets/{switch-CWzL-0WF.js → switch-RowEjq0T.js} +1 -1
- package/dist/assets/{terminal-BWM0fOMh.js → terminal-BhbNfCNw.js} +1 -1
- package/dist/assets/{textarea-CfvBt_Xm.js → textarea-Di1KKcL4.js} +1 -1
- package/dist/assets/{tracing-Kscqc1t3.js → tracing-nvbrZdpf.js} +1 -1
- package/dist/assets/{tracing-panel-BEzOflWc.js → tracing-panel-CTXJaO-A.js} +2 -2
- package/dist/assets/{types-DhuSHMNQ.js → types-CT2U5Ljy.js} +1 -1
- package/dist/assets/{useAddCell-C9lbOVO1.js → useAddCell-COb93CUl.js} +1 -1
- package/dist/assets/{useBoolean-B-A0dyIW.js → useBoolean-B_S7yTZz.js} +1 -1
- package/dist/assets/{useCellActionButton-fsh9MTAX.js → useCellActionButton-D5Zt1dDz.js} +1 -1
- package/dist/assets/{useDateFormatter-CV0QXb5P.js → useDateFormatter-DsANziQR.js} +1 -1
- package/dist/assets/useDeleteCell-DHF_xvAh.js +1 -0
- package/dist/assets/{useDependencyPanelTab-CngFbla0.js → useDependencyPanelTab-D59iW_MD.js} +1 -1
- package/dist/assets/useInterval-BGPIviJp.js +1 -0
- package/dist/assets/{useNotebookActions-D01w160c.js → useNotebookActions-DEl-rH-3.js} +1 -1
- package/dist/assets/{useNumberFormatter-D8ks3oPN.js → useNumberFormatter-FoXhpyAb.js} +1 -1
- package/dist/assets/usePress-DTwIUo40.js +7 -0
- package/dist/assets/useRunCells-CKEmgeKM.js +1 -0
- package/dist/assets/useSplitCell-D9YiO-z5.js +1 -0
- package/dist/assets/{useTheme-DfP1CWaW.js → useTheme-CNj0G_ol.js} +1 -1
- package/dist/assets/utilities.esm-DG4qccZc.js +3 -0
- package/dist/assets/utils-pfqq9IdB.js +1 -0
- package/dist/assets/{vega-component-B8ghmMYW.js → vega-component-C1voDf5W.js} +1 -1
- package/dist/assets/{write-secret-modal-CLm48gMe.js → write-secret-modal-hOetwavI.js} +1 -1
- package/dist/index.html +56 -56
- package/package.json +5 -5
- package/src/__mocks__/requests.ts +1 -0
- package/src/__tests__/mount.test.ts +128 -0
- package/src/components/app-config/__tests__/get-dirty-values.test.ts +1 -1
- package/src/components/app-config/ai-config.tsx +328 -28
- package/src/components/app-config/user-config-form.tsx +10 -3
- package/src/components/chat/acp/agent-panel.tsx +56 -43
- package/src/components/chat/chat-utils.ts +0 -19
- package/src/components/data-table/column-header.tsx +1 -1
- package/src/components/editor/KernelStartupErrorModal.tsx +2 -2
- package/src/components/editor/actions/name-cell-input.tsx +10 -4
- package/src/components/editor/ai/completion-handlers.tsx +1 -1
- package/src/components/editor/alerts/connecting-alert.tsx +33 -6
- package/src/components/editor/chrome/types.ts +2 -4
- package/src/components/editor/chrome/wrapper/app-chrome.tsx +55 -58
- package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +150 -96
- package/src/components/editor/renderers/vertical-layout/__tests__/useFocusFirstEditor.test.ts +27 -0
- package/src/components/editor/renderers/vertical-layout/useFocusFirstEditor.ts +6 -0
- package/src/components/utils/lazy-mount.tsx +29 -8
- package/src/core/ai/ids/ids.ts +12 -4
- package/src/core/cells/cells.ts +2 -0
- package/src/core/cells/scrollCellIntoView.ts +3 -2
- package/src/core/codemirror/cm.ts +2 -0
- package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +123 -0
- package/src/core/codemirror/lsp/notebook-lsp.ts +44 -4
- package/src/core/codemirror/misc/__tests__/string-braces.test.ts +200 -0
- package/src/core/codemirror/misc/string-braces.ts +37 -0
- package/src/core/config/__tests__/config-schema.test.ts +36 -0
- package/src/core/config/config-schema.ts +1 -0
- package/src/core/export/__tests__/hooks.test.ts +504 -0
- package/src/core/export/hooks.ts +93 -4
- package/src/core/islands/bridge.ts +1 -0
- package/src/core/kernel/__tests__/handlers.test.ts +2 -2
- package/src/core/kernel/state.ts +1 -0
- package/src/core/network/__tests__/requests-lazy.test.ts +1 -1
- package/src/core/network/__tests__/requests-network.test.ts +0 -18
- package/src/core/network/requests-lazy.ts +3 -2
- package/src/core/network/requests-network.ts +10 -7
- package/src/core/network/requests-static.ts +1 -0
- package/src/core/network/requests-toasting.tsx +1 -0
- package/src/core/network/types.ts +2 -0
- package/src/core/wasm/bridge.ts +1 -0
- package/src/css/globals.css +2 -0
- package/src/hooks/__tests__/useInterval.test.tsx +104 -0
- package/src/hooks/useInterval.ts +32 -6
- package/src/mount.tsx +6 -0
- package/src/plugins/impl/chat/ChatPlugin.tsx +2 -4
- package/src/plugins/impl/chat/chat-ui.tsx +62 -191
- package/src/plugins/impl/chat/types.ts +5 -12
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +3 -1
- package/src/utils/events.ts +1 -0
- package/dist/assets/VisuallyHidden-BodIky8L.js +0 -1
- package/dist/assets/agent-panel-Bm-vW8YL.js +0 -287
- package/dist/assets/button-DuYGqRtX.js +0 -1
- package/dist/assets/cell-editor-Cdtc1m3g.js +0 -23
- package/dist/assets/cell-link-CFAPzUg5.js +0 -1
- package/dist/assets/client-DfkWorYM.js +0 -4
- package/dist/assets/common-jorbwXZC.js +0 -1
- package/dist/assets/config-Ba3eeYri.js +0 -1
- package/dist/assets/context-BAYdLMF_.js +0 -1
- package/dist/assets/edit-page-B1Ed6RKp.js +0 -12
- package/dist/assets/index-DNg7_e7t.js +0 -43
- package/dist/assets/index-__6MNWbe.css +0 -2
- package/dist/assets/input-CaEtLL8p.js +0 -1
- package/dist/assets/links-Bpd4gqTj.js +0 -1
- package/dist/assets/mode-yhfN-4ye.js +0 -1
- package/dist/assets/name-cell-input-CmuWqgFR.js +0 -1
- package/dist/assets/scratchpad-panel-C6PpCYtK.js +0 -1
- package/dist/assets/state-DEHWsmkM.js +0 -1
- package/dist/assets/state-DXAf-ejz.js +0 -1
- package/dist/assets/useDeleteCell-ByImoTpm.js +0 -1
- package/dist/assets/useInterval-DpipYmgs.js +0 -1
- package/dist/assets/usePress-C2LPFxyv.js +0 -7
- package/dist/assets/useRunCells-CmnSPQtM.js +0 -1
- package/dist/assets/useSplitCell-BTH64tve.js +0 -1
- package/dist/assets/utilities.esm-CMQs6YPp.js +0 -3
- package/dist/assets/utils-CJJIceVn.js +0 -1
|
@@ -593,7 +593,7 @@ const PopoverFilterByValues = <TData, TValue>({
|
|
|
593
593
|
<>
|
|
594
594
|
<Command className="text-sm outline-hidden" shouldFilter={false}>
|
|
595
595
|
<CommandInput
|
|
596
|
-
placeholder=
|
|
596
|
+
placeholder={`Search among the top ${data.length} values`}
|
|
597
597
|
autoFocus={true}
|
|
598
598
|
onValueChange={(value) => setQuery(value.trim())}
|
|
599
599
|
/>
|
|
@@ -65,7 +65,7 @@ export const KernelStartupErrorModal: React.FC = () => {
|
|
|
65
65
|
manager can't install your notebook's dependencies.
|
|
66
66
|
</AlertDialogDescription>
|
|
67
67
|
</AlertDialogHeader>
|
|
68
|
-
<div className="my-4">
|
|
68
|
+
<div className="my-4 overflow-hidden">
|
|
69
69
|
<div className="flex items-center justify-between mb-2">
|
|
70
70
|
<span className="text-sm font-medium text-muted-foreground">
|
|
71
71
|
Error Details
|
|
@@ -80,7 +80,7 @@ export const KernelStartupErrorModal: React.FC = () => {
|
|
|
80
80
|
Copy
|
|
81
81
|
</Button>
|
|
82
82
|
</div>
|
|
83
|
-
<pre className="bg-muted p-4 rounded-md text-sm font-mono overflow-auto max-h-80
|
|
83
|
+
<pre className="bg-muted p-4 rounded-md text-sm font-mono overflow-auto max-h-80">
|
|
84
84
|
{error}
|
|
85
85
|
</pre>
|
|
86
86
|
</div>
|
|
@@ -93,11 +93,17 @@ export const NameCellContentEditable: React.FC<{
|
|
|
93
93
|
onChange={inputProps.onChange}
|
|
94
94
|
onBlur={inputProps.onBlur}
|
|
95
95
|
onFocus={inputProps.onFocus}
|
|
96
|
-
onKeyDown={
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
onKeyDown={(e) => {
|
|
97
|
+
// Prevent all key presses from triggering hotkeys
|
|
98
|
+
e.stopPropagation();
|
|
99
|
+
|
|
100
|
+
// On Enter, blur the input to commit the change
|
|
101
|
+
if (e.key === "Enter") {
|
|
102
|
+
if (e.target instanceof HTMLElement) {
|
|
103
|
+
e.target.blur();
|
|
104
|
+
}
|
|
99
105
|
}
|
|
100
|
-
}
|
|
106
|
+
}}
|
|
101
107
|
>
|
|
102
108
|
{value}
|
|
103
109
|
</span>
|
|
@@ -124,7 +124,7 @@ export const AcceptCompletionButton: React.FC<{
|
|
|
124
124
|
size={size}
|
|
125
125
|
disabled={isLoading}
|
|
126
126
|
onClick={handleAcceptAndRun}
|
|
127
|
-
className={`${baseClasses} rounded-l-none px-1.5 ${borderless && "border-0 border-l
|
|
127
|
+
className={`${baseClasses} rounded-l-none px-1.5 ${borderless && "border-0 border-l"} ${playButtonStyles}`}
|
|
128
128
|
>
|
|
129
129
|
<PlayIcon className="h-2.5 w-2.5" />
|
|
130
130
|
</Button>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useAtomValue } from "jotai";
|
|
4
4
|
import { LoadingEllipsis } from "@/components/icons/loading-ellipsis";
|
|
5
|
+
import { Spinner } from "@/components/icons/spinner";
|
|
5
6
|
import { Button } from "@/components/ui/button";
|
|
6
7
|
import { DelayMount } from "@/components/utils/delay-mount";
|
|
7
8
|
import {
|
|
@@ -10,24 +11,50 @@ import {
|
|
|
10
11
|
isNotStartedAtom,
|
|
11
12
|
} from "@/core/network/connection";
|
|
12
13
|
import { useConnectToRuntime } from "@/core/runtime/config";
|
|
14
|
+
import { Banner } from "@/plugins/impl/common/error-banner";
|
|
13
15
|
import { Tooltip } from "../../ui/tooltip";
|
|
14
16
|
import { FloatingAlert } from "./floating-alert";
|
|
15
17
|
|
|
16
18
|
const SHORT_DELAY_MS = 1000; // 1 second
|
|
19
|
+
const LONG_DELAY_MS = 5000; // 5 seconds
|
|
17
20
|
|
|
18
21
|
export const ConnectingAlert: React.FC = () => {
|
|
19
22
|
const isConnecting = useAtomValue(isConnectingAtom);
|
|
20
23
|
const isClosed = useAtomValue(isClosedAtom);
|
|
21
24
|
|
|
22
25
|
if (isConnecting) {
|
|
26
|
+
const subtleNotification = (
|
|
27
|
+
<Tooltip content="Connecting to a marimo runtime">
|
|
28
|
+
<div className="flex items-center">
|
|
29
|
+
<LoadingEllipsis size={5} className="text-yellow-500" />
|
|
30
|
+
</div>
|
|
31
|
+
</Tooltip>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const longNotification = (
|
|
35
|
+
<Banner
|
|
36
|
+
kind="info"
|
|
37
|
+
className="flex flex-col rounded py-2 px-4 animate-in slide-in-from-top w-fit"
|
|
38
|
+
>
|
|
39
|
+
<div className="flex flex-col gap-4 justify-between items-start text-muted-foreground text-base">
|
|
40
|
+
<div className="flex items-center gap-2">
|
|
41
|
+
<Spinner className="h-4 w-4" />
|
|
42
|
+
<p>Connecting to a marimo runtime ...</p>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</Banner>
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// This waits for 1 second to show the subtle notification, then shows the long notification after 5 seconds.
|
|
23
49
|
return (
|
|
24
50
|
<DelayMount milliseconds={SHORT_DELAY_MS}>
|
|
25
|
-
<div className="
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
51
|
+
<div className="m-0 flex items-center min-h-[28px] fixed top-5 left-1/2 transform -translate-x-1/2 z-200">
|
|
52
|
+
<DelayMount
|
|
53
|
+
milliseconds={LONG_DELAY_MS}
|
|
54
|
+
fallback={subtleNotification}
|
|
55
|
+
>
|
|
56
|
+
{longNotification}
|
|
57
|
+
</DelayMount>
|
|
31
58
|
</div>
|
|
32
59
|
</DelayMount>
|
|
33
60
|
);
|
|
@@ -194,10 +194,8 @@ export function isPanelHidden(
|
|
|
194
194
|
if (panel.hidden) {
|
|
195
195
|
return true;
|
|
196
196
|
}
|
|
197
|
-
if (panel.requiredCapability) {
|
|
198
|
-
|
|
199
|
-
return true;
|
|
200
|
-
}
|
|
197
|
+
if (panel.requiredCapability && !capabilities[panel.requiredCapability]) {
|
|
198
|
+
return true;
|
|
201
199
|
}
|
|
202
200
|
return false;
|
|
203
201
|
}
|
|
@@ -20,7 +20,7 @@ import { XIcon } from "lucide-react";
|
|
|
20
20
|
import { Button } from "@/components/ui/button";
|
|
21
21
|
import { ReorderableList } from "@/components/ui/reorderable-list";
|
|
22
22
|
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
23
|
-
import {
|
|
23
|
+
import { LazyActivity } from "@/components/utils/lazy-mount";
|
|
24
24
|
import { cellErrorCount } from "@/core/cells/cells";
|
|
25
25
|
import { capabilitiesAtom } from "@/core/config/capabilities";
|
|
26
26
|
import { getFeatureFlag } from "@/core/config/feature-flag";
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
PANEL_MAP,
|
|
35
35
|
PANELS,
|
|
36
36
|
type PanelDescriptor,
|
|
37
|
+
type PanelType,
|
|
37
38
|
} from "../types";
|
|
38
39
|
import { BackendConnectionStatus } from "./footer-items/backend-status";
|
|
39
40
|
import { PanelsWrapper } from "./panels";
|
|
@@ -253,6 +254,29 @@ export const AppChrome: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
253
254
|
return <LazyChatPanel />;
|
|
254
255
|
};
|
|
255
256
|
|
|
257
|
+
const SIDEBAR_PANELS: Record<PanelType, React.ReactNode> = {
|
|
258
|
+
files: <LazyFileExplorerPanel />,
|
|
259
|
+
variables: <LazySessionPanel />,
|
|
260
|
+
dependencies: <LazyDependencyGraphPanel />,
|
|
261
|
+
packages: <LazyPackagesPanel />,
|
|
262
|
+
outline: <LazyOutlinePanel />,
|
|
263
|
+
documentation: <LazyDocumentationPanel />,
|
|
264
|
+
snippets: <LazySnippetsPanel />,
|
|
265
|
+
ai: renderAiPanel(),
|
|
266
|
+
errors: <LazyErrorsPanel />,
|
|
267
|
+
scratchpad: <LazyScratchpadPanel />,
|
|
268
|
+
tracing: <LazyTracingPanel />,
|
|
269
|
+
secrets: <LazySecretsPanel />,
|
|
270
|
+
logs: <LazyLogsPanel />,
|
|
271
|
+
terminal: (
|
|
272
|
+
<LazyTerminal
|
|
273
|
+
visible={isSidebarOpen && selectedPanel === "terminal"}
|
|
274
|
+
onClose={() => setIsSidebarOpen(false)}
|
|
275
|
+
/>
|
|
276
|
+
),
|
|
277
|
+
cache: <LazyCachePanel />,
|
|
278
|
+
};
|
|
279
|
+
|
|
256
280
|
const helpPaneBody = (
|
|
257
281
|
<ErrorBoundary>
|
|
258
282
|
<PanelSectionProvider value="sidebar">
|
|
@@ -328,26 +352,14 @@ export const AppChrome: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
328
352
|
</div>
|
|
329
353
|
<Suspense>
|
|
330
354
|
<TooltipProvider>
|
|
331
|
-
{
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
{selectedPanel === "errors" && <LazyErrorsPanel />}
|
|
340
|
-
{selectedPanel === "scratchpad" && <LazyScratchpadPanel />}
|
|
341
|
-
{selectedPanel === "tracing" && <LazyTracingPanel />}
|
|
342
|
-
{selectedPanel === "secrets" && <LazySecretsPanel />}
|
|
343
|
-
{selectedPanel === "logs" && <LazyLogsPanel />}
|
|
344
|
-
{selectedPanel === "terminal" && (
|
|
345
|
-
<LazyTerminal
|
|
346
|
-
visible={isSidebarOpen}
|
|
347
|
-
onClose={() => setIsSidebarOpen(false)}
|
|
348
|
-
/>
|
|
349
|
-
)}
|
|
350
|
-
{selectedPanel === "cache" && <LazyCachePanel />}
|
|
355
|
+
{Object.entries(SIDEBAR_PANELS).map(([key, Panel]) => (
|
|
356
|
+
<LazyActivity
|
|
357
|
+
key={key}
|
|
358
|
+
mode={selectedPanel === key ? "visible" : "hidden"}
|
|
359
|
+
>
|
|
360
|
+
{Panel}
|
|
361
|
+
</LazyActivity>
|
|
362
|
+
))}
|
|
351
363
|
</TooltipProvider>
|
|
352
364
|
</Suspense>
|
|
353
365
|
</div>
|
|
@@ -388,6 +400,18 @@ export const AppChrome: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
388
400
|
</Panel>
|
|
389
401
|
);
|
|
390
402
|
|
|
403
|
+
const DEVELOPER_PANELS: Record<PanelType, React.ReactNode> = {
|
|
404
|
+
...SIDEBAR_PANELS,
|
|
405
|
+
terminal: (
|
|
406
|
+
<LazyTerminal
|
|
407
|
+
visible={
|
|
408
|
+
isDeveloperPanelOpen && selectedDeveloperPanelTab === "terminal"
|
|
409
|
+
}
|
|
410
|
+
onClose={() => setIsDeveloperPanelOpen(false)}
|
|
411
|
+
/>
|
|
412
|
+
),
|
|
413
|
+
};
|
|
414
|
+
|
|
391
415
|
const bottomPanel = (
|
|
392
416
|
<Panel
|
|
393
417
|
ref={developerPanelRef}
|
|
@@ -475,43 +499,16 @@ export const AppChrome: React.FC<PropsWithChildren> = ({ children }) => {
|
|
|
475
499
|
<Suspense fallback={<div />}>
|
|
476
500
|
<PanelSectionProvider value="developer-panel">
|
|
477
501
|
<div className="flex-1 overflow-hidden">
|
|
478
|
-
{
|
|
479
|
-
<
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
<LazyPackagesPanel />
|
|
489
|
-
)}
|
|
490
|
-
{selectedDeveloperPanelTab === "outline" && <LazyOutlinePanel />}
|
|
491
|
-
{selectedDeveloperPanelTab === "documentation" && (
|
|
492
|
-
<LazyDocumentationPanel />
|
|
493
|
-
)}
|
|
494
|
-
{selectedDeveloperPanelTab === "snippets" && (
|
|
495
|
-
<LazySnippetsPanel />
|
|
496
|
-
)}
|
|
497
|
-
{selectedDeveloperPanelTab === "ai" && renderAiPanel()}
|
|
498
|
-
{selectedDeveloperPanelTab === "errors" && <LazyErrorsPanel />}
|
|
499
|
-
{selectedDeveloperPanelTab === "scratchpad" && (
|
|
500
|
-
<LazyScratchpadPanel />
|
|
501
|
-
)}
|
|
502
|
-
{selectedDeveloperPanelTab === "tracing" && <LazyTracingPanel />}
|
|
503
|
-
{selectedDeveloperPanelTab === "secrets" && <LazySecretsPanel />}
|
|
504
|
-
{selectedDeveloperPanelTab === "logs" && <LazyLogsPanel />}
|
|
505
|
-
{/* LazyMount needed for Terminal to avoid spurious connection */}
|
|
506
|
-
{selectedDeveloperPanelTab === "terminal" && (
|
|
507
|
-
<LazyMount isOpen={isDeveloperPanelOpen}>
|
|
508
|
-
<LazyTerminal
|
|
509
|
-
visible={isDeveloperPanelOpen}
|
|
510
|
-
onClose={() => setIsDeveloperPanelOpen(false)}
|
|
511
|
-
/>
|
|
512
|
-
</LazyMount>
|
|
513
|
-
)}
|
|
514
|
-
{selectedDeveloperPanelTab === "cache" && <LazyCachePanel />}
|
|
502
|
+
{Object.entries(DEVELOPER_PANELS).map(([key, Panel]) => (
|
|
503
|
+
<LazyActivity
|
|
504
|
+
key={key}
|
|
505
|
+
mode={
|
|
506
|
+
selectedDeveloperPanelTab === key ? "visible" : "hidden"
|
|
507
|
+
}
|
|
508
|
+
>
|
|
509
|
+
{Panel}
|
|
510
|
+
</LazyActivity>
|
|
511
|
+
))}
|
|
515
512
|
</div>
|
|
516
513
|
</PanelSectionProvider>
|
|
517
514
|
</Suspense>
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
ChevronDownIcon,
|
|
5
|
+
ExternalLinkIcon,
|
|
6
|
+
InfoIcon,
|
|
5
7
|
PowerOffIcon,
|
|
6
8
|
ZapIcon,
|
|
7
9
|
ZapOffIcon,
|
|
@@ -15,7 +17,9 @@ import {
|
|
|
15
17
|
DropdownMenuSeparator,
|
|
16
18
|
DropdownMenuTrigger,
|
|
17
19
|
} from "@/components/ui/dropdown-menu";
|
|
20
|
+
import { ExternalLink } from "@/components/ui/links";
|
|
18
21
|
import { Switch } from "@/components/ui/switch";
|
|
22
|
+
import { Tooltip, TooltipProvider } from "@/components/ui/tooltip";
|
|
19
23
|
import { useResolvedMarimoConfig } from "@/core/config/config";
|
|
20
24
|
import { useRequestClient } from "@/core/network/requests";
|
|
21
25
|
import { isWasm } from "@/core/wasm/utils";
|
|
@@ -99,117 +103,167 @@ export const RuntimeSettings: React.FC<RuntimeSettingsProps> = ({
|
|
|
99
103
|
</FooterItem>
|
|
100
104
|
</DropdownMenuTrigger>
|
|
101
105
|
<DropdownMenuContent align="start" className="w-64">
|
|
102
|
-
<DropdownMenuLabel>
|
|
106
|
+
<DropdownMenuLabel>
|
|
107
|
+
<div className="flex items-center justify-between w-full">
|
|
108
|
+
<span>Runtime reactivity</span>
|
|
109
|
+
<ExternalLink href="https://links.marimo.app/runtime-configuration">
|
|
110
|
+
<span className="text-xs font-normal flex items-center gap-1">
|
|
111
|
+
Docs
|
|
112
|
+
<ExternalLinkIcon className="w-3 h-3" />
|
|
113
|
+
</span>
|
|
114
|
+
</ExternalLink>
|
|
115
|
+
</div>
|
|
116
|
+
</DropdownMenuLabel>
|
|
103
117
|
<DropdownMenuSeparator />
|
|
104
118
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
<
|
|
108
|
-
<div className="flex items-center
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
<div
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
<TooltipProvider>
|
|
120
|
+
{/* On startup toggle */}
|
|
121
|
+
<DisableIfOverridden name="runtime.auto_instantiate">
|
|
122
|
+
<div className="flex items-center justify-between px-2 py-2">
|
|
123
|
+
<div className="flex items-center space-x-2">
|
|
124
|
+
{config.runtime.auto_instantiate ? (
|
|
125
|
+
<ZapIcon size={14} className="text-amber-500" />
|
|
126
|
+
) : (
|
|
127
|
+
<ZapOffIcon size={14} className="text-muted-foreground" />
|
|
128
|
+
)}
|
|
129
|
+
<div>
|
|
130
|
+
<div className="text-sm font-medium flex items-center gap-1">
|
|
131
|
+
On startup
|
|
132
|
+
<Tooltip
|
|
133
|
+
content={
|
|
134
|
+
<div className="max-w-[200px]">
|
|
135
|
+
Whether to automatically run the notebook on startup
|
|
136
|
+
</div>
|
|
137
|
+
}
|
|
138
|
+
>
|
|
139
|
+
<InfoIcon className="w-3 h-3" />
|
|
140
|
+
</Tooltip>
|
|
141
|
+
</div>
|
|
142
|
+
<div className="text-xs text-muted-foreground">
|
|
143
|
+
{config.runtime.auto_instantiate ? "autorun" : "lazy"}
|
|
144
|
+
</div>
|
|
118
145
|
</div>
|
|
119
146
|
</div>
|
|
147
|
+
<Switch
|
|
148
|
+
checked={config.runtime.auto_instantiate}
|
|
149
|
+
onCheckedChange={handleStartupToggle}
|
|
150
|
+
size="sm"
|
|
151
|
+
/>
|
|
120
152
|
</div>
|
|
121
|
-
|
|
122
|
-
checked={config.runtime.auto_instantiate}
|
|
123
|
-
onCheckedChange={handleStartupToggle}
|
|
124
|
-
size="sm"
|
|
125
|
-
/>
|
|
126
|
-
</div>
|
|
127
|
-
</DisableIfOverridden>
|
|
153
|
+
</DisableIfOverridden>
|
|
128
154
|
|
|
129
|
-
|
|
155
|
+
<DropdownMenuSeparator />
|
|
130
156
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
157
|
+
{/* On cell change toggle */}
|
|
158
|
+
<DisableIfOverridden name="runtime.on_cell_change">
|
|
159
|
+
<div className="flex items-center justify-between px-2 py-2">
|
|
160
|
+
<div className="flex items-center space-x-2">
|
|
161
|
+
{config.runtime.on_cell_change === "autorun" ? (
|
|
162
|
+
<ZapIcon size={14} className="text-amber-500" />
|
|
163
|
+
) : (
|
|
164
|
+
<ZapOffIcon size={14} className="text-muted-foreground" />
|
|
165
|
+
)}
|
|
166
|
+
<div>
|
|
167
|
+
<div className="text-sm font-medium flex items-center gap-1">
|
|
168
|
+
On cell change
|
|
169
|
+
<Tooltip
|
|
170
|
+
content={
|
|
171
|
+
<div className="max-w-[300px]">
|
|
172
|
+
Whether to automatically run dependent cells after
|
|
173
|
+
running a cell
|
|
174
|
+
</div>
|
|
175
|
+
}
|
|
176
|
+
>
|
|
177
|
+
<InfoIcon className="w-3 h-3" />
|
|
178
|
+
</Tooltip>
|
|
179
|
+
</div>
|
|
180
|
+
<div className="text-xs text-muted-foreground">
|
|
181
|
+
{config.runtime.on_cell_change}
|
|
182
|
+
</div>
|
|
144
183
|
</div>
|
|
145
184
|
</div>
|
|
185
|
+
<Switch
|
|
186
|
+
checked={config.runtime.on_cell_change === "autorun"}
|
|
187
|
+
onCheckedChange={handleCellChangeToggle}
|
|
188
|
+
size="sm"
|
|
189
|
+
/>
|
|
146
190
|
</div>
|
|
147
|
-
|
|
148
|
-
checked={config.runtime.on_cell_change === "autorun"}
|
|
149
|
-
onCheckedChange={handleCellChangeToggle}
|
|
150
|
-
size="sm"
|
|
151
|
-
/>
|
|
152
|
-
</div>
|
|
153
|
-
</DisableIfOverridden>
|
|
191
|
+
</DisableIfOverridden>
|
|
154
192
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
193
|
+
{!isWasm() && (
|
|
194
|
+
<>
|
|
195
|
+
<DropdownMenuSeparator />
|
|
158
196
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
197
|
+
{/* On module change dropdown */}
|
|
198
|
+
<DisableIfOverridden name="runtime.auto_reload">
|
|
199
|
+
<div className="px-2 py-1">
|
|
200
|
+
<div className="flex items-center space-x-2 mb-2">
|
|
201
|
+
{config.runtime.auto_reload === "off" && (
|
|
202
|
+
<PowerOffIcon
|
|
203
|
+
size={14}
|
|
204
|
+
className="text-muted-foreground"
|
|
205
|
+
/>
|
|
206
|
+
)}
|
|
207
|
+
{config.runtime.auto_reload === "lazy" && (
|
|
208
|
+
<ZapOffIcon size={14} className="text-muted-foreground" />
|
|
209
|
+
)}
|
|
210
|
+
{config.runtime.auto_reload === "autorun" && (
|
|
211
|
+
<ZapIcon size={14} className="text-amber-500" />
|
|
212
|
+
)}
|
|
213
|
+
<div>
|
|
214
|
+
<div className="text-sm font-medium flex items-center gap-1">
|
|
215
|
+
On module change
|
|
216
|
+
<Tooltip
|
|
217
|
+
content={
|
|
218
|
+
<div className="max-w-[300px]">
|
|
219
|
+
Whether to run affected cells, mark them as stale,
|
|
220
|
+
or do nothing when an external module is updated
|
|
221
|
+
</div>
|
|
222
|
+
}
|
|
223
|
+
>
|
|
224
|
+
<InfoIcon className="w-3 h-3" />
|
|
225
|
+
</Tooltip>
|
|
226
|
+
</div>
|
|
227
|
+
<div className="text-xs text-muted-foreground">
|
|
228
|
+
{config.runtime.auto_reload}
|
|
229
|
+
</div>
|
|
176
230
|
</div>
|
|
177
231
|
</div>
|
|
232
|
+
<div className="space-y-1">
|
|
233
|
+
{["off", "lazy", "autorun"].map((option) => (
|
|
234
|
+
<button
|
|
235
|
+
key={option}
|
|
236
|
+
onClick={() =>
|
|
237
|
+
handleModuleReloadChange(
|
|
238
|
+
option as "off" | "lazy" | "autorun",
|
|
239
|
+
)
|
|
240
|
+
}
|
|
241
|
+
className={cn(
|
|
242
|
+
"w-full flex items-center px-2 py-1 text-sm rounded hover:bg-accent",
|
|
243
|
+
option === config.runtime.auto_reload && "bg-accent",
|
|
244
|
+
)}
|
|
245
|
+
>
|
|
246
|
+
{option === "off" && (
|
|
247
|
+
<PowerOffIcon size={12} className="mr-2" />
|
|
248
|
+
)}
|
|
249
|
+
{option === "lazy" && (
|
|
250
|
+
<ZapOffIcon size={12} className="mr-2" />
|
|
251
|
+
)}
|
|
252
|
+
{option === "autorun" && (
|
|
253
|
+
<ZapIcon size={12} className="mr-2" />
|
|
254
|
+
)}
|
|
255
|
+
<span className="capitalize">{option}</span>
|
|
256
|
+
{option === config.runtime.auto_reload && (
|
|
257
|
+
<span className="ml-auto">✓</span>
|
|
258
|
+
)}
|
|
259
|
+
</button>
|
|
260
|
+
))}
|
|
261
|
+
</div>
|
|
178
262
|
</div>
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
onClick={() =>
|
|
184
|
-
handleModuleReloadChange(
|
|
185
|
-
option as "off" | "lazy" | "autorun",
|
|
186
|
-
)
|
|
187
|
-
}
|
|
188
|
-
className={cn(
|
|
189
|
-
"w-full flex items-center px-2 py-1 text-sm rounded hover:bg-accent",
|
|
190
|
-
option === config.runtime.auto_reload && "bg-accent",
|
|
191
|
-
)}
|
|
192
|
-
>
|
|
193
|
-
{option === "off" && (
|
|
194
|
-
<PowerOffIcon size={12} className="mr-2" />
|
|
195
|
-
)}
|
|
196
|
-
{option === "lazy" && (
|
|
197
|
-
<ZapOffIcon size={12} className="mr-2" />
|
|
198
|
-
)}
|
|
199
|
-
{option === "autorun" && (
|
|
200
|
-
<ZapIcon size={12} className="mr-2" />
|
|
201
|
-
)}
|
|
202
|
-
<span className="capitalize">{option}</span>
|
|
203
|
-
{option === config.runtime.auto_reload && (
|
|
204
|
-
<span className="ml-auto">✓</span>
|
|
205
|
-
)}
|
|
206
|
-
</button>
|
|
207
|
-
))}
|
|
208
|
-
</div>
|
|
209
|
-
</div>
|
|
210
|
-
</DisableIfOverridden>
|
|
211
|
-
</>
|
|
212
|
-
)}
|
|
263
|
+
</DisableIfOverridden>
|
|
264
|
+
</>
|
|
265
|
+
)}
|
|
266
|
+
</TooltipProvider>
|
|
213
267
|
</DropdownMenuContent>
|
|
214
268
|
</DropdownMenu>
|
|
215
269
|
);
|
package/src/components/editor/renderers/vertical-layout/__tests__/useFocusFirstEditor.test.ts
CHANGED
|
@@ -12,6 +12,8 @@ describe("useFocusFirstEditor", () => {
|
|
|
12
12
|
cb(0);
|
|
13
13
|
return 0;
|
|
14
14
|
});
|
|
15
|
+
// Mock document.hasFocus() to return true so focus logic runs
|
|
16
|
+
vi.spyOn(document, "hasFocus").mockReturnValue(true);
|
|
15
17
|
});
|
|
16
18
|
|
|
17
19
|
afterEach(() => {
|
|
@@ -120,4 +122,29 @@ describe("useFocusFirstEditor", () => {
|
|
|
120
122
|
writable: true,
|
|
121
123
|
});
|
|
122
124
|
});
|
|
125
|
+
|
|
126
|
+
it("should not focus when document does not have focus", () => {
|
|
127
|
+
// Mock document.hasFocus() to return false (e.g., when embedded in iframe)
|
|
128
|
+
vi.spyOn(document, "hasFocus").mockReturnValue(false);
|
|
129
|
+
|
|
130
|
+
const mockEditor = { focus: vi.fn() };
|
|
131
|
+
vi.spyOn(cellsModule, "getNotebook").mockReturnValue({
|
|
132
|
+
cellIds: { iterateTopLevelIds: ["cell-1"] },
|
|
133
|
+
cellData: {
|
|
134
|
+
"cell-1": { config: { hide_code: false } },
|
|
135
|
+
},
|
|
136
|
+
cellHandles: {
|
|
137
|
+
"cell-1": { current: { editorView: mockEditor } },
|
|
138
|
+
},
|
|
139
|
+
} as unknown as cellsModule.NotebookState);
|
|
140
|
+
|
|
141
|
+
renderHook(() => useFocusFirstEditor());
|
|
142
|
+
|
|
143
|
+
act(() => {
|
|
144
|
+
vi.advanceTimersByTime(100);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Focus should NOT be called when document doesn't have focus
|
|
148
|
+
expect(mockEditor.focus).not.toHaveBeenCalled();
|
|
149
|
+
});
|
|
123
150
|
});
|
|
@@ -19,6 +19,12 @@ export function useFocusFirstEditor() {
|
|
|
19
19
|
const timeout = setTimeout(() => {
|
|
20
20
|
// Let the DOM render
|
|
21
21
|
requestAnimationFrame(() => {
|
|
22
|
+
// Skip auto-focus if the document doesn't have focus to avoid
|
|
23
|
+
// stealing focus from outside (e.g., when embedded in an iframe)
|
|
24
|
+
if (!document.hasFocus()) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
// Check if the URL contains a scrollTo parameter
|
|
23
29
|
const hash = window.location.hash;
|
|
24
30
|
const cellName = extractCellNameFromHash(hash);
|