@marimo-team/islands 0.23.3-dev7 → 0.23.3-dev8

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
@@ -22,18 +22,18 @@ import { _ as Logger, c as Objects, g as cn, h as Events, i as NOT_SET, l as use
22
22
  import { t as require_react } from "./react-DA-nE2FX.js";
23
23
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
24
24
  import { n as Copy, r as toast, t as copyToClipboard } from "./copy-TGGAUEWp.js";
25
- import { An as FileText, B as safeExtractSetUIElementMessageBuffers, C as AccordionContent, Dn as LoaderCircle, E as BorderAllIcon, F as base64ToDataView, Fn as CircleAlert, Gt as requestClientAtom, H as hasRunAnyCellAtom, In as Braces, It as PluralWords, J as notebookOutline, K as getCellNames, Kt as useRequestClient, L as dataViewToBase64, Lt as DATA_TYPE_ICON, Mn as Database, Nn as Columns2, Nt as jotaiJsonStorage, On as Layers, Ot as DeferredRequestRegistry, Pn as CircleX, Q as useCellIds, Qt as NotebookScopedLocalStorage, Rt as getDataTypeColor, S as Accordion, Sn as Trigger2, St as MarkdownLanguageAdapter, T as AccordionTrigger, Tn as PaintRoller, Tt as Paths, Ut as convertStatsName, V as renderHTML, W as createActions, Wt as getRequestClient, X as reducer, Y as numColumnsAtom, Z as useCellActions, _t as getValidName, a as useLastFocusedCellId, an as HTMLCellId, at as initialModeAtom, bn as Item$1, bt as Checkbox, c as Popover$1, cn as findCellId, d as PopoverTrigger, dn as jsonParseWithSpecialChar, dt as isErrorMime, et as createCell, f as isOutputEmpty, ft as headingToIdentifier, gn as selectAtom, hn as atomWithStorage, i as useCellFocusActions, it as getInitialAppMode, jn as Eye, jt as repl, k as ChevronDownIcon, kn as Info, kt as generateUUID, ln as OBJECT_ID_ATTR, lt as outputIsLoading, mn as atomWithReducer, nn as parseDataset, o as maybeAddAltairImport, ot as kioskModeAtom, p as useExpandedConsoleOutput, q as notebookAtom, qt as isUninstantiated, r as LazyAnyLanguageCodeMirror, rn as parseInitialValue, s as Spinner, sn as UIElementId, tn as parseAttrValue, u as PopoverContent, un as RANDOM_ID_ATTR, ut as outputIsStale, vt as isInternalCellName, w as AccordionItem, wn as Table2, wt as PathBuilder, xn as Root2$2, xt as customPythonLanguageSupport, yn as Content2, yt as normalizeName, zt as require_client, __tla as __tla_0 } from "./html-to-image-BdsDysfl.js";
25
+ import { An as FileText, B as safeExtractSetUIElementMessageBuffers, C as AccordionContent, Dn as LoaderCircle, E as BorderAllIcon, F as base64ToDataView, Fn as CircleAlert, Gt as requestClientAtom, H as hasRunAnyCellAtom, In as Braces, It as PluralWords, J as notebookOutline, K as getCellNames, Kt as useRequestClient, L as dataViewToBase64, Lt as DATA_TYPE_ICON, Mn as Database, Nn as Columns2, Nt as jotaiJsonStorage, On as Layers, Ot as DeferredRequestRegistry, Pn as CircleX, Q as useCellIds, Qt as NotebookScopedLocalStorage, Rt as getDataTypeColor, S as Accordion, Sn as Trigger2, St as MarkdownLanguageAdapter, T as AccordionTrigger, Tn as PaintRoller, Tt as Paths, Ut as convertStatsName, V as renderHTML, W as createActions, Wt as getRequestClient, X as reducer, Y as numColumnsAtom, Z as useCellActions, _t as getValidName, a as useLastFocusedCellId, an as HTMLCellId, at as initialModeAtom, bn as Item$1, bt as Checkbox, c as Popover$1, cn as findCellId, d as PopoverTrigger, dn as jsonParseWithSpecialChar, dt as isErrorMime, et as createCell, f as isOutputEmpty, ft as headingToIdentifier, gn as selectAtom, hn as atomWithStorage, i as useCellFocusActions, it as getInitialAppMode, jn as Eye, jt as repl, k as ChevronDownIcon, kn as Info, kt as generateUUID, ln as OBJECT_ID_ATTR, lt as outputIsLoading, mn as atomWithReducer, nn as parseDataset, o as maybeAddAltairImport, ot as kioskModeAtom, p as useExpandedConsoleOutput, q as notebookAtom, qt as isUninstantiated, r as LazyAnyLanguageCodeMirror, rn as parseInitialValue, s as Spinner, sn as UIElementId, tn as parseAttrValue, u as PopoverContent, un as RANDOM_ID_ATTR, ut as outputIsStale, vt as isInternalCellName, w as AccordionItem, wn as Table2, wt as PathBuilder, xn as Root2$2, xt as customPythonLanguageSupport, yn as Content2, yt as normalizeName, zt as require_client, __tla as __tla_0 } from "./html-to-image-XYwXqg2E.js";
26
26
  import { __tla as __tla_1 } from "./chunk-5FQGJX7Z-CO1e63h_.js";
27
27
  import { o as useSize, s as Root$3, u as createLucideIcon } from "./dist-ESg7xyoD.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-BKWq0wn2.js";
29
- import { $ as CommandItem, A as TableHeader, B as usePrevious$1, C as Toggle, Ct as Download, D as TableBody, Dt as ChevronsDownUp, E as Table, Et as ChevronsLeft, F as renderCellValue, G as SELECT_COLUMN_ID, H as loadTableAndRawData, I as ColumnChartContext, J as getMimeValues, K as TOO_MANY_ROWS, L as ColumnChartSpecModel, M as NAMELESS_COLUMN_PREFIX, N as generateColumns, O as TableCell, Ot as ChevronLeft, P as inferFieldTypes, Q as CommandInput, R as DelayMount, S as slotsController, St as Ellipsis, T as Provider$1, Tt as ChevronsRight, U as loadTableData, V as getPageIndexForRow, W as INDEX_COLUMN_NAME, X as Command, Y as filtersToFilterGroup, Z as CommandEmpty, _ as contextAwarePanelOpen, _t as isStaticNotebook, a as DataTable, at as TabsList, b as isCellAwareAtom, bt as Funnel, c as downloadBlob, ct as ChartInfoState, d as Filenames, dt as useOverflowDetection, et as CommandList, f as prettifyRowColumnCount, ft as RenderTextWithLinks, g as PANEL_TYPES, gt as getStaticVirtualFiles, h as ContextAwarePanelItem, ht as EmotionCacheProvider, i as OutputRenderer, it as TabsContent, j as TableRow, k as TableHead, kt as ArrowDownWideNarrow, l as downloadByURL, lt as ChartLoadingState, m as useInternalStateWithSync, mt as HtmlOutput, n as JsonOutput, nt as Maps, o as InstallPackageButton, ot as TabsTrigger, p as prettifyRowCount, pt as Kbd, q as toFieldTypes, r as OutputArea, rt as Tabs, s as ADD_PRINTING_CLASS, st as ChartErrorState, t as Slide, tt as CommandSeparator, u as downloadHTMLAsImage, ut as LazyVegaEmbed, v as contextAwarePanelOwner, vt as TextWrap, w as Fill, wt as ChevronsUpDown, x as SlotNames, y as contextAwarePanelType, yt as GripHorizontal, z as useIntersectionObserver, __tla as __tla_2 } from "./slide-BEerfanN.js";
29
+ import { $ as CommandItem, A as TableHeader, B as usePrevious$1, C as Toggle, Ct as Download, D as TableBody, Dt as ChevronsDownUp, E as Table, Et as ChevronsLeft, F as renderCellValue, G as SELECT_COLUMN_ID, H as loadTableAndRawData, I as ColumnChartContext, J as getMimeValues, K as TOO_MANY_ROWS, L as ColumnChartSpecModel, M as NAMELESS_COLUMN_PREFIX, N as generateColumns, O as TableCell, Ot as ChevronLeft, P as inferFieldTypes, Q as CommandInput, R as DelayMount, S as slotsController, St as Ellipsis, T as Provider$1, Tt as ChevronsRight, U as loadTableData, V as getPageIndexForRow, W as INDEX_COLUMN_NAME, X as Command, Y as filtersToFilterGroup, Z as CommandEmpty, _ as contextAwarePanelOpen, _t as isStaticNotebook, a as DataTable, at as TabsList, b as isCellAwareAtom, bt as Funnel, c as downloadBlob, ct as ChartInfoState, d as Filenames, dt as useOverflowDetection, et as CommandList, f as prettifyRowColumnCount, ft as RenderTextWithLinks, g as PANEL_TYPES, gt as getStaticVirtualFiles, h as ContextAwarePanelItem, ht as EmotionCacheProvider, i as OutputRenderer, it as TabsContent, j as TableRow, k as TableHead, kt as ArrowDownWideNarrow, l as downloadByURL, lt as ChartLoadingState, m as useInternalStateWithSync, mt as HtmlOutput, n as JsonOutput, nt as Maps, o as InstallPackageButton, ot as TabsTrigger, p as prettifyRowCount, pt as Kbd, q as toFieldTypes, r as OutputArea, rt as Tabs, s as ADD_PRINTING_CLASS, st as ChartErrorState, t as Slide, tt as CommandSeparator, u as downloadHTMLAsImage, ut as LazyVegaEmbed, v as contextAwarePanelOwner, vt as TextWrap, w as Fill, wt as ChevronsUpDown, x as SlotNames, y as contextAwarePanelType, yt as GripHorizontal, z as useIntersectionObserver, __tla as __tla_2 } from "./slide-Dl7Rf496.js";
30
30
  import { c as Calendar, i as createReducerAndAtoms, n as useOnUnmount, o as ToggleLeft, r as Badge, t as useOnMount } from "./useLifecycle-smVfjLNI.js";
31
31
  import { n as $fb18d541ea1ad717$export$ad991b66133851cf, r as $5a387cc49350e6db$export$722debc0e56fea39, t as $896ba0a80a8f4d36$export$85fd5fdf27bacc79 } from "./useDateFormatter-B3mCQMP3.js";
32
32
  import { t as Check } from "./check-CFM2mVDr.js";
33
33
  import { A as Trigger$1, C as $a916eb452884faea$export$b7a616150fdb9f44, D as $b5e257d569688ac6$export$535bd6ca7f90a273, E as $18f2051aff69b9bf$export$a54013f0d02a8f82, F as X, L as ChevronDown, M as usePrevious$2, N as useDirection, P as createCollection, S as logNever, T as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7, a as SelectGroup, c as SelectSeparator, d as NativeSelect, f as selectStyles, i as SelectContent, j as clamp$2, k as Icon, l as SelectTrigger, n as capitalize, o as SelectItem, r as Select, s as SelectLabel, t as Strings, u as SelectValue, w as $488c6ddbf4ef74c2$export$cc77c4ff7e8673c5, x as assertNever } from "./strings-B_FOH6eV.js";
34
34
  import { $ as $e5be200c675c3b3a$export$aca958c65c314e6c, A as $d2b4bc8c273e7be6$export$24d547caef80ccd1, At as $c87311424ea30a05$export$fedb369cb70207f1, B as $64fa3d84918910a7$export$c62b8e45d58ddad9, Bt as $431fbd86ca7dc216$export$f21a1ffae260145a, C as $a049562f99e7db0e$export$eb2fcfdbd7ba97d4, Ct as $8ae05eaa5c114e9c$export$7f54fc3180508a52, D as $ee014567cb39d3f0$export$ff05c3ac10437e03, Dt as $c87311424ea30a05$export$78551043582a6a98, E as $ee014567cb39d3f0$export$f551688fc98f2e09, Et as $c87311424ea30a05$export$6446a186d09e379e, F as $64fa3d84918910a7$export$2881499e37b75b9a, Ft as $d4ee10de306f2510$export$b4f377a2b6254582, H as $64fa3d84918910a7$export$ef03459518577ad4, Ht as $bdb11010cef70236$export$b4cc09c592e8fdb8, I as $64fa3d84918910a7$export$29f1550f4b0d4415, It as $d4ee10de306f2510$export$cd4e5573fbe2b576, J as $d2e8511e6f209edf$export$e908e06f4b8e3402, K as useDebounceControlledState, L as $64fa3d84918910a7$export$4d86445c2cf5e3, Lt as $d4ee10de306f2510$export$e58f029f0fbfdb29, M as $01b77f81d0f07f68$export$75b6ee27786ba447, Mt as $65484d02dcb7eb3e$export$457c3d6518dd4c6f, N as $01b77f81d0f07f68$export$b04be29aa201d4f5, Nt as $3ef42575df84b30b$export$9d1611c77c2fe928, O as $514c0188e459b4c0$export$5f1af8db9871e1d6, Ot as $c87311424ea30a05$export$9ac100e40613ea10, P as $f39a9eba43920ace$export$b5d7cc18bb8d2b59, Pt as $d4ee10de306f2510$export$4282f70798064fe0, Q as $e5be200c675c3b3a$export$a763b9476acd3eb, R as $64fa3d84918910a7$export$9d4c57ee4c6ffdd8, Rt as $f4e2df6bd15f8569$export$98658e8c59125e6a, S as $3985021b0ad6602f$export$f5b8910cec6cf069, St as $e9faafb641e167db$export$90fc3a17d93f704c, T as $d3e0e05bdfcf66bd$export$c24727297075ec6a, Tt as $313b98861ee5dd6c$export$d6875122194c7b44, U as $64fa3d84918910a7$export$fabf2dc03a41866e, Ut as $bdb11010cef70236$export$f680877a34711e37, V as $64fa3d84918910a7$export$df3a06d6289f983e, Vt as $ff5963eb1fccf552$export$e08e3b67e392101e, Wt as $f0a04ccd8dbdd83b$export$e5c5a5f917a5871c, X as $e93e671b31057976$export$b8473d3665f3a75a, Y as $2baaea4c71418dea$export$294aa081a6c6f55d, Z as $e5be200c675c3b3a$export$75ee7c75d68f5b0e, _t as $9446cca9a3875146$export$7d15b64cf5a3a4c4, a as NumberField, at as $6c7bd7858deea686$export$cd11ab140839f11d, b as DropdownMenuTrigger, bt as $b4b717babfbb907b$export$bebd5a1431fec25d, c as prettyNumber, cn as Item$2, ct as $6db58dc88e78b024$export$2f817fcdc4b89ae0, d as DropdownMenuContent, dt as $9ab94262bd0047c7$export$420e68273165f4ec, et as $e5be200c675c3b3a$export$dad6ae84456c676a, f as DropdownMenuGroup, fn as Circle, ft as $3ad3f6e1647bc98d$export$80f3e147d781571c, g as DropdownMenuSeparator, gt as $ae1eeba8b9eafd08$export$5165eccb35aaadb5, ht as _class_private_field_init, i as OnBlurredInput, it as $701a24aa0da5b062$export$ea18c227d4417cc3, j as $d2b4bc8c273e7be6$export$353f5b6fc5456de1, jt as $7215afc6de606d6b$export$de79e2c695e052f3, k as $514c0188e459b4c0$export$9afb8bc826b033ea, kt as $c87311424ea30a05$export$a11b0059900ceec8, l as prettyScientificNumber, ln as Root$4, lt as $5b160d28a433310d$export$c17fa47878dc55b6, m as DropdownMenuLabel, mt as $f6c31cce2adf654f$export$45712eceda6fad21, n as DebouncedNumberInput, nt as $319e236875307eab$export$a9b970dcc4ae71a9, ot as $fca6afa0e843324b$export$87b761675e8eaa10, p as DropdownMenuItem, pn as ChevronRight, pt as $507fabe10e71c6fb$export$630ff653c5ada6a9, q as useDebouncedCallback, r as Input, rt as $f7dceffc5ad7768b$export$4e328f61c538687f, st as $fca6afa0e843324b$export$f12b703ca79dfbb1, t as DebouncedInput, tt as $e5be200c675c3b3a$export$fc1a364ae1f3ff10, u as DropdownMenu, un as createRovingFocusGroupScope, ut as $6179b936705e76d3$export$ae780daf29e6d456, vt as $458b0a5536c1a7cf$export$40bfa8c7b0832715, w as $a049562f99e7db0e$export$f9c6924e160136d1, wt as $df56164dff5785e2$export$4338b53315abf666, x as $3985021b0ad6602f$export$37fb8590cf2c088c, xt as $99facab73266f662$export$5add1d006293d136, yt as $b4b717babfbb907b$export$4c063cf1350e6fed, z as $64fa3d84918910a7$export$c245e6201fed2f75, zt as $431fbd86ca7dc216$export$b204af158042fbac } from "./input-Drx1pguW.js";
35
35
  import { c as asRemoteURL, f as require_cuid2, g as CircleQuestionMark, h as isWasm, m as Deferred, u as appendQueryParams } from "./toDate-yqOcZ_tY.js";
36
- import { a as MarimoIncomingMessageEvent, c as MarimoValueUpdateEvent, d as Trash2, f as File, i as PythonIcon, l as createInputEvent, n as blobToString, o as MarimoValueInputEvent, r as filesToBase64, s as MarimoValueReadyEvent, t as processOutput, u as deserializeBlob } from "./process-output-COL2Pf5I.js";
36
+ import { a as MarimoIncomingMessageEvent, c as MarimoValueUpdateEvent, d as Trash2, f as File, i as PythonIcon, l as createInputEvent, n as blobToString, o as MarimoValueInputEvent, r as filesToBase64, s as MarimoValueReadyEvent, t as processOutput, u as deserializeBlob } from "./process-output-BDVjDpbu.js";
37
37
  import { i as Pencil, n as Trash, r as Plus, t as BulkEdit } from "./types-DBtDeUKD.js";
38
38
  import { t as require_react_dom } from "./react-dom-BWRJ_g_k.js";
39
39
  import { t as require_jsx_runtime } from "./jsx-runtime-COBk7ree.js";
@@ -13868,7 +13868,7 @@ Defaulting to \`null\`.`;
13868
13868
  };
13869
13869
  }
13870
13870
  };
13871
- var LazyChatbot = import_react.lazy(() => import("./chat-ui-CTt4WX0V.js").then((e) => ({
13871
+ var LazyChatbot = import_react.lazy(() => import("./chat-ui-BLFhPclV.js").then((e) => ({
13872
13872
  default: e.Chatbot
13873
13873
  }))), messageSchema = array(object({
13874
13874
  id: string(),
@@ -44992,7 +44992,7 @@ ${c}
44992
44992
  function asCellId(e) {
44993
44993
  return typeof e == "string" ? e : null;
44994
44994
  }
44995
- var import_compiler_runtime$10 = require_compiler_runtime(), LazySlidesComponent = import_react.lazy(() => import("./reveal-component-Cd5Y35Ny.js"));
44995
+ var import_compiler_runtime$10 = require_compiler_runtime(), LazySlidesComponent = import_react.lazy(() => import("./reveal-component-CrnLosc4.js"));
44996
44996
  const SlidesLayoutRenderer = (e) => {
44997
44997
  var _a3;
44998
44998
  let r = (0, import_compiler_runtime$10.c)(20), { cells: c, mode: l } = e, u = l === "read", d = useAtomValue(numColumnsAtom) > 1, [f, p] = (0, import_react.useState)(null), m = (0, import_react.useRef)(null), h, g;
@@ -45525,7 +45525,7 @@ ${c}
45525
45525
  return Logger.warn("Failed to get version from mount config"), null;
45526
45526
  }
45527
45527
  }
45528
- const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.3-dev7"), showCodeInRunModeAtom = atom(true);
45528
+ const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.3-dev8"), showCodeInRunModeAtom = atom(true);
45529
45529
  atom(null);
45530
45530
  var VIRTUAL_FILE_REGEX = /\/@file\/([^\s"&'/]+)\.([\dA-Za-z]+)/g, VirtualFileTracker = class e {
45531
45531
  constructor() {
@@ -1,6 +1,6 @@
1
1
  import { s as __toESM } from "./chunk-BNovOVIE.js";
2
2
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
3
- import { nt as parseHtmlContent, tt as ansiToPlainText } from "./html-to-image-BdsDysfl.js";
3
+ import { nt as parseHtmlContent, tt as ansiToPlainText } from "./html-to-image-XYwXqg2E.js";
4
4
  import { u as createLucideIcon } from "./dist-ESg7xyoD.js";
5
5
  import { t as Strings } from "./strings-B_FOH6eV.js";
6
6
  import { t as require_jsx_runtime } from "./jsx-runtime-COBk7ree.js";
@@ -6,9 +6,9 @@ import { s as __toESM } from "./chunk-BNovOVIE.js";
6
6
  import { _ as Logger, h as Events, t as Button } from "./button-CA5pI2YF.js";
7
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
- import "./html-to-image-BdsDysfl.js";
9
+ import "./html-to-image-XYwXqg2E.js";
10
10
  import "./chunk-5FQGJX7Z-CO1e63h_.js";
11
- import { t as Slide, xt as Expand } from "./slide-BEerfanN.js";
11
+ import { t as Slide, xt as Expand } from "./slide-Dl7Rf496.js";
12
12
  import "./input-Drx1pguW.js";
13
13
  import "./toDate-yqOcZ_tY.js";
14
14
  import "./react-dom-BWRJ_g_k.js";
@@ -6,7 +6,7 @@ import { _ as Logger, c as Objects, g as cn, h as Events, p as composeRefs, r as
6
6
  import { t as require_react } from "./react-DA-nE2FX.js";
7
7
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
8
8
  import { n as Copy, r as toast, t as copyToClipboard } from "./copy-TGGAUEWp.js";
9
- import { $ as useCellNames, A as ChevronRightIcon, An as FileText, At as useChromeActions, C as AccordionContent, Cn as Wrench, Dn as LoaderCircle, Dt as goToCellLine, En as NotebookPen, Ft as PluralWord, G as getCellEditorView, I as base64ToUint8Array, In as Braces, Kt as useRequestClient, Ln as esm_default, Lt as DATA_TYPE_ICON, M as PinLeftIcon, Mt as adaptForLocalStorage, N as PinRightIcon, Nt as jotaiJsonStorage, O as CheckIcon, Q as useCellIds, R as extractBase64FromDataURL, Rn as import_lib, S as Accordion, T as AccordionTrigger, V as renderHTML, Wt as getRequestClient, Xt as extractAllTracebackInfo, Yt as elementContainsMarimoCellFile, Z as useCellActions, Zt as getTracebackInfo, an as HTMLCellId, bt as Checkbox, c as Popover, ct as viewStateAtom, d as PopoverTrigger, dn as jsonParseWithSpecialChar, en as filenameAtom, fn as jsonToMarkdown, g as getDatasourceContext, gt as displayCellName, hn as atomWithStorage, ht as getCellDomProps, in as CellOutputId, j as DotFilledIcon, l as PopoverClose$1, lt as outputIsLoading, m as useExpandedOutput, mt as DATA_CELL_ID, n as MarkdownRenderer, on as SCRATCH_CELL_ID, pn as jsonToTSV, pt as sanitizeHtml, q as notebookAtom, rt as AnsiUp, s as Spinner, st as useInstallAllowed, t as toPng, u as PopoverContent, vn as Close$1, w as AccordionItem, z as isDataURLString, __tla as __tla_0 } from "./html-to-image-BdsDysfl.js";
9
+ import { $ as useCellNames, A as ChevronRightIcon, An as FileText, At as useChromeActions, C as AccordionContent, Cn as Wrench, Dn as LoaderCircle, Dt as goToCellLine, En as NotebookPen, Ft as PluralWord, G as getCellEditorView, I as base64ToUint8Array, In as Braces, Kt as useRequestClient, Ln as esm_default, Lt as DATA_TYPE_ICON, M as PinLeftIcon, Mt as adaptForLocalStorage, N as PinRightIcon, Nt as jotaiJsonStorage, O as CheckIcon, Q as useCellIds, R as extractBase64FromDataURL, Rn as import_lib, S as Accordion, T as AccordionTrigger, V as renderHTML, Wt as getRequestClient, Xt as extractAllTracebackInfo, Yt as elementContainsMarimoCellFile, Z as useCellActions, Zt as getTracebackInfo, an as HTMLCellId, bt as Checkbox, c as Popover, ct as viewStateAtom, d as PopoverTrigger, dn as jsonParseWithSpecialChar, en as filenameAtom, fn as jsonToMarkdown, g as getDatasourceContext, gt as displayCellName, hn as atomWithStorage, ht as getCellDomProps, in as CellOutputId, j as DotFilledIcon, l as PopoverClose$1, lt as outputIsLoading, m as useExpandedOutput, mt as DATA_CELL_ID, n as MarkdownRenderer, on as SCRATCH_CELL_ID, pn as jsonToTSV, pt as sanitizeHtml, q as notebookAtom, rt as AnsiUp, s as Spinner, st as useInstallAllowed, t as toPng, u as PopoverContent, vn as Close$1, w as AccordionItem, z as isDataURLString, __tla as __tla_0 } from "./html-to-image-XYwXqg2E.js";
10
10
  import { u as createLucideIcon } from "./dist-ESg7xyoD.js";
11
11
  import { i as createReducerAndAtoms, r as Badge } from "./useLifecycle-smVfjLNI.js";
12
12
  import { a as ListFilter, i as Table$1, o as ChartPie, t as $896ba0a80a8f4d36$export$85fd5fdf27bacc79 } from "./useDateFormatter-B3mCQMP3.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.23.3-dev7",
3
+ "version": "0.23.3-dev8",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -182,10 +182,24 @@ describe("RequestingTree", () => {
182
182
  expect(mockOnChange).toHaveBeenCalled();
183
183
  });
184
184
 
185
+ test("delete should drop a file on success", async () => {
186
+ sendDeleteFileOrFolder.mockResolvedValue({ success: true });
187
+
188
+ await requestingTree.delete("1.1");
189
+ expect(sendDeleteFileOrFolder).toHaveBeenCalledWith({
190
+ path: "/root/file1",
191
+ });
192
+ const lastCall = mockOnChange.mock.calls.at(-1);
193
+ expect(lastCall?.[0].map((f: { id: string }) => f.id)).toEqual([
194
+ "1.2",
195
+ "1.3",
196
+ ]);
197
+ });
198
+
185
199
  test("createFile should create a new file", async () => {
186
200
  sendCreateFileOrFolder.mockResolvedValue({ success: true });
187
201
 
188
- await requestingTree.createFile("file3", "1.2");
202
+ await requestingTree.createFile({ name: "file3", parentId: "1.2" });
189
203
  expect(sendCreateFileOrFolder).toHaveBeenCalledWith({
190
204
  path: "/root/folder1",
191
205
  type: "file",
@@ -197,7 +211,11 @@ describe("RequestingTree", () => {
197
211
  test("createFile should create a new notebook", async () => {
198
212
  sendCreateFileOrFolder.mockResolvedValue({ success: true });
199
213
 
200
- await requestingTree.createFile("notebook1", "1.2", "notebook");
214
+ await requestingTree.createFile({
215
+ name: "notebook1",
216
+ parentId: "1.2",
217
+ type: "notebook",
218
+ });
201
219
  expect(sendCreateFileOrFolder).toHaveBeenCalledWith({
202
220
  path: "/root/folder1",
203
221
  type: "notebook",
@@ -277,6 +295,70 @@ describe("RequestingTree", () => {
277
295
  });
278
296
  });
279
297
 
298
+ test("rename should NOT mutate the local tree on API failure", async () => {
299
+ sendRenameFileOrFolder.mockResolvedValue({
300
+ success: false,
301
+ message: "Error renaming",
302
+ });
303
+ const changesBefore = mockOnChange.mock.calls.length;
304
+
305
+ await requestingTree.rename("1.1", "file2");
306
+
307
+ // No further onChange calls should fire after the failed rename, so the
308
+ // tree stays in sync with the backend.
309
+ expect(mockOnChange.mock.calls.length).toBe(changesBefore);
310
+ });
311
+
312
+ test("delete should NOT drop the node on API failure", async () => {
313
+ sendDeleteFileOrFolder.mockResolvedValue({
314
+ success: false,
315
+ message: "Error deleting",
316
+ });
317
+ const changesBefore = mockOnChange.mock.calls.length;
318
+
319
+ await requestingTree.delete("1.1");
320
+ expect(sendDeleteFileOrFolder).toHaveBeenCalledWith({
321
+ path: "/root/file1",
322
+ });
323
+ expect(toast).toHaveBeenCalledWith({
324
+ title: "Failed",
325
+ description: "Error deleting",
326
+ });
327
+ expect(mockOnChange.mock.calls.length).toBe(changesBefore);
328
+ });
329
+
330
+ test("move should NOT mutate the local tree when rename fails", async () => {
331
+ sendRenameFileOrFolder.mockResolvedValue({
332
+ success: false,
333
+ message: "Error moving",
334
+ });
335
+
336
+ await requestingTree.move(["1.1"], "1.2");
337
+
338
+ expect(toast).toHaveBeenCalledWith({
339
+ title: "Failed",
340
+ description: "Error moving",
341
+ });
342
+ // The last emitted state should still have file1 at the top level, not
343
+ // moved under folder1.
344
+ const lastCall = mockOnChange.mock.calls.at(-1);
345
+ expect(lastCall?.[0]).toEqual([
346
+ { id: "1.1", name: "file1", path: "/root/file1" },
347
+ {
348
+ id: "1.2",
349
+ name: "folder1",
350
+ isDirectory: true,
351
+ path: "/root/folder1",
352
+ },
353
+ {
354
+ id: "1.3",
355
+ name: "folder2",
356
+ isDirectory: true,
357
+ path: "/root/folder2",
358
+ },
359
+ ]);
360
+ });
361
+
280
362
  test("copy should handle API failure", async () => {
281
363
  sendCopyFileOrFolder.mockResolvedValue({
282
364
  success: false,
@@ -6,21 +6,18 @@ import {
6
6
  ArrowLeftIcon,
7
7
  BetweenHorizontalStartIcon,
8
8
  BracesIcon,
9
- CopyIcon,
10
9
  CopyMinusIcon,
11
10
  DownloadIcon,
12
- Edit3Icon,
13
11
  ExternalLinkIcon,
14
12
  EyeOffIcon,
15
13
  FilePlus2Icon,
16
14
  FolderPlusIcon,
17
15
  ListTreeIcon,
18
16
  PlaySquareIcon,
19
- Trash2Icon,
20
17
  UploadIcon,
21
18
  ViewIcon,
22
19
  } from "lucide-react";
23
- import React, { Suspense, use, useEffect, useRef, useState } from "react";
20
+ import React, { Suspense, use, useRef, useState } from "react";
24
21
  import {
25
22
  type NodeApi,
26
23
  type NodeRendererProps,
@@ -34,9 +31,15 @@ import {
34
31
  type FileIconType,
35
32
  guessFileIconType,
36
33
  } from "@/components/editor/file-tree/file-icons";
34
+ import {
35
+ DeleteMenuItem,
36
+ DuplicateMenuItem,
37
+ FileActionsDropdown,
38
+ RenameMenuItem,
39
+ } from "@/components/editor/file-tree/file-operations";
40
+ import { FileNameInput } from "@/components/editor/file-tree/file-name-input";
37
41
  import {
38
42
  MENU_ITEM_ICON_CLASS,
39
- MoreActionsButton,
40
43
  RefreshIconButton,
41
44
  TreeChevron,
42
45
  } from "@/components/editor/file-tree/tree-actions";
@@ -46,11 +49,8 @@ import { useImperativeModal } from "@/components/modal/ImperativeModal";
46
49
  import { AlertDialogDestructiveAction } from "@/components/ui/alert-dialog";
47
50
  import { Button, buttonVariants } from "@/components/ui/button";
48
51
  import {
49
- DropdownMenu,
50
- DropdownMenuContent,
51
52
  DropdownMenuItem,
52
53
  DropdownMenuSeparator,
53
- DropdownMenuTrigger,
54
54
  } from "@/components/ui/dropdown-menu";
55
55
  import { Tooltip } from "@/components/ui/tooltip";
56
56
  import { toast } from "@/components/ui/use-toast";
@@ -69,7 +69,7 @@ import { downloadBlob } from "@/utils/download";
69
69
  import { type Base64String, base64ToDataURL } from "@/utils/json/base64";
70
70
  import { openNotebook } from "@/utils/links";
71
71
  import type { FilePath } from "@/utils/paths";
72
- import { fileSplit } from "@/utils/pathUtils";
72
+ import { makeDuplicateName } from "@/utils/pathUtils";
73
73
  import { jotaiJsonStorage } from "@/utils/storage/jotai";
74
74
  import { useTreeDndManager } from "./dnd-wrapper";
75
75
  import { FileViewer } from "./file-viewer";
@@ -131,7 +131,7 @@ export const FileExplorer: React.FC<{
131
131
  openPrompt({
132
132
  title: "File name",
133
133
  onConfirm: async (name) => {
134
- tree.createFile(name, null);
134
+ tree.createFile({ name, parentId: null });
135
135
  },
136
136
  });
137
137
  });
@@ -140,7 +140,7 @@ export const FileExplorer: React.FC<{
140
140
  openPrompt({
141
141
  title: "Notebook name",
142
142
  onConfirm: async (name) => {
143
- tree.createFile(name, null, "notebook");
143
+ tree.createFile({ name, parentId: null, type: "notebook" });
144
144
  },
145
145
  });
146
146
  });
@@ -392,33 +392,6 @@ const Show = ({
392
392
  );
393
393
  };
394
394
 
395
- const Edit = ({ node }: { node: NodeApi<FileInfo> }) => {
396
- const ref = useRef<HTMLInputElement>(null);
397
- useEffect(() => {
398
- ref.current?.focus();
399
- // Select everything, but the extension
400
- ref.current?.setSelectionRange(0, node.data.name.lastIndexOf("."));
401
- }, [node.data.name]);
402
-
403
- return (
404
- <input
405
- ref={ref}
406
- className="flex-1 bg-transparent border border-border text-muted-foreground"
407
- defaultValue={node.data.name}
408
- onClick={(e) => e.stopPropagation()}
409
- onBlur={() => node.reset()}
410
- onKeyDown={(e) => {
411
- if (e.key === "Escape") {
412
- node.reset();
413
- }
414
- if (e.key === "Enter") {
415
- node.submit(e.currentTarget.value);
416
- }
417
- }}
418
- />
419
- );
420
- };
421
-
422
395
  const Node = ({ node, style, dragHandle }: NodeRendererProps<FileInfo>) => {
423
396
  const { openFile, sendFileDetails } = useRequestClient();
424
397
  const disableFileDownloads = useAtomValue(disableFileDownloadsAtom);
@@ -486,7 +459,7 @@ const Node = ({ node, style, dragHandle }: NodeRendererProps<FileInfo>) => {
486
459
  openPrompt({
487
460
  title: "File name",
488
461
  onConfirm: async (name) => {
489
- tree?.createFile(name, node.id);
462
+ tree?.createFile({ name, parentId: node.id });
490
463
  },
491
464
  });
492
465
  });
@@ -496,7 +469,7 @@ const Node = ({ node, style, dragHandle }: NodeRendererProps<FileInfo>) => {
496
469
  openPrompt({
497
470
  title: "Notebook name",
498
471
  onConfirm: async (name) => {
499
- tree?.createFile(name, node.id, "notebook");
472
+ tree?.createFile({ name, parentId: node.id, type: "notebook" });
500
473
  },
501
474
  });
502
475
  });
@@ -505,158 +478,9 @@ const Node = ({ node, style, dragHandle }: NodeRendererProps<FileInfo>) => {
505
478
  if (!tree) {
506
479
  return;
507
480
  }
508
-
509
- const [name, extension] = fileSplit(node.data.name);
510
- const duplicateName = `${name}_copy${extension}`;
511
-
512
- await tree.copy(node.id, duplicateName);
481
+ await tree.copy(node.id, makeDuplicateName(node.data.name));
513
482
  });
514
483
 
515
- const renderActions = () => {
516
- const ic = MENU_ITEM_ICON_CLASS;
517
- return (
518
- <DropdownMenuContent
519
- align="end"
520
- className="print:hidden w-[220px]"
521
- onClick={(e) => e.stopPropagation()}
522
- onCloseAutoFocus={(e) => e.preventDefault()}
523
- >
524
- {!node.data.isDirectory && (
525
- <DropdownMenuItem onSelect={() => node.select()}>
526
- <ViewIcon className={ic} />
527
- Open file
528
- </DropdownMenuItem>
529
- )}
530
- {!node.data.isDirectory && !isWasm() && (
531
- <DropdownMenuItem
532
- onSelect={() => {
533
- openFile({ path: node.data.path });
534
- }}
535
- >
536
- <ExternalLinkIcon className={ic} />
537
- Open file in external editor
538
- </DropdownMenuItem>
539
- )}
540
- {node.data.isDirectory && (
541
- <>
542
- <DropdownMenuItem onSelect={() => handleCreateNotebook()}>
543
- <MarimoPlusIcon className={ic} />
544
- Create notebook
545
- </DropdownMenuItem>
546
- <DropdownMenuItem onSelect={() => handleCreateFile()}>
547
- <FilePlus2Icon className={ic} />
548
- Create file
549
- </DropdownMenuItem>
550
- <DropdownMenuItem onSelect={() => handleCreateFolder()}>
551
- <FolderPlusIcon className={ic} />
552
- Create folder
553
- </DropdownMenuItem>
554
- <DropdownMenuSeparator />
555
- </>
556
- )}
557
- <DropdownMenuItem onSelect={() => node.edit()}>
558
- <Edit3Icon className={ic} />
559
- Rename
560
- </DropdownMenuItem>
561
- <DropdownMenuItem onSelect={handleDuplicate}>
562
- <CopyIcon className={ic} />
563
- Duplicate
564
- </DropdownMenuItem>
565
- <DropdownMenuItem
566
- onSelect={async () => {
567
- await copyToClipboard(node.data.path);
568
- toast({ title: "Copied to clipboard" });
569
- }}
570
- >
571
- <ListTreeIcon className={ic} />
572
- Copy path
573
- </DropdownMenuItem>
574
- {tree && (
575
- <DropdownMenuItem
576
- onSelect={async () => {
577
- await copyToClipboard(
578
- tree.relativeFromRoot(node.data.path as FilePath),
579
- );
580
- toast({ title: "Copied to clipboard" });
581
- }}
582
- >
583
- <ListTreeIcon className={ic} />
584
- Copy relative path
585
- </DropdownMenuItem>
586
- )}
587
- <DropdownMenuSeparator />
588
-
589
- <DropdownMenuItem
590
- onSelect={() => {
591
- const { path } = node.data;
592
- const pythonCode = PYTHON_CODE_FOR_FILE_TYPE[fileType](path);
593
- handleInsertCode(pythonCode);
594
- }}
595
- >
596
- <BetweenHorizontalStartIcon className={ic} />
597
- Insert snippet for reading file
598
- </DropdownMenuItem>
599
- <DropdownMenuItem
600
- onSelect={async () => {
601
- toast({
602
- title: "Copied to clipboard",
603
- description:
604
- "Code to open the file has been copied to your clipboard. You can also drag and drop this file into the editor",
605
- });
606
- const { path } = node.data;
607
- const pythonCode = PYTHON_CODE_FOR_FILE_TYPE[fileType](path);
608
- await copyToClipboard(pythonCode);
609
- }}
610
- >
611
- <BracesIcon className={ic} />
612
- Copy snippet for reading file
613
- </DropdownMenuItem>
614
- {/* Not shown in WASM */}
615
- {node.data.isMarimoFile && !isWasm() && (
616
- <>
617
- <DropdownMenuSeparator />
618
- <DropdownMenuItem onSelect={handleOpenMarimoFile}>
619
- <PlaySquareIcon className={ic} />
620
- Open notebook
621
- </DropdownMenuItem>
622
- </>
623
- )}
624
- <DropdownMenuSeparator />
625
- {!node.data.isDirectory && !disableFileDownloads && (
626
- <>
627
- <DropdownMenuItem
628
- onSelect={async () => {
629
- const details = await sendFileDetails({ path: node.data.path });
630
- if (details.isBase64 && details.contents) {
631
- const blob = deserializeBlob(
632
- base64ToDataURL(
633
- details.contents as Base64String,
634
- details.mimeType || "application/octet-stream",
635
- ),
636
- );
637
- downloadBlob(blob, node.data.name);
638
- } else {
639
- downloadBlob(
640
- new Blob([details.contents || ""]),
641
- node.data.name,
642
- );
643
- }
644
- }}
645
- >
646
- <DownloadIcon className={ic} />
647
- Download
648
- </DropdownMenuItem>
649
- <DropdownMenuSeparator />
650
- </>
651
- )}
652
- <DropdownMenuItem onSelect={handleDeleteFile} variant="danger">
653
- <Trash2Icon className={ic} />
654
- Delete
655
- </DropdownMenuItem>
656
- </DropdownMenuContent>
657
- );
658
- };
659
-
660
484
  return (
661
485
  <div
662
486
  style={style}
@@ -690,23 +514,138 @@ const Node = ({ node, style, dragHandle }: NodeRendererProps<FileInfo>) => {
690
514
  />
691
515
  )}
692
516
  {node.isEditing ? (
693
- <Edit node={node} />
517
+ <FileNameInput node={node} />
694
518
  ) : (
695
519
  <Show node={node} onOpenMarimoFile={handleOpenMarimoFile} />
696
520
  )}
697
- <DropdownMenu modal={false}>
698
- <DropdownMenuTrigger
699
- asChild={true}
700
- tabIndex={-1}
701
- onClick={(e) => e.stopPropagation()}
521
+ <FileActionsDropdown
522
+ testId="file-explorer-more-button"
523
+ iconClassName="w-5 h-5"
524
+ >
525
+ {!node.data.isDirectory && (
526
+ <DropdownMenuItem onSelect={() => node.select()}>
527
+ <ViewIcon className={MENU_ITEM_ICON_CLASS} />
528
+ Open file
529
+ </DropdownMenuItem>
530
+ )}
531
+ {!node.data.isDirectory && !isWasm() && (
532
+ <DropdownMenuItem
533
+ onSelect={() => {
534
+ openFile({ path: node.data.path });
535
+ }}
536
+ >
537
+ <ExternalLinkIcon className={MENU_ITEM_ICON_CLASS} />
538
+ Open file in external editor
539
+ </DropdownMenuItem>
540
+ )}
541
+ {node.data.isDirectory && (
542
+ <>
543
+ <DropdownMenuItem onSelect={() => handleCreateNotebook()}>
544
+ <MarimoPlusIcon className={MENU_ITEM_ICON_CLASS} />
545
+ Create notebook
546
+ </DropdownMenuItem>
547
+ <DropdownMenuItem onSelect={() => handleCreateFile()}>
548
+ <FilePlus2Icon className={MENU_ITEM_ICON_CLASS} />
549
+ Create file
550
+ </DropdownMenuItem>
551
+ <DropdownMenuItem onSelect={() => handleCreateFolder()}>
552
+ <FolderPlusIcon className={MENU_ITEM_ICON_CLASS} />
553
+ Create folder
554
+ </DropdownMenuItem>
555
+ <DropdownMenuSeparator />
556
+ </>
557
+ )}
558
+ <RenameMenuItem onSelect={() => node.edit()} />
559
+ <DuplicateMenuItem onSelect={handleDuplicate} />
560
+ <DropdownMenuItem
561
+ onSelect={async () => {
562
+ await copyToClipboard(node.data.path);
563
+ toast({ title: "Copied to clipboard" });
564
+ }}
702
565
  >
703
- <MoreActionsButton
704
- data-testid="file-explorer-more-button"
705
- iconClassName="w-5 h-5"
706
- />
707
- </DropdownMenuTrigger>
708
- {renderActions()}
709
- </DropdownMenu>
566
+ <ListTreeIcon className={MENU_ITEM_ICON_CLASS} />
567
+ Copy path
568
+ </DropdownMenuItem>
569
+ {tree && (
570
+ <DropdownMenuItem
571
+ onSelect={async () => {
572
+ await copyToClipboard(
573
+ tree.relativeFromRoot(node.data.path as FilePath),
574
+ );
575
+ toast({ title: "Copied to clipboard" });
576
+ }}
577
+ >
578
+ <ListTreeIcon className={MENU_ITEM_ICON_CLASS} />
579
+ Copy relative path
580
+ </DropdownMenuItem>
581
+ )}
582
+ <DropdownMenuSeparator />
583
+ <DropdownMenuItem
584
+ onSelect={() => {
585
+ const { path } = node.data;
586
+ const pythonCode = PYTHON_CODE_FOR_FILE_TYPE[fileType](path);
587
+ handleInsertCode(pythonCode);
588
+ }}
589
+ >
590
+ <BetweenHorizontalStartIcon className={MENU_ITEM_ICON_CLASS} />
591
+ Insert snippet for reading file
592
+ </DropdownMenuItem>
593
+ <DropdownMenuItem
594
+ onSelect={async () => {
595
+ toast({
596
+ title: "Copied to clipboard",
597
+ description:
598
+ "Code to open the file has been copied to your clipboard. You can also drag and drop this file into the editor",
599
+ });
600
+ const { path } = node.data;
601
+ const pythonCode = PYTHON_CODE_FOR_FILE_TYPE[fileType](path);
602
+ await copyToClipboard(pythonCode);
603
+ }}
604
+ >
605
+ <BracesIcon className={MENU_ITEM_ICON_CLASS} />
606
+ Copy snippet for reading file
607
+ </DropdownMenuItem>
608
+ {node.data.isMarimoFile && !isWasm() && (
609
+ <>
610
+ <DropdownMenuSeparator />
611
+ <DropdownMenuItem onSelect={handleOpenMarimoFile}>
612
+ <PlaySquareIcon className={MENU_ITEM_ICON_CLASS} />
613
+ Open notebook
614
+ </DropdownMenuItem>
615
+ </>
616
+ )}
617
+ <DropdownMenuSeparator />
618
+ {!node.data.isDirectory && !disableFileDownloads && (
619
+ <>
620
+ <DropdownMenuItem
621
+ onSelect={async () => {
622
+ const details = await sendFileDetails({
623
+ path: node.data.path,
624
+ });
625
+ if (details.isBase64 && details.contents) {
626
+ const blob = deserializeBlob(
627
+ base64ToDataURL(
628
+ details.contents as Base64String,
629
+ details.mimeType || "application/octet-stream",
630
+ ),
631
+ );
632
+ downloadBlob(blob, node.data.name);
633
+ } else {
634
+ downloadBlob(
635
+ new Blob([details.contents || ""]),
636
+ node.data.name,
637
+ );
638
+ }
639
+ }}
640
+ >
641
+ <DownloadIcon className={MENU_ITEM_ICON_CLASS} />
642
+ Download
643
+ </DropdownMenuItem>
644
+ <DropdownMenuSeparator />
645
+ </>
646
+ )}
647
+ <DeleteMenuItem onSelect={handleDeleteFile} />
648
+ </FileActionsDropdown>
710
649
  </span>
711
650
  </div>
712
651
  );