@marimo-team/islands 0.23.7-dev0 → 0.23.7-dev2
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.
|
@@ -8,7 +8,7 @@ import { t as require_react } from "./react-DA-nE2FX.js";
|
|
|
8
8
|
import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
9
9
|
import "./html-to-image-hMMPiNe_.js";
|
|
10
10
|
import "./chunk-5FQGJX7Z-CO1e63h_.js";
|
|
11
|
-
import {
|
|
11
|
+
import { Ft as Code, Mt as Expand, a as DEFAULT_SLIDE_TYPE, c as Slide, i as DEFAULT_DECK_TRANSITION, jt as EyeOff, s as SlideSidebar, t as useNotebookCodeAvailable } from "./code-visibility-BZocwq8O.js";
|
|
12
12
|
import "./input-BAOe64zx.js";
|
|
13
13
|
import "./toDate-CHtl9vts.js";
|
|
14
14
|
import "./react-dom-BWRJ_g_k.js";
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@ import { useLocale } from "react-aria";
|
|
|
12
12
|
import { logNever } from "@/utils/assertNever";
|
|
13
13
|
import { cn } from "@/utils/cn";
|
|
14
14
|
import { copyToClipboard } from "@/utils/copy";
|
|
15
|
-
import { downloadByURL } from "@/utils/download";
|
|
15
|
+
import { downloadByURL, withLoadingToast } from "@/utils/download";
|
|
16
16
|
import { prettyError } from "@/utils/errors";
|
|
17
17
|
import { Filenames } from "@/utils/filenames";
|
|
18
18
|
import {
|
|
@@ -33,17 +33,6 @@ import {
|
|
|
33
33
|
import { Tooltip } from "../ui/tooltip";
|
|
34
34
|
import { toast } from "../ui/use-toast";
|
|
35
35
|
|
|
36
|
-
type DownloadFormat = "csv" | "json" | "parquet";
|
|
37
|
-
|
|
38
|
-
export interface ExportActionProps {
|
|
39
|
-
downloadAs: (req: { format: DownloadFormat }) => Promise<{
|
|
40
|
-
url: string;
|
|
41
|
-
filename: string;
|
|
42
|
-
error?: string | null;
|
|
43
|
-
missing_packages?: string[] | null;
|
|
44
|
-
}>;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
36
|
const FILE_TYPES = {
|
|
48
37
|
CSV: {
|
|
49
38
|
label: "CSV",
|
|
@@ -84,8 +73,23 @@ const copyOptions = [
|
|
|
84
73
|
FILE_TYPES.CSV,
|
|
85
74
|
FILE_TYPES.MARKDOWN,
|
|
86
75
|
];
|
|
76
|
+
|
|
77
|
+
type DownloadFormat = (typeof downloadOptions)[number]["format"];
|
|
78
|
+
type CopyFormat = (typeof copyOptions)[number]["format"];
|
|
79
|
+
|
|
80
|
+
export interface ExportActionProps {
|
|
81
|
+
downloadAs: (req: { format: DownloadFormat }) => Promise<{
|
|
82
|
+
url: string;
|
|
83
|
+
filename: string;
|
|
84
|
+
error?: string | null;
|
|
85
|
+
missing_packages?: string[] | null;
|
|
86
|
+
}>;
|
|
87
|
+
}
|
|
88
|
+
|
|
87
89
|
const labelForDownloadFormat = (format: DownloadFormat): string =>
|
|
88
90
|
downloadOptions.find((opt) => opt.format === format)?.label ?? format;
|
|
91
|
+
const labelForCopyFormat = (format: CopyFormat): string =>
|
|
92
|
+
copyOptions.find((opt) => opt.format === format)?.label ?? format;
|
|
89
93
|
|
|
90
94
|
export const ExportMenu: React.FC<ExportActionProps> = (props) => {
|
|
91
95
|
const { locale } = useLocale();
|
|
@@ -143,71 +147,84 @@ export const ExportMenu: React.FC<ExportActionProps> = (props) => {
|
|
|
143
147
|
};
|
|
144
148
|
|
|
145
149
|
const handleDownload = async (format: DownloadFormat) => {
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
150
|
+
const label = labelForDownloadFormat(format);
|
|
151
|
+
const ok = await withLoadingToast(
|
|
152
|
+
`Preparing ${label} export...`,
|
|
153
|
+
async () => {
|
|
154
|
+
const result = await resolveDownloadUrl(format, () => {
|
|
155
|
+
void handleDownload(format);
|
|
156
|
+
});
|
|
157
|
+
if (!result) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
const rawName = (result.filename ?? "").trim();
|
|
161
|
+
const baseName = Filenames.withoutExtension(rawName) || "download";
|
|
162
|
+
const downloadName = `${baseName}.${format}`;
|
|
163
|
+
// Append ?download=1 so the server returns Content-Disposition: attachment.
|
|
164
|
+
// This forces a save even when <a download> is ignored — e.g., inside
|
|
165
|
+
// sandboxed iframes that lack `allow-downloads`. Skip for data: URLs
|
|
166
|
+
// (used in pyodide/wasm) since query params would corrupt the payload.
|
|
167
|
+
let downloadUrl = result.url;
|
|
168
|
+
if (!downloadUrl.startsWith("data:")) {
|
|
169
|
+
const separator = downloadUrl.includes("?") ? "&" : "?";
|
|
170
|
+
const params = new URLSearchParams({
|
|
171
|
+
download: "1",
|
|
172
|
+
filename: downloadName,
|
|
173
|
+
});
|
|
174
|
+
downloadUrl = `${downloadUrl}${separator}${params.toString()}`;
|
|
175
|
+
}
|
|
176
|
+
downloadByURL(downloadUrl, downloadName);
|
|
177
|
+
return true;
|
|
178
|
+
},
|
|
179
|
+
);
|
|
180
|
+
if (ok) {
|
|
181
|
+
toast({ title: `${label} download started` });
|
|
167
182
|
}
|
|
168
|
-
downloadByURL(downloadUrl, downloadName);
|
|
169
183
|
};
|
|
170
184
|
|
|
171
|
-
const handleClipboardCopy = async (
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
185
|
+
const handleClipboardCopy = async (format: CopyFormat) => {
|
|
186
|
+
await withLoadingToast(
|
|
187
|
+
`Preparing ${labelForCopyFormat(format)} for clipboard...`,
|
|
188
|
+
async () => {
|
|
189
|
+
const sourceFormat: DownloadFormat = format === "csv" ? "csv" : "json";
|
|
190
|
+
const result = await resolveDownloadUrl(sourceFormat, () => {
|
|
191
|
+
void handleClipboardCopy(format);
|
|
192
|
+
});
|
|
193
|
+
if (!result) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
181
196
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
197
|
+
let text: string;
|
|
198
|
+
switch (format) {
|
|
199
|
+
case "tsv": {
|
|
200
|
+
const json = await fetchJson(result.url);
|
|
201
|
+
text = jsonToTSV(json, locale);
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
case "json": {
|
|
205
|
+
const json = await fetchJson(result.url);
|
|
206
|
+
text = JSON.stringify(json, null, 2);
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
case "csv":
|
|
210
|
+
text = await fetchText(result.url);
|
|
211
|
+
break;
|
|
212
|
+
case "markdown": {
|
|
213
|
+
const json = await fetchJson(result.url);
|
|
214
|
+
text = jsonToMarkdown(json);
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
default:
|
|
218
|
+
logNever(format);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
206
221
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
222
|
+
await copyToClipboard(text);
|
|
223
|
+
toast({
|
|
224
|
+
title: "Copied to clipboard",
|
|
225
|
+
});
|
|
226
|
+
},
|
|
227
|
+
);
|
|
211
228
|
};
|
|
212
229
|
|
|
213
230
|
return (
|