@marimo-team/islands 0.19.7-dev35 → 0.19.7-dev37

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 (33) hide show
  1. package/dist/{glide-data-editor-DHsjQhtP.js → glide-data-editor-C3T7HsLi.js} +1 -1
  2. package/dist/main.js +32 -21
  3. package/dist/style.css +1 -1
  4. package/dist/{types-DBsIRhMX.js → types-CzEZ3EWT.js} +1 -1
  5. package/package.json +1 -1
  6. package/src/components/data-table/TableActions.tsx +5 -3
  7. package/src/components/data-table/download-actions.tsx +7 -2
  8. package/src/components/data-table/pagination.tsx +4 -4
  9. package/src/components/debug/indicator.tsx +1 -1
  10. package/src/components/editor/actions/useNotebookActions.tsx +4 -2
  11. package/src/components/editor/chrome/panels/context-aware-panel/context-aware-panel.tsx +1 -1
  12. package/src/components/editor/chrome/wrapper/app-chrome.tsx +6 -4
  13. package/src/components/editor/chrome/wrapper/footer-items/lsp-status.tsx +178 -0
  14. package/src/components/editor/chrome/wrapper/footer.tsx +1 -1
  15. package/src/components/editor/chrome/wrapper/sidebar.tsx +1 -1
  16. package/src/components/editor/controls/Controls.tsx +2 -2
  17. package/src/components/editor/controls/notebook-menu-dropdown.tsx +1 -1
  18. package/src/components/editor/file-tree/file-explorer.tsx +1 -1
  19. package/src/components/editor/header/status.tsx +1 -1
  20. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +13 -4
  21. package/src/components/home/components.tsx +1 -1
  22. package/src/components/static-html/static-banner.tsx +1 -1
  23. package/src/components/ui/dropdown-menu.tsx +1 -1
  24. package/src/components/ui/table.tsx +1 -1
  25. package/src/core/export/__tests__/hooks.test.ts +60 -58
  26. package/src/core/export/hooks.ts +71 -31
  27. package/src/core/network/types.ts +4 -0
  28. package/src/css/app/print.css +0 -14
  29. package/src/utils/__tests__/async-capture-tracker.test.ts +353 -0
  30. package/src/utils/__tests__/download.test.tsx +5 -114
  31. package/src/utils/async-capture-tracker.ts +168 -0
  32. package/src/utils/download.ts +17 -57
  33. package/src/utils/html-to-image.ts +9 -12
@@ -46,50 +46,21 @@ function findElementForCell(cellId: CellId): HTMLElement | undefined {
46
46
  return element;
47
47
  }
48
48
 
49
- /**
50
- * Reference counter for body.printing class to handle concurrent screenshot captures.
51
- * Only adds the class when count goes 0→1, only removes when count goes 1→0.
52
- */
53
- let bodyPrintingRefCount = 0;
54
-
55
- function acquireBodyPrinting() {
56
- bodyPrintingRefCount++;
57
- if (bodyPrintingRefCount === 1) {
58
- document.body.classList.add("printing");
59
- }
60
- }
61
-
62
- function releaseBodyPrinting() {
63
- bodyPrintingRefCount--;
64
- if (bodyPrintingRefCount === 0) {
65
- document.body.classList.remove("printing");
66
- }
67
- }
68
-
69
49
  /**
70
50
  * Prepare a cell element for screenshot capture.
71
51
  *
72
52
  * @param element - The cell output element to prepare
73
- * @param snappy - When true, avoids layout shifts and speeds up the capture.
74
53
  * @returns A cleanup function to restore the element's original state
75
54
  */
76
- function prepareCellElementForScreenshot(
77
- element: HTMLElement,
78
- snappy: boolean,
79
- ) {
80
- element.classList.add("printing-output");
81
- if (!snappy) {
82
- acquireBodyPrinting();
83
- }
55
+ function prepareCellElementForScreenshot(element: HTMLElement) {
84
56
  const originalOverflow = element.style.overflow;
85
- element.style.overflow = "auto";
57
+ const maxHeight = element.style.maxHeight;
58
+ element.style.overflow = "visible";
59
+ element.style.maxHeight = "none";
86
60
 
87
61
  return () => {
88
- element.classList.remove("printing-output");
89
- if (!snappy) {
90
- releaseBodyPrinting();
91
- }
92
62
  element.style.overflow = originalOverflow;
63
+ element.style.maxHeight = maxHeight;
93
64
  };
94
65
  }
95
66
 
@@ -99,12 +70,10 @@ const THRESHOLD_TIME_MS = 500;
99
70
  * Capture a cell output as a PNG data URL.
100
71
  *
101
72
  * @param cellId - The ID of the cell to capture
102
- * @param snappy - When true, uses a faster method to capture the image. Avoids layout shifts.
103
73
  * @returns The PNG as a data URL, or undefined if the cell element wasn't found
104
74
  */
105
75
  export async function getImageDataUrlForCell(
106
76
  cellId: CellId,
107
- snappy = false,
108
77
  ): Promise<string | undefined> {
109
78
  const element = findElementForCell(cellId);
110
79
  if (!element) {
@@ -116,11 +85,11 @@ export async function getImageDataUrlForCell(
116
85
  return iframeDataUrl;
117
86
  }
118
87
 
119
- const cleanup = prepareCellElementForScreenshot(element, snappy);
88
+ const cleanup = prepareCellElementForScreenshot(element);
120
89
 
121
90
  try {
122
91
  const startTime = Date.now();
123
- const dataUrl = await toPng(element, undefined, snappy);
92
+ const dataUrl = await toPng(element);
124
93
  const timeTaken = Date.now() - startTime;
125
94
  if (timeTaken > THRESHOLD_TIME_MS) {
126
95
  Logger.debug(
@@ -142,25 +111,20 @@ export async function downloadCellOutputAsImage(
142
111
  cellId: CellId,
143
112
  filename: string,
144
113
  ) {
145
- const element = findElementForCell(cellId);
146
- if (!element) {
147
- return;
148
- }
149
-
150
- // Cell outputs that are iframes
151
- const iframeDataUrl = await captureIframeAsImage(element);
152
- if (iframeDataUrl) {
153
- downloadByURL(iframeDataUrl, Filenames.toPNG(filename));
114
+ const dataUrl = await getImageDataUrlForCell(cellId);
115
+ if (!dataUrl) {
154
116
  return;
155
117
  }
156
-
157
- await downloadHTMLAsImage({
158
- element,
159
- filename,
160
- prepare: () => prepareCellElementForScreenshot(element, false),
161
- });
118
+ return downloadByURL(dataUrl, Filenames.toPNG(filename));
162
119
  }
163
120
 
121
+ export const ADD_PRINTING_CLASS = (): (() => void) => {
122
+ document.body.classList.add("printing");
123
+ return () => {
124
+ document.body.classList.remove("printing");
125
+ };
126
+ };
127
+
164
128
  export async function downloadHTMLAsImage(opts: {
165
129
  element: HTMLElement;
166
130
  filename: string;
@@ -175,10 +139,6 @@ export async function downloadHTMLAsImage(opts: {
175
139
  let cleanup: (() => void) | undefined;
176
140
  if (prepare) {
177
141
  cleanup = prepare(element);
178
- } else {
179
- // When no prepare function is provided (e.g., downloading full notebook),
180
- // add body.printing ourselves
181
- document.body.classList.add("printing");
182
142
  }
183
143
 
184
144
  try {
@@ -113,10 +113,9 @@ export const necessaryStyleProperties = [
113
113
  "clip-path",
114
114
 
115
115
  // Overflow & Visibility
116
- // We don't include overflow properties because they can include scrollbars
117
- // "overflow",
118
- // "overflow-x",
119
- // "overflow-y",
116
+ "overflow",
117
+ "overflow-x",
118
+ "overflow-y",
120
119
  "visibility",
121
120
 
122
121
  // SVG
@@ -149,12 +148,11 @@ export const defaultHtmlToImageOptions: HtmlToImageOptions = {
149
148
  filter: (node) => {
150
149
  try {
151
150
  if ("classList" in node) {
152
- // Filter out matplotlib toolbars
153
- if (node.classList.contains("mpl-toolbar")) {
154
- return false;
155
- }
156
-
157
- if (node.classList.contains("no-print")) {
151
+ const classes = node.classList;
152
+ if (
153
+ classes.contains("mpl-toolbar") ||
154
+ classes.contains("print:hidden")
155
+ ) {
158
156
  return false;
159
157
  }
160
158
  }
@@ -167,6 +165,7 @@ export const defaultHtmlToImageOptions: HtmlToImageOptions = {
167
165
  onImageErrorHandler: (event) => {
168
166
  Logger.error("Error loading image:", event);
169
167
  },
168
+ includeStyleProperties: necessaryStyleProperties,
170
169
  };
171
170
 
172
171
  /**
@@ -176,11 +175,9 @@ export const defaultHtmlToImageOptions: HtmlToImageOptions = {
176
175
  export async function toPng(
177
176
  element: HTMLElement,
178
177
  options?: HtmlToImageOptions,
179
- snappy?: boolean,
180
178
  ): Promise<string> {
181
179
  return htmlToImageToPng(element, {
182
180
  ...defaultHtmlToImageOptions,
183
- includeStyleProperties: snappy ? necessaryStyleProperties : undefined,
184
181
  ...options,
185
182
  });
186
183
  }