@marimo-team/islands 0.21.2-dev44 → 0.21.2-dev47

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/main.js CHANGED
@@ -70883,7 +70883,7 @@ Image URL: ${r.imageUrl}`)), contextToXml({
70883
70883
  return Logger.warn("Failed to get version from mount config"), null;
70884
70884
  }
70885
70885
  }
70886
- const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.21.2-dev44"), showCodeInRunModeAtom = atom(true);
70886
+ const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.21.2-dev47"), showCodeInRunModeAtom = atom(true);
70887
70887
  atom(null);
70888
70888
  var import_compiler_runtime$89 = require_compiler_runtime();
70889
70889
  function useKeydownOnElement(e, r) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.21.2-dev44",
3
+ "version": "0.21.2-dev47",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -4,27 +4,32 @@ import { FileIcon, LoaderCircle, RefreshCwIcon } from "lucide-react";
4
4
  import type React from "react";
5
5
  import { useCallback } from "react";
6
6
  import { useLocale } from "react-aria";
7
+ import { useAddCodeToNewCell } from "@/components/editor/cell/useAddCell";
7
8
  import { FilePreviewHeader } from "@/components/editor/file-tree/file-header";
8
9
  import { renderFileIcon } from "@/components/editor/file-tree/file-icons";
9
10
  import {
10
11
  FileContentRenderer,
11
12
  isMediaMime,
12
13
  } from "@/components/editor/file-tree/renderers";
14
+ import { Tooltip } from "@/components/ui/tooltip";
13
15
  import { toast } from "@/components/ui/use-toast";
14
16
  import { DownloadStorage } from "@/core/storage/request-registry";
15
- import type { StorageEntry } from "@/core/storage/types";
17
+ import type { StorageEntry, StorageNamespace } from "@/core/storage/types";
16
18
  import { useAsyncData } from "@/hooks/useAsyncData";
17
19
  import { downloadByURL } from "@/utils/download";
18
20
  import { formatBytes } from "@/utils/formatting";
19
21
  import { Logger } from "@/utils/Logger";
20
22
  import { CopyClipboardIcon } from "../icons/copy-icon";
21
23
  import { Button } from "../ui/button";
24
+ import { STORAGE_SNIPPETS } from "./storage-snippets";
22
25
 
23
26
  const MAX_MEDIA_PREVIEW_SIZE = 100 * 1024 * 1024; // 100 MB
24
27
 
25
28
  interface Props {
26
29
  entry: StorageEntry;
27
30
  namespace: string;
31
+ protocol: string;
32
+ backendType: StorageNamespace["backendType"];
28
33
  onBack: () => void;
29
34
  }
30
35
 
@@ -41,9 +46,12 @@ type PreviewData =
41
46
  export const StorageFileViewer: React.FC<Props> = ({
42
47
  entry,
43
48
  namespace,
49
+ protocol,
50
+ backendType,
44
51
  onBack,
45
52
  }) => {
46
53
  const { locale } = useLocale();
54
+ const addCodeToNewCell = useAddCodeToNewCell();
47
55
  const name = displayName(entry.path);
48
56
  const mime = entry.mimeType || "text/plain";
49
57
  const isMedia = isMediaMime(mime);
@@ -111,12 +119,38 @@ export const StorageFileViewer: React.FC<Props> = ({
111
119
  }
112
120
  }, [namespace, entry.path, name]);
113
121
 
122
+ const snippetActions = STORAGE_SNIPPETS.map((snippet) => {
123
+ const code = snippet.getCode({
124
+ variableName: namespace,
125
+ protocol,
126
+ entry,
127
+ backendType,
128
+ });
129
+ if (code === null) {
130
+ return null;
131
+ }
132
+ const Icon = snippet.icon;
133
+ return (
134
+ <Tooltip key={snippet.id} content={snippet.label}>
135
+ <Button
136
+ variant="text"
137
+ size="xs"
138
+ onClick={() => addCodeToNewCell(code)}
139
+ aria-label={snippet.label}
140
+ >
141
+ <Icon className="h-3.5 w-3.5" />
142
+ </Button>
143
+ </Tooltip>
144
+ );
145
+ });
146
+
114
147
  const header = (
115
148
  <FilePreviewHeader
116
149
  filename={name}
117
150
  filenameIcon={renderFileIcon(name)}
118
151
  onBack={onBack}
119
152
  onDownload={handleDownload}
153
+ actions={snippetActions}
120
154
  />
121
155
  );
122
156
 
@@ -64,6 +64,8 @@ import { STORAGE_SNIPPETS } from "./storage-snippets";
64
64
  interface OpenFileInfo {
65
65
  entry: StorageEntry;
66
66
  namespace: string;
67
+ protocol: string;
68
+ backendType: StorageNamespace["backendType"];
67
69
  }
68
70
 
69
71
  // Pixels per depth level. Applied as paddingLeft on each full-width item
@@ -315,7 +317,7 @@ const StorageEntryRow: React.FC<{
315
317
  if (isDir) {
316
318
  setIsExpanded(!effectiveExpanded);
317
319
  } else {
318
- onOpenFile({ entry, namespace });
320
+ onOpenFile({ entry, namespace, protocol, backendType });
319
321
  }
320
322
  }}
321
323
  >
@@ -361,7 +363,9 @@ const StorageEntryRow: React.FC<{
361
363
  >
362
364
  {!isDir && (
363
365
  <DropdownMenuItem
364
- onSelect={() => onOpenFile({ entry, namespace })}
366
+ onSelect={() =>
367
+ onOpenFile({ entry, namespace, protocol, backendType })
368
+ }
365
369
  >
366
370
  <ViewIcon className={MENU_ITEM_ICON_CLASS} />
367
371
  View
@@ -585,6 +589,8 @@ export const StorageInspector: React.FC = () => {
585
589
  <StorageFileViewer
586
590
  entry={openFile.entry}
587
591
  namespace={openFile.namespace}
592
+ protocol={openFile.protocol}
593
+ backendType={openFile.backendType}
588
594
  onBack={() => setOpenFile(null)}
589
595
  />
590
596
  )}
@@ -1,7 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  import type { LucideIcon } from "lucide-react";
4
- import { BookOpenIcon, LinkIcon } from "lucide-react";
4
+ import { BookPlusIcon, FileSymlink } from "lucide-react";
5
5
  import type { StorageEntry, StorageNamespace } from "@/core/storage/types";
6
6
 
7
7
  type BackendType = StorageNamespace["backendType"];
@@ -31,7 +31,7 @@ export const STORAGE_SNIPPETS: StorageSnippet[] = [
31
31
  {
32
32
  id: "read-file",
33
33
  label: "Insert read snippet",
34
- icon: BookOpenIcon,
34
+ icon: BookPlusIcon,
35
35
  getCode: (ctx) => {
36
36
  if (ctx.entry.kind === "directory") {
37
37
  return null;
@@ -46,7 +46,7 @@ export const STORAGE_SNIPPETS: StorageSnippet[] = [
46
46
  {
47
47
  id: "download-file",
48
48
  label: "Insert download snippet",
49
- icon: LinkIcon,
49
+ icon: FileSymlink,
50
50
  getCode: (ctx) => {
51
51
  if (ctx.entry.kind === "directory") {
52
52
  return null;