@marimo-team/islands 0.23.16-dev42 → 0.23.16-dev45

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.
@@ -36338,7 +36338,7 @@ ${d}`,
36338
36338
  return Logger.warn("Failed to get version from mount config"), null;
36339
36339
  }
36340
36340
  }
36341
- marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.16-dev42");
36341
+ marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.16-dev45");
36342
36342
  showCodeInRunModeAtom = atom(true);
36343
36343
  atom(null);
36344
36344
  var import_compiler_runtime = require_compiler_runtime();
package/dist/main.js CHANGED
@@ -26,7 +26,7 @@ import { $ as notebookOutline, $t as publishedCellClasses, A as ChevronDownIcon,
26
26
  import { __tla as __tla_1 } from "./chunk-5FQGJX7Z-B9WoXK1R.js";
27
27
  import { o as useSize, s as Root$1, u as createLucideIcon } from "./dist-DIlxLFXG.js";
28
28
  import { A as SquareFunction, C as DEFAULT_COLOR_SCHEME, D as SCALE_TYPE_DESCRIPTIONS, E as EMPTY_VALUE$1, O as TIME_UNIT_DESCRIPTIONS, S as DEFAULT_AGGREGATION, T as DEFAULT_TIME_UNIT, _ as AGGREGATION_TYPE_DESCRIPTIONS, a as AGGREGATION_FNS$1, b as COLOR_SCHEMES, c as COLOR_BY_FIELDS, d as NONE_VALUE, f as SELECTABLE_DATA_TYPES, g as TIME_UNITS, h as STRING_AGGREGATION_FNS, i as convertDataTypeToSelectable, j as ChartColumn, k as escapeFieldName, l as COMBINED_TIME_UNITS, m as SORT_TYPES, n as createSpecWithoutData, o as BIN_AGGREGATION, p as SINGLE_TIME_UNITS, r as isFieldSet, s as CHART_TYPES, t as augmentSpecWithData, u as ChartType, v as AGGREGATION_TYPE_ICON, w as DEFAULT_MAX_BINS_FACET, x as COUNT_FIELD, y as CHART_TYPE_ICON } from "./spec-CQKL_D3i.js";
29
- import { $ as CommandSeparator, $t as Kbd, A as ErrorState, At as getPageIndexForRow, B as ContextMenuTrigger, Bt as dateToLocalISODate, C as downloadHTMLAsImage, Ct as inferFieldTypes, D as ColumnName, Dt as DelayMount, E as downloadSizeLimitAtom, Et as ColumnChartSpecModel, F as getUserColumnVisibilityCounts, Ft as TOO_MANY_ROWS, G as DateRangePicker, Gt as TabsList, H as useSelectList, Ht as dateToLocalISOTime, I as ContextMenu, It as toFieldTypes, J as Command, Jt as ChartInfoState, K as Combobox, Kt as TabsTrigger, L as ContextMenuContent, Lt as getMimeValues, M as prettifyRowColumnCount, Mt as loadTableData, N as prettifyRowCount, Nt as INDEX_COLUMN_NAME, O as ColumnPreviewContainer, Ot as useIntersectionObserver, P as getColumnCountForDisplay, Pt as SELECT_COLUMN_ID, Q as CommandList, Qt as RenderTextWithLinks, R as ContextMenuItem, Rt as isNullishFilter, S as downloadExportedFile, St as generateColumns, T as Filenames, Tt as ColumnChartContext, U as CompactChipRow, Ut as Tabs, V as useInternalStateWithSync, Vt as dateToLocalISODateTime, W as DatePicker, Wt as TabsContent, X as CommandInput, Xt as LazyVegaEmbed, Y as CommandEmpty, Yt as ChartLoadingState, Z as CommandItem, Zt as useOverflowDetection, _ as DataTable, _n as ChevronLeft, _t as TableCell, an as TextWrap, at as contextAwarePanelType, b as downloadBlob, bt as TableRow, c as SLIDE_TYPE_OPTIONS_BY_VALUE, cn as EyeOff, ct as slotsController, d as Switch, dn as Download, en as HtmlOutput, et as smartMatch, f as RadioGroup, fn as Code, g as OutputRenderer, gn as ChevronsDownUp, gt as TableBody, h as OutputArea, hn as ChevronsLeft, ht as Table, i as showCodeInRunModeAtom, in as $fae977aafc393c5c$export$6b862160d295c8e, it as contextAwarePanelOwner, j as LoadingState, jt as loadTableAndRawData, k as EmptyState, kt as usePrevious$1, lt as Toggle, m as JsonOutput, mn as ChevronsRight, mt as Provider$1, n as useNotebookCodeAvailable, nn as safeLocale, nt as PANEL_TYPES, on as GripHorizontal, ot as isCellAwareAtom, p as RadioGroupItem, pn as ChevronsUpDown, pt as Fill, q as ComboboxItem, qt as ChartErrorState, r as marimoVersionAtom, rn as $fae977aafc393c5c$export$588937bcd60ade55, rt as contextAwarePanelOpen, sn as Funnel, st as SlotNames, t as cellDomProps, tn as EmotionCacheProvider, tt as ContextAwarePanelItem, u as Slide, un as Ellipsis, v as InstallPackageButton, vn as ArrowDownWideNarrow, vt as TableHead, w as Progress, wt as renderCellValue, x as downloadByURL, xt as NAMELESS_COLUMN_PREFIX, y as ADD_PRINTING_CLASS, yt as TableHeader, z as ContextMenuSeparator, zt as Maps, __tla as __tla_2 } from "./common-Cpyr1gtj.js";
29
+ import { $ as CommandSeparator, $t as Kbd, A as ErrorState, At as getPageIndexForRow, B as ContextMenuTrigger, Bt as dateToLocalISODate, C as downloadHTMLAsImage, Ct as inferFieldTypes, D as ColumnName, Dt as DelayMount, E as downloadSizeLimitAtom, Et as ColumnChartSpecModel, F as getUserColumnVisibilityCounts, Ft as TOO_MANY_ROWS, G as DateRangePicker, Gt as TabsList, H as useSelectList, Ht as dateToLocalISOTime, I as ContextMenu, It as toFieldTypes, J as Command, Jt as ChartInfoState, K as Combobox, Kt as TabsTrigger, L as ContextMenuContent, Lt as getMimeValues, M as prettifyRowColumnCount, Mt as loadTableData, N as prettifyRowCount, Nt as INDEX_COLUMN_NAME, O as ColumnPreviewContainer, Ot as useIntersectionObserver, P as getColumnCountForDisplay, Pt as SELECT_COLUMN_ID, Q as CommandList, Qt as RenderTextWithLinks, R as ContextMenuItem, Rt as isNullishFilter, S as downloadExportedFile, St as generateColumns, T as Filenames, Tt as ColumnChartContext, U as CompactChipRow, Ut as Tabs, V as useInternalStateWithSync, Vt as dateToLocalISODateTime, W as DatePicker, Wt as TabsContent, X as CommandInput, Xt as LazyVegaEmbed, Y as CommandEmpty, Yt as ChartLoadingState, Z as CommandItem, Zt as useOverflowDetection, _ as DataTable, _n as ChevronLeft, _t as TableCell, an as TextWrap, at as contextAwarePanelType, b as downloadBlob, bt as TableRow, c as SLIDE_TYPE_OPTIONS_BY_VALUE, cn as EyeOff, ct as slotsController, d as Switch, dn as Download, en as HtmlOutput, et as smartMatch, f as RadioGroup, fn as Code, g as OutputRenderer, gn as ChevronsDownUp, gt as TableBody, h as OutputArea, hn as ChevronsLeft, ht as Table, i as showCodeInRunModeAtom, in as $fae977aafc393c5c$export$6b862160d295c8e, it as contextAwarePanelOwner, j as LoadingState, jt as loadTableAndRawData, k as EmptyState, kt as usePrevious$1, lt as Toggle, m as JsonOutput, mn as ChevronsRight, mt as Provider$1, n as useNotebookCodeAvailable, nn as safeLocale, nt as PANEL_TYPES, on as GripHorizontal, ot as isCellAwareAtom, p as RadioGroupItem, pn as ChevronsUpDown, pt as Fill, q as ComboboxItem, qt as ChartErrorState, r as marimoVersionAtom, rn as $fae977aafc393c5c$export$588937bcd60ade55, rt as contextAwarePanelOpen, sn as Funnel, st as SlotNames, t as cellDomProps, tn as EmotionCacheProvider, tt as ContextAwarePanelItem, u as Slide, un as Ellipsis, v as InstallPackageButton, vn as ArrowDownWideNarrow, vt as TableHead, w as Progress, wt as renderCellValue, x as downloadByURL, xt as NAMELESS_COLUMN_PREFIX, y as ADD_PRINTING_CLASS, yt as TableHeader, z as ContextMenuSeparator, zt as Maps, __tla as __tla_2 } from "./common-CWszsqAm.js";
30
30
  import { c as Calendar, i as createReducerAndAtoms, n as useOnUnmount, o as ToggleLeft, t as useOnMount } from "./useLifecycle-CMJGqBaY.js";
31
31
  import { t as Check } from "./check-DP7U0H0G.js";
32
32
  import { A as Icon, C as logNever, D as $18f2051aff69b9bf$export$a54013f0d02a8f82, E as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7, F as createCollection, I as X, M as clamp$2, N as usePrevious$2, P as useDirection, R as ChevronDown, S as assertNever, a as SelectGroup, c as SelectSeparator, d as NativeSelect, i as SelectContent, j as Trigger$1, l as SelectTrigger, n as capitalize, o as SelectItem, r as Select, s as SelectLabel, t as Strings, u as SelectValue, w as $a916eb452884faea$export$b7a616150fdb9f44 } from "./strings-DIy9NAmg.js";
@@ -38147,7 +38147,7 @@ ${c}
38147
38147
  function _temp2$2(e) {
38148
38148
  e.target === e.currentTarget && e.key === "Enter" && (e.preventDefault(), e.stopPropagation(), e.currentTarget.click());
38149
38149
  }
38150
- var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-WrehlJCP.js"));
38150
+ var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-C1UBr2Io.js"));
38151
38151
  const SlidesLayoutRenderer = ({ layout: e, setLayout: r, cells: c, mode: l }) => {
38152
38152
  var _a5;
38153
38153
  let u = useAtomValue(kioskModeAtom), d = l === "read" || u, f = useAtomValue(numColumnsAtom) > 1, [p, m] = (0, import_react.useState)(null), { slideCells: h, skippedIds: g, noOutputIds: _, slideTypes: v, startCellIndex: y } = (0, import_react.useMemo)(() => computeSlideCellsInfo(c, e), [
@@ -9,7 +9,7 @@ import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
9
9
  import { ut as outputIsStale } from "./html-to-image-3w0AakWW.js";
10
10
  import "./chunk-5FQGJX7Z-B9WoXK1R.js";
11
11
  import { u as createLucideIcon } from "./dist-DIlxLFXG.js";
12
- import { a as DEFAULT_DECK_TRANSITION, cn as EyeOff, dt as PanelGroup, fn as Code, ft as PanelResizeHandle, l as SlideSidebar, ln as Expand, n as useNotebookCodeAvailable, o as DEFAULT_DECK_VERTICAL_ALIGN, s as DEFAULT_SLIDE_TYPE, t as cellDomProps, u as Slide, ut as Panel } from "./common-Cpyr1gtj.js";
12
+ import { a as DEFAULT_DECK_TRANSITION, cn as EyeOff, dt as PanelGroup, fn as Code, ft as PanelResizeHandle, l as SlideSidebar, ln as Expand, n as useNotebookCodeAvailable, o as DEFAULT_DECK_VERTICAL_ALIGN, s as DEFAULT_SLIDE_TYPE, t as cellDomProps, u as Slide, ut as Panel } from "./common-CWszsqAm.js";
13
13
  import { R as ChevronDown } from "./strings-DIy9NAmg.js";
14
14
  import { X as useDebouncedCallback } from "./input-C5K4VBvB.js";
15
15
  import { v as kioskModeAtom } from "./toDate-CqhBWjvO.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.23.16-dev42",
3
+ "version": "0.23.16-dev45",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -54,6 +54,20 @@ describe("ViewerBanner", () => {
54
54
  expect(container).toBeEmptyDOMElement();
55
55
  });
56
56
 
57
+ it("pins the banner without reserving layout space", () => {
58
+ const store = createStore();
59
+ store.set(kioskModeAtom, true);
60
+ render(
61
+ <Provider store={store}>
62
+ <TooltipProvider>
63
+ <ViewerBanner />
64
+ </TooltipProvider>
65
+ </Provider>,
66
+ );
67
+ const wrapper = screen.getByTestId("takeover-button").closest("div.sticky");
68
+ expect(wrapper).toHaveClass("sticky", "top-2", "h-0");
69
+ });
70
+
57
71
  it("renders nothing in present mode", () => {
58
72
  const store = createStore();
59
73
  store.set(kioskModeAtom, true);
@@ -4,35 +4,58 @@ import { describe, expect, it, vi } from "vitest";
4
4
  import { runServerSidePDFDownload } from "../pdf-export";
5
5
 
6
6
  describe("runServerSidePDFDownload", () => {
7
- it("downloads document preset via backend PDF endpoint", async () => {
8
- const downloadPDF = vi.fn().mockResolvedValue(undefined);
7
+ it("captures current outputs before downloading the PDF", async () => {
8
+ const calls: string[] = [];
9
+ const captureOutputs = vi.fn(async () => {
10
+ calls.push("capture:start");
11
+ await Promise.resolve();
12
+ calls.push("capture:end");
13
+ });
14
+ const downloadPDF = vi.fn(async () => {
15
+ calls.push("download");
16
+ });
9
17
 
10
18
  await runServerSidePDFDownload({
11
- preset: "document",
19
+ exportOptions: {
20
+ webpdf: false,
21
+ preset: "document",
22
+ includeInputs: true,
23
+ includeOutputs: true,
24
+ },
25
+ captureOutputs,
12
26
  downloadPDF,
13
27
  });
14
28
 
29
+ expect(calls).toEqual(["capture:start", "capture:end", "download"]);
15
30
  expect(downloadPDF).toHaveBeenCalledWith({
16
31
  webpdf: false,
17
32
  preset: "document",
18
33
  includeInputs: true,
19
- rasterServer: "static",
34
+ includeOutputs: true,
20
35
  });
21
36
  });
22
37
 
23
- it("downloads slides preset via backend PDF endpoint", async () => {
38
+ it("skips browser capture when outputs are excluded", async () => {
39
+ const captureOutputs = vi.fn().mockResolvedValue(undefined);
24
40
  const downloadPDF = vi.fn().mockResolvedValue(undefined);
25
41
 
26
42
  await runServerSidePDFDownload({
27
- preset: "slides",
43
+ exportOptions: {
44
+ webpdf: true,
45
+ preset: "slides",
46
+ includeInputs: false,
47
+ includeOutputs: false,
48
+ },
49
+ captureOutputs,
28
50
  downloadPDF,
29
51
  });
30
52
 
53
+ expect(captureOutputs).not.toHaveBeenCalled();
31
54
  expect(downloadPDF).toHaveBeenCalledWith({
32
- webpdf: false,
55
+ webpdf: true,
33
56
  preset: "slides",
34
- includeInputs: true,
35
- rasterServer: "static",
57
+ includeInputs: false,
58
+ includeOutputs: false,
36
59
  });
37
60
  });
38
61
  });
@@ -1,23 +1,23 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  type Preset = "document" | "slides";
4
- type DownloadPDF = (opts: {
4
+ interface PDFExportOptions {
5
5
  webpdf: boolean;
6
6
  preset: Preset;
7
7
  includeInputs: boolean;
8
- rasterServer: "live" | "static";
9
- }) => Promise<void>;
8
+ includeOutputs: boolean;
9
+ }
10
+ type DownloadPDF = (opts: PDFExportOptions) => Promise<void>;
10
11
 
11
12
  export async function runServerSidePDFDownload(opts: {
12
- preset: Preset;
13
+ exportOptions: PDFExportOptions;
14
+ captureOutputs: () => Promise<void>;
13
15
  downloadPDF: DownloadPDF;
14
16
  }): Promise<void> {
15
- const { preset, downloadPDF } = opts;
17
+ const { exportOptions, captureOutputs, downloadPDF } = opts;
16
18
 
17
- await downloadPDF({
18
- webpdf: false,
19
- preset,
20
- includeInputs: true,
21
- rasterServer: "static",
22
- });
19
+ if (exportOptions.includeOutputs) {
20
+ await captureOutputs();
21
+ }
22
+ await downloadPDF(exportOptions);
23
23
  }
@@ -193,12 +193,18 @@ export function useNotebookActions() {
193
193
  }
194
194
 
195
195
  const runDownload = async (progress: ProgressState) => {
196
- await updateCellOutputsWithScreenshots({
197
- takeScreenshots: () => takeScreenshots({ progress }),
198
- updateCellOutputs,
199
- });
200
196
  await runServerSidePDFDownload({
201
- preset,
197
+ exportOptions: {
198
+ webpdf: false,
199
+ preset,
200
+ includeInputs: true,
201
+ includeOutputs: true,
202
+ },
203
+ captureOutputs: () =>
204
+ updateCellOutputsWithScreenshots({
205
+ takeScreenshots: () => takeScreenshots({ progress }),
206
+ updateCellOutputs,
207
+ }),
202
208
  downloadPDF: downloadAsPDF,
203
209
  });
204
210
  };
@@ -51,8 +51,11 @@ export const ViewerBanner = () => {
51
51
  }
52
52
  };
53
53
 
54
+ // A zero-height sticky row pins the banner to the top-left of the notebook
55
+ // scroll area, so it stays visible while scrolling without reserving space in
56
+ // the flow.
54
57
  return (
55
- <div className="absolute top-2 left-2 z-50 w-fit print:hidden">
58
+ <div className="sticky top-2 left-2 z-50 h-0 ml-2 w-fit print:hidden">
56
59
  <Banner
57
60
  kind="info"
58
61
  className="flex items-center gap-2 rounded px-2 py-1 text-xs shadow-sm"
@@ -164,6 +164,7 @@ export const EditApp: React.FC<AppProps> = ({
164
164
  width={appConfig.width}
165
165
  onReconnect={reconnect}
166
166
  >
167
+ <ViewerBanner />
167
168
  <AppHeader
168
169
  connection={connection}
169
170
  className={cn(
@@ -179,8 +180,6 @@ export const EditApp: React.FC<AppProps> = ({
179
180
  )}
180
181
  </AppHeader>
181
182
 
182
- <ViewerBanner />
183
-
184
183
  {/* Don't render until we have a single cell. NotStartedConnectionAlert
185
184
  still covers the "no remote runtime started" prompt. */}
186
185
  <ProgressiveBoundary
@@ -648,8 +648,7 @@ describe("updateCellOutputsWithScreenshots", () => {
648
648
  );
649
649
  expect(toast).toHaveBeenCalledWith({
650
650
  title: "Failed to capture cell outputs",
651
- description:
652
- "Some outputs may not appear in the PDF. Continuing with export.",
651
+ description: "Some outputs may be missing from the export. Continuing.",
653
652
  variant: "danger",
654
653
  });
655
654
  });
@@ -679,8 +678,7 @@ describe("updateCellOutputsWithScreenshots", () => {
679
678
  );
680
679
  expect(toast).toHaveBeenCalledWith({
681
680
  title: "Failed to capture cell outputs",
682
- description:
683
- "Some outputs may not appear in the PDF. Continuing with export.",
681
+ description: "Some outputs may be missing from the export. Continuing.",
684
682
  variant: "danger",
685
683
  });
686
684
  });
@@ -112,7 +112,9 @@ interface UseEnrichCellOutputsOptions {
112
112
  }
113
113
 
114
114
  /**
115
- * Take screenshots of cells with HTML outputs. These images will be sent to the backend to be exported to IPYNB.
115
+ * Capture browser-rendered cell outputs for current-session exports.
116
+ *
117
+ * The caller uploads these PNG representations before requesting an export.
116
118
  * @returns A map of cell IDs to their screenshots data.
117
119
  */
118
120
  export function useEnrichCellOutputs(): (
@@ -221,8 +223,7 @@ export async function updateCellOutputsWithScreenshots(opts: {
221
223
  Logger.error("Error updating cell outputs with screenshots:", error);
222
224
  toast({
223
225
  title: "Failed to capture cell outputs",
224
- description:
225
- "Some outputs may not appear in the PDF. Continuing with export.",
226
+ description: "Some outputs may be missing from the export. Continuing.",
226
227
  variant: "danger",
227
228
  });
228
229
  }
@@ -205,9 +205,26 @@ describe("downloadAsPDF", () => {
205
205
  webpdf: false,
206
206
  preset: "slides",
207
207
  includeInputs: true,
208
- rasterizeOutputs: true,
209
- rasterScale: 4,
210
- rasterServer: "static",
208
+ includeOutputs: true,
209
+ });
210
+ });
211
+
212
+ it("should send input and output selections", async () => {
213
+ mockExportAsPDF.mockRejectedValue(new Error("network"));
214
+
215
+ await expect(
216
+ downloadAsPDF({
217
+ webpdf: true,
218
+ includeInputs: false,
219
+ includeOutputs: false,
220
+ }),
221
+ ).rejects.toThrow("network");
222
+
223
+ expect(mockExportAsPDF).toHaveBeenCalledWith({
224
+ webpdf: true,
225
+ preset: "document",
226
+ includeInputs: false,
227
+ includeOutputs: false,
211
228
  });
212
229
  });
213
230
  });
@@ -211,18 +211,14 @@ export async function downloadAsPDF(opts: {
211
211
  webpdf: boolean;
212
212
  preset?: PDFExportPreset;
213
213
  includeInputs?: boolean;
214
- rasterizeOutputs?: boolean;
215
- rasterScale?: number;
216
- rasterServer?: "static" | "live";
214
+ includeOutputs?: boolean;
217
215
  }) {
218
216
  const client = getRequestClient();
219
217
  const {
220
218
  webpdf,
221
219
  preset = "document",
222
220
  includeInputs = true,
223
- rasterizeOutputs = true,
224
- rasterScale = 4,
225
- rasterServer = "static",
221
+ includeOutputs = true,
226
222
  } = opts;
227
223
 
228
224
  try {
@@ -230,9 +226,7 @@ export async function downloadAsPDF(opts: {
230
226
  webpdf,
231
227
  preset,
232
228
  includeInputs,
233
- rasterizeOutputs,
234
- rasterScale,
235
- rasterServer,
229
+ includeOutputs,
236
230
  });
237
231
 
238
232
  downloadExportedFile(exportedFile);