@marimo-team/islands 0.25.3-dev192 → 0.25.3-dev196
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/{ConnectedDataExplorerComponent-BBbOElk3.js → ConnectedDataExplorerComponent-BRuwLOIx.js} +9 -9
- package/dist/{ErrorBoundary-Dw6uRKVk.js → ErrorBoundary-C3Xv3yzV.js} +2 -2
- package/dist/{abnfDiagram-VCTEODGH-DhMT6Uhd.js → abnfDiagram-VCTEODGH-LlJTOOU_.js} +2 -2
- package/dist/{architectureDiagram-5GKGNRK7-BVbEiJLq.js → architectureDiagram-5GKGNRK7-9PQtGLLZ.js} +1 -1
- package/dist/{arrays-R6JsImiT.js → arrays-DA6KkLfq.js} +6 -12
- package/dist/assets/__vite-browser-external-BCJsx8QS.js +1 -0
- package/dist/assets/{worker-C6e9ERyd.js → worker-DodjWT_Z.js} +2 -2
- package/dist/{capabilities-CI4xUPsp.js → capabilities-CvWU-ey_.js} +1 -1
- package/dist/{chat-ui-BguxTQEL.js → chat-ui-Bl2euMBD.js} +93 -93
- package/dist/{chunk-IMKFNOWR-By5hSbJJ.js → chunk-IMKFNOWR-DcXv-BD5.js} +1 -1
- package/dist/{chunk-SHT3W25Y-DFrEYG54.js → chunk-SHT3W25Y-VwnELN23.js} +1 -1
- package/dist/{chunk-SVP7TREG-DFXGc9ew.js → chunk-SVP7TREG-DgQpI5Zi.js} +1 -1
- package/dist/{chunk-TICWLB2K-DZdNIpoZ.js → chunk-TICWLB2K-CTg6VTJT.js} +1 -1
- package/dist/{classDiagram-ZZMXUADV-Cgj_eEQA.js → classDiagram-ZZMXUADV-UzmcFrnW.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-DLAUrSqj.js → classDiagram-v2-VYDZK3BY-DhjiI6IQ.js} +2 -2
- package/dist/{code-visibility-v_7ijLtx.js → code-visibility-BCcqmP58.js} +38 -42
- package/dist/{common-BUwWHpnK.js → common-DrNB2bY2.js} +849 -849
- package/dist/{cynefinDiagram-5FMLGOSQ-Cikf9AKa.js → cynefinDiagram-5FMLGOSQ-O4ShIbJX.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-C5KEi5_l.js → dagre-GXQ25YYZ-dtHhhcPu.js} +1 -1
- package/dist/{data-grid-overlay-editor-4IZymnXZ.js → data-grid-overlay-editor-TGXV_Hf4.js} +1 -1
- package/dist/{diagram-S7CK7UJ4-BaoBTQjR.js → diagram-S7CK7UJ4-ppPYVZ6W.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-DDufBsUA.js → diagram-UQ7AKVKN-CMZDf--k.js} +1 -1
- package/dist/{diagram-VX7I27RA-CY6RALJ8.js → diagram-VX7I27RA-CFvJdx-C.js} +1 -1
- package/dist/{diagram-Z3DM3KII-Bc-LHsD6.js → diagram-Z3DM3KII-Dt6_uFbv.js} +1 -1
- package/dist/{dropdown-menu-drDjxJyV.js → dropdown-menu-CeaOsjWZ.js} +2 -2
- package/dist/{ebnfDiagram-PWID7BFC-Cz0J-tcC.js → ebnfDiagram-PWID7BFC-DpRFrKK-.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-DTXTDgFu.js → erDiagram-RLTQ6QDP-CqAU4b0u.js} +1 -1
- package/dist/{error-entries-CZ1NQ6Kv.js → error-entries-CYGwr5-O.js} +5596 -6012
- package/dist/feedback-button-PTiPn2GP.js +374 -0
- package/dist/{flowDiagram-HODETNUW-RbwWf2zc.js → flowDiagram-HODETNUW-i8-Gw8HO.js} +2 -2
- package/dist/{formats-DbXnijtH.js → formats-BtoHHy42.js} +1 -1
- package/dist/{glide-data-editor-DU8_EDG5.js → glide-data-editor-BSyexjkB.js} +5 -5
- package/dist/{globals-BeBDOk22.js → globals-B7gkJAxm.js} +2 -2
- package/dist/{html-to-image-D_4_hQ8U.js → html-to-image-Cy5UDpQJ.js} +56 -56
- package/dist/{infoDiagram-27XIBGKW-DlmzZjmI.js → infoDiagram-27XIBGKW-DpfOKdLL.js} +1 -1
- package/dist/{ishikawaDiagram-5VMMS53U-EN3TYP_q.js → ishikawaDiagram-5VMMS53U-Dg7mrMG7.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-CK_-Ru7Q.js → kanban-definition-UXKFOSKX-QB6e3Jrj.js} +1 -1
- package/dist/main.js +5875 -5876
- package/dist/{mermaid-DU9ZRmkG.js → mermaid-CeWG4Egr.js} +48 -48
- package/dist/{mindmap-definition-YA3MSWOX-C-hqgUvF.js → mindmap-definition-YA3MSWOX-BTz3uTGe.js} +1 -1
- package/dist/{number-overlay-editor-BoIkyh6H.js → number-overlay-editor-Bb91yQ46.js} +1 -1
- package/dist/{once-eG8Vmvjd.js → once-DWGO2mQ2.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-BiMejYPB.js → pegDiagram-XKGWAZYB-3ZIEa3mB.js} +2 -2
- package/dist/{pieDiagram-E7YTZNPT-B1zCZ1eq.js → pieDiagram-E7YTZNPT-BJAlk046.js} +1 -1
- package/dist/{process-output-DxSCHBWp.js → process-output-q9MTAIMX.js} +2 -2
- package/dist/{railroadDiagram-O6MQD6OU-BLcfaASl.js → railroadDiagram-O6MQD6OU-Dn3bsSRa.js} +2 -2
- package/dist/{requirementDiagram-BXWQKSXE-DtBOf52-.js → requirementDiagram-BXWQKSXE-wcOmQQCL.js} +1 -1
- package/dist/{reveal-component-5M3a2rpj.js → reveal-component-vTdjiyDv.js} +17 -17
- package/dist/{sequenceDiagram-WJ2MYXX4-DIwF19_n.js → sequenceDiagram-WJ2MYXX4-DSh_qxoF.js} +1 -1
- package/dist/{spec-DZDnnlgT.js → spec-C7Fos-If.js} +1 -1
- package/dist/{stateDiagram-D77RDMKH-sWk1AdYL.js → stateDiagram-D77RDMKH-DH_H8NMH.js} +2 -2
- package/dist/{stateDiagram-v2-MP3YSRHH-CiNo-OI7.js → stateDiagram-v2-MP3YSRHH-D_JM7MEK.js} +2 -2
- package/dist/style.css +1 -1
- package/dist/{swimlanes-42K2YHIH-Bj3hiOY5.js → swimlanes-42K2YHIH-CfoTJO-9.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-BzEo2r_N.js → swimlanesDiagram-VR7AAH4N-Z_QhvK0G.js} +2 -2
- package/dist/{swiper-component-BkCm-kLg.js → swiper-component-D2geL1Ku.js} +1 -1
- package/dist/{timeline-definition-24CTP7MA-CrPQk42H.js → timeline-definition-24CTP7MA-BFtdScaL.js} +1 -1
- package/dist/{toDate-Cu2pIZcC.js → toDate-CQAFSwos.js} +24 -24
- package/dist/{useAsyncData-DEhLdRIu.js → useAsyncData-BeyZyjso.js} +1 -1
- package/dist/{useDeepCompareMemoize-RjZGVhBV.js → useDeepCompareMemoize-DOQgae0W.js} +1 -1
- package/dist/{useIframeCapabilities-CSdWn6NP.js → useIframeCapabilities-DNvaj9wM.js} +1 -1
- package/dist/{useLifecycle-DtcB2s1z.js → useLifecycle-n2lnCFS8.js} +1 -1
- package/dist/{useTheme-CoEtr4mK.js → useTheme-CY777LXN.js} +303 -99
- package/dist/{vega-component-BhjTrP9-.js → vega-component-0nQzA-I8.js} +6 -6
- package/dist/{vennDiagram-4TSXK5OY-BaYMoIpj.js → vennDiagram-4TSXK5OY-BXY8IGCA.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-DjHeuj8p.js → wardleyDiagram-VM6X3IG4-D0tFe6eC.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-Bc_hcuXS.js → xychartDiagram-S5SC5T6Z-Dx8wFM-y.js} +1 -1
- package/package.json +1 -1
- package/src/__mocks__/notebook.ts +0 -1
- package/src/__mocks__/partial.ts +26 -0
- package/src/__tests__/main.test.tsx +24 -1
- package/src/components/app-config/app-config-form.tsx +5 -9
- package/src/components/editor/__tests__/data-attributes.test.tsx +0 -1
- package/src/components/editor/__tests__/output-persistence.test.tsx +0 -1
- package/src/components/editor/actions/useCellActionButton.tsx +6 -5
- package/src/components/editor/actions/useConfigActions.tsx +3 -4
- package/src/components/editor/actions/useNotebookActions.tsx +5 -4
- package/src/components/editor/cell/code/cell-editor.tsx +13 -6
- package/src/components/editor/cell/collapse.tsx +6 -1
- package/src/components/editor/chrome/components/feedback-button.tsx +1 -7
- package/src/components/editor/controls/Controls.tsx +1 -1
- package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +8 -6
- package/src/components/editor/navigation/__tests__/navigation.test.ts +15 -15
- package/src/components/editor/navigation/__tests__/selection.test.ts +44 -21
- package/src/components/editor/navigation/focus-utils.ts +19 -0
- package/src/components/editor/navigation/multi-cell-action-toolbar.tsx +6 -13
- package/src/components/editor/navigation/navigation.ts +52 -43
- package/src/components/editor/navigation/selection.ts +30 -29
- package/src/components/editor/notebook-cell.tsx +10 -18
- package/src/components/editor/renderers/cell-array.tsx +6 -5
- package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +1 -1
- package/src/components/pages/edit-page.tsx +0 -13
- package/src/components/scratchpad/scratchpad.tsx +0 -1
- package/src/components/slides/reveal-component.tsx +1 -1
- package/src/components/slides/slide-cell-view.tsx +0 -1
- package/src/components/sort/SortableCellsProvider.tsx +6 -5
- package/src/core/MarimoApp.tsx +1 -1
- package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +0 -37
- package/src/core/cells/__tests__/actions.test.ts +190 -80
- package/src/core/cells/__tests__/arrange.test.ts +263 -0
- package/src/core/cells/__tests__/cells.test.ts +11 -1101
- package/src/core/cells/__tests__/document.test.ts +3 -32
- package/src/core/cells/__tests__/editor.test.ts +57 -0
- package/src/core/cells/__tests__/harness.ts +82 -0
- package/src/core/cells/__tests__/layout.test.ts +189 -0
- package/src/core/cells/__tests__/notebook-outline.test.ts +7 -1
- package/src/core/cells/__tests__/session.test.ts +329 -174
- package/src/core/cells/__tests__/utils.test.ts +0 -1
- package/src/core/cells/actions.ts +247 -82
- package/src/core/cells/arrange.ts +341 -0
- package/src/core/cells/cells.ts +27 -516
- package/src/core/cells/document.ts +6 -5
- package/src/core/cells/edit.ts +30 -0
- package/src/core/cells/editor.ts +82 -0
- package/src/core/cells/layout.ts +152 -0
- package/src/core/cells/session.ts +75 -52
- package/src/core/cells/types.ts +0 -5
- package/src/core/cells/utils.ts +6 -4
- package/src/core/config/__tests__/app-config.test.ts +64 -0
- package/src/core/config/__tests__/config-schema.test.ts +1 -1
- package/src/core/config/config-schema.ts +6 -2
- package/src/core/config/config.ts +26 -12
- package/src/core/islands/bootstrap.ts +0 -1
- package/src/core/kernel/handlers.ts +1 -13
- package/src/core/meta/__tests__/code-visibility.test.tsx +78 -70
- package/src/core/meta/code-visibility.ts +18 -9
- package/src/core/notebook/__tests__/operations.test.ts +51 -0
- package/src/core/notebook/document/__tests__/codemirror.test.ts +33 -7
- package/src/core/notebook/index.ts +2 -1
- package/src/core/notebook/operations.ts +30 -0
- package/src/core/saving/__tests__/state.test.ts +111 -0
- package/src/core/saving/save-component.tsx +19 -33
- package/src/core/saving/state.ts +38 -39
- package/src/core/saving/useAutoSave.ts +8 -35
- package/src/core/session/__tests__/backend.test.ts +1 -0
- package/src/core/session/__tests__/useNotebookReplica.hook.test.tsx +1 -0
- package/src/core/session/active-notebook.ts +11 -0
- package/src/core/session/backend.ts +17 -19
- package/src/core/session/embedded.ts +7 -0
- package/src/core/session/useNotebookReplica.ts +3 -1
- package/src/core/session/useNotebookSession.tsx +7 -8
- package/src/core/transports/__tests__/static.test.ts +139 -8
- package/src/core/transports/static.ts +98 -16
- package/src/core/wasm/__tests__/bridge.test.ts +1 -0
- package/src/mount.tsx +19 -10
- package/src/stories/cell.stories.tsx +0 -2
- package/src/stories/layout/vertical/one-column.stories.tsx +0 -2
- package/src/utils/__tests__/id-tree.test.ts +20 -1548
- package/src/utils/id-tree.tsx +12 -537
- package/dist/assets/__vite-browser-external-C8gQho07.js +0 -1
- package/dist/feedback-button-MpeoIn1D.js +0 -379
- package/src/components/editor/navigation/__tests__/state.test.ts +0 -81
- package/src/components/editor/navigation/state.ts +0 -65
package/package.json
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A partial mock of `T` that throws when a member the test did not provide
|
|
5
|
+
* is read, so a test cannot silently depend on an undefined field.
|
|
6
|
+
*/
|
|
7
|
+
export function partial<T extends object>(
|
|
8
|
+
members: Partial<T>,
|
|
9
|
+
name = "mock",
|
|
10
|
+
): T {
|
|
11
|
+
return new Proxy(members as T, {
|
|
12
|
+
get(target, key, receiver) {
|
|
13
|
+
// Only the members the test gave count as provided, not those every
|
|
14
|
+
// object inherits. Promise detection and well-known symbols may probe
|
|
15
|
+
// any object.
|
|
16
|
+
if (
|
|
17
|
+
Object.hasOwn(target, key) ||
|
|
18
|
+
typeof key === "symbol" ||
|
|
19
|
+
key === "then"
|
|
20
|
+
) {
|
|
21
|
+
return Reflect.get(target, key, receiver);
|
|
22
|
+
}
|
|
23
|
+
throw new Error(`${name}.${String(key)} is not implemented in this test`);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -10,8 +10,11 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
appConfigAtom,
|
|
12
12
|
configOverridesAtom,
|
|
13
|
+
pageAppConfigAtom,
|
|
13
14
|
userConfigAtom,
|
|
14
15
|
} from "../core/config/config";
|
|
16
|
+
import { exportedForTesting, notebookAtom } from "../core/cells/cells";
|
|
17
|
+
import { SCRATCH_CELL_ID } from "../core/cells/ids";
|
|
15
18
|
import { marimoVersionAtom, showCodeInRunModeAtom } from "../core/meta/state";
|
|
16
19
|
import { type AppMode, viewStateAtom } from "../core/mode";
|
|
17
20
|
import { codeAtom, filenameAtom } from "../core/saving/file-state";
|
|
@@ -40,7 +43,8 @@ describe("main", () => {
|
|
|
40
43
|
store.set(filenameAtom, null);
|
|
41
44
|
store.set(showCodeInRunModeAtom, false);
|
|
42
45
|
store.set(marimoVersionAtom, "unknown");
|
|
43
|
-
store.set(
|
|
46
|
+
store.set(notebookAtom, exportedForTesting.initialNotebookState());
|
|
47
|
+
store.set(pageAppConfigAtom, {});
|
|
44
48
|
store.set(userConfigAtom, defaultUserConfig());
|
|
45
49
|
store.set(configOverridesAtom, {});
|
|
46
50
|
});
|
|
@@ -99,6 +103,25 @@ describe("main", () => {
|
|
|
99
103
|
expect(store.get(viewStateAtom).mode).toBe("edit");
|
|
100
104
|
});
|
|
101
105
|
|
|
106
|
+
it("seeds runtime from a session snapshot without dropping the scratch cell", () => {
|
|
107
|
+
const el = document.createElement("div");
|
|
108
|
+
const error = mount(
|
|
109
|
+
{
|
|
110
|
+
mode: "edit",
|
|
111
|
+
session: {
|
|
112
|
+
version: "1",
|
|
113
|
+
metadata: { marimo_version: "1", script_metadata_hash: null },
|
|
114
|
+
cells: [{ id: "cell-1", code_hash: null, console: [], outputs: [] }],
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
el,
|
|
118
|
+
);
|
|
119
|
+
expect(error).toBeUndefined();
|
|
120
|
+
const { cellRuntime } = store.get(notebookAtom);
|
|
121
|
+
expect(cellRuntime["cell-1" as never]).toBeDefined();
|
|
122
|
+
expect(cellRuntime[SCRATCH_CELL_ID]).toBeDefined();
|
|
123
|
+
});
|
|
124
|
+
|
|
102
125
|
it("should mount with empty config", () => {
|
|
103
126
|
const el = document.createElement("div");
|
|
104
127
|
const error = mount(
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
const FORM_DEBOUNCE = 100; // ms;
|
|
38
38
|
|
|
39
39
|
export const AppConfigForm: React.FC = () => {
|
|
40
|
-
const
|
|
40
|
+
const config = useAppConfig();
|
|
41
41
|
const { saveAppConfig } = useRequestClient();
|
|
42
42
|
const htmlCheckboxId = useId();
|
|
43
43
|
const ipynbCheckboxId = useId();
|
|
@@ -50,18 +50,14 @@ export const AppConfigForm: React.FC = () => {
|
|
|
50
50
|
defaultValues: config,
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
+
// The host document carries the saved config back.
|
|
53
54
|
const onSubmit = async (values: AppConfig) => {
|
|
54
|
-
await saveAppConfig({ config: values })
|
|
55
|
-
.then(() => {
|
|
56
|
-
setConfig(values);
|
|
57
|
-
})
|
|
58
|
-
.catch(() => {
|
|
59
|
-
setConfig(values);
|
|
60
|
-
});
|
|
55
|
+
await saveAppConfig({ config: values });
|
|
61
56
|
};
|
|
62
57
|
|
|
63
58
|
const debouncedSubmit = useDebouncedCallback((v: AppConfig) => {
|
|
64
|
-
|
|
59
|
+
// The request client reports a failed save, so nothing is left to handle.
|
|
60
|
+
onSubmit(v).catch(() => undefined);
|
|
65
61
|
}, FORM_DEBOUNCE);
|
|
66
62
|
|
|
67
63
|
// When width is changed, dispatch a resize event so widgets know to resize
|
|
@@ -39,6 +39,7 @@ import { aiCompletionCellAtom } from "@/core/ai/state";
|
|
|
39
39
|
import { maybeAddMarimoImport } from "@/core/cells/add-missing-import";
|
|
40
40
|
import { hasOnlyOneCellAtom } from "@/core/cells/cells";
|
|
41
41
|
import { useCellActions } from "@/core/cells/actions";
|
|
42
|
+
import { showHiddenCodeAtom } from "@/core/cells/editor";
|
|
42
43
|
import { type CellId, SETUP_CELL_ID } from "@/core/cells/ids";
|
|
43
44
|
import { useNotebookDocumentEdit } from "@/core/notebook/document";
|
|
44
45
|
import type { CellData } from "@/core/cells/types";
|
|
@@ -54,8 +55,8 @@ import {
|
|
|
54
55
|
appWidthAtom,
|
|
55
56
|
autoInstantiateAtom,
|
|
56
57
|
} from "@/core/config/config";
|
|
57
|
-
import { kioskModeAtom } from "@/core/mode";
|
|
58
58
|
import type { CellConfig, RuntimeState } from "@/core/network/types";
|
|
59
|
+
import { canEditAtom } from "@/core/notebook";
|
|
59
60
|
import { canLinkToCell, createCellLink } from "@/utils/cell-urls";
|
|
60
61
|
import { copyToClipboard } from "@/utils/copy";
|
|
61
62
|
import { downloadCellOutputAsImage } from "@/utils/download";
|
|
@@ -89,9 +90,9 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
|
|
|
89
90
|
sendToBottom,
|
|
90
91
|
addColumnBreakpoint,
|
|
91
92
|
clearCellOutput,
|
|
92
|
-
markUntouched,
|
|
93
93
|
createCell,
|
|
94
94
|
} = useCellActions();
|
|
95
|
+
const showHiddenCode = useSetAtom(showHiddenCodeAtom);
|
|
95
96
|
const edit = useNotebookDocumentEdit();
|
|
96
97
|
const splitCell = useSplitCellCallback();
|
|
97
98
|
const runCell = useRunCell(cell?.cellId);
|
|
@@ -102,10 +103,10 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
|
|
|
102
103
|
const setAiCompletionCell = useSetAtom(aiCompletionCellAtom);
|
|
103
104
|
const aiFeaturesEnabled = useAtomValue(aiFeaturesEnabledAtom);
|
|
104
105
|
const autoInstantiate = useAtomValue(autoInstantiateAtom);
|
|
105
|
-
const
|
|
106
|
+
const canEdit = useAtomValue(canEditAtom);
|
|
106
107
|
const appWidth = useAtomValue(appWidthAtom);
|
|
107
108
|
|
|
108
|
-
if (!cell ||
|
|
109
|
+
if (!cell || !canEdit) {
|
|
109
110
|
return [];
|
|
110
111
|
}
|
|
111
112
|
|
|
@@ -229,7 +230,7 @@ export function useCellActionButtons({ cell, closePopover }: Props) {
|
|
|
229
230
|
hide_code: MARKDOWN_INITIAL_HIDE_CODE,
|
|
230
231
|
}),
|
|
231
232
|
);
|
|
232
|
-
|
|
233
|
+
showHiddenCode({ cellId });
|
|
233
234
|
}
|
|
234
235
|
},
|
|
235
236
|
hidden: isSetupCell,
|
|
@@ -8,7 +8,7 @@ import type { ActionButton } from "./types";
|
|
|
8
8
|
|
|
9
9
|
export function useConfigActions() {
|
|
10
10
|
const [config, setConfig] = useResolvedMarimoConfig();
|
|
11
|
-
const
|
|
11
|
+
const appConfig = useAppConfig();
|
|
12
12
|
const { saveAppConfig, saveUserConfig } = useRequestClient();
|
|
13
13
|
|
|
14
14
|
const handleUserConfig = async (values: Partial<UserConfig>) => {
|
|
@@ -17,10 +17,9 @@ export function useConfigActions() {
|
|
|
17
17
|
});
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
// The host document carries the saved config back.
|
|
20
21
|
const handleAppConfig = async (values: AppConfig) => {
|
|
21
|
-
await saveAppConfig({ config: values })
|
|
22
|
-
setAppConfig(values);
|
|
23
|
-
});
|
|
22
|
+
await saveAppConfig({ config: values });
|
|
24
23
|
};
|
|
25
24
|
|
|
26
25
|
const actions: ActionButton[] = [
|
|
@@ -65,13 +65,14 @@ import {
|
|
|
65
65
|
} from "@/core/cells/cells";
|
|
66
66
|
import { useCellActions } from "@/core/cells/actions";
|
|
67
67
|
import { useNotebookDocumentEdit } from "@/core/notebook/document";
|
|
68
|
+
import { canEditAtom } from "@/core/notebook";
|
|
68
69
|
import { disabledCellIds } from "@/core/cells/utils";
|
|
69
70
|
import { capabilitiesAtom } from "@/core/config/capabilities";
|
|
70
71
|
import { aiEnabledAtom, useResolvedMarimoConfig } from "@/core/config/config";
|
|
71
72
|
import { Constants } from "@/core/constants";
|
|
72
73
|
import { useLayoutActions, useLayoutState } from "@/core/layout/state";
|
|
73
74
|
import { useTogglePresenting } from "@/core/layout/useTogglePresenting";
|
|
74
|
-
import {
|
|
75
|
+
import { viewStateAtom } from "@/core/mode";
|
|
75
76
|
import { useRequestClient } from "@/core/network/requests";
|
|
76
77
|
import { useFilename } from "@/core/saving/filename";
|
|
77
78
|
import { createShareableLink } from "@/core/wasm/share";
|
|
@@ -119,7 +120,7 @@ export function useNotebookActions({
|
|
|
119
120
|
const { toggleApplication } = useChromeActions();
|
|
120
121
|
const { selectedPanel } = useChromeState();
|
|
121
122
|
const [viewState] = useAtom(viewStateAtom);
|
|
122
|
-
const
|
|
123
|
+
const canEdit = useAtomValue(canEditAtom);
|
|
123
124
|
const setCodeVisibility = useSetCodeVisibility();
|
|
124
125
|
const setOutputsExpanded = useSetOutputsExpanded();
|
|
125
126
|
const [resolvedConfig] = useResolvedMarimoConfig();
|
|
@@ -448,7 +449,7 @@ export function useNotebookActions({
|
|
|
448
449
|
{
|
|
449
450
|
icon: <ZapIcon size={14} strokeWidth={1.5} />,
|
|
450
451
|
label: "Enable all cells",
|
|
451
|
-
hidden: !hasDisabledCells ||
|
|
452
|
+
hidden: !hasDisabledCells || !canEdit,
|
|
452
453
|
handle: () => {
|
|
453
454
|
const ids = disabledCellIds(getNotebook());
|
|
454
455
|
edit((tx) => {
|
|
@@ -538,7 +539,7 @@ export function useNotebookActions({
|
|
|
538
539
|
{
|
|
539
540
|
icon: <Undo2Icon size={14} strokeWidth={1.5} />,
|
|
540
541
|
label: undoLabel,
|
|
541
|
-
hidden: !canUndoDeletes ||
|
|
542
|
+
hidden: !canUndoDeletes || !canEdit,
|
|
542
543
|
handle: () => {
|
|
543
544
|
undoDeleteCell();
|
|
544
545
|
},
|
|
@@ -3,7 +3,7 @@ import { historyField } from "@codemirror/commands";
|
|
|
3
3
|
import { EditorState, type Extension, StateEffect } from "@codemirror/state";
|
|
4
4
|
import { EditorView, ViewPlugin } from "@codemirror/view";
|
|
5
5
|
import { useIntersectionObserver } from "@uidotdev/usehooks";
|
|
6
|
-
import { useAtom, useAtomValue } from "jotai";
|
|
6
|
+
import { useAtom, useAtomValue, useSetAtom } from "jotai";
|
|
7
7
|
import React, { memo, useEffect, useMemo, useRef, useState } from "react";
|
|
8
8
|
import useEvent from "react-use-event-hook";
|
|
9
9
|
import { Button } from "@/components/ui/button";
|
|
@@ -12,6 +12,11 @@ import { aiCompletionCellAtom } from "@/core/ai/state";
|
|
|
12
12
|
import { maybeAddMarimoImport } from "@/core/cells/add-missing-import";
|
|
13
13
|
import { getNotebook } from "@/core/cells/cells";
|
|
14
14
|
import { useCellActions } from "@/core/cells/actions";
|
|
15
|
+
import {
|
|
16
|
+
showHiddenCodeAtom,
|
|
17
|
+
takeRestoredEditorStateAtom,
|
|
18
|
+
useRestoredEditorState,
|
|
19
|
+
} from "@/core/cells/editor";
|
|
15
20
|
import { useNotebookDocumentEdit } from "@/core/notebook/document";
|
|
16
21
|
import { SETUP_CELL_ID } from "@/core/cells/ids";
|
|
17
22
|
import { usePendingDeleteService } from "@/core/cells/pending-delete-service";
|
|
@@ -58,7 +63,7 @@ import { LanguageToggles } from "./language-toggle";
|
|
|
58
63
|
export interface CellEditorProps
|
|
59
64
|
extends
|
|
60
65
|
Pick<CellRuntimeState, "status">,
|
|
61
|
-
Pick<CellData, "id" | "code" | "
|
|
66
|
+
Pick<CellData, "id" | "code" | "config"> {
|
|
62
67
|
runCell: () => void;
|
|
63
68
|
theme: Theme;
|
|
64
69
|
showPlaceholder: boolean;
|
|
@@ -116,7 +121,6 @@ const CellEditorInternal = ({
|
|
|
116
121
|
config: cellConfig,
|
|
117
122
|
code,
|
|
118
123
|
status,
|
|
119
|
-
serializedEditorState,
|
|
120
124
|
setEditorView,
|
|
121
125
|
runCell,
|
|
122
126
|
userConfig,
|
|
@@ -133,6 +137,9 @@ const CellEditorInternal = ({
|
|
|
133
137
|
tooltipParentSelector,
|
|
134
138
|
}: CellEditorProps) => {
|
|
135
139
|
const [aiCompletionCell, setAiCompletionCell] = useAtom(aiCompletionCellAtom);
|
|
140
|
+
const serializedEditorState = useRestoredEditorState(cellId);
|
|
141
|
+
const takeRestoredEditorState = useSetAtom(takeRestoredEditorStateAtom);
|
|
142
|
+
const showHiddenCodeNow = useSetAtom(showHiddenCodeAtom);
|
|
136
143
|
const deleteCell = useDeleteCellCallback();
|
|
137
144
|
const { saveOrNameNotebook } = useSaveNotebook();
|
|
138
145
|
const pendingDeleteService = usePendingDeleteService();
|
|
@@ -192,7 +199,7 @@ const CellEditorInternal = ({
|
|
|
192
199
|
edit((tx) =>
|
|
193
200
|
tx.updateConfig(cellId, { hide_code: MARKDOWN_INITIAL_HIDE_CODE }),
|
|
194
201
|
);
|
|
195
|
-
|
|
202
|
+
showHiddenCodeNow({ cellId });
|
|
196
203
|
}
|
|
197
204
|
});
|
|
198
205
|
|
|
@@ -422,8 +429,8 @@ const CellEditorInternal = ({
|
|
|
422
429
|
});
|
|
423
430
|
}
|
|
424
431
|
setEditorView(ev);
|
|
425
|
-
//
|
|
426
|
-
|
|
432
|
+
// The restored state is used once; the next mount builds a fresh editor.
|
|
433
|
+
takeRestoredEditorState({ cellId });
|
|
427
434
|
});
|
|
428
435
|
const [isEditorMounted, setIsEditorMounted] = useState(
|
|
429
436
|
serializedEditorState !== null,
|
|
@@ -14,6 +14,7 @@ import { Toolbar } from "@/components/layout/toolbar";
|
|
|
14
14
|
import { Button } from "@/components/ui/button";
|
|
15
15
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
16
16
|
import { useNotebook } from "@/core/cells/cells";
|
|
17
|
+
import { columnOf, useLayout } from "@/core/cells/layout";
|
|
17
18
|
import type { CellId } from "@/core/cells/ids";
|
|
18
19
|
import { getDescendantsStatus } from "@/core/cells/utils";
|
|
19
20
|
import { cn } from "@/utils/cn";
|
|
@@ -64,7 +65,11 @@ export const CollapsedCellBanner: React.FC<{
|
|
|
64
65
|
count: number;
|
|
65
66
|
}> = memo(({ onClick, count, cellId }) => {
|
|
66
67
|
const notebook = useNotebook();
|
|
67
|
-
const
|
|
68
|
+
const layout = useLayout();
|
|
69
|
+
const states = getDescendantsStatus(
|
|
70
|
+
notebook,
|
|
71
|
+
columnOf(layout, cellId).folds.get(cellId) ?? [],
|
|
72
|
+
);
|
|
68
73
|
|
|
69
74
|
return (
|
|
70
75
|
<button
|
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
DialogTitle,
|
|
19
19
|
} from "@/components/ui/dialog";
|
|
20
20
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
21
|
-
import { notebookAtom } from "@/core/cells/cells";
|
|
22
21
|
import { Constants } from "@/core/constants";
|
|
23
22
|
import {
|
|
24
23
|
buildBugReportUrl,
|
|
@@ -116,13 +115,8 @@ export const FeedbackModal: React.FC<{
|
|
|
116
115
|
return requestClient.getEnvironmentInfo();
|
|
117
116
|
}, [requestClient]);
|
|
118
117
|
|
|
119
|
-
const notebook = useAtomValue(notebookAtom);
|
|
120
118
|
const errors = getCellErrorEntries(store);
|
|
121
|
-
|
|
122
|
-
const cells = notebook.cellIds.inOrderIds.map(
|
|
123
|
-
(cellId) => notebook.cellData[cellId],
|
|
124
|
-
);
|
|
125
|
-
const codeAvailable = useNotebookCodeAvailable(cells);
|
|
119
|
+
const codeAvailable = useNotebookCodeAvailable();
|
|
126
120
|
const filename = useAtomValue(filenameAtom);
|
|
127
121
|
const connection = useAtomValue(connectionAtom);
|
|
128
122
|
const notebookSourceReason = getNotebookSourceUnavailableReason({
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
ERROR_MESSAGE_INSTRUCTIONS,
|
|
25
25
|
} from "@/core/cells/error-report";
|
|
26
26
|
import { pairConfigAtom } from "@/core/config/pair";
|
|
27
|
-
import {
|
|
27
|
+
import { readExport } from "@/core/cells/session";
|
|
28
28
|
import type { MarimoError, OutputMessage } from "@/core/kernel/messages";
|
|
29
29
|
import {
|
|
30
30
|
type StableSessionId,
|
|
@@ -317,8 +317,8 @@ describe("SendErrorReportButton", () => {
|
|
|
317
317
|
});
|
|
318
318
|
|
|
319
319
|
it("sends the restored exception type and complete traceback", async () => {
|
|
320
|
-
const
|
|
321
|
-
{
|
|
320
|
+
const { cellRuntime } = readExport({
|
|
321
|
+
session: {
|
|
322
322
|
version: "1",
|
|
323
323
|
metadata: { marimo_version: "1", script_metadata_hash: null },
|
|
324
324
|
cells: [
|
|
@@ -342,9 +342,11 @@ describe("SendErrorReportButton", () => {
|
|
|
342
342
|
},
|
|
343
343
|
],
|
|
344
344
|
},
|
|
345
|
-
null,
|
|
346
|
-
|
|
347
|
-
|
|
345
|
+
notebook: null,
|
|
346
|
+
filename: null,
|
|
347
|
+
appConfig: {},
|
|
348
|
+
});
|
|
349
|
+
const message = cellRuntime[CELL_ID].output;
|
|
348
350
|
expect(message).toBeDefined();
|
|
349
351
|
renderButton({
|
|
350
352
|
content: message && <OutputRenderer cellId={CELL_ID} message={message} />,
|
|
@@ -27,6 +27,7 @@ import { aiCompletionCellAtom } from "@/core/ai/state";
|
|
|
27
27
|
import type { CellActions } from "@/core/cells/actions";
|
|
28
28
|
import { notebookAtom } from "@/core/cells/cells";
|
|
29
29
|
import type { CellId } from "@/core/cells/ids";
|
|
30
|
+
import { layoutAtom } from "@/core/cells/layout";
|
|
30
31
|
import type { DocumentModel } from "@/core/notebook/document";
|
|
31
32
|
import {
|
|
32
33
|
cell,
|
|
@@ -165,7 +166,6 @@ const mockCellActions = MockNotebook.cellActions({
|
|
|
165
166
|
moveCell: vi.fn(),
|
|
166
167
|
sendToTop: vi.fn(),
|
|
167
168
|
sendToBottom: vi.fn(),
|
|
168
|
-
markTouched: vi.fn(),
|
|
169
169
|
deleteCells: vi.fn(),
|
|
170
170
|
undoDeleteCell: vi.fn(),
|
|
171
171
|
});
|
|
@@ -318,7 +318,7 @@ describe("useCellNavigationProps", () => {
|
|
|
318
318
|
selectionActions.select({ cellId: cellId1 });
|
|
319
319
|
selectionActions.extend({
|
|
320
320
|
cellId: cellId2,
|
|
321
|
-
|
|
321
|
+
layout: store.get(layoutAtom),
|
|
322
322
|
});
|
|
323
323
|
|
|
324
324
|
const { result } = renderWithProvider(() =>
|
|
@@ -850,7 +850,7 @@ describe("useCellNavigationProps", () => {
|
|
|
850
850
|
selectionActions.select({ cellId: cellId1 });
|
|
851
851
|
selectionActions.extend({
|
|
852
852
|
cellId: cellId2,
|
|
853
|
-
|
|
853
|
+
layout: store.get(layoutAtom),
|
|
854
854
|
});
|
|
855
855
|
|
|
856
856
|
const { result } = renderWithProvider(() =>
|
|
@@ -873,7 +873,7 @@ describe("useCellNavigationProps", () => {
|
|
|
873
873
|
selectionActions.select({ cellId: cellId1 });
|
|
874
874
|
selectionActions.extend({
|
|
875
875
|
cellId: cellId3,
|
|
876
|
-
|
|
876
|
+
layout: store.get(layoutAtom),
|
|
877
877
|
});
|
|
878
878
|
|
|
879
879
|
const { result } = renderWithProvider(() =>
|
|
@@ -896,7 +896,7 @@ describe("useCellNavigationProps", () => {
|
|
|
896
896
|
selectionActions.select({ cellId: cellId1 });
|
|
897
897
|
selectionActions.extend({
|
|
898
898
|
cellId: cellId3,
|
|
899
|
-
|
|
899
|
+
layout: store.get(layoutAtom),
|
|
900
900
|
});
|
|
901
901
|
|
|
902
902
|
const { result } = renderWithProvider(() =>
|
|
@@ -919,7 +919,7 @@ describe("useCellNavigationProps", () => {
|
|
|
919
919
|
selectionActions.select({ cellId: cellId2 });
|
|
920
920
|
selectionActions.extend({
|
|
921
921
|
cellId: cellId3,
|
|
922
|
-
|
|
922
|
+
layout: store.get(layoutAtom),
|
|
923
923
|
});
|
|
924
924
|
|
|
925
925
|
const { result } = renderWithProvider(() =>
|
|
@@ -954,7 +954,7 @@ describe("useCellNavigationProps", () => {
|
|
|
954
954
|
selectionActions.select({ cellId: cellId1 });
|
|
955
955
|
selectionActions.extend({
|
|
956
956
|
cellId: cellId2,
|
|
957
|
-
|
|
957
|
+
layout: store.get(layoutAtom),
|
|
958
958
|
});
|
|
959
959
|
|
|
960
960
|
const { result } = renderWithProvider(() =>
|
|
@@ -990,7 +990,7 @@ describe("useCellNavigationProps", () => {
|
|
|
990
990
|
selectionActions.select({ cellId: cellId2 });
|
|
991
991
|
selectionActions.extend({
|
|
992
992
|
cellId: cellId3,
|
|
993
|
-
|
|
993
|
+
layout: store.get(layoutAtom),
|
|
994
994
|
});
|
|
995
995
|
|
|
996
996
|
const { result } = renderWithProvider(() =>
|
|
@@ -1023,7 +1023,7 @@ describe("useCellNavigationProps", () => {
|
|
|
1023
1023
|
selectionActions.select({ cellId: cellId1 });
|
|
1024
1024
|
selectionActions.extend({
|
|
1025
1025
|
cellId: cellId2,
|
|
1026
|
-
|
|
1026
|
+
layout: store.get(layoutAtom),
|
|
1027
1027
|
});
|
|
1028
1028
|
|
|
1029
1029
|
const { result } = renderWithProvider(() =>
|
|
@@ -1056,7 +1056,7 @@ describe("useCellNavigationProps", () => {
|
|
|
1056
1056
|
selectionActions.select({ cellId: cellId1 });
|
|
1057
1057
|
selectionActions.extend({
|
|
1058
1058
|
cellId: cellId2,
|
|
1059
|
-
|
|
1059
|
+
layout: store.get(layoutAtom),
|
|
1060
1060
|
});
|
|
1061
1061
|
|
|
1062
1062
|
const { result } = renderWithProvider(() =>
|
|
@@ -1084,7 +1084,7 @@ describe("useCellNavigationProps", () => {
|
|
|
1084
1084
|
selectionActions.select({ cellId: cellId2 });
|
|
1085
1085
|
selectionActions.extend({
|
|
1086
1086
|
cellId: cellId3,
|
|
1087
|
-
|
|
1087
|
+
layout: store.get(layoutAtom),
|
|
1088
1088
|
});
|
|
1089
1089
|
|
|
1090
1090
|
const { result } = renderWithProvider(() =>
|
|
@@ -1138,7 +1138,7 @@ describe("useCellNavigationProps", () => {
|
|
|
1138
1138
|
selectionActions.select({ cellId: cellId1 });
|
|
1139
1139
|
selectionActions.extend({
|
|
1140
1140
|
cellId: cellId2,
|
|
1141
|
-
|
|
1141
|
+
layout: store.get(layoutAtom),
|
|
1142
1142
|
});
|
|
1143
1143
|
|
|
1144
1144
|
const { result } = renderWithProvider(() =>
|
|
@@ -1166,7 +1166,7 @@ describe("useCellNavigationProps", () => {
|
|
|
1166
1166
|
selectionActions.select({ cellId: cellId1 });
|
|
1167
1167
|
selectionActions.extend({
|
|
1168
1168
|
cellId: cellId2,
|
|
1169
|
-
|
|
1169
|
+
layout: store.get(layoutAtom),
|
|
1170
1170
|
});
|
|
1171
1171
|
|
|
1172
1172
|
const { result } = renderWithProvider(() =>
|
|
@@ -1228,7 +1228,7 @@ describe("useCellNavigationProps", () => {
|
|
|
1228
1228
|
selectionActions.select({ cellId: cellId1 });
|
|
1229
1229
|
selectionActions.extend({
|
|
1230
1230
|
cellId: cellId2,
|
|
1231
|
-
|
|
1231
|
+
layout: store.get(layoutAtom),
|
|
1232
1232
|
});
|
|
1233
1233
|
|
|
1234
1234
|
const { result } = renderWithProvider(() =>
|
|
@@ -1622,7 +1622,7 @@ describe("useCellNavigationProps", () => {
|
|
|
1622
1622
|
selectionActions.select({ cellId: cellId1 });
|
|
1623
1623
|
selectionActions.extend({
|
|
1624
1624
|
cellId: cellId2,
|
|
1625
|
-
|
|
1625
|
+
layout: store.get(layoutAtom),
|
|
1626
1626
|
});
|
|
1627
1627
|
|
|
1628
1628
|
const { result } = renderWithProvider(() =>
|