@marimo-team/islands 0.25.3-dev173 → 0.25.3-dev176
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/{ErrorBoundary-wT3f3iJ1.js → ErrorBoundary-D66f-xAE.js} +1 -1
- package/dist/{any-language-editor-B92WMzoC.js → any-language-editor-BVFHDDQ3.js} +2 -2
- package/dist/{chat-ui-CuORr6fL.js → chat-ui-X-cWrL9u.js} +1222 -1222
- package/dist/{code-visibility-ZReaeMaF.js → code-visibility-CVVeTAwi.js} +2 -2
- package/dist/{common-DCevHg1m.js → common-DNlm9Cdj.js} +1074 -1078
- package/dist/{data-grid-overlay-editor-CTC-bJus.js → data-grid-overlay-editor-BArE3_zi.js} +1 -1
- package/dist/{dist-F8Ep36rk.js → dist-B1M0bGO3.js} +1 -1
- package/dist/{dist-D6d86eNJ.js → dist-BA13RJj5.js} +1 -1
- package/dist/{dist-Bvs24R_E.js → dist-BJtmSgcE.js} +48 -48
- package/dist/{dist-CN_BeG2I.js → dist-Ba2VIn1K.js} +53 -53
- package/dist/{dist-PXYI_yuP.js → dist-Bj4bmwUm.js} +12 -12
- package/dist/{dist-DoE4XJBC.js → dist-BmS-ZGjl.js} +8626 -8626
- package/dist/{dist-BorMD-uX.js → dist-Bzogh7CW.js} +87 -87
- package/dist/{dist-CN8zI-XC.js → dist-CThPVKaP.js} +1385 -1382
- package/dist/{dist-DiDibOYr.js → dist-CTi5FTiV.js} +87 -87
- package/dist/{dist-diIx5qJW.js → dist-Ck_C32ye.js} +2 -2
- package/dist/{dist-BLfKmR-l.js → dist-D1fnFp1J.js} +1 -1
- package/dist/{dist-OR1OnN-y.js → dist-D3x9__Fu.js} +46 -46
- package/dist/{dist-BMQf5zIS.js → dist-D7mrh5sO.js} +36 -36
- package/dist/{dist-CSJ0MDRw.js → dist-D9Q3xjiP.js} +1 -1
- package/dist/{dist-BuaRHxOc.js → dist-DP60Ubh8.js} +2 -2
- package/dist/{dist-CSbh1PNP.js → dist-DTv9KkpW.js} +12 -12
- package/dist/{dist-D-wwqlzJ.js → dist-DVVwOfrD.js} +109 -109
- package/dist/{dist-C8fAKSH1.js → dist-DYXM73-k.js} +36 -36
- package/dist/{dist-DBtSl3sf.js → dist-DjeybPOb.js} +1 -1
- package/dist/{dist-CrSP_H1M.js → dist-DtGn9N4h.js} +197 -197
- package/dist/{dist-CLdpGQVr.js → dist-KN80qWCP.js} +2 -2
- package/dist/{dist-Cg7gzw-a.js → dist-O0qFpEJh.js} +56 -56
- package/dist/{dist-CkTTIdBe.js → dist-OUle2RT7.js} +207 -207
- package/dist/{dist-BK4Oj99o.js → dist-T5rh6JvL.js} +1 -1
- package/dist/{error-entries-CmWMEsY_.js → error-entries-mpoD5t79.js} +4939 -4983
- package/dist/{esm-D2gTsXEV.js → esm-Bbw_Njjx.js} +575 -575
- package/dist/{esm-AMFssoNp.js → esm-mDQNEFe_.js} +354 -354
- package/dist/{feedback-button-DwXkmewo.js → feedback-button-CyvqdxXN.js} +21 -21
- package/dist/{glide-data-editor-BlmcP-lw.js → glide-data-editor-BxvYRMC3.js} +3 -3
- package/dist/{globals-BdRitZ4p.js → globals-BJla9q8e.js} +1 -1
- package/dist/{html-to-image-bpiQh7ND.js → html-to-image-BoZthB4P.js} +454 -445
- package/dist/main.js +3587 -3587
- package/dist/{number-overlay-editor-DQG-hFHT.js → number-overlay-editor-BWg7xiRF.js} +1 -1
- package/dist/{process-output-BzloOI7F.js → process-output-DLS4Mqg_.js} +2 -2
- package/dist/{reveal-component-D3r3vSTK.js → reveal-component-feAltY24.js} +3 -3
- package/package.json +1 -1
- package/src/__mocks__/document.tsx +54 -0
- package/src/__mocks__/notebook.ts +2 -1
- package/src/__mocks__/requests.ts +0 -2
- package/src/components/chat/chat-panel.tsx +3 -3
- package/src/components/datasources/__tests__/column-preview.test.tsx +6 -8
- package/src/components/datasources/column-preview.tsx +4 -8
- package/src/components/datasources/datasources.tsx +4 -3
- package/src/components/dependency-graph/minimap-content.tsx +2 -6
- package/src/components/dependency-graph/panels.tsx +2 -1
- package/src/components/editor/__tests__/Output.test.tsx +50 -32
- package/src/components/editor/__tests__/data-attributes.test.tsx +22 -11
- package/src/components/editor/__tests__/output-persistence.test.tsx +6 -1
- package/src/components/editor/actions/__tests__/name-cell-input.test.tsx +69 -0
- package/src/components/editor/actions/name-cell-input.tsx +4 -3
- package/src/components/editor/actions/useCellActionButton.tsx +20 -26
- package/src/components/editor/actions/useNotebookActions.tsx +13 -18
- package/src/components/editor/actions/useSetCodeVisibility.ts +10 -11
- package/src/components/editor/actions/useSetOutputsExpanded.ts +13 -18
- package/src/components/editor/cell/CreateCellButton.tsx +5 -9
- package/src/components/editor/cell/__tests__/StagedAICell.test.tsx +3 -1
- package/src/components/editor/cell/code/cell-editor.tsx +13 -20
- package/src/components/editor/cell/useAddCell.ts +4 -8
- package/src/components/editor/cell/useDeleteCell.tsx +10 -36
- package/src/components/editor/cell/useRunCells.ts +2 -5
- package/src/components/editor/cell/useSplitCell.tsx +2 -1
- package/src/components/editor/chrome/panels/logs-panel.tsx +2 -1
- package/src/components/editor/chrome/panels/snippets-panel.tsx +5 -11
- package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +3 -1
- package/src/components/editor/columns/sortable-column.tsx +1 -1
- package/src/components/editor/connections/components.tsx +4 -9
- package/src/components/editor/controls/Controls.tsx +1 -1
- package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +9 -3
- package/src/components/editor/documentation.css +34 -11
- package/src/components/editor/errors/auto-fix.tsx +4 -8
- package/src/components/editor/file-tree/file-explorer.tsx +3 -7
- package/src/components/editor/links/__tests__/cell-link.test.tsx +3 -1
- package/src/components/editor/links/cell-link.tsx +2 -1
- package/src/components/editor/navigation/__tests__/clipboard.test.ts +60 -38
- package/src/components/editor/navigation/__tests__/navigation.test.ts +73 -64
- package/src/components/editor/navigation/clipboard.ts +12 -11
- package/src/components/editor/navigation/multi-cell-action-toolbar.tsx +11 -20
- package/src/components/editor/navigation/navigation.ts +20 -28
- package/src/components/editor/notebook-cell.tsx +7 -10
- package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +125 -69
- package/src/components/editor/renderers/cell-array.tsx +10 -17
- package/src/components/markdown/markdown-renderer.tsx +4 -8
- package/src/components/pages/edit-page.tsx +32 -17
- package/src/components/scratchpad/scratchpad.test.tsx +3 -1
- package/src/components/scratchpad/scratchpad.tsx +4 -7
- package/src/components/slides/__tests__/minimap-actions.test.tsx +9 -25
- package/src/components/slides/minimap.tsx +7 -3
- package/src/components/slides/slide-cell-view.tsx +3 -3
- package/src/components/sort/SortableCellsProvider.tsx +2 -1
- package/src/core/ai/__tests__/staged-cells.test.ts +18 -20
- package/src/core/ai/staged-cells.ts +8 -16
- package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +2 -2
- package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +2 -2
- package/src/core/ai/tools/base.ts +2 -2
- package/src/core/ai/tools/edit-notebook-tool.ts +13 -21
- package/src/core/cells/__tests__/actions.test.ts +474 -34
- package/src/core/cells/__tests__/add-missing-import.test.ts +7 -8
- package/src/core/cells/__tests__/cells.test.ts +171 -813
- package/src/core/cells/__tests__/document.test.ts +5 -35
- package/src/core/cells/__tests__/notebook-outline.test.ts +7 -1
- package/src/core/cells/__tests__/outputs.test.tsx +71 -53
- package/src/core/cells/actions.ts +391 -3
- package/src/core/cells/add-missing-import.ts +46 -42
- package/src/core/cells/cells.ts +38 -413
- package/src/core/cells/document.ts +7 -4
- package/src/core/cells/outputs.ts +12 -28
- package/src/core/codemirror/cells/extensions.ts +6 -6
- package/src/core/codemirror/cells/state.ts +1 -1
- package/src/core/codemirror/keymaps/vim.ts +2 -2
- package/src/core/edit-app.tsx +19 -27
- package/src/core/islands/bridge.ts +0 -2
- package/src/core/kernel/handlers.ts +3 -3
- package/src/core/network/__tests__/requests-lazy.test.ts +1 -3
- package/src/core/network/requests-lazy.ts +0 -2
- package/src/core/network/requests-network.ts +0 -16
- package/src/core/network/requests-static.ts +0 -2
- package/src/core/network/requests-toasting.tsx +0 -2
- package/src/core/network/types.ts +0 -7
- package/src/core/notebook/document/__tests__/codemirror.test.ts +5 -0
- package/src/core/notebook/document/__tests__/draft.test.ts +41 -0
- package/src/core/notebook/document/__tests__/state.test.ts +21 -0
- package/src/core/notebook/document/draft.ts +35 -5
- package/src/core/notebook/document/index.ts +1 -0
- package/src/core/notebook/document/state.ts +6 -2
- package/src/core/session/useNotebookSession.tsx +6 -2
- package/src/core/wasm/bridge.ts +0 -16
- package/src/css/globals.css +56 -22
- package/src/stories/runtime-story.tsx +22 -15
|
@@ -2,17 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
import { act, fireEvent, render, screen } from "@testing-library/react";
|
|
4
4
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { createStore, Provider } from "jotai";
|
|
5
6
|
import { SetupMocks } from "@/__mocks__/common";
|
|
7
|
+
import { mockDocumentModel } from "@/__mocks__/document";
|
|
6
8
|
import { cellId } from "@/__tests__/branded";
|
|
7
9
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
8
10
|
import type { WithResponse } from "@/core/cells/types";
|
|
11
|
+
import { DocumentProvider } from "@/core/notebook/document";
|
|
9
12
|
import type { OutputMessage } from "@/core/kernel/messages";
|
|
10
13
|
import { CONSOLE_CLEAR_DEBOUNCE_MS, ConsoleOutput } from "../ConsoleOutput";
|
|
11
14
|
|
|
12
15
|
SetupMocks.resizeObserver();
|
|
13
16
|
|
|
17
|
+
const store = createStore();
|
|
18
|
+
const { model } = mockDocumentModel(store, null);
|
|
19
|
+
|
|
14
20
|
const renderWithProvider = (ui: React.ReactElement) => {
|
|
15
|
-
return render(
|
|
21
|
+
return render(
|
|
22
|
+
<Provider store={store}>
|
|
23
|
+
<DocumentProvider model={model}>
|
|
24
|
+
<TooltipProvider>{ui}</TooltipProvider>
|
|
25
|
+
</DocumentProvider>
|
|
26
|
+
</Provider>,
|
|
27
|
+
);
|
|
16
28
|
};
|
|
17
29
|
|
|
18
30
|
describe("ConsoleOutput integration", () => {
|
|
@@ -104,13 +116,17 @@ describe("ConsoleOutput pdb history", () => {
|
|
|
104
116
|
];
|
|
105
117
|
|
|
106
118
|
rerender(
|
|
107
|
-
<
|
|
108
|
-
<
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
119
|
+
<Provider store={store}>
|
|
120
|
+
<DocumentProvider model={model}>
|
|
121
|
+
<TooltipProvider>
|
|
122
|
+
<ConsoleOutput
|
|
123
|
+
{...defaultProps}
|
|
124
|
+
consoleOutputs={outputs2}
|
|
125
|
+
onSubmitDebugger={onSubmitDebugger}
|
|
126
|
+
/>
|
|
127
|
+
</TooltipProvider>
|
|
128
|
+
</DocumentProvider>
|
|
129
|
+
</Provider>,
|
|
114
130
|
);
|
|
115
131
|
|
|
116
132
|
// New StdInput mounted — press ArrowUp to recall previous command
|
|
@@ -138,13 +154,17 @@ describe("ConsoleOutput pdb history", () => {
|
|
|
138
154
|
fireEvent.keyDown(nameInput, { key: "Enter" });
|
|
139
155
|
|
|
140
156
|
rerender(
|
|
141
|
-
<
|
|
142
|
-
<
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
157
|
+
<Provider store={store}>
|
|
158
|
+
<DocumentProvider model={model}>
|
|
159
|
+
<TooltipProvider>
|
|
160
|
+
<ConsoleOutput
|
|
161
|
+
{...defaultProps}
|
|
162
|
+
consoleOutputs={[stdinPrompt("Name: ", "marimo"), passwordPrompt]}
|
|
163
|
+
onSubmitDebugger={onSubmitDebugger}
|
|
164
|
+
/>
|
|
165
|
+
</TooltipProvider>
|
|
166
|
+
</DocumentProvider>
|
|
167
|
+
</Provider>,
|
|
148
168
|
);
|
|
149
169
|
const input = screen.getByTestId("console-input");
|
|
150
170
|
expect(input).toHaveAttribute("type", "password");
|
|
@@ -161,16 +181,20 @@ describe("ConsoleOutput pdb history", () => {
|
|
|
161
181
|
expect(input).toHaveValue("");
|
|
162
182
|
|
|
163
183
|
rerender(
|
|
164
|
-
<
|
|
165
|
-
<
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
184
|
+
<Provider store={store}>
|
|
185
|
+
<DocumentProvider model={model}>
|
|
186
|
+
<TooltipProvider>
|
|
187
|
+
<ConsoleOutput
|
|
188
|
+
{...defaultProps}
|
|
189
|
+
consoleOutputs={[
|
|
190
|
+
stdinPrompt("Name: ", "marimo"),
|
|
191
|
+
{ ...passwordPrompt, response: "" },
|
|
192
|
+
stdinPrompt("Name: "),
|
|
193
|
+
]}
|
|
194
|
+
/>
|
|
195
|
+
</TooltipProvider>
|
|
196
|
+
</DocumentProvider>
|
|
197
|
+
</Provider>,
|
|
174
198
|
);
|
|
175
199
|
const nextInput = screen.getByTestId("console-input");
|
|
176
200
|
fireEvent.keyDown(nextInput, { key: "ArrowUp" });
|
|
@@ -239,13 +263,17 @@ describe("ConsoleOutput pdb history", () => {
|
|
|
239
263
|
stdinPrompt("(Pdb) "),
|
|
240
264
|
];
|
|
241
265
|
rerender(
|
|
242
|
-
<
|
|
243
|
-
<
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
266
|
+
<Provider store={store}>
|
|
267
|
+
<DocumentProvider model={model}>
|
|
268
|
+
<TooltipProvider>
|
|
269
|
+
<ConsoleOutput
|
|
270
|
+
{...defaultProps}
|
|
271
|
+
consoleOutputs={outputs2}
|
|
272
|
+
onSubmitDebugger={onSubmitDebugger}
|
|
273
|
+
/>
|
|
274
|
+
</TooltipProvider>
|
|
275
|
+
</DocumentProvider>
|
|
276
|
+
</Provider>,
|
|
249
277
|
);
|
|
250
278
|
|
|
251
279
|
// Submit an empty value; this should NOT enter the history stack.
|
|
@@ -258,13 +286,17 @@ describe("ConsoleOutput pdb history", () => {
|
|
|
258
286
|
stdinPrompt("(Pdb) "),
|
|
259
287
|
];
|
|
260
288
|
rerender(
|
|
261
|
-
<
|
|
262
|
-
<
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
289
|
+
<Provider store={store}>
|
|
290
|
+
<DocumentProvider model={model}>
|
|
291
|
+
<TooltipProvider>
|
|
292
|
+
<ConsoleOutput
|
|
293
|
+
{...defaultProps}
|
|
294
|
+
consoleOutputs={outputs3}
|
|
295
|
+
onSubmitDebugger={onSubmitDebugger}
|
|
296
|
+
/>
|
|
297
|
+
</TooltipProvider>
|
|
298
|
+
</DocumentProvider>
|
|
299
|
+
</Provider>,
|
|
268
300
|
);
|
|
269
301
|
|
|
270
302
|
// ArrowUp should jump back to "step", skipping the empty submission.
|
|
@@ -299,13 +331,17 @@ describe("ConsoleOutput pdb history", () => {
|
|
|
299
331
|
];
|
|
300
332
|
|
|
301
333
|
rerender(
|
|
302
|
-
<
|
|
303
|
-
<
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
334
|
+
<Provider store={store}>
|
|
335
|
+
<DocumentProvider model={model}>
|
|
336
|
+
<TooltipProvider>
|
|
337
|
+
<ConsoleOutput
|
|
338
|
+
{...defaultProps}
|
|
339
|
+
consoleOutputs={outputs2}
|
|
340
|
+
onSubmitDebugger={onSubmitDebugger}
|
|
341
|
+
/>
|
|
342
|
+
</TooltipProvider>
|
|
343
|
+
</DocumentProvider>
|
|
344
|
+
</Provider>,
|
|
309
345
|
);
|
|
310
346
|
|
|
311
347
|
// Submit "print(x)"
|
|
@@ -321,13 +357,17 @@ describe("ConsoleOutput pdb history", () => {
|
|
|
321
357
|
];
|
|
322
358
|
|
|
323
359
|
rerender(
|
|
324
|
-
<
|
|
325
|
-
<
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
360
|
+
<Provider store={store}>
|
|
361
|
+
<DocumentProvider model={model}>
|
|
362
|
+
<TooltipProvider>
|
|
363
|
+
<ConsoleOutput
|
|
364
|
+
{...defaultProps}
|
|
365
|
+
consoleOutputs={outputs3}
|
|
366
|
+
onSubmitDebugger={onSubmitDebugger}
|
|
367
|
+
/>
|
|
368
|
+
</TooltipProvider>
|
|
369
|
+
</DocumentProvider>
|
|
370
|
+
</Provider>,
|
|
331
371
|
);
|
|
332
372
|
|
|
333
373
|
// ArrowUp should show most recent command first
|
|
@@ -370,13 +410,17 @@ describe("ConsoleOutput pdb history", () => {
|
|
|
370
410
|
// Same outputs, but the cell isn't interrupted -- this is a real
|
|
371
411
|
// bare-Enter submission, so we should render the (empty) placeholder.
|
|
372
412
|
rerender(
|
|
373
|
-
<
|
|
374
|
-
<
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
413
|
+
<Provider store={store}>
|
|
414
|
+
<DocumentProvider model={model}>
|
|
415
|
+
<TooltipProvider>
|
|
416
|
+
<ConsoleOutput
|
|
417
|
+
{...defaultProps}
|
|
418
|
+
consoleOutputs={interruptedOutputs}
|
|
419
|
+
interrupted={false}
|
|
420
|
+
/>
|
|
421
|
+
</TooltipProvider>
|
|
422
|
+
</DocumentProvider>
|
|
423
|
+
</Provider>,
|
|
380
424
|
);
|
|
381
425
|
|
|
382
426
|
expect(screen.getByLabelText("stdin response")).toBeInTheDocument();
|
|
@@ -426,9 +470,13 @@ describe("ConsoleOutput debounced clearing", () => {
|
|
|
426
470
|
|
|
427
471
|
// Clear outputs (simulates cell re-run)
|
|
428
472
|
rerender(
|
|
429
|
-
<
|
|
430
|
-
<
|
|
431
|
-
|
|
473
|
+
<Provider store={store}>
|
|
474
|
+
<DocumentProvider model={model}>
|
|
475
|
+
<TooltipProvider>
|
|
476
|
+
<ConsoleOutput {...defaultProps} consoleOutputs={[]} />
|
|
477
|
+
</TooltipProvider>
|
|
478
|
+
</DocumentProvider>
|
|
479
|
+
</Provider>,
|
|
432
480
|
);
|
|
433
481
|
|
|
434
482
|
// Old output should still be visible during debounce period
|
|
@@ -437,9 +485,13 @@ describe("ConsoleOutput debounced clearing", () => {
|
|
|
437
485
|
// New outputs arrive before debounce fires
|
|
438
486
|
const outputs2 = [createOutput("new output")];
|
|
439
487
|
rerender(
|
|
440
|
-
<
|
|
441
|
-
<
|
|
442
|
-
|
|
488
|
+
<Provider store={store}>
|
|
489
|
+
<DocumentProvider model={model}>
|
|
490
|
+
<TooltipProvider>
|
|
491
|
+
<ConsoleOutput {...defaultProps} consoleOutputs={outputs2} />
|
|
492
|
+
</TooltipProvider>
|
|
493
|
+
</DocumentProvider>
|
|
494
|
+
</Provider>,
|
|
443
495
|
);
|
|
444
496
|
|
|
445
497
|
// New output should be shown immediately
|
|
@@ -458,9 +510,13 @@ describe("ConsoleOutput debounced clearing", () => {
|
|
|
458
510
|
|
|
459
511
|
// Clear outputs
|
|
460
512
|
rerender(
|
|
461
|
-
<
|
|
462
|
-
<
|
|
463
|
-
|
|
513
|
+
<Provider store={store}>
|
|
514
|
+
<DocumentProvider model={model}>
|
|
515
|
+
<TooltipProvider>
|
|
516
|
+
<ConsoleOutput {...defaultProps} consoleOutputs={[]} />
|
|
517
|
+
</TooltipProvider>
|
|
518
|
+
</DocumentProvider>
|
|
519
|
+
</Provider>,
|
|
464
520
|
);
|
|
465
521
|
|
|
466
522
|
// Still visible during debounce
|
|
@@ -33,10 +33,10 @@ import type { CellColumnId } from "@/utils/id-tree";
|
|
|
33
33
|
import { invariant } from "@/utils/invariant";
|
|
34
34
|
import {
|
|
35
35
|
columnIdsAtom,
|
|
36
|
-
useCellActions,
|
|
37
36
|
useCellIds,
|
|
38
37
|
useScrollKey,
|
|
39
38
|
} from "../../../core/cells/cells";
|
|
39
|
+
import { useCellActions } from "../../../core/cells/actions";
|
|
40
40
|
import { formatAll } from "../../../core/codemirror/format";
|
|
41
41
|
import type { AppConfig, UserConfig } from "../../../core/config/config-schema";
|
|
42
42
|
import type { AppMode } from "../../../core/mode";
|
|
@@ -267,7 +267,7 @@ const AddCellButtons: React.FC<{
|
|
|
267
267
|
columnId: CellColumnId;
|
|
268
268
|
className?: string;
|
|
269
269
|
}> = ({ columnId, className }) => {
|
|
270
|
-
const {
|
|
270
|
+
const { createCell } = useCellActions();
|
|
271
271
|
const [isAiButtonOpen, isAiButtonOpenActions] = useBoolean(false);
|
|
272
272
|
const aiEnabled = useAtomValue(aiEnabledAtom);
|
|
273
273
|
const aiFeaturesEnabled = useAtomValue(aiFeaturesEnabledAtom);
|
|
@@ -291,12 +291,7 @@ const AddCellButtons: React.FC<{
|
|
|
291
291
|
variant="text"
|
|
292
292
|
size="sm"
|
|
293
293
|
disabled={!canInteractWithApp}
|
|
294
|
-
onClick={() =>
|
|
295
|
-
createNewCell({
|
|
296
|
-
cellId: { type: "__end__", columnId },
|
|
297
|
-
before: false,
|
|
298
|
-
})
|
|
299
|
-
}
|
|
294
|
+
onClick={() => createCell({ endOf: columnId })}
|
|
300
295
|
>
|
|
301
296
|
<SquareCodeIcon className="mr-2 size-4 shrink-0" />
|
|
302
297
|
Python
|
|
@@ -307,13 +302,12 @@ const AddCellButtons: React.FC<{
|
|
|
307
302
|
size="sm"
|
|
308
303
|
disabled={!canInteractWithApp}
|
|
309
304
|
onClick={() => {
|
|
310
|
-
maybeAddMarimoImport({ autoInstantiate: true,
|
|
305
|
+
maybeAddMarimoImport({ autoInstantiate: true, createCell });
|
|
311
306
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
before: false,
|
|
307
|
+
createCell({
|
|
308
|
+
endOf: columnId,
|
|
315
309
|
code: LanguageAdapters.markdown.defaultCode,
|
|
316
|
-
|
|
310
|
+
config: { hide_code: MARKDOWN_INITIAL_HIDE_CODE },
|
|
317
311
|
});
|
|
318
312
|
}}
|
|
319
313
|
>
|
|
@@ -326,11 +320,10 @@ const AddCellButtons: React.FC<{
|
|
|
326
320
|
size="sm"
|
|
327
321
|
disabled={!canInteractWithApp}
|
|
328
322
|
onClick={() => {
|
|
329
|
-
maybeAddMarimoImport({ autoInstantiate: true,
|
|
323
|
+
maybeAddMarimoImport({ autoInstantiate: true, createCell });
|
|
330
324
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
before: false,
|
|
325
|
+
createCell({
|
|
326
|
+
endOf: columnId,
|
|
334
327
|
code: LanguageAdapters.sql.defaultCode,
|
|
335
328
|
});
|
|
336
329
|
}}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "streamdown";
|
|
13
13
|
import { Button, type ButtonProps } from "@/components/ui/button";
|
|
14
14
|
import { maybeAddMarimoImport } from "@/core/cells/add-missing-import";
|
|
15
|
-
import { useCellActions } from "@/core/cells/
|
|
15
|
+
import { useCellActions } from "@/core/cells/actions";
|
|
16
16
|
import { useLastFocusedCellId } from "@/core/cells/focus";
|
|
17
17
|
import { MarkdownLanguageAdapter } from "@/core/codemirror/language/languages/markdown";
|
|
18
18
|
import { SQLLanguageAdapter } from "@/core/codemirror/language/languages/sql/sql";
|
|
@@ -71,7 +71,7 @@ function maybeTransform(
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
const InsertCodeBlockButton = ({ code, language }: CodeBlockProps) => {
|
|
74
|
-
const {
|
|
74
|
+
const { createCell } = useCellActions();
|
|
75
75
|
const lastFocusedCellId = useLastFocusedCellId();
|
|
76
76
|
const autoInstantiate = useAtomValue(autoInstantiateAtom);
|
|
77
77
|
|
|
@@ -81,15 +81,11 @@ const InsertCodeBlockButton = ({ code, language }: CodeBlockProps) => {
|
|
|
81
81
|
if (language === "sql") {
|
|
82
82
|
maybeAddMarimoImport({
|
|
83
83
|
autoInstantiate,
|
|
84
|
-
|
|
84
|
+
createCell,
|
|
85
85
|
fromCellId: lastFocusedCellId,
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
code: result.code,
|
|
90
|
-
before: false,
|
|
91
|
-
cellId: lastFocusedCellId ?? "__end__",
|
|
92
|
-
});
|
|
88
|
+
createCell({ after: lastFocusedCellId, code: result.code });
|
|
93
89
|
};
|
|
94
90
|
|
|
95
91
|
return (
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useSetAtom, useStore } from "jotai";
|
|
4
|
+
import { notebookAtom } from "@/core/cells/cells";
|
|
5
|
+
import { notebookCells } from "@/core/cells/utils";
|
|
4
6
|
import type { AppConfig, UserConfig } from "@/core/config/config-schema";
|
|
5
7
|
import { KnownQueryParams } from "@/core/constants";
|
|
6
8
|
import { EditApp } from "@/core/edit-app";
|
|
9
|
+
import { getSessionId } from "@/core/kernel/session";
|
|
10
|
+
import { DocumentProvider } from "@/core/notebook/document";
|
|
11
|
+
import { lastSavedNotebookAtom } from "@/core/saving/state";
|
|
12
|
+
import { useNotebookSession } from "@/core/session/useNotebookSession";
|
|
7
13
|
import { AppChrome } from "../editor/chrome/wrapper/app-chrome";
|
|
8
14
|
|
|
9
|
-
const LazyCommandPalette = lazy(
|
|
10
|
-
() => import("../editor/controls/command-palette"),
|
|
11
|
-
);
|
|
12
|
-
|
|
13
15
|
interface Props {
|
|
14
16
|
userConfig: UserConfig;
|
|
15
17
|
appConfig: AppConfig;
|
|
@@ -20,21 +22,34 @@ const hideChrome = (() => {
|
|
|
20
22
|
return url.searchParams.get(KnownQueryParams.showChrome) === "false";
|
|
21
23
|
})();
|
|
22
24
|
|
|
25
|
+
/** Own the notebook session and provide its document model to the editor and its chrome. */
|
|
23
26
|
const EditPage = (props: Props) => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
const store = useStore();
|
|
28
|
+
const setLastSavedNotebook = useSetAtom(lastSavedNotebookAtom);
|
|
29
|
+
const { connection, reconnect, documentModel } = useNotebookSession({
|
|
30
|
+
autoInstantiate: props.userConfig.runtime.auto_instantiate,
|
|
31
|
+
onKernelReady: (layout) => {
|
|
32
|
+
const cells = notebookCells(store.get(notebookAtom));
|
|
33
|
+
const names = cells.map((cell) => cell.name);
|
|
34
|
+
const codes = cells.map((cell) => cell.code);
|
|
35
|
+
const configs = cells.map((cell) => cell.config);
|
|
36
|
+
setLastSavedNotebook({ names, codes, configs, layout });
|
|
37
|
+
},
|
|
38
|
+
sessionId: getSessionId(),
|
|
39
|
+
});
|
|
40
|
+
const app = (
|
|
41
|
+
<EditApp
|
|
42
|
+
{...props}
|
|
43
|
+
hideControls={hideChrome}
|
|
44
|
+
connection={connection}
|
|
45
|
+
reconnect={reconnect}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
32
48
|
|
|
33
49
|
return (
|
|
34
|
-
<
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
</AppChrome>
|
|
50
|
+
<DocumentProvider model={documentModel}>
|
|
51
|
+
{hideChrome ? app : <AppChrome>{app}</AppChrome>}
|
|
52
|
+
</DocumentProvider>
|
|
38
53
|
);
|
|
39
54
|
};
|
|
40
55
|
|
|
@@ -21,8 +21,10 @@ const state = vi.hoisted(() => ({
|
|
|
21
21
|
|
|
22
22
|
vi.mock("@/core/cells/cells", () => ({
|
|
23
23
|
useNotebook: () => ({ cellRuntime: {}, cellData: {} }),
|
|
24
|
+
}));
|
|
25
|
+
vi.mock("@/core/cells/actions", () => ({
|
|
24
26
|
useCellActions: () => ({
|
|
25
|
-
|
|
27
|
+
createCell: vi.fn(),
|
|
26
28
|
updateCellCode: state.updateCellCode,
|
|
27
29
|
}),
|
|
28
30
|
}));
|
|
@@ -13,7 +13,8 @@ import type React from "react";
|
|
|
13
13
|
import { Suspense, useRef, useState } from "react";
|
|
14
14
|
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
|
|
15
15
|
import useEvent from "react-use-event-hook";
|
|
16
|
-
import {
|
|
16
|
+
import { useNotebook } from "@/core/cells/cells";
|
|
17
|
+
import { useCellActions } from "@/core/cells/actions";
|
|
17
18
|
import { useLastFocusedCellId } from "@/core/cells/focus";
|
|
18
19
|
import { HTMLCellId, SCRATCH_CELL_ID } from "@/core/cells/ids";
|
|
19
20
|
import { DEFAULT_CELL_NAME } from "@/core/cells/names";
|
|
@@ -55,7 +56,7 @@ export const ScratchPad: React.FC = () => {
|
|
|
55
56
|
const { theme } = useTheme();
|
|
56
57
|
const ref = useRef<EditorView | null>(null);
|
|
57
58
|
const lastFocusedCellId = useLastFocusedCellId();
|
|
58
|
-
const {
|
|
59
|
+
const { updateCellCode, createCell } = useCellActions();
|
|
59
60
|
const { sendRunScratchpad } = useRequestClient();
|
|
60
61
|
const orientation = usePanelOrientation();
|
|
61
62
|
const section = usePanelSection();
|
|
@@ -81,11 +82,7 @@ export const ScratchPad: React.FC = () => {
|
|
|
81
82
|
if (!code.trim()) {
|
|
82
83
|
return;
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
-
code,
|
|
86
|
-
before: false,
|
|
87
|
-
cellId: lastFocusedCellId ?? "__end__",
|
|
88
|
-
});
|
|
85
|
+
createCell({ after: lastFocusedCellId, code });
|
|
89
86
|
});
|
|
90
87
|
|
|
91
88
|
const handleClearCode = useEvent(() => {
|
|
@@ -13,17 +13,19 @@ const A = cellId("a");
|
|
|
13
13
|
const B = cellId("b");
|
|
14
14
|
|
|
15
15
|
// Spies shared with the hoisted module mocks below.
|
|
16
|
-
const {
|
|
17
|
-
|
|
16
|
+
const { createCell, deleteCell, moveCellToIndex } = vi.hoisted(() => ({
|
|
17
|
+
createCell: vi.fn(),
|
|
18
18
|
deleteCell: vi.fn(),
|
|
19
19
|
moveCellToIndex: vi.fn(),
|
|
20
20
|
}));
|
|
21
21
|
|
|
22
|
+
vi.mock("@/core/cells/actions", () => ({
|
|
23
|
+
useCellActions: () => ({ moveCellToIndex, createCell }),
|
|
24
|
+
}));
|
|
22
25
|
vi.mock("@/core/cells/cells", async (importOriginal) => {
|
|
23
26
|
const actual = await importOriginal<typeof import("@/core/cells/cells")>();
|
|
24
27
|
return {
|
|
25
28
|
...actual,
|
|
26
|
-
useCellActions: () => ({ moveCellToIndex, createNewCell }),
|
|
27
29
|
useCellIds: () => MultiColumn.from([[A, B]]),
|
|
28
30
|
};
|
|
29
31
|
});
|
|
@@ -91,8 +93,6 @@ function renderMinimap() {
|
|
|
91
93
|
return { ...utils, onSlideClick };
|
|
92
94
|
}
|
|
93
95
|
|
|
94
|
-
const EMPTY_CELL = { code: "", autoFocus: false } as const;
|
|
95
|
-
|
|
96
96
|
describe("SlidesMinimap insert lines", () => {
|
|
97
97
|
it("inserts a blank cell above the first row and below any row", () => {
|
|
98
98
|
renderMinimap();
|
|
@@ -102,25 +102,13 @@ describe("SlidesMinimap insert lines", () => {
|
|
|
102
102
|
expect(inserts).toHaveLength(3);
|
|
103
103
|
|
|
104
104
|
fireEvent.click(inserts[0]);
|
|
105
|
-
expect(
|
|
106
|
-
cellId: A,
|
|
107
|
-
before: true,
|
|
108
|
-
...EMPTY_CELL,
|
|
109
|
-
});
|
|
105
|
+
expect(createCell).toHaveBeenLastCalledWith({ before: A, focus: false });
|
|
110
106
|
|
|
111
107
|
fireEvent.click(inserts[1]);
|
|
112
|
-
expect(
|
|
113
|
-
cellId: A,
|
|
114
|
-
before: false,
|
|
115
|
-
...EMPTY_CELL,
|
|
116
|
-
});
|
|
108
|
+
expect(createCell).toHaveBeenLastCalledWith({ after: A, focus: false });
|
|
117
109
|
|
|
118
110
|
fireEvent.click(inserts[2]);
|
|
119
|
-
expect(
|
|
120
|
-
cellId: B,
|
|
121
|
-
before: false,
|
|
122
|
-
...EMPTY_CELL,
|
|
123
|
-
});
|
|
111
|
+
expect(createCell).toHaveBeenLastCalledWith({ after: B, focus: false });
|
|
124
112
|
});
|
|
125
113
|
});
|
|
126
114
|
|
|
@@ -135,11 +123,7 @@ describe("SlidesMinimap context menu", () => {
|
|
|
135
123
|
const { container } = renderMinimap();
|
|
136
124
|
openRowMenu(container, A);
|
|
137
125
|
fireEvent.click(screen.getByText("Add cell"));
|
|
138
|
-
expect(
|
|
139
|
-
cellId: A,
|
|
140
|
-
before: false,
|
|
141
|
-
...EMPTY_CELL,
|
|
142
|
-
});
|
|
126
|
+
expect(createCell).toHaveBeenCalledWith({ after: A, focus: false });
|
|
143
127
|
});
|
|
144
128
|
|
|
145
129
|
it('"Delete cell" deletes the row\'s cell', () => {
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { useDeleteCellCallback } from "@/components/editor/cell/useDeleteCell";
|
|
4
4
|
import { outputIsStale } from "@/core/cells/cell";
|
|
5
|
-
import {
|
|
5
|
+
import { useCellIds } from "@/core/cells/cells";
|
|
6
|
+
import { useCellActions } from "@/core/cells/actions";
|
|
6
7
|
import type { CellId } from "@/core/cells/ids";
|
|
7
8
|
import type { CellColumnId } from "@/utils/id-tree";
|
|
8
9
|
import { useEffect, useRef, useState } from "react";
|
|
@@ -229,7 +230,7 @@ export const SlidesMinimap = ({
|
|
|
229
230
|
onSlideClick,
|
|
230
231
|
}: SlidesMinimapProps) => {
|
|
231
232
|
const cellIds = useCellIds();
|
|
232
|
-
const { moveCellToIndex,
|
|
233
|
+
const { moveCellToIndex, createCell } = useCellActions();
|
|
233
234
|
const deleteCell = useDeleteCellCallback();
|
|
234
235
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
235
236
|
const visibleIds = useVisibleCellIds(containerRef);
|
|
@@ -240,7 +241,10 @@ export const SlidesMinimap = ({
|
|
|
240
241
|
const dimensions = computeThumbnailDimensions(thumbnailWidth);
|
|
241
242
|
|
|
242
243
|
const insertCell = (cellId: CellId, before: boolean) => {
|
|
243
|
-
|
|
244
|
+
createCell({
|
|
245
|
+
...(before ? { before: cellId } : { after: cellId }),
|
|
246
|
+
focus: false,
|
|
247
|
+
});
|
|
244
248
|
};
|
|
245
249
|
|
|
246
250
|
useEffect(() => {
|
|
@@ -14,7 +14,7 @@ import { useRunCell } from "@/components/editor/cell/useRunCells";
|
|
|
14
14
|
import { Slide as CellOutputSlide } from "@/components/slides/slide";
|
|
15
15
|
import { maybeAddMarimoImport } from "@/core/cells/add-missing-import";
|
|
16
16
|
import { outputIsStale } from "@/core/cells/cell";
|
|
17
|
-
import { useCellActions } from "@/core/cells/
|
|
17
|
+
import { useCellActions } from "@/core/cells/actions";
|
|
18
18
|
import { autoInstantiateAtom, useUserConfig } from "@/core/config/config";
|
|
19
19
|
import {
|
|
20
20
|
cellNeedsRun,
|
|
@@ -42,7 +42,7 @@ export const SlideCellView = ({ cell }: { cell: RuntimeCell }) => {
|
|
|
42
42
|
const { theme } = useTheme();
|
|
43
43
|
const runCell = useRunCell(cell.id);
|
|
44
44
|
const connection = useAtomValue(connectionAtom);
|
|
45
|
-
const
|
|
45
|
+
const { createCell } = useCellActions();
|
|
46
46
|
const autoInstantiate = useAtomValue(autoInstantiateAtom);
|
|
47
47
|
const editorViewRef = useRef<EditorView | null>(null);
|
|
48
48
|
const editorViewParentRef = useRef<HTMLDivElement | null>(null);
|
|
@@ -53,7 +53,7 @@ export const SlideCellView = ({ cell }: { cell: RuntimeCell }) => {
|
|
|
53
53
|
const afterToggleLanguage = useEvent(() => {
|
|
54
54
|
maybeAddMarimoImport({
|
|
55
55
|
autoInstantiate,
|
|
56
|
-
|
|
56
|
+
createCell,
|
|
57
57
|
});
|
|
58
58
|
});
|
|
59
59
|
|
|
@@ -24,7 +24,8 @@ import { useAppConfig } from "@/core/config/config";
|
|
|
24
24
|
import { Arrays } from "@/utils/arrays";
|
|
25
25
|
import type { CellColumnId, MultiColumn } from "@/utils/id-tree";
|
|
26
26
|
import { invariant } from "@/utils/invariant";
|
|
27
|
-
import { getNotebook
|
|
27
|
+
import { getNotebook } from "../../core/cells/cells";
|
|
28
|
+
import { useCellActions } from "../../core/cells/actions";
|
|
28
29
|
import { useEvent } from "../../hooks/useEvent";
|
|
29
30
|
|
|
30
31
|
interface SortableCellsProviderProps {
|