@marimo-team/frontend 0.24.1-dev80 → 0.24.1-dev82

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.
Files changed (128) hide show
  1. package/dist/assets/{CellStatus-DMQfH9wD.js → CellStatus-GcHBZKLm.js} +1 -1
  2. package/dist/assets/{JsonOutput-B7sDhGzR.js → JsonOutput-CUJlEdsN.js} +8 -8
  3. package/dist/assets/{MarimoErrorOutput-C0vk393J.js → MarimoErrorOutput-DCAezqcJ.js} +2 -2
  4. package/dist/assets/{RenderHTML-BnMaGpV8.js → RenderHTML-D9-75ltP.js} +1 -1
  5. package/dist/assets/{RunButton-nocIODpS.js → RunButton-plSsbubG.js} +1 -1
  6. package/dist/assets/{add-cell-with-ai-B_TSaqjJ.js → add-cell-with-ai-Cfby28hZ.js} +14 -14
  7. package/dist/assets/{add-connection-dialog-DOuojDa-.js → add-connection-dialog-By0i0Fq5.js} +42 -42
  8. package/dist/assets/{agent-panel-CkKCGjDp.js → agent-panel-Cf482jaA.js} +4 -4
  9. package/dist/assets/ai-model-dropdown-DMfaGQ8o.js +3 -0
  10. package/dist/assets/app-config-button-93unbEYx.js +1 -0
  11. package/dist/assets/{blob-CYM8xQsK.js → blob-yxfhyyvD.js} +1 -1
  12. package/dist/assets/cell-editor-CZmqG6aB.js +21 -0
  13. package/dist/assets/{cell-link-DCOAqVkE.js → cell-link-hHrWcozB.js} +1 -1
  14. package/dist/assets/{cells-C6lBv8kg.js → cells-yuYDzbAy.js} +51 -51
  15. package/dist/assets/{chat-display-B6GBZDq8.js → chat-display-CnhvADgL.js} +1 -1
  16. package/dist/assets/{chat-panel-wWuBXhXw.js → chat-panel-CdE97AxM.js} +2 -2
  17. package/dist/assets/{chat-ui-CQ7A3qdB.js → chat-ui-BD3rpULw.js} +2 -2
  18. package/dist/assets/{column-preview-CatwdUda.js → column-preview-BEmcYaKl.js} +1 -1
  19. package/dist/assets/{command-palette-DcPM_WiO.js → command-palette-BGRRw0sn.js} +1 -1
  20. package/dist/assets/{common-B4aMxphz.js → common-Bs2kaOs2.js} +1 -1
  21. package/dist/assets/{components-D8-ffQsq.js → components-ByyAzQxP.js} +1 -1
  22. package/dist/assets/{datasource-D-_jFtGs.js → datasource-DeZYq5UY.js} +2 -2
  23. package/dist/assets/{dependency-graph-panel-BQli6zxh.js → dependency-graph-panel-g10osAFc.js} +4 -4
  24. package/dist/assets/{documentation-panel-_QE3nPOg.js → documentation-panel-CZ1mKkDh.js} +1 -1
  25. package/dist/assets/{download-Cqjqrhzo.js → download-D1crMjD8.js} +1 -1
  26. package/dist/assets/edit-page-Bk1sT7Wb.js +9 -0
  27. package/dist/assets/{error-entries-c5sIySli.js → error-entries-B6XTLRyE.js} +1 -1
  28. package/dist/assets/{error-panel-CXKrWK_u.js → error-panel-lexB3L6f.js} +1 -1
  29. package/dist/assets/{file-explorer-panel-BZiAb4x_.js → file-explorer-panel-DHRH2J-3.js} +1 -1
  30. package/dist/assets/{file-icons-uUY_hGYm.js → file-icons-Dx3v6lMu.js} +1 -1
  31. package/dist/assets/{file-name-input-DWUKg4LS.js → file-name-input-DzL8D_7x.js} +1 -1
  32. package/dist/assets/{floating-outline-DhGtHg6T.js → floating-outline-3rQEbxxk.js} +1 -1
  33. package/dist/assets/{home-page-Bka_7H02.js → home-page-Dnz4tfZB.js} +1 -1
  34. package/dist/assets/index-BID9w87A.js +29 -0
  35. package/dist/assets/layout-qHVpnnQT.js +9 -0
  36. package/dist/assets/{logs-panel-ragZa1sf.js → logs-panel-CSbUhhRo.js} +1 -1
  37. package/dist/assets/{markdown-renderer-B-uA_6mP.js → markdown-renderer-BgUTGtM0.js} +1 -1
  38. package/dist/assets/{name-cell-input-gC1flbyT.js → name-cell-input-pEE4FGAL.js} +1 -1
  39. package/dist/assets/{outline-panel-D7H7bhOh.js → outline-panel-BgnjEQWg.js} +1 -1
  40. package/dist/assets/{packages-panel-BZnsUm4S.js → packages-panel-BprfUOzZ.js} +1 -1
  41. package/dist/assets/panel-accordion-state-vpqEc3Kd.js +1 -0
  42. package/dist/assets/panels-3h7Cf8xJ.js +4 -0
  43. package/dist/assets/{process-output-DQQ8T5gv.js → process-output-siRm_lza.js} +1 -1
  44. package/dist/assets/{readonly-code-display-Bc0VX9i6.js → readonly-code-display-CLWV76FT.js} +1 -1
  45. package/dist/assets/readonly-python-code-Bor9b9pV.js +1 -0
  46. package/dist/assets/reveal-component-DNPksvzT.js +1069 -0
  47. package/dist/assets/run-page-C4aONLoP.js +1 -0
  48. package/dist/assets/{scratchpad-panel-BJHlMBZV.js → scratchpad-panel-BQSoRQvQ.js} +1 -1
  49. package/dist/assets/session-panel-DB5qEYqt.js +1 -0
  50. package/dist/assets/skeleton-BSxwEE0h.js +1 -0
  51. package/dist/assets/{snippets-panel-2jq36DdG.js → snippets-panel-B8Yi81tz.js} +1 -1
  52. package/dist/assets/state-D1N9_41P.js +3 -0
  53. package/dist/assets/state-O8w98G11.js +1 -0
  54. package/dist/assets/{tracing-91_akEkv.js → tracing-DuLkr7ts.js} +1 -1
  55. package/dist/assets/{tracing-panel-BvE81RYx.js → tracing-panel-CeLKVG8M.js} +2 -2
  56. package/dist/assets/{tree-actions-CGkbUSfG.js → tree-actions-Bh-Nnaub.js} +1 -1
  57. package/dist/assets/useAddCell-_JRYhAFd.js +1 -0
  58. package/dist/assets/useBoolean-Cu7Eado1.js +1 -0
  59. package/dist/assets/{useCellActionButton-cv6xOsnc.js → useCellActionButton-Bi8Lnv3F.js} +1 -1
  60. package/dist/assets/{useDeleteCell-DB-bhhnO.js → useDeleteCell-CBQiavzs.js} +1 -1
  61. package/dist/assets/{useDependencyPanelTab-BDnVzNV-.js → useDependencyPanelTab-BOn3UJ07.js} +1 -1
  62. package/dist/assets/useNotebookActions--pblpIWF.js +10 -0
  63. package/dist/assets/{useRunCells-GCTS1YFv.js → useRunCells-BFQfLlUl.js} +1 -1
  64. package/dist/assets/{useSplitCell-DhT9BA2_.js → useSplitCell-Ig9P6lAn.js} +1 -1
  65. package/dist/index.html +20 -20
  66. package/package.json +1 -1
  67. package/src/__tests__/mount.test.ts +54 -2
  68. package/src/components/editor/__tests__/viewer-banner.test.tsx +1 -1
  69. package/src/components/editor/actions/export-dialog/__tests__/export-notebook.test.ts +9 -0
  70. package/src/components/editor/actions/export-dialog/export-notebook.ts +8 -1
  71. package/src/components/editor/actions/export-dialog/use-export-dialog.ts +2 -0
  72. package/src/components/editor/actions/useNotebookActions.tsx +1 -1
  73. package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +1 -1
  74. package/src/components/editor/renderers/__tests__/cells-renderer.test.tsx +1 -1
  75. package/src/components/editor/renderers/cells-renderer.tsx +15 -28
  76. package/src/components/editor/renderers/grid-layout/__tests__/plugin.test.ts +42 -0
  77. package/src/components/editor/renderers/grid-layout/plugin.tsx +20 -10
  78. package/src/components/editor/renderers/layout-select.tsx +1 -1
  79. package/src/components/editor/renderers/plugins.ts +7 -1
  80. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +49 -15
  81. package/src/components/editor/renderers/slides-layout/slides-layout.tsx +16 -2
  82. package/src/components/editor/renderers/slides-layout/types.ts +15 -11
  83. package/src/components/editor/renderers/types.ts +5 -5
  84. package/src/components/editor/viewer-banner.tsx +1 -1
  85. package/src/components/pages/run-page.tsx +16 -7
  86. package/src/components/slides/__tests__/reveal-component.test.ts +33 -8
  87. package/src/components/slides/__tests__/speaker-view.test.ts +27 -0
  88. package/src/components/slides/reveal-component.tsx +110 -45
  89. package/src/components/slides/speaker-view.ts +22 -0
  90. package/src/components/static-html/share-modal.tsx +2 -0
  91. package/src/core/cells/__tests__/document-changes.test.ts +343 -26
  92. package/src/core/cells/document-changes.ts +181 -4
  93. package/src/core/export/hooks.ts +2 -0
  94. package/src/core/export/layout.ts +9 -0
  95. package/src/core/kernel/handlers.ts +7 -16
  96. package/src/core/kernel/state.ts +2 -0
  97. package/src/core/layout/__tests__/layout.test.ts +95 -0
  98. package/src/core/layout/layout.ts +59 -65
  99. package/src/core/layout/state.ts +121 -0
  100. package/src/core/meta/__tests__/code-visibility.test.tsx +28 -0
  101. package/src/core/meta/code-visibility.ts +3 -1
  102. package/src/core/run-app.tsx +6 -2
  103. package/src/core/saving/__tests__/save-component.test.ts +31 -1
  104. package/src/core/saving/save-component.tsx +39 -29
  105. package/src/core/saving/state.ts +1 -1
  106. package/src/core/static/download-html.ts +2 -0
  107. package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +47 -14
  108. package/src/core/websocket/useMarimoKernelConnection.tsx +7 -2
  109. package/src/mount.tsx +24 -6
  110. package/dist/assets/ai-model-dropdown-CfWMIzjl.js +0 -3
  111. package/dist/assets/app-config-button-ii-Hj5CZ.js +0 -1
  112. package/dist/assets/cell-editor-BVb6iKbw.js +0 -21
  113. package/dist/assets/edit-page-RuyN164g.js +0 -9
  114. package/dist/assets/index-ChbtcNW2.js +0 -29
  115. package/dist/assets/layout-Uv1ZP5XB.js +0 -9
  116. package/dist/assets/panel-accordion-state-BLU7OiMD.js +0 -1
  117. package/dist/assets/panels-B3Y6fue9.js +0 -4
  118. package/dist/assets/readonly-python-code-D2HXwAfT.js +0 -1
  119. package/dist/assets/reveal-component-BN1C8zFu.js +0 -1069
  120. package/dist/assets/run-page-ByVvsH9G.js +0 -1
  121. package/dist/assets/session-panel-CdCKWAOf.js +0 -1
  122. package/dist/assets/skeleton-DirOIQrj.js +0 -1
  123. package/dist/assets/state-C9O-2hQL.js +0 -3
  124. package/dist/assets/state-DyxPdcEa.js +0 -1
  125. package/dist/assets/types-CoHi_MQq.js +0 -1
  126. package/dist/assets/useAddCell-DqvY2ulx.js +0 -1
  127. package/dist/assets/useBoolean-DWBCpKfT.js +0 -1
  128. package/dist/assets/useNotebookActions-Dxp4gTEa.js +0 -10
@@ -56,12 +56,45 @@ import { SlideNotesEditor } from "./slide-notes-editor";
56
56
  import { buildSubslideNotes, NOTES_DIVIDER } from "./slide-notes";
57
57
  import { cn } from "@/utils/cn";
58
58
  import { isIslands } from "@/core/islands/utils";
59
+ import { initialRunCompletedAtom } from "@/core/kernel/state";
59
60
  import { useNotebookCodeAvailable } from "@/core/meta/code-visibility";
60
61
  import { type AppMode, kioskModeAtom } from "@/core/mode";
62
+ import { runtimeAdapterAtom } from "@/core/runtime/adapter";
61
63
  import { useAtomValue } from "jotai";
62
64
  import RevealNotes from "reveal.js/plugin/notes";
65
+ import {
66
+ createSpeakerViewUrl,
67
+ isSpeakerViewReceiver,
68
+ supportsSpeakerView,
69
+ } from "./speaker-view";
63
70
 
64
71
  const ASPECT_RATIO = 16 / 9;
72
+ const CODE_TOGGLE_KEY_CODE = 67;
73
+
74
+ // Reveal retains custom key bindings after initialization. Replace the `C`
75
+ // binding when code availability or receiver mode changes so it cannot keep a
76
+ // stale handler.
77
+ export function syncCodeToggleKeyBinding({
78
+ deck,
79
+ enabled,
80
+ onToggle,
81
+ }: {
82
+ deck: Pick<RevealApi, "addKeyBinding" | "removeKeyBinding">;
83
+ enabled: boolean;
84
+ onToggle: () => void;
85
+ }): void {
86
+ deck.removeKeyBinding(CODE_TOGGLE_KEY_CODE);
87
+ if (enabled) {
88
+ deck.addKeyBinding(
89
+ {
90
+ keyCode: CODE_TOGGLE_KEY_CODE,
91
+ key: "C",
92
+ description: "Toggle code editor",
93
+ },
94
+ onToggle,
95
+ );
96
+ }
97
+ }
65
98
 
66
99
  /**
67
100
  * reveal.js caches the last visited vertical index on each stack and can
@@ -161,10 +194,10 @@ export function shouldShowCode(options: {
161
194
  cells: ReadonlyMap<CellId, SlideConfig>;
162
195
  cellId: CellId | undefined;
163
196
  showCodeOverrides: ReadonlySet<CellId>;
164
- codeToggleEnabled: boolean;
197
+ codeAvailable: boolean;
165
198
  }): boolean {
166
- const { cells, cellId, showCodeOverrides, codeToggleEnabled } = options;
167
- if (cellId == null || !codeToggleEnabled) {
199
+ const { cells, cellId, showCodeOverrides, codeAvailable } = options;
200
+ if (cellId == null || !codeAvailable) {
168
201
  return false;
169
202
  }
170
203
  const configured = cells.get(cellId)?.showCode ?? false;
@@ -450,12 +483,15 @@ const RevealSlidesComponent = ({
450
483
  const { width, height } = useSlideDimensions(containerRef);
451
484
  const isFullscreen = useFullScreenElement() != null;
452
485
 
453
- // Skip the Notes plugin inside reveal's own speaker-view iframes so pressing
454
- // `S` there doesn't try to spawn another popup.
486
+ // A receiver frame cannot spawn another speaker view. WebAssembly exports
487
+ // also omit the plugin because each receiver would start another runtime.
455
488
  const kioskMode = useAtomValue(kioskModeAtom);
489
+ const runtimeKind = useAtomValue(runtimeAdapterAtom).kind;
490
+ const initialRunCompleted = useAtomValue(initialRunCompletedAtom);
491
+ const canResolveInitialHash = runtimeKind !== "wasm" || initialRunCompleted;
456
492
  const deckPlugins = useMemo(
457
- () => (kioskMode ? [] : [RevealNotes]),
458
- [kioskMode],
493
+ () => (kioskMode || !supportsSpeakerView(runtimeKind) ? [] : [RevealNotes]),
494
+ [kioskMode, runtimeKind],
459
495
  );
460
496
 
461
497
  // Store the state of the code toggle for each cell
@@ -464,7 +500,12 @@ const RevealSlidesComponent = ({
464
500
  ReadonlySet<CellId>
465
501
  >(() => new Set());
466
502
  const codeAvailable = useNotebookCodeAvailable(slideCells);
467
- const codeToggleEnabled = !isIslands() && codeAvailable;
503
+ const codeRenderingEnabled = !isIslands() && codeAvailable;
504
+ const isSpeakerReceiver = isSpeakerViewReceiver(
505
+ kioskMode,
506
+ window.location.search,
507
+ );
508
+ const codeToggleEnabled = !isSpeakerReceiver && codeRenderingEnabled;
468
509
 
469
510
  const activeCell = activeIndex != null ? slideCells[activeIndex] : undefined;
470
511
  // Fall back to the first cell while the deck settles on an initial slide.
@@ -489,7 +530,7 @@ const RevealSlidesComponent = ({
489
530
  cells: layout.cells,
490
531
  cellId,
491
532
  showCodeOverrides,
492
- codeToggleEnabled,
533
+ codeAvailable: codeRenderingEnabled,
493
534
  });
494
535
 
495
536
  // `C` and the toolbar button target the active slide's cell (the revealed
@@ -501,7 +542,7 @@ const RevealSlidesComponent = ({
501
542
 
502
543
  // A slide persisted with `showCode: true` always renders code
503
544
  const codeAlwaysShown =
504
- codeToggleEnabled &&
545
+ codeRenderingEnabled &&
505
546
  cellIdToShowCode != null &&
506
547
  (layout.cells.get(cellIdToShowCode)?.showCode ?? false);
507
548
 
@@ -540,10 +581,7 @@ const RevealSlidesComponent = ({
540
581
  // app chrome hidden, which `<SlidesLayoutRenderer>` interprets the same as
541
582
  // read mode (no minimap, sidebar, or notes editor).
542
583
  const kioskUrl = useMemo(() => {
543
- const url = new URL(window.location.href);
544
- url.searchParams.set("kiosk", "true");
545
- url.searchParams.set("show-chrome", "false");
546
- return url.toString();
584
+ return createSpeakerViewUrl(window.location.href);
547
585
  }, []);
548
586
 
549
587
  const revealConfig: RevealConfig = useMemo(
@@ -566,6 +604,14 @@ const RevealSlidesComponent = ({
566
604
  );
567
605
 
568
606
  const navigateDeckToActiveCell = useEvent((deck: RevealApi) => {
607
+ if (activeIndex == null && window.location.hash.startsWith("#/")) {
608
+ if (!canResolveInitialHash) {
609
+ return;
610
+ }
611
+ window.dispatchEvent(new HashChangeEvent("hashchange"));
612
+ clearPreviousVerticalIndices(deck);
613
+ return;
614
+ }
569
615
  const target = resolveDeckNavigationTarget({
570
616
  activeIndex,
571
617
  cells: slideCells,
@@ -586,7 +632,13 @@ const RevealSlidesComponent = ({
586
632
  return;
587
633
  }
588
634
  navigateDeckToActiveCell(deck);
589
- }, [activeIndex, cellToTarget, slideCells, navigateDeckToActiveCell]);
635
+ }, [
636
+ activeIndex,
637
+ canResolveInitialHash,
638
+ cellToTarget,
639
+ slideCells,
640
+ navigateDeckToActiveCell,
641
+ ]);
590
642
 
591
643
  // Toggling code (re)mounts a CodeMirror editor on the active slide. Defer
592
644
  // the state update so the button/keypress paints first and the heavier mount
@@ -612,18 +664,52 @@ const RevealSlidesComponent = ({
612
664
  );
613
665
  });
614
666
 
667
+ useEffect(() => {
668
+ const deck = deckRef.current;
669
+ if (deck) {
670
+ syncCodeToggleKeyBinding({
671
+ deck,
672
+ enabled: codeToggleEnabled,
673
+ onToggle: toggleShowCode,
674
+ });
675
+ }
676
+ return () => {
677
+ deckRef.current?.removeKeyBinding(CODE_TOGGLE_KEY_CODE);
678
+ };
679
+ }, [codeToggleEnabled, toggleShowCode]);
680
+
681
+ // Ignore programmatic preview navigation so the minimap selection remains
682
+ // pinned to the previewed cell.
683
+ const reportDeckCell = useEvent((deck: RevealApi) => {
684
+ if (parkedPreviewCell != null) {
685
+ return;
686
+ }
687
+ const flatIndex = resolveActiveCellIndex(
688
+ targetToCellIndex,
689
+ deck.getIndices(),
690
+ );
691
+ if (flatIndex != null) {
692
+ onSlideChange?.(flatIndex);
693
+ }
694
+ });
695
+
696
+ const reportCurrentCell = useEvent(() => {
697
+ const deck = deckRef.current;
698
+ if (deck) {
699
+ reportDeckCell(deck);
700
+ }
701
+ });
702
+
615
703
  const handleDeckReady = useEvent((deck: RevealApi) => {
616
704
  navigateDeckToActiveCell(deck);
617
- if (codeToggleEnabled) {
618
- deck.addKeyBinding(
619
- {
620
- keyCode: 67,
621
- key: "C",
622
- description: "Toggle code editor",
623
- },
624
- toggleShowCode,
625
- );
705
+ if (canResolveInitialHash) {
706
+ reportDeckCell(deck);
626
707
  }
708
+ syncCodeToggleKeyBinding({
709
+ deck,
710
+ enabled: codeToggleEnabled,
711
+ onToggle: toggleShowCode,
712
+ });
627
713
 
628
714
  // Reveal listens for `keydown` on `document` and bails when
629
715
  // `document.activeElement` is an input/contenteditable (e.g. the speaker
@@ -636,27 +722,6 @@ const RevealSlidesComponent = ({
636
722
  }
637
723
  });
638
724
 
639
- // Forward the deck's current cell to the parent, except while a parked
640
- // preview is parked: every reveal.js event during that window is an echo
641
- // of the programmatic park (possibly with transient indices), so ignoring
642
- // them keeps `activeCellId` pinned on the minimap cell.
643
- const reportCurrentCell = useEvent(() => {
644
- if (parkedPreviewCell != null) {
645
- return;
646
- }
647
- const deck = deckRef.current;
648
- if (!deck) {
649
- return;
650
- }
651
- const flatIndex = resolveActiveCellIndex(
652
- targetToCellIndex,
653
- deck.getIndices(),
654
- );
655
- if (flatIndex != null) {
656
- onSlideChange?.(flatIndex);
657
- }
658
- });
659
-
660
725
  // While parked on a preview, step through minimap order instead of
661
726
  // letting reveal.js advance from the parked slide the user can't see.
662
727
  const handleParkedNavKey = useEvent((event: KeyboardEvent) => {
@@ -0,0 +1,22 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import type { RuntimeKind } from "@/core/runtime/adapter";
4
+
5
+ export function createSpeakerViewUrl(href: string): string {
6
+ const url = new URL(href);
7
+ url.hash = "";
8
+ url.searchParams.set("kiosk", "true");
9
+ url.searchParams.set("show-chrome", "false");
10
+ return url.toString();
11
+ }
12
+
13
+ export function isSpeakerViewReceiver(
14
+ kioskMode: boolean,
15
+ search: string,
16
+ ): boolean {
17
+ return kioskMode && new URLSearchParams(search).has("receiver");
18
+ }
19
+
20
+ export function supportsSpeakerView(runtimeKind: RuntimeKind): boolean {
21
+ return runtimeKind !== "wasm";
22
+ }
@@ -12,6 +12,7 @@ import {
12
12
  } from "@/components/ui/dialog";
13
13
  import { toast } from "@/components/ui/use-toast";
14
14
  import { Constants } from "@/core/constants";
15
+ import { getExportLayout } from "@/core/export/layout";
15
16
  import { useRequestClient } from "@/core/network/requests";
16
17
  import { VirtualFileTracker } from "@/core/static/virtual-file-tracker";
17
18
  import { copyToClipboard } from "@/utils/copy";
@@ -44,6 +45,7 @@ export const ShareStaticNotebookModal: React.FC<{
44
45
  download: false,
45
46
  includeCode: true,
46
47
  files: VirtualFileTracker.INSTANCE.filenames(),
48
+ layout: await getExportLayout(),
47
49
  });
48
50
 
49
51
  const prevToast = toast({