@marimo-team/islands 0.24.1-dev0 → 0.24.1-dev3
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/{chat-ui-o-tATfmW.js → chat-ui-ChBRy1iT.js} +3 -3
- package/dist/{common-CDI91x0c.js → common-BvTQu-LJ.js} +4 -4
- package/dist/{formats-HSfYlcA8.js → formats-Dz0QNUEa.js} +1 -1
- package/dist/{html-to-image-BOiFHx3u.js → html-to-image-BtNr4zrO.js} +1 -1
- package/dist/main.js +9 -8
- package/dist/{process-output-HrsM52f8.js → process-output-Dch8KCi8.js} +1 -1
- package/dist/{reveal-component-jN-3ZqwN.js → reveal-component-qNkzuPp3.js} +3 -3
- package/dist/{toDate-BGM7kFtQ.js → toDate-CjUYDkFI.js} +2 -2
- package/dist/{vega-component-CJug-VdR.js → vega-component-CioKuDut.js} +2 -2
- package/package.json +1 -1
- package/src/__mocks__/requests.ts +4 -0
- package/src/components/editor/actions/export-dialog/__tests__/export-dialog.test.tsx +206 -34
- package/src/components/editor/actions/export-dialog/export-dialog.tsx +9 -3
- package/src/components/editor/actions/export-dialog/format-notice.tsx +69 -24
- package/src/components/editor/actions/export-dialog/use-export-dialog.ts +27 -2
- package/src/components/ui/toaster.tsx +14 -1
- package/src/core/islands/bridge.ts +1 -0
- package/src/core/mode.ts +6 -1
- package/src/core/network/__tests__/requests-lazy.test.ts +40 -0
- package/src/core/network/__tests__/requests-network.test.ts +13 -0
- package/src/core/network/requests-lazy.ts +11 -4
- package/src/core/network/requests-network.ts +8 -0
- package/src/core/network/requests-static.ts +1 -0
- package/src/core/network/requests-toasting.tsx +1 -0
- package/src/core/network/types.ts +5 -0
- package/src/core/wasm/bridge.ts +1 -0
|
@@ -6,13 +6,13 @@ import { c as useEventListener, g as Logger, h as cn, t as Button } from "./butt
|
|
|
6
6
|
import { t as require_react } from "./react-DhGsCS90.js";
|
|
7
7
|
import { t as require_compiler_runtime } from "./compiler-runtime-DsR6imPN.js";
|
|
8
8
|
import { r as toast } from "./copy-C7ZKMKox.js";
|
|
9
|
-
import { Bt as PluralWord, C as Accordion, Dn as Anchor2, E as AccordionTrigger, Ft as variablesAtom, H as renderHTML, Hn as FileText, Jt as getTableType, Kt as allTablesAtom, Nn as Wrench, O as ChatBubbleIcon, Pn as Trash2, Pt as jotaiJsonStorage, Q as notebookAtom, S as AIContextRegistry, T as AccordionItem, Tn as atomWithStorage, Vn as Info, Wn as ExternalLink, Xt as getRequestClient, an as singleFacet, b as contextToXml, c as Popover, d as PopoverTrigger, f as isOutputEmpty, g as formatDatasourceContextForCell, h as DatasourceContextProvider, hn as CellOutputId, ht as displayCellName, in as isTracebackMime, jt as generateUUID, kt as moveToEndOfEditor, n as Spinner, nn as isErrorMime, qn as CircleX, qt as dataSourceConnectionsAtom, r as MarkdownRenderer, rn as isMarimoErrorsMime, st as parseHtmlContent, t as toPng, u as PopoverContent, un as ZodLocalStorage, v as Boosts, w as AccordionContent, wt as createVariableInfoElement, x as AIContextProvider, y as Sections, zn as LoaderCircle } from "./html-to-image-
|
|
9
|
+
import { Bt as PluralWord, C as Accordion, Dn as Anchor2, E as AccordionTrigger, Ft as variablesAtom, H as renderHTML, Hn as FileText, Jt as getTableType, Kt as allTablesAtom, Nn as Wrench, O as ChatBubbleIcon, Pn as Trash2, Pt as jotaiJsonStorage, Q as notebookAtom, S as AIContextRegistry, T as AccordionItem, Tn as atomWithStorage, Vn as Info, Wn as ExternalLink, Xt as getRequestClient, an as singleFacet, b as contextToXml, c as Popover, d as PopoverTrigger, f as isOutputEmpty, g as formatDatasourceContextForCell, h as DatasourceContextProvider, hn as CellOutputId, ht as displayCellName, in as isTracebackMime, jt as generateUUID, kt as moveToEndOfEditor, n as Spinner, nn as isErrorMime, qn as CircleX, qt as dataSourceConnectionsAtom, r as MarkdownRenderer, rn as isMarimoErrorsMime, st as parseHtmlContent, t as toPng, u as PopoverContent, un as ZodLocalStorage, v as Boosts, w as AccordionContent, wt as createVariableInfoElement, x as AIContextProvider, y as Sections, zn as LoaderCircle } from "./html-to-image-BtNr4zrO.js";
|
|
10
10
|
import "./chunk-5FQGJX7Z-BRZ_XYUw.js";
|
|
11
11
|
import { u as createLucideIcon } from "./dist-j30bBjjN.js";
|
|
12
12
|
import { C as logNever, I as X, R as ChevronDown, t as Strings } from "./strings-DMLVGXRo.js";
|
|
13
13
|
import { C as DropdownMenuTrigger, a as NumberField, f as DropdownMenu, h as DropdownMenuItem, p as DropdownMenuContent, r as Input } from "./input-BRE2a7Ay.js";
|
|
14
|
-
import { p as isUrl, w as CircleQuestionMark } from "./toDate-
|
|
15
|
-
import { a as MarimoIncomingMessageEvent, d as fileDetailsToBlob, f as Square, n as blobToString, p as File$1, t as processOutput } from "./process-output-
|
|
14
|
+
import { p as isUrl, w as CircleQuestionMark } from "./toDate-CjUYDkFI.js";
|
|
15
|
+
import { a as MarimoIncomingMessageEvent, d as fileDetailsToBlob, f as Square, n as blobToString, p as File$1, t as processOutput } from "./process-output-Dch8KCi8.js";
|
|
16
16
|
import "./react-dom-CmENFV8Q.js";
|
|
17
17
|
import { t as require_jsx_runtime } from "./jsx-runtime-Dp_oQwaf.js";
|
|
18
18
|
import { A as looseObject, B as unknown, C as any, D as discriminatedUnion, E as custom, I as record, L as string, M as never, N as number, O as lazy, P as object$1, S as _null, T as boolean, U as toJSONSchema, V as safeParseAsync, b as _enum, k as literal, w as array$1, x as _instanceof, z as union } from "./zod-BFY2SnzC.js";
|
|
@@ -6,14 +6,14 @@ import { _ as Functions, f as composeRefs, g as Logger, h as cn, m as Events, n
|
|
|
6
6
|
import { t as require_react } from "./react-DhGsCS90.js";
|
|
7
7
|
import { t as require_compiler_runtime } from "./compiler-runtime-DsR6imPN.js";
|
|
8
8
|
import { n as Copy, r as toast, t as copyToClipboard } from "./copy-C7ZKMKox.js";
|
|
9
|
-
import { B as isDataURLString, Bt as PluralWord, C as Accordion, Cn as jsonToMarkdown, Dt as toggleBreakpoint, E as AccordionTrigger, H as renderHTML, Hn as FileText, Ht as DATA_TYPE_ICON, It as getFeatureFlag, J as getCellEditorView, L as base64ToUint8Array, Ln as NotebookPen, M as DotFilledIcon, Mt as useChromeActions, N as PinLeftIcon, Nn as Wrench, Nt as adaptForLocalStorage, On as Close$1, Ot as goToCellLine, P as PinRightIcon, Pn as Trash2, Pt as jotaiJsonStorage, Q as notebookAtom, Qt as useRequestClient, Rn as Minus, Sn as jsonParseWithSpecialChar, St as isRecord, T as AccordionItem, Tn as atomWithStorage, Un as Eye, Ut as getDataTypeColor, Vn as Info, Wn as ExternalLink, Wt as resolveDataType, Xn as esm_default, Xt as getRequestClient, Yn as Braces, Zn as import_lib, _ as getDatasourceContext, _n as SCRATCH_CELL_ID, c as Popover, cn as getTracebackInfo, ct as AnsiUp, d as PopoverTrigger, dn as filenameAtom, ft as sanitizeHtml, gn as HTMLCellId, hn as CellOutputId, ht as displayCellName, it as useCellNames, j as ChevronRightIcon, k as CheckIcon, l as PopoverClose, lt as outputIsLoading, m as useExpandedOutput, mt as getCellDomProps, n as Spinner, nt as useCellActions, on as elementContainsMarimoCellFile, pt as DATA_CELL_ID, qn as CircleX, r as MarkdownRenderer, rt as useCellIds, sn as extractAllTracebackInfo, t as toPng, u as PopoverContent, w as AccordionContent, yt as Checkbox, z as extractBase64FromDataURL, zn as LoaderCircle, __tla as __tla_0 } from "./html-to-image-
|
|
9
|
+
import { B as isDataURLString, Bt as PluralWord, C as Accordion, Cn as jsonToMarkdown, Dt as toggleBreakpoint, E as AccordionTrigger, H as renderHTML, Hn as FileText, Ht as DATA_TYPE_ICON, It as getFeatureFlag, J as getCellEditorView, L as base64ToUint8Array, Ln as NotebookPen, M as DotFilledIcon, Mt as useChromeActions, N as PinLeftIcon, Nn as Wrench, Nt as adaptForLocalStorage, On as Close$1, Ot as goToCellLine, P as PinRightIcon, Pn as Trash2, Pt as jotaiJsonStorage, Q as notebookAtom, Qt as useRequestClient, Rn as Minus, Sn as jsonParseWithSpecialChar, St as isRecord, T as AccordionItem, Tn as atomWithStorage, Un as Eye, Ut as getDataTypeColor, Vn as Info, Wn as ExternalLink, Wt as resolveDataType, Xn as esm_default, Xt as getRequestClient, Yn as Braces, Zn as import_lib, _ as getDatasourceContext, _n as SCRATCH_CELL_ID, c as Popover, cn as getTracebackInfo, ct as AnsiUp, d as PopoverTrigger, dn as filenameAtom, ft as sanitizeHtml, gn as HTMLCellId, hn as CellOutputId, ht as displayCellName, it as useCellNames, j as ChevronRightIcon, k as CheckIcon, l as PopoverClose, lt as outputIsLoading, m as useExpandedOutput, mt as getCellDomProps, n as Spinner, nt as useCellActions, on as elementContainsMarimoCellFile, pt as DATA_CELL_ID, qn as CircleX, r as MarkdownRenderer, rt as useCellIds, sn as extractAllTracebackInfo, t as toPng, u as PopoverContent, w as AccordionContent, yt as Checkbox, z as extractBase64FromDataURL, zn as LoaderCircle, __tla as __tla_0 } from "./html-to-image-BtNr4zrO.js";
|
|
10
10
|
import { o as useSize, u as createLucideIcon } from "./dist-j30bBjjN.js";
|
|
11
11
|
import { c as Calendar, i as createReducerAndAtoms, r as Badge } from "./useLifecycle-Bw4wRj_O.js";
|
|
12
12
|
import { a as ListFilter, i as Table$1, n as $fb18d541ea1ad717$export$ad991b66133851cf, o as ChartPie, r as $5a387cc49350e6db$export$722debc0e56fea39, t as $896ba0a80a8f4d36$export$85fd5fdf27bacc79 } from "./useDateFormatter-B_vTzxpm.js";
|
|
13
13
|
import { t as Check } from "./check-58HHfHKy.js";
|
|
14
14
|
import { C as logNever, E as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7, I as X, N as usePrevious$1, O as $b5e257d569688ac6$export$535bd6ca7f90a273, P as useDirection, R as ChevronDown, S as assertNever, T as $488c6ddbf4ef74c2$export$cc77c4ff7e8673c5, _ as menuControlVariants, b as menuSeparatorVariants, f as selectStyles, g as menuControlCheckVariants, h as menuContentCommon, i as SelectContent, l as SelectTrigger, o as SelectItem, p as MENU_ITEM_DISABLED, r as Select, t as Strings, u as SelectValue, v as menuItemVariants, w as $a916eb452884faea$export$b7a616150fdb9f44, x as menuSubTriggerVariants, y as menuLabelVariants } from "./strings-DMLVGXRo.js";
|
|
15
15
|
import { $ as $e93e671b31057976$export$b8473d3665f3a75a, $t as Item2$2, A as $ee014567cb39d3f0$export$ff05c3ac10437e03, At as $c87311424ea30a05$export$78551043582a6a98, B as $64fa3d84918910a7$export$4d86445c2cf5e3, Bt as $d4ee10de306f2510$export$e58f029f0fbfdb29, C as DropdownMenuTrigger, Ct as $b4b717babfbb907b$export$bebd5a1431fec25d, D as $a049562f99e7db0e$export$f9c6924e160136d1, Dt as $df56164dff5785e2$export$4338b53315abf666, E as $a049562f99e7db0e$export$eb2fcfdbd7ba97d4, Et as $8ae05eaa5c114e9c$export$7f54fc3180508a52, F as $01b77f81d0f07f68$export$75b6ee27786ba447, Ft as $65484d02dcb7eb3e$export$457c3d6518dd4c6f, G as $64fa3d84918910a7$export$ef03459518577ad4, Gt as $bdb11010cef70236$export$b4cc09c592e8fdb8, H as $64fa3d84918910a7$export$c245e6201fed2f75, Ht as $431fbd86ca7dc216$export$b204af158042fbac, I as $01b77f81d0f07f68$export$b04be29aa201d4f5, It as $3ef42575df84b30b$export$9d1611c77c2fe928, J as marked, Jt as Anchor2, K as $64fa3d84918910a7$export$fabf2dc03a41866e, Kt as $bdb11010cef70236$export$f680877a34711e37, L as $f39a9eba43920ace$export$b5d7cc18bb8d2b59, Lt as $d4ee10de306f2510$export$4282f70798064fe0, M as $514c0188e459b4c0$export$9afb8bc826b033ea, Mt as $c87311424ea30a05$export$a11b0059900ceec8, N as $d2b4bc8c273e7be6$export$24d547caef80ccd1, Nt as $c87311424ea30a05$export$fedb369cb70207f1, O as $d3e0e05bdfcf66bd$export$c24727297075ec6a, Ot as $313b98861ee5dd6c$export$d6875122194c7b44, P as $d2b4bc8c273e7be6$export$353f5b6fc5456de1, Pt as $7215afc6de606d6b$export$de79e2c695e052f3, Q as $2baaea4c71418dea$export$294aa081a6c6f55d, Qt as Group, R as $64fa3d84918910a7$export$2881499e37b75b9a, Rt as $d4ee10de306f2510$export$b4f377a2b6254582, S as DropdownMenuSubTrigger, St as $b4b717babfbb907b$export$4c063cf1350e6fed, T as $3985021b0ad6602f$export$f5b8910cec6cf069, Tt as $e9faafb641e167db$export$90fc3a17d93f704c, U as $64fa3d84918910a7$export$c62b8e45d58ddad9, Ut as $431fbd86ca7dc216$export$f21a1ffae260145a, V as $64fa3d84918910a7$export$9d4c57ee4c6ffdd8, Vt as $f4e2df6bd15f8569$export$98658e8c59125e6a, W as $64fa3d84918910a7$export$df3a06d6289f983e, Wt as $ff5963eb1fccf552$export$e08e3b67e392101e, Xt as CheckboxItem, Yt as Arrow2, Z as $d2e8511e6f209edf$export$e908e06f4b8e3402, Zt as Content2$1, _ as DropdownMenuPortal, _t as $f6c31cce2adf654f$export$45712eceda6fad21, a as NumberField, an as Root3, at as $319e236875307eab$export$a9b970dcc4ae71a9, b as DropdownMenuSub, bt as $9446cca9a3875146$export$7d15b64cf5a3a4c4, c as prettyEngineeringNumber, cn as SubContent, ct as $6c7bd7858deea686$export$cd11ab140839f11d, dn as Item, dt as $6db58dc88e78b024$export$2f817fcdc4b89ae0, en as ItemIndicator, et as $e5be200c675c3b3a$export$75ee7c75d68f5b0e, f as DropdownMenu, fn as Root$3, ft as $5b160d28a433310d$export$c17fa47878dc55b6, g as DropdownMenuLabel, gn as ChevronRight, gt as $507fabe10e71c6fb$export$630ff653c5ada6a9, h as DropdownMenuItem, hn as Circle, ht as $3ad3f6e1647bc98d$export$80f3e147d781571c, in as RadioItem, it as $e5be200c675c3b3a$export$fc1a364ae1f3ff10, j as $514c0188e459b4c0$export$5f1af8db9871e1d6, jt as $c87311424ea30a05$export$9ac100e40613ea10, k as $ee014567cb39d3f0$export$f551688fc98f2e09, kt as $c87311424ea30a05$export$6446a186d09e379e, l as prettyNumber, ln as SubTrigger, lt as $fca6afa0e843324b$export$87b761675e8eaa10, mn as Search, mt as $9ab94262bd0047c7$export$420e68273165f4ec, nn as Portal, nt as $e5be200c675c3b3a$export$aca958c65c314e6c, on as Separator$1, ot as $f7dceffc5ad7768b$export$4e328f61c538687f, p as DropdownMenuContent, pn as createRovingFocusGroupScope, pt as $6179b936705e76d3$export$ae780daf29e6d456, qt as $f0a04ccd8dbdd83b$export$e5c5a5f917a5871c, r as Input, rn as RadioGroup$2, rt as $e5be200c675c3b3a$export$dad6ae84456c676a, s as maxFractionalDigits, sn as Sub, tn as Label$1, tt as $e5be200c675c3b3a$export$a763b9476acd3eb, u as prettyScientificNumber, un as createMenuScope, ut as $fca6afa0e843324b$export$f12b703ca79dfbb1, v as DropdownMenuSeparator, vt as _class_private_field_init, w as $3985021b0ad6602f$export$37fb8590cf2c088c, wt as $99facab73266f662$export$5add1d006293d136, x as DropdownMenuSubContent, xt as $458b0a5536c1a7cf$export$40bfa8c7b0832715, yt as $ae1eeba8b9eafd08$export$5165eccb35aaadb5, z as $64fa3d84918910a7$export$29f1550f4b0d4415, zt as $d4ee10de306f2510$export$cd4e5573fbe2b576 } from "./input-BRE2a7Ay.js";
|
|
16
|
-
import { S as isWasm, a as millisecondsInMinute, b as viewStateAtom, c as asRemoteURL, d as isStaticNotebook, i as millisecondsInHour, n as constructFrom, o as millisecondsInSecond, p as isUrl, r as millisecondsInDay, s as millisecondsInWeek, t as toDate, v as kioskModeAtom, y as useInstallAllowed } from "./toDate-
|
|
16
|
+
import { S as isWasm, a as millisecondsInMinute, b as viewStateAtom, c as asRemoteURL, d as isStaticNotebook, i as millisecondsInHour, n as constructFrom, o as millisecondsInSecond, p as isUrl, r as millisecondsInDay, s as millisecondsInWeek, t as toDate, v as kioskModeAtom, y as useInstallAllowed } from "./toDate-CjUYDkFI.js";
|
|
17
17
|
import { r as Plus, t as ErrorBoundary } from "./ErrorBoundary-BniTEhHn.js";
|
|
18
18
|
import { n as clsx_default } from "./clsx-CIWA5tNO.js";
|
|
19
19
|
import { t as require_react_dom } from "./react-dom-CmENFV8Q.js";
|
|
@@ -30,7 +30,7 @@ import { c as uniqueBy, t as Arrays } from "./arrays-C56grfjL.js";
|
|
|
30
30
|
import { t as Objects } from "./objects-UzwQd5gx.js";
|
|
31
31
|
import { n as once, t as memoizeLastValue } from "./once-Boutk_9X.js";
|
|
32
32
|
import { a as parser } from "./dist-Ckfsc8C3.js";
|
|
33
|
-
import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-
|
|
33
|
+
import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-Dz0QNUEa.js";
|
|
34
34
|
import { n as memoize$1, t as isPropValid } from "./emotion-is-prop-valid.esm-_z-EwK5u.js";
|
|
35
35
|
import { A as getContainerWidth, n as formats } from "./vega-loader.browser-CGb-2Kwi.js";
|
|
36
36
|
import { a as tooltipHandler, n as vegaLoadData, r as createBatchedLoader, t as parseCsvData } from "./loader-DTnbNSVZ.js";
|
|
@@ -36331,7 +36331,7 @@ ${d}`,
|
|
|
36331
36331
|
return Logger.warn("Failed to get version from mount config"), null;
|
|
36332
36332
|
}
|
|
36333
36333
|
}
|
|
36334
|
-
marimoVersionAtom = atom(getVersionFromMountConfig() || "0.24.1-
|
|
36334
|
+
marimoVersionAtom = atom(getVersionFromMountConfig() || "0.24.1-dev3");
|
|
36335
36335
|
showCodeInRunModeAtom = atom(true);
|
|
36336
36336
|
atom(null);
|
|
36337
36337
|
var import_compiler_runtime = require_compiler_runtime();
|
|
@@ -2,7 +2,7 @@ import { o as __toESM } from "./chunk-Bfp04NdC.js";
|
|
|
2
2
|
import { h as cn, r as cva } from "./button-Dr2uAwhT.js";
|
|
3
3
|
import { t as require_react } from "./react-DhGsCS90.js";
|
|
4
4
|
import { t as require_compiler_runtime } from "./compiler-runtime-DsR6imPN.js";
|
|
5
|
-
import { t as toDate } from "./toDate-
|
|
5
|
+
import { t as toDate } from "./toDate-CjUYDkFI.js";
|
|
6
6
|
import { t as require_jsx_runtime } from "./jsx-runtime-Dp_oQwaf.js";
|
|
7
7
|
import { i as tableFromIPC } from "./loader-DTnbNSVZ.js";
|
|
8
8
|
function isDate(e) {
|
|
@@ -12,7 +12,7 @@ import { a as Type, c as Calendar, i as createReducerAndAtoms, o as ToggleLeft,
|
|
|
12
12
|
import { t as Check } from "./check-58HHfHKy.js";
|
|
13
13
|
import { C as logNever, F as createCollection, I as X, N as usePrevious, P as useDirection, R as ChevronDown, S as assertNever, a as SelectGroup, c as SelectSeparator, i as SelectContent, l as SelectTrigger, o as SelectItem, r as Select, s as SelectLabel, t as Strings, u as SelectValue } from "./strings-DMLVGXRo.js";
|
|
14
14
|
import { J as marked, X as useDebouncedCallback, _t as $f6c31cce2adf654f$export$45712eceda6fad21, q as useNonce } from "./input-BRE2a7Ay.js";
|
|
15
|
-
import { C as assertExists, S as isWasm, _ as initialModeAtom, g as getInitialAppMode, h as waitForConnectionOpen, l as getRuntimeManager, t as toDate, v as kioskModeAtom, w as CircleQuestionMark, x as Deferred } from "./toDate-
|
|
15
|
+
import { C as assertExists, S as isWasm, _ as initialModeAtom, g as getInitialAppMode, h as waitForConnectionOpen, l as getRuntimeManager, t as toDate, v as kioskModeAtom, w as CircleQuestionMark, x as Deferred } from "./toDate-CjUYDkFI.js";
|
|
16
16
|
import { t as require_react_dom } from "./react-dom-CmENFV8Q.js";
|
|
17
17
|
import { t as require_jsx_runtime } from "./jsx-runtime-Dp_oQwaf.js";
|
|
18
18
|
import { $ as StyleNamespace, J as MAX_HEIGHT_OFFSET, L as string$2, N as number$2, P as object, T as boolean$2, X as withFullScreenAsRoot, Z as withSmartCollisionBoundary, _t as Primitive, at as FocusScope, ct as Root$1, dt as Presence, et as hideOthers, ft as useControllableState, gt as createContextScope, it as Portal, k as literal, lt as useCallbackRef, mt as composeEventHandlers, ot as Branch, pt as useLayoutEffect2, rt as useFocusGuards, st as DismissableLayer, tt as Combination_default, ut as useId, vt as dispatchDiscreteCustomEvent, w as array$2, z as union } from "./zod-BFY2SnzC.js";
|
package/dist/main.js
CHANGED
|
@@ -22,17 +22,17 @@ import { _ as Functions, c as useEventListener, f as composeRefs, g as Logger, h
|
|
|
22
22
|
import { t as require_react } from "./react-DhGsCS90.js";
|
|
23
23
|
import { t as require_compiler_runtime } from "./compiler-runtime-DsR6imPN.js";
|
|
24
24
|
import { n as Copy, r as toast, t as copyToClipboard } from "./copy-C7ZKMKox.js";
|
|
25
|
-
import { $ as notebookOutline, $t as isUninstantiated, A as ChevronDownIcon, An as Item$1, At as DeferredRequestRegistry, Bn as Layers, C as Accordion, Ct as MarkdownLanguageAdapter, D as BorderAllIcon, E as AccordionTrigger, En as selectAtom, Et as Paths, Fn as Table2, G as hasRunAnyCellAtom, Gn as Database, Gt as require_client, H as renderHTML, Hn as FileText, Ht as DATA_TYPE_ICON, I as base64ToDataView, In as PaintRoller, Jn as CircleAlert, K as cellIdsAtom, Kn as Columns2, Lt as repl, Mn as Trigger2, Pn as Trash2, Pt as jotaiJsonStorage, Q as notebookAtom, Qt as useRequestClient, R as dataViewToBase64, Rt as SQLParser, Sn as jsonParseWithSpecialChar, St as isRecord, T as AccordionItem, Tn as atomWithStorage, Tt as PathBuilder, U as getMarimoExportContext, Un as Eye, V as safeExtractSetUIElementMessageBuffers, Vn as Info, Vt as PluralWords, W as hasTrustedExportContext, X as hasOnlyOneCellAtom, Xt as getRequestClient, Y as getCellNames, Yn as Braces, Yt as convertStatsName, Z as initialNotebookState, Zt as requestClientAtom, _t as isInternalCellName, a as useCellFocusActions, at as createCell, bn as OBJECT_ID_ATTR, bt as customPythonLanguageSupport, dt as headingToIdentifier, en as publishedCellClasses, et as numColumnsAtom, f as isOutputEmpty, fn as parseAttrValue, gn as HTMLCellId, gt as getValidName, i as LazyAnyLanguageCodeMirror, jn as Root2$1, jt as generateUUID, kn as Content2, ln as NotebookScopedLocalStorage, lt as outputIsLoading, mn as parseInitialValue, n as Spinner, nt as useCellActions, o as useLastFocusedCellId, p as useExpandedConsoleOutput, pn as parseDataset, q as createActions, rt as useCellIds, s as maybeAddAltairImport, tn as shouldHidePublishedCell, tt as reducer, ut as outputIsStale, vn as UIElementId, vt as normalizeName, w as AccordionContent, wn as atomWithReducer, xn as RANDOM_ID_ATTR, xt as hasFunctionProperty, yn as findCellId, yt as Checkbox, zn as LoaderCircle, zt as MarkdownParser, __tla as __tla_0 } from "./html-to-image-
|
|
25
|
+
import { $ as notebookOutline, $t as isUninstantiated, A as ChevronDownIcon, An as Item$1, At as DeferredRequestRegistry, Bn as Layers, C as Accordion, Ct as MarkdownLanguageAdapter, D as BorderAllIcon, E as AccordionTrigger, En as selectAtom, Et as Paths, Fn as Table2, G as hasRunAnyCellAtom, Gn as Database, Gt as require_client, H as renderHTML, Hn as FileText, Ht as DATA_TYPE_ICON, I as base64ToDataView, In as PaintRoller, Jn as CircleAlert, K as cellIdsAtom, Kn as Columns2, Lt as repl, Mn as Trigger2, Pn as Trash2, Pt as jotaiJsonStorage, Q as notebookAtom, Qt as useRequestClient, R as dataViewToBase64, Rt as SQLParser, Sn as jsonParseWithSpecialChar, St as isRecord, T as AccordionItem, Tn as atomWithStorage, Tt as PathBuilder, U as getMarimoExportContext, Un as Eye, V as safeExtractSetUIElementMessageBuffers, Vn as Info, Vt as PluralWords, W as hasTrustedExportContext, X as hasOnlyOneCellAtom, Xt as getRequestClient, Y as getCellNames, Yn as Braces, Yt as convertStatsName, Z as initialNotebookState, Zt as requestClientAtom, _t as isInternalCellName, a as useCellFocusActions, at as createCell, bn as OBJECT_ID_ATTR, bt as customPythonLanguageSupport, dt as headingToIdentifier, en as publishedCellClasses, et as numColumnsAtom, f as isOutputEmpty, fn as parseAttrValue, gn as HTMLCellId, gt as getValidName, i as LazyAnyLanguageCodeMirror, jn as Root2$1, jt as generateUUID, kn as Content2, ln as NotebookScopedLocalStorage, lt as outputIsLoading, mn as parseInitialValue, n as Spinner, nt as useCellActions, o as useLastFocusedCellId, p as useExpandedConsoleOutput, pn as parseDataset, q as createActions, rt as useCellIds, s as maybeAddAltairImport, tn as shouldHidePublishedCell, tt as reducer, ut as outputIsStale, vn as UIElementId, vt as normalizeName, w as AccordionContent, wn as atomWithReducer, xn as RANDOM_ID_ATTR, xt as hasFunctionProperty, yn as findCellId, yt as Checkbox, zn as LoaderCircle, zt as MarkdownParser, __tla as __tla_0 } from "./html-to-image-BtNr4zrO.js";
|
|
26
26
|
import { __tla as __tla_1 } from "./chunk-5FQGJX7Z-BRZ_XYUw.js";
|
|
27
27
|
import { o as useSize, s as Root$1, u as createLucideIcon } from "./dist-j30bBjjN.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, 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-BL1GSUUF.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-
|
|
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-BvTQu-LJ.js";
|
|
30
30
|
import { c as Calendar, i as createReducerAndAtoms, n as useOnUnmount, o as ToggleLeft, t as useOnMount } from "./useLifecycle-Bw4wRj_O.js";
|
|
31
31
|
import { t as Check } from "./check-58HHfHKy.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-DMLVGXRo.js";
|
|
33
33
|
import { B as $64fa3d84918910a7$export$4d86445c2cf5e3, C as DropdownMenuTrigger, Ft as $65484d02dcb7eb3e$export$457c3d6518dd4c6f, It as $3ef42575df84b30b$export$9d1611c77c2fe928, W as $64fa3d84918910a7$export$df3a06d6289f983e, Wt as $ff5963eb1fccf552$export$e08e3b67e392101e, X as useDebouncedCallback, Y as useDebounceControlledState, a as NumberField, d as roundToFractionDigits, f as DropdownMenu, g as DropdownMenuLabel, gn as ChevronRight, h as DropdownMenuItem, hn as Circle, i as OnBlurredInput, l as prettyNumber, m as DropdownMenuGroup, n as DebouncedNumberInput, o as maxFractionDigitsForSteps, ot as $f7dceffc5ad7768b$export$4e328f61c538687f, p as DropdownMenuContent, pt as $6179b936705e76d3$export$ae780daf29e6d456, r as Input, st as $701a24aa0da5b062$export$ea18c227d4417cc3, t as DebouncedInput, u as prettyScientificNumber, v as DropdownMenuSeparator, xt as $458b0a5536c1a7cf$export$40bfa8c7b0832715, y as DropdownMenuShortcut, z as $64fa3d84918910a7$export$29f1550f4b0d4415 } from "./input-BRE2a7Ay.js";
|
|
34
|
-
import { S as isWasm, _ as initialModeAtom, b as viewStateAtom, c as asRemoteURL, d as isStaticNotebook, f as appendQueryParams, g as getInitialAppMode, m as require_cuid2, u as getStaticVirtualFiles, v as kioskModeAtom, w as CircleQuestionMark, x as Deferred } from "./toDate-
|
|
35
|
-
import { a as MarimoIncomingMessageEvent, c as MarimoValueUpdateEvent, f as Square, i as PythonIcon, l as createInputEvent, n as blobToString, o as MarimoValueInputEvent, p as File, r as filesToBase64, s as MarimoValueReadyEvent, t as processOutput, u as deserializeBlob } from "./process-output-
|
|
34
|
+
import { S as isWasm, _ as initialModeAtom, b as viewStateAtom, c as asRemoteURL, d as isStaticNotebook, f as appendQueryParams, g as getInitialAppMode, m as require_cuid2, u as getStaticVirtualFiles, v as kioskModeAtom, w as CircleQuestionMark, x as Deferred } from "./toDate-CjUYDkFI.js";
|
|
35
|
+
import { a as MarimoIncomingMessageEvent, c as MarimoValueUpdateEvent, f as Square, i as PythonIcon, l as createInputEvent, n as blobToString, o as MarimoValueInputEvent, p as File, r as filesToBase64, s as MarimoValueReadyEvent, t as processOutput, u as deserializeBlob } from "./process-output-Dch8KCi8.js";
|
|
36
36
|
import { n as Trash, r as Pencil, t as BulkEdit } from "./types-DT8UHI5w.js";
|
|
37
37
|
import { n as require_prop_types, r as Plus, t as ErrorBoundary } from "./ErrorBoundary-BniTEhHn.js";
|
|
38
38
|
import { t as require_react_dom } from "./react-dom-CmENFV8Q.js";
|
|
@@ -59,7 +59,7 @@ import "./dist-D1vYHETp.js";
|
|
|
59
59
|
import { r as python } from "./dist-Ckfsc8C3.js";
|
|
60
60
|
import { n as minimalSetup, t as esm_default } from "./esm-QLUgkqzZ.js";
|
|
61
61
|
import "./purify.es-DR5PNXwx.js";
|
|
62
|
-
import { i as AlertTitle, n as Alert, r as AlertDescription } from "./formats-
|
|
62
|
+
import { i as AlertTitle, n as Alert, r as AlertDescription } from "./formats-Dz0QNUEa.js";
|
|
63
63
|
import { A as getContainerWidth, j as getVegaFieldTypes } from "./vega-loader.browser-CGb-2Kwi.js";
|
|
64
64
|
import { a as tooltipHandler, n as vegaLoadData } from "./loader-DTnbNSVZ.js";
|
|
65
65
|
import "./defaultLocale-CMezyvMc.js";
|
|
@@ -9016,7 +9016,7 @@ let __tla = Promise.all([
|
|
|
9016
9016
|
};
|
|
9017
9017
|
}
|
|
9018
9018
|
};
|
|
9019
|
-
var LazyChatbot = import_react.lazy(() => import("./chat-ui-
|
|
9019
|
+
var LazyChatbot = import_react.lazy(() => import("./chat-ui-ChBRy1iT.js").then((e) => ({
|
|
9020
9020
|
default: e.Chatbot
|
|
9021
9021
|
}))), messageSchema = array(object({
|
|
9022
9022
|
id: string(),
|
|
@@ -28441,7 +28441,7 @@ ${c}
|
|
|
28441
28441
|
return true;
|
|
28442
28442
|
}
|
|
28443
28443
|
}
|
|
28444
|
-
var LazyVegaComponent = import_react.lazy(() => import("./vega-component-
|
|
28444
|
+
var LazyVegaComponent = import_react.lazy(() => import("./vega-component-CioKuDut.js")), VegaPlugin = class {
|
|
28445
28445
|
constructor() {
|
|
28446
28446
|
__publicField(this, "tagName", "marimo-vega");
|
|
28447
28447
|
__publicField(this, "validator", object({
|
|
@@ -38213,7 +38213,7 @@ ${c}
|
|
|
38213
38213
|
function _temp2$2(e) {
|
|
38214
38214
|
e.target === e.currentTarget && e.key === "Enter" && (e.preventDefault(), e.stopPropagation(), e.currentTarget.click());
|
|
38215
38215
|
}
|
|
38216
|
-
var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-
|
|
38216
|
+
var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-qNkzuPp3.js"));
|
|
38217
38217
|
const SlidesLayoutRenderer = ({ layout: e, setLayout: r, cells: c, mode: l }) => {
|
|
38218
38218
|
var _a5;
|
|
38219
38219
|
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), [
|
|
@@ -40354,6 +40354,7 @@ ${c}
|
|
|
40354
40354
|
__publicField(this, "sendFileDetails", throwNotImplemented);
|
|
40355
40355
|
__publicField(this, "openTutorial", throwNotImplemented);
|
|
40356
40356
|
__publicField(this, "getExportAvailability", throwNotImplemented);
|
|
40357
|
+
__publicField(this, "installExportRequirements", throwNotImplemented);
|
|
40357
40358
|
__publicField(this, "exportAsHTML", throwNotImplemented);
|
|
40358
40359
|
__publicField(this, "exportAsIPYNB", throwNotImplemented);
|
|
40359
40360
|
__publicField(this, "exportAsMarkdown", throwNotImplemented);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { o as __toESM } from "./chunk-Bfp04NdC.js";
|
|
2
2
|
import { t as require_compiler_runtime } from "./compiler-runtime-DsR6imPN.js";
|
|
3
|
-
import { F as base64ToDataURL, ot as ansiToPlainText, st as parseHtmlContent } from "./html-to-image-
|
|
3
|
+
import { F as base64ToDataURL, ot as ansiToPlainText, st as parseHtmlContent } from "./html-to-image-BtNr4zrO.js";
|
|
4
4
|
import { u as createLucideIcon } from "./dist-j30bBjjN.js";
|
|
5
5
|
import { t as Strings } from "./strings-DMLVGXRo.js";
|
|
6
6
|
import { t as require_jsx_runtime } from "./jsx-runtime-Dp_oQwaf.js";
|
|
@@ -6,13 +6,13 @@ import { o as __toESM } from "./chunk-Bfp04NdC.js";
|
|
|
6
6
|
import { c as useEventListener, g as Logger, h as cn, m as Events, t as Button } from "./button-Dr2uAwhT.js";
|
|
7
7
|
import { t as require_react } from "./react-DhGsCS90.js";
|
|
8
8
|
import { t as require_compiler_runtime } from "./compiler-runtime-DsR6imPN.js";
|
|
9
|
-
import { ut as outputIsStale } from "./html-to-image-
|
|
9
|
+
import { ut as outputIsStale } from "./html-to-image-BtNr4zrO.js";
|
|
10
10
|
import "./chunk-5FQGJX7Z-BRZ_XYUw.js";
|
|
11
11
|
import { u as createLucideIcon } from "./dist-j30bBjjN.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-
|
|
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-BvTQu-LJ.js";
|
|
13
13
|
import { R as ChevronDown } from "./strings-DMLVGXRo.js";
|
|
14
14
|
import { X as useDebouncedCallback } from "./input-BRE2a7Ay.js";
|
|
15
|
-
import { v as kioskModeAtom } from "./toDate-
|
|
15
|
+
import { v as kioskModeAtom } from "./toDate-CjUYDkFI.js";
|
|
16
16
|
import "./react-dom-CmENFV8Q.js";
|
|
17
17
|
import { t as require_jsx_runtime } from "./jsx-runtime-Dp_oQwaf.js";
|
|
18
18
|
import { Y as useFullScreenElement } from "./zod-BFY2SnzC.js";
|
|
@@ -54,8 +54,8 @@ const viewStateAtom = atom({
|
|
|
54
54
|
cellAnchor: null
|
|
55
55
|
}), initialModeAtom = atom(void 0), kioskModeAtom = atom(false);
|
|
56
56
|
function useInstallAllowed() {
|
|
57
|
-
let { mode: e } = useAtomValue(viewStateAtom);
|
|
58
|
-
return e !== "read";
|
|
57
|
+
let { mode: e } = useAtomValue(viewStateAtom), S = useAtomValue(kioskModeAtom), C = new URLSearchParams(window.location.search).get(KnownQueryParams.kiosk) === "true";
|
|
58
|
+
return e !== "read" && !S && !C;
|
|
59
59
|
}
|
|
60
60
|
const WebSocketState = {
|
|
61
61
|
NOT_STARTED: "NOT_STARTED",
|
|
@@ -2,7 +2,7 @@ import { o as __toESM } from "./chunk-Bfp04NdC.js";
|
|
|
2
2
|
import { g as Logger, h as cn, m as Events } from "./button-Dr2uAwhT.js";
|
|
3
3
|
import { t as require_react } from "./react-DhGsCS90.js";
|
|
4
4
|
import { t as require_compiler_runtime } from "./compiler-runtime-DsR6imPN.js";
|
|
5
|
-
import { c as asRemoteURL, w as CircleQuestionMark } from "./toDate-
|
|
5
|
+
import { c as asRemoteURL, w as CircleQuestionMark } from "./toDate-CjUYDkFI.js";
|
|
6
6
|
import "./react-dom-CmENFV8Q.js";
|
|
7
7
|
import { t as require_jsx_runtime } from "./jsx-runtime-Dp_oQwaf.js";
|
|
8
8
|
import "./zod-BFY2SnzC.js";
|
|
@@ -12,7 +12,7 @@ import { t as debounce_default } from "./debounce-D784bpms.js";
|
|
|
12
12
|
import { A as useEvent_default, n as useTheme } from "./useTheme-BzEXeAR5.js";
|
|
13
13
|
import { s as uniq } from "./arrays-C56grfjL.js";
|
|
14
14
|
import { t as Objects } from "./objects-UzwQd5gx.js";
|
|
15
|
-
import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-
|
|
15
|
+
import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-Dz0QNUEa.js";
|
|
16
16
|
import { A as getContainerWidth, n as formats } from "./vega-loader.browser-CGb-2Kwi.js";
|
|
17
17
|
import { a as tooltipHandler, n as vegaLoadData } from "./loader-DTnbNSVZ.js";
|
|
18
18
|
import { t as j } from "./react-vega-zyfTF9SY.js";
|
package/package.json
CHANGED
|
@@ -100,6 +100,10 @@ export const MockRequestClient = {
|
|
|
100
100
|
},
|
|
101
101
|
],
|
|
102
102
|
}),
|
|
103
|
+
installExportRequirements: vi.fn().mockResolvedValue({
|
|
104
|
+
source: "server",
|
|
105
|
+
formats: [],
|
|
106
|
+
}),
|
|
103
107
|
exportAsHTML: vi.fn().mockResolvedValue({
|
|
104
108
|
contents: "",
|
|
105
109
|
filename: "notebook.html",
|
|
@@ -13,12 +13,16 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
13
13
|
import { MockRequestClient } from "@/__mocks__/requests";
|
|
14
14
|
import { Dialog } from "@/components/ui/dialog";
|
|
15
15
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
16
|
-
import { viewStateAtom } from "@/core/mode";
|
|
16
|
+
import { kioskModeAtom, viewStateAtom } from "@/core/mode";
|
|
17
17
|
import { requestClientAtom } from "@/core/network/requests";
|
|
18
|
+
import { createErrorToastingRequests } from "@/core/network/requests-toasting";
|
|
19
|
+
import type { ExportAvailabilityResponse } from "@/core/network/types";
|
|
18
20
|
import { filenameAtom } from "@/core/saving/file-state";
|
|
19
21
|
import { store } from "@/core/state/jotai";
|
|
20
22
|
import { isWasm } from "@/core/wasm/utils";
|
|
21
23
|
import * as copyModule from "@/utils/copy";
|
|
24
|
+
import { Deferred } from "@/utils/Deferred";
|
|
25
|
+
import { HTTPError } from "@/utils/errors";
|
|
22
26
|
import { ExportDialog } from "../export-dialog";
|
|
23
27
|
import {
|
|
24
28
|
DEFAULT_EXPORT_OPTIONS,
|
|
@@ -27,14 +31,22 @@ import {
|
|
|
27
31
|
lastExportFormatAtom,
|
|
28
32
|
} from "../state";
|
|
29
33
|
|
|
30
|
-
const { exportNotebookMock } = vi.hoisted(() => ({
|
|
34
|
+
const { exportNotebookMock, toastMock } = vi.hoisted(() => ({
|
|
31
35
|
exportNotebookMock: vi.fn().mockResolvedValue(undefined),
|
|
36
|
+
toastMock: vi.fn(() => ({
|
|
37
|
+
dismiss: vi.fn(),
|
|
38
|
+
update: vi.fn(),
|
|
39
|
+
})),
|
|
32
40
|
}));
|
|
33
41
|
|
|
34
42
|
vi.mock("@/utils/copy", () => ({
|
|
35
43
|
copyToClipboard: vi.fn().mockResolvedValue(undefined),
|
|
36
44
|
}));
|
|
37
45
|
|
|
46
|
+
vi.mock("@/components/ui/use-toast", () => ({
|
|
47
|
+
toast: toastMock,
|
|
48
|
+
}));
|
|
49
|
+
|
|
38
50
|
vi.mock("@/core/wasm/utils", async (importOriginal) => {
|
|
39
51
|
const actual = await importOriginal<typeof import("@/core/wasm/utils")>();
|
|
40
52
|
return { ...actual, isWasm: vi.fn(() => false) };
|
|
@@ -67,6 +79,32 @@ async function waitForExportEnabled() {
|
|
|
67
79
|
);
|
|
68
80
|
}
|
|
69
81
|
|
|
82
|
+
type FormatAvailability = ExportAvailabilityResponse["formats"][number];
|
|
83
|
+
|
|
84
|
+
function formatAvailability(
|
|
85
|
+
format: FormatAvailability["format"],
|
|
86
|
+
overrides: Partial<Omit<FormatAvailability, "format">> = {},
|
|
87
|
+
): FormatAvailability {
|
|
88
|
+
return {
|
|
89
|
+
format,
|
|
90
|
+
dependenciesAvailable: true,
|
|
91
|
+
missingPackages: [],
|
|
92
|
+
missingSetup: [],
|
|
93
|
+
...overrides,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function serverAvailability(
|
|
98
|
+
...formats: FormatAvailability[]
|
|
99
|
+
): ExportAvailabilityResponse {
|
|
100
|
+
return { source: "server", formats };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const PLAYWRIGHT_SETUP = {
|
|
104
|
+
name: "playwright-chromium",
|
|
105
|
+
command: "uv run playwright install chromium",
|
|
106
|
+
} as const;
|
|
107
|
+
|
|
70
108
|
describe("ExportDialog", () => {
|
|
71
109
|
beforeEach(() => {
|
|
72
110
|
vi.clearAllMocks();
|
|
@@ -74,8 +112,10 @@ describe("ExportDialog", () => {
|
|
|
74
112
|
store.set(requestClientAtom, MockRequestClient.create());
|
|
75
113
|
store.set(filenameAtom, "/project/notebook.py");
|
|
76
114
|
store.set(viewStateAtom, { mode: "edit", cellAnchor: null });
|
|
115
|
+
store.set(kioskModeAtom, false);
|
|
77
116
|
store.set(exportOptionsAtom, DEFAULT_EXPORT_OPTIONS);
|
|
78
117
|
store.set(lastExportFormatAtom, "html");
|
|
118
|
+
window.history.replaceState(null, "", "/");
|
|
79
119
|
vi.mocked(isWasm).mockReturnValue(false);
|
|
80
120
|
vi.stubGlobal("matchMedia", () => ({
|
|
81
121
|
matches: false,
|
|
@@ -248,54 +288,80 @@ describe("ExportDialog", () => {
|
|
|
248
288
|
expect(tablist).toHaveAttribute("aria-orientation", "vertical");
|
|
249
289
|
});
|
|
250
290
|
|
|
251
|
-
it("
|
|
291
|
+
it("installs missing packages and applies refreshed availability", async () => {
|
|
292
|
+
const install = new Deferred<ExportAvailabilityResponse>();
|
|
293
|
+
const installExportRequirements = vi.fn(() => install.promise);
|
|
294
|
+
const getExportAvailability = vi.fn().mockResolvedValue(
|
|
295
|
+
serverAvailability(
|
|
296
|
+
formatAvailability("ipynb", {
|
|
297
|
+
dependenciesAvailable: false,
|
|
298
|
+
missingPackages: ["nbformat"],
|
|
299
|
+
}),
|
|
300
|
+
formatAvailability("pdf", {
|
|
301
|
+
dependenciesAvailable: false,
|
|
302
|
+
missingPackages: ["nbconvert[webpdf]", "nbformat"],
|
|
303
|
+
}),
|
|
304
|
+
),
|
|
305
|
+
);
|
|
252
306
|
store.set(
|
|
253
307
|
requestClientAtom,
|
|
254
308
|
MockRequestClient.create({
|
|
255
|
-
getExportAvailability
|
|
256
|
-
|
|
257
|
-
formats: [
|
|
258
|
-
{
|
|
259
|
-
format: "pdf",
|
|
260
|
-
dependenciesAvailable: false,
|
|
261
|
-
missingPackages: ["nbconvert[webpdf]"],
|
|
262
|
-
missingSetup: [],
|
|
263
|
-
},
|
|
264
|
-
],
|
|
265
|
-
}),
|
|
309
|
+
getExportAvailability,
|
|
310
|
+
installExportRequirements,
|
|
266
311
|
}),
|
|
267
312
|
);
|
|
268
313
|
|
|
269
314
|
renderDialog("pdf");
|
|
270
315
|
|
|
271
|
-
|
|
272
|
-
expect(
|
|
273
|
-
|
|
274
|
-
)
|
|
316
|
+
const packages = await screen.findByText("nbconvert[webpdf], nbformat");
|
|
317
|
+
expect(packages.parentElement).toHaveTextContent(
|
|
318
|
+
"PDF export requires nbconvert[webpdf], nbformat.",
|
|
319
|
+
);
|
|
275
320
|
expect(screen.getByTestId("export-submit")).toBeDisabled();
|
|
276
321
|
expect(screen.getByTestId("export-format-pdf")).toBeVisible();
|
|
322
|
+
|
|
323
|
+
const installButton = screen.getByRole("button", { name: "Install" });
|
|
324
|
+
const pdfTab = screen.getByTestId("export-format-pdf");
|
|
325
|
+
const htmlTab = screen.getByTestId("export-format-html");
|
|
326
|
+
|
|
327
|
+
fireEvent.click(installButton);
|
|
328
|
+
|
|
329
|
+
await waitFor(() =>
|
|
330
|
+
expect(installExportRequirements).toHaveBeenCalledWith({ format: "pdf" }),
|
|
331
|
+
);
|
|
332
|
+
expect(installButton).toHaveAttribute("aria-busy", "true");
|
|
333
|
+
expect(htmlTab).toBeDisabled();
|
|
334
|
+
|
|
335
|
+
fireEvent.click(installButton);
|
|
336
|
+
fireEvent.click(htmlTab);
|
|
337
|
+
expect(installExportRequirements).toHaveBeenCalledOnce();
|
|
338
|
+
expect(pdfTab).toHaveAttribute("data-state", "active");
|
|
339
|
+
|
|
340
|
+
install.resolve(
|
|
341
|
+
serverAvailability(
|
|
342
|
+
formatAvailability("ipynb"),
|
|
343
|
+
formatAvailability("pdf"),
|
|
344
|
+
),
|
|
345
|
+
);
|
|
346
|
+
await waitForExportEnabled();
|
|
347
|
+
expect(getExportAvailability).toHaveBeenCalledOnce();
|
|
348
|
+
|
|
349
|
+
fireEvent.click(screen.getByTestId("export-format-ipynb"));
|
|
350
|
+
expect(screen.getByTestId("export-submit")).toBeEnabled();
|
|
277
351
|
});
|
|
278
352
|
|
|
279
353
|
it("explains missing Playwright Chromium setup", async () => {
|
|
280
354
|
store.set(
|
|
281
355
|
requestClientAtom,
|
|
282
356
|
MockRequestClient.create({
|
|
283
|
-
getExportAvailability: vi.fn().mockResolvedValue(
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
{
|
|
287
|
-
format: "pdf",
|
|
357
|
+
getExportAvailability: vi.fn().mockResolvedValue(
|
|
358
|
+
serverAvailability(
|
|
359
|
+
formatAvailability("pdf", {
|
|
288
360
|
dependenciesAvailable: false,
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
command: "uv run playwright install chromium",
|
|
294
|
-
},
|
|
295
|
-
],
|
|
296
|
-
},
|
|
297
|
-
],
|
|
298
|
-
}),
|
|
361
|
+
missingSetup: [PLAYWRIGHT_SETUP],
|
|
362
|
+
}),
|
|
363
|
+
),
|
|
364
|
+
),
|
|
299
365
|
}),
|
|
300
366
|
);
|
|
301
367
|
|
|
@@ -305,9 +371,115 @@ describe("ExportDialog", () => {
|
|
|
305
371
|
await screen.findByText("PDF export requires Playwright Chromium."),
|
|
306
372
|
).toBeVisible();
|
|
307
373
|
expect(
|
|
308
|
-
screen.
|
|
374
|
+
screen.queryByText("uv run playwright install chromium"),
|
|
375
|
+
).not.toBeInTheDocument();
|
|
376
|
+
expect(screen.getByTestId("export-submit")).toBeDisabled();
|
|
377
|
+
expect(screen.getByRole("button", { name: "Install" })).toBeVisible();
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
it.each([
|
|
381
|
+
["read mode", "read", false, false],
|
|
382
|
+
["connected kiosk mode", "edit", true, false],
|
|
383
|
+
["pre-connection kiosk mode", "edit", false, true],
|
|
384
|
+
] as const)(
|
|
385
|
+
"shows the setup command when installation is not allowed in %s",
|
|
386
|
+
async (_label, mode, kioskMode, kioskRequested) => {
|
|
387
|
+
store.set(viewStateAtom, { mode, cellAnchor: null });
|
|
388
|
+
store.set(kioskModeAtom, kioskMode);
|
|
389
|
+
if (kioskRequested) {
|
|
390
|
+
window.history.replaceState(null, "", "/?kiosk=true");
|
|
391
|
+
}
|
|
392
|
+
store.set(
|
|
393
|
+
requestClientAtom,
|
|
394
|
+
MockRequestClient.create({
|
|
395
|
+
getExportAvailability: vi.fn().mockResolvedValue(
|
|
396
|
+
serverAvailability(
|
|
397
|
+
formatAvailability("pdf", {
|
|
398
|
+
dependenciesAvailable: false,
|
|
399
|
+
missingSetup: [PLAYWRIGHT_SETUP],
|
|
400
|
+
}),
|
|
401
|
+
),
|
|
402
|
+
),
|
|
403
|
+
}),
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
renderDialog("pdf");
|
|
407
|
+
|
|
408
|
+
expect(
|
|
409
|
+
await screen.findByText("PDF export requires Playwright Chromium."),
|
|
410
|
+
).toBeVisible();
|
|
411
|
+
expect(
|
|
412
|
+
screen.getByText("uv run playwright install chromium"),
|
|
413
|
+
).toBeVisible();
|
|
414
|
+
expect(
|
|
415
|
+
screen.queryByRole("button", { name: "Install" }),
|
|
416
|
+
).not.toBeInTheDocument();
|
|
417
|
+
},
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
it("allows requirement installation when kiosk is false", async () => {
|
|
421
|
+
window.history.replaceState(null, "", "/?kiosk=false");
|
|
422
|
+
store.set(
|
|
423
|
+
requestClientAtom,
|
|
424
|
+
MockRequestClient.create({
|
|
425
|
+
getExportAvailability: vi.fn().mockResolvedValue(
|
|
426
|
+
serverAvailability(
|
|
427
|
+
formatAvailability("pdf", {
|
|
428
|
+
dependenciesAvailable: false,
|
|
429
|
+
missingSetup: [PLAYWRIGHT_SETUP],
|
|
430
|
+
}),
|
|
431
|
+
),
|
|
432
|
+
),
|
|
433
|
+
}),
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
renderDialog("pdf");
|
|
437
|
+
|
|
438
|
+
expect(
|
|
439
|
+
await screen.findByRole("button", { name: "Install" }),
|
|
309
440
|
).toBeVisible();
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
it("restores the install action when installation fails", async () => {
|
|
444
|
+
const error = new HTTPError(500, "Server Error", {
|
|
445
|
+
detail: "Playwright Chromium installation failed. Check the server logs.",
|
|
446
|
+
});
|
|
447
|
+
const installExportRequirements = vi.fn().mockRejectedValue(error);
|
|
448
|
+
const getExportAvailability = vi.fn().mockResolvedValue(
|
|
449
|
+
serverAvailability(
|
|
450
|
+
formatAvailability("pdf", {
|
|
451
|
+
dependenciesAvailable: false,
|
|
452
|
+
missingPackages: ["nbconvert[webpdf]"],
|
|
453
|
+
}),
|
|
454
|
+
),
|
|
455
|
+
);
|
|
456
|
+
store.set(
|
|
457
|
+
requestClientAtom,
|
|
458
|
+
createErrorToastingRequests(
|
|
459
|
+
MockRequestClient.create({
|
|
460
|
+
getExportAvailability,
|
|
461
|
+
installExportRequirements,
|
|
462
|
+
}),
|
|
463
|
+
),
|
|
464
|
+
);
|
|
465
|
+
|
|
466
|
+
renderDialog("pdf");
|
|
467
|
+
|
|
468
|
+
const install = await screen.findByRole("button", { name: "Install" });
|
|
469
|
+
fireEvent.click(install);
|
|
470
|
+
|
|
471
|
+
await waitFor(() =>
|
|
472
|
+
expect(toastMock).toHaveBeenCalledWith({
|
|
473
|
+
title: "Failed to install export requirements",
|
|
474
|
+
description:
|
|
475
|
+
"Playwright Chromium installation failed. Check the server logs.",
|
|
476
|
+
variant: "danger",
|
|
477
|
+
}),
|
|
478
|
+
);
|
|
479
|
+
expect(install).toBeEnabled();
|
|
480
|
+
expect(install).toHaveAttribute("aria-busy", "false");
|
|
310
481
|
expect(screen.getByTestId("export-submit")).toBeDisabled();
|
|
482
|
+
expect(getExportAvailability).toHaveBeenCalledOnce();
|
|
311
483
|
});
|
|
312
484
|
|
|
313
485
|
it("announces requirement checks as status updates", () => {
|
|
@@ -28,13 +28,17 @@ export const ExportDialog: React.FC<{
|
|
|
28
28
|
const {
|
|
29
29
|
dialogRef,
|
|
30
30
|
isExporting,
|
|
31
|
+
isInstalling,
|
|
32
|
+
canInstall,
|
|
31
33
|
formats,
|
|
32
34
|
options,
|
|
33
35
|
selected,
|
|
34
36
|
selectFormat,
|
|
35
37
|
updateOptions,
|
|
38
|
+
installRequirements,
|
|
36
39
|
submit,
|
|
37
40
|
} = useExportDialog({ initialFormat, onClose });
|
|
41
|
+
const isBusy = isExporting || isInstalling;
|
|
38
42
|
const desktopLayout = useMediaQuery(DESKTOP_LAYOUT_QUERY);
|
|
39
43
|
const {
|
|
40
44
|
format,
|
|
@@ -86,7 +90,7 @@ export const ExportDialog: React.FC<{
|
|
|
86
90
|
<TabsTrigger
|
|
87
91
|
key={candidate}
|
|
88
92
|
value={candidate}
|
|
89
|
-
disabled={
|
|
93
|
+
disabled={isBusy}
|
|
90
94
|
className="min-w-0 justify-start gap-2 px-2.5 py-2 text-xs data-[state=active]:shadow-xs sm:w-full sm:text-sm"
|
|
91
95
|
data-testid={`export-format-${candidate}`}
|
|
92
96
|
>
|
|
@@ -119,13 +123,15 @@ export const ExportDialog: React.FC<{
|
|
|
119
123
|
format={format}
|
|
120
124
|
formatLabel={definition.label}
|
|
121
125
|
status={status}
|
|
126
|
+
onInstall={canInstall ? installRequirements : undefined}
|
|
127
|
+
isInstalling={isInstalling}
|
|
122
128
|
/>
|
|
123
129
|
|
|
124
130
|
{usesBrowserPrint ? null : (
|
|
125
131
|
<FormatOptions
|
|
126
132
|
options={options}
|
|
127
133
|
updateOptions={updateOptions}
|
|
128
|
-
disabled={
|
|
134
|
+
disabled={isBusy}
|
|
129
135
|
/>
|
|
130
136
|
)}
|
|
131
137
|
</TabsContent>
|
|
@@ -173,7 +179,7 @@ export const ExportDialog: React.FC<{
|
|
|
173
179
|
) : null}
|
|
174
180
|
<Button
|
|
175
181
|
type="button"
|
|
176
|
-
disabled={!status.available ||
|
|
182
|
+
disabled={!status.available || isBusy}
|
|
177
183
|
aria-busy={isExporting}
|
|
178
184
|
onClick={submit}
|
|
179
185
|
className={cn(
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
import { AlertCircleIcon } from "lucide-react";
|
|
3
|
+
import { AlertCircleIcon, DownloadCloudIcon } from "lucide-react";
|
|
4
4
|
import type { PropsWithChildren } from "react";
|
|
5
5
|
import { Spinner } from "@/components/icons/spinner";
|
|
6
6
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
7
|
+
import { Button } from "@/components/ui/button";
|
|
7
8
|
import { assertNever } from "@/utils/assertNever";
|
|
8
9
|
import { cn } from "@/utils/cn";
|
|
9
10
|
import type {
|
|
@@ -56,10 +57,14 @@ export function FormatNotice({
|
|
|
56
57
|
format,
|
|
57
58
|
formatLabel,
|
|
58
59
|
status,
|
|
60
|
+
onInstall,
|
|
61
|
+
isInstalling = false,
|
|
59
62
|
}: {
|
|
60
63
|
format: ExportFormat;
|
|
61
64
|
formatLabel: string;
|
|
62
65
|
status: ExportFormatStatus;
|
|
66
|
+
onInstall?: () => void;
|
|
67
|
+
isInstalling?: boolean;
|
|
63
68
|
}) {
|
|
64
69
|
if (status.availabilityCheckFailed) {
|
|
65
70
|
return (
|
|
@@ -80,20 +85,47 @@ export function FormatNotice({
|
|
|
80
85
|
format={format}
|
|
81
86
|
formatLabel={formatLabel}
|
|
82
87
|
reason={status.reason}
|
|
88
|
+
onInstall={onInstall}
|
|
89
|
+
isInstalling={isInstalling}
|
|
83
90
|
/>
|
|
84
91
|
</div>
|
|
85
92
|
);
|
|
86
93
|
}
|
|
87
94
|
|
|
88
|
-
function Notice({
|
|
95
|
+
function Notice({
|
|
96
|
+
children,
|
|
97
|
+
onInstall,
|
|
98
|
+
isInstalling = false,
|
|
99
|
+
}: PropsWithChildren<{
|
|
100
|
+
onInstall?: () => void;
|
|
101
|
+
isInstalling?: boolean;
|
|
102
|
+
}>) {
|
|
89
103
|
return (
|
|
90
104
|
<Alert
|
|
91
105
|
variant="warning"
|
|
92
|
-
className="flex items-
|
|
106
|
+
className="flex items-center gap-2.5 px-3 py-2 text-(--yellow-12) has-[svg]:pl-3 [&>svg]:static [&>svg+div]:translate-y-0"
|
|
93
107
|
>
|
|
94
|
-
<AlertCircleIcon className="
|
|
95
|
-
<AlertDescription className="min-w-0 flex-1 text-sm leading-5">
|
|
96
|
-
{children}
|
|
108
|
+
<AlertCircleIcon className="size-4 shrink-0" />
|
|
109
|
+
<AlertDescription className="flex min-w-0 flex-1 items-center gap-3 text-sm leading-5">
|
|
110
|
+
<span className="min-w-0 flex-1">{children}</span>
|
|
111
|
+
{onInstall ? (
|
|
112
|
+
<Button
|
|
113
|
+
type="button"
|
|
114
|
+
variant="outline"
|
|
115
|
+
size="xs"
|
|
116
|
+
className="shrink-0 border-input bg-background text-foreground hover:border-input hover:bg-muted hover:text-foreground"
|
|
117
|
+
disabled={isInstalling}
|
|
118
|
+
aria-busy={isInstalling}
|
|
119
|
+
onClick={onInstall}
|
|
120
|
+
>
|
|
121
|
+
{isInstalling ? (
|
|
122
|
+
<Spinner size="small" className="mr-1.5 size-3.5" />
|
|
123
|
+
) : (
|
|
124
|
+
<DownloadCloudIcon className="mr-1.5 size-3.5" />
|
|
125
|
+
)}
|
|
126
|
+
Install
|
|
127
|
+
</Button>
|
|
128
|
+
) : null}
|
|
97
129
|
</AlertDescription>
|
|
98
130
|
</Alert>
|
|
99
131
|
);
|
|
@@ -103,10 +135,14 @@ function ReasonNotice({
|
|
|
103
135
|
format,
|
|
104
136
|
formatLabel,
|
|
105
137
|
reason,
|
|
138
|
+
onInstall,
|
|
139
|
+
isInstalling,
|
|
106
140
|
}: {
|
|
107
141
|
format: ExportFormat;
|
|
108
142
|
formatLabel: string;
|
|
109
143
|
reason: ExportBlockReason;
|
|
144
|
+
onInstall?: () => void;
|
|
145
|
+
isInstalling: boolean;
|
|
110
146
|
}) {
|
|
111
147
|
switch (reason.type) {
|
|
112
148
|
case "checking-requirements":
|
|
@@ -126,30 +162,39 @@ function ReasonNotice({
|
|
|
126
162
|
return <Notice>Name and save this notebook before exporting.</Notice>;
|
|
127
163
|
case "missing-packages":
|
|
128
164
|
return (
|
|
129
|
-
<Notice>
|
|
130
|
-
|
|
165
|
+
<Notice onInstall={onInstall} isInstalling={isInstalling}>
|
|
166
|
+
{formatLabel} export requires{" "}
|
|
131
167
|
<code className="break-words font-mono">
|
|
132
168
|
{reason.packages.join(", ")}
|
|
133
|
-
</code>
|
|
134
|
-
|
|
169
|
+
</code>
|
|
170
|
+
.
|
|
135
171
|
</Notice>
|
|
136
172
|
);
|
|
137
173
|
case "missing-setup":
|
|
138
174
|
return (
|
|
139
|
-
<Notice>
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
175
|
+
<Notice onInstall={onInstall} isInstalling={isInstalling}>
|
|
176
|
+
{onInstall ? (
|
|
177
|
+
reason.requirements
|
|
178
|
+
.map(
|
|
179
|
+
(requirement) =>
|
|
180
|
+
SETUP_REQUIREMENTS[requirement.name].description,
|
|
181
|
+
)
|
|
182
|
+
.join(" ")
|
|
183
|
+
) : (
|
|
184
|
+
<span className="block min-w-0">
|
|
185
|
+
{reason.requirements.map((requirement) => {
|
|
186
|
+
const details = SETUP_REQUIREMENTS[requirement.name];
|
|
187
|
+
return (
|
|
188
|
+
<span className="block" key={requirement.name}>
|
|
189
|
+
{details.description}
|
|
190
|
+
<code className="mt-1 block break-all font-mono">
|
|
191
|
+
{requirement.command}
|
|
192
|
+
</code>
|
|
193
|
+
</span>
|
|
194
|
+
);
|
|
195
|
+
})}
|
|
196
|
+
</span>
|
|
197
|
+
)}
|
|
153
198
|
</Notice>
|
|
154
199
|
);
|
|
155
200
|
case "wasm-runtime":
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
updateCellOutputsWithScreenshots,
|
|
8
8
|
useEnrichCellOutputs,
|
|
9
9
|
} from "@/core/export/hooks";
|
|
10
|
-
import { runDuringPresentMode } from "@/core/mode";
|
|
10
|
+
import { runDuringPresentMode, useInstallAllowed } from "@/core/mode";
|
|
11
11
|
import { useRequestClient } from "@/core/network/requests";
|
|
12
12
|
import type { ExportAvailabilityResponse } from "@/core/network/types";
|
|
13
13
|
import { useFilename } from "@/core/saving/filename";
|
|
@@ -116,6 +116,8 @@ function useExportDialogState(initialFormat?: ExportFormat) {
|
|
|
116
116
|
);
|
|
117
117
|
const runtime = isWasm() ? "wasm" : "server";
|
|
118
118
|
const requests = useRequestClient();
|
|
119
|
+
const installAllowed = useInstallAllowed();
|
|
120
|
+
const [isInstalling, setIsInstalling] = useState(false);
|
|
119
121
|
|
|
120
122
|
const availabilityRequest =
|
|
121
123
|
useAsyncData<ExportAvailabilityResponse | null>(async () => {
|
|
@@ -135,6 +137,10 @@ function useExportDialogState(initialFormat?: ExportFormat) {
|
|
|
135
137
|
availability,
|
|
136
138
|
});
|
|
137
139
|
const status = statusFor(format);
|
|
140
|
+
const canInstall =
|
|
141
|
+
installAllowed &&
|
|
142
|
+
(status.reason?.type === "missing-packages" ||
|
|
143
|
+
status.reason?.type === "missing-setup");
|
|
138
144
|
const formats = EXPORT_FORMATS.map((candidate) => ({
|
|
139
145
|
format: candidate,
|
|
140
146
|
status: statusFor(candidate),
|
|
@@ -184,6 +190,22 @@ function useExportDialogState(initialFormat?: ExportFormat) {
|
|
|
184
190
|
});
|
|
185
191
|
};
|
|
186
192
|
|
|
193
|
+
const installRequirements = async () => {
|
|
194
|
+
if (!canInstall || isInstalling || format === "png") {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
setIsInstalling(true);
|
|
199
|
+
try {
|
|
200
|
+
const availability = await requests.installExportRequirements({ format });
|
|
201
|
+
availabilityRequest.setData(availability);
|
|
202
|
+
} catch {
|
|
203
|
+
// Request failures are surfaced by the shared toast layer.
|
|
204
|
+
} finally {
|
|
205
|
+
setIsInstalling(false);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
187
209
|
return {
|
|
188
210
|
formats,
|
|
189
211
|
options,
|
|
@@ -205,6 +227,9 @@ function useExportDialogState(initialFormat?: ExportFormat) {
|
|
|
205
227
|
},
|
|
206
228
|
selectFormat,
|
|
207
229
|
updateOptions,
|
|
230
|
+
canInstall,
|
|
231
|
+
isInstalling,
|
|
232
|
+
installRequirements,
|
|
208
233
|
};
|
|
209
234
|
}
|
|
210
235
|
|
|
@@ -364,7 +389,7 @@ export function useExportDialog({
|
|
|
364
389
|
...state,
|
|
365
390
|
...action,
|
|
366
391
|
selectFormat: (value: string) => {
|
|
367
|
-
if (!action.isExporting) {
|
|
392
|
+
if (!action.isExporting && !state.isInstalling) {
|
|
368
393
|
selectFormat(value);
|
|
369
394
|
}
|
|
370
395
|
},
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
import type { ComponentPropsWithoutRef, ReactElement, ReactNode } from "react";
|
|
3
3
|
import { useRef } from "react";
|
|
4
|
+
import { createPortal } from "react-dom";
|
|
4
5
|
import { CopyClipboardIcon } from "@/components/icons/copy-icon";
|
|
5
6
|
import { useToast } from "@/components/ui/use-toast";
|
|
7
|
+
import { StyleNamespace } from "@/theme/namespace";
|
|
6
8
|
import { cn } from "@/utils/cn";
|
|
9
|
+
import { withFullScreenAsRoot } from "./fullscreen";
|
|
7
10
|
import {
|
|
8
11
|
Toast,
|
|
9
12
|
ToastClose,
|
|
@@ -28,11 +31,21 @@ export const Toaster = () => {
|
|
|
28
31
|
{...props}
|
|
29
32
|
/>
|
|
30
33
|
))}
|
|
31
|
-
<
|
|
34
|
+
<ToastViewportPortal />
|
|
32
35
|
</ToastProvider>
|
|
33
36
|
);
|
|
34
37
|
};
|
|
35
38
|
|
|
39
|
+
const ToastViewportPortal = withFullScreenAsRoot(
|
|
40
|
+
({ container }: { container?: Element | DocumentFragment | null }) =>
|
|
41
|
+
createPortal(
|
|
42
|
+
<StyleNamespace>
|
|
43
|
+
<ToastViewport />
|
|
44
|
+
</StyleNamespace>,
|
|
45
|
+
container ?? document.body,
|
|
46
|
+
),
|
|
47
|
+
);
|
|
48
|
+
|
|
36
49
|
type ToastItemProps = Omit<
|
|
37
50
|
ComponentPropsWithoutRef<typeof Toast>,
|
|
38
51
|
"title" | "children"
|
|
@@ -356,6 +356,7 @@ export class IslandsPyodideBridge implements RunRequests, EditRequests {
|
|
|
356
356
|
sendFileDetails = throwNotImplemented;
|
|
357
357
|
openTutorial = throwNotImplemented;
|
|
358
358
|
getExportAvailability = throwNotImplemented;
|
|
359
|
+
installExportRequirements = throwNotImplemented;
|
|
359
360
|
exportAsHTML = throwNotImplemented;
|
|
360
361
|
exportAsIPYNB = throwNotImplemented;
|
|
361
362
|
exportAsMarkdown = throwNotImplemented;
|
package/src/core/mode.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { atom, useAtomValue } from "jotai";
|
|
4
|
+
import { KnownQueryParams } from "@/core/constants";
|
|
4
5
|
import { isIslands } from "@/core/islands/utils";
|
|
5
6
|
import { assertExists } from "@/utils/assertExists";
|
|
6
7
|
import { invariant } from "@/utils/invariant";
|
|
@@ -98,5 +99,9 @@ export const kioskModeAtom = atom<boolean>(false);
|
|
|
98
99
|
*/
|
|
99
100
|
export function useInstallAllowed(): boolean {
|
|
100
101
|
const { mode } = useAtomValue(viewStateAtom);
|
|
101
|
-
|
|
102
|
+
const kioskMode = useAtomValue(kioskModeAtom);
|
|
103
|
+
const kioskRequested =
|
|
104
|
+
new URLSearchParams(window.location.search).get(KnownQueryParams.kiosk) ===
|
|
105
|
+
"true";
|
|
106
|
+
return mode !== "read" && !kioskMode && !kioskRequested;
|
|
102
107
|
}
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
4
|
import { cellId, requestId, uiElementId } from "@/__tests__/branded";
|
|
5
|
+
import { waitForKernelToBeInstantiated } from "../../kernel/state";
|
|
5
6
|
import type { RuntimeManager } from "../../runtime/runtime";
|
|
7
|
+
import { waitForConnectionOpen } from "../connection";
|
|
6
8
|
import { createLazyRequests } from "../requests-lazy";
|
|
7
9
|
import type {
|
|
8
10
|
EditRequests,
|
|
@@ -55,6 +57,10 @@ describe("createLazyRequests", () => {
|
|
|
55
57
|
sendInterrupt: vi.fn().mockResolvedValue({ interrupted: true }),
|
|
56
58
|
sendPdb: vi.fn().mockResolvedValue({ pdb: true }),
|
|
57
59
|
sendRunScratchpad: vi.fn().mockResolvedValue({ run: true }),
|
|
60
|
+
installExportRequirements: vi.fn().mockResolvedValue({
|
|
61
|
+
source: "server",
|
|
62
|
+
formats: [],
|
|
63
|
+
}),
|
|
58
64
|
} as unknown as EditRequests & RunRequests;
|
|
59
65
|
});
|
|
60
66
|
|
|
@@ -104,6 +110,40 @@ describe("createLazyRequests", () => {
|
|
|
104
110
|
expect(mockDelegate.getExportAvailability).toHaveBeenCalledOnce();
|
|
105
111
|
});
|
|
106
112
|
|
|
113
|
+
it("installs export requirements without waiting for the kernel", async () => {
|
|
114
|
+
const lazyRequests = createLazyRequests(
|
|
115
|
+
mockDelegate,
|
|
116
|
+
mockGetRuntimeManager,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
await lazyRequests.installExportRequirements({ format: "pdf" });
|
|
120
|
+
|
|
121
|
+
expect(mockInit).toHaveBeenCalledOnce();
|
|
122
|
+
expect(waitForConnectionOpen).toHaveBeenCalledOnce();
|
|
123
|
+
expect(waitForKernelToBeInstantiated).not.toHaveBeenCalled();
|
|
124
|
+
expect(mockDelegate.installExportRequirements).toHaveBeenCalledWith({
|
|
125
|
+
format: "pdf",
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("sends instantiate without waiting for the kernel", async () => {
|
|
130
|
+
const lazyRequests = createLazyRequests(
|
|
131
|
+
mockDelegate,
|
|
132
|
+
mockGetRuntimeManager,
|
|
133
|
+
);
|
|
134
|
+
const request = {
|
|
135
|
+
objectIds: [uiElementId("obj1")],
|
|
136
|
+
values: [],
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
await lazyRequests.sendInstantiate(request);
|
|
140
|
+
|
|
141
|
+
expect(mockInit).toHaveBeenCalledOnce();
|
|
142
|
+
expect(waitForConnectionOpen).toHaveBeenCalledOnce();
|
|
143
|
+
expect(waitForKernelToBeInstantiated).not.toHaveBeenCalled();
|
|
144
|
+
expect(mockDelegate.sendInstantiate).toHaveBeenCalledWith(request);
|
|
145
|
+
});
|
|
146
|
+
|
|
107
147
|
it("should call init once before first request", async () => {
|
|
108
148
|
const lazyRequests = createLazyRequests(
|
|
109
149
|
mockDelegate,
|
|
@@ -143,6 +143,19 @@ describe("createNetworkRequests", () => {
|
|
|
143
143
|
expect(mockClient.GET).toHaveBeenCalledWith("/api/export/availability");
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
+
it("installExportRequirements should POST the export format", async () => {
|
|
147
|
+
const requests = createNetworkRequests();
|
|
148
|
+
await requests.installExportRequirements({ format: "pdf" });
|
|
149
|
+
|
|
150
|
+
expect(mockClient.POST).toHaveBeenCalledWith(
|
|
151
|
+
"/api/export/requirements/install",
|
|
152
|
+
expect.objectContaining({
|
|
153
|
+
body: { format: "pdf" },
|
|
154
|
+
params: expect.anything(),
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
});
|
|
158
|
+
|
|
146
159
|
it("discoverDataSources should POST to the discovery endpoint", async () => {
|
|
147
160
|
const requests = createNetworkRequests();
|
|
148
161
|
const request = { requestId: "discovery-request" } as any;
|
|
@@ -26,6 +26,10 @@ type AllRequests = EditRequests & RunRequests;
|
|
|
26
26
|
// executing. Use for user-initiated actions that should "just work" and
|
|
27
27
|
// kick off the kernel if needed (e.g., clicking Run).
|
|
28
28
|
//
|
|
29
|
+
// - startConnectionWithoutKernel: Initializes the runtime and waits for an open
|
|
30
|
+
// connection. Use for session-scoped server requests that do not need an
|
|
31
|
+
// instantiated kernel.
|
|
32
|
+
//
|
|
29
33
|
// - waitForConnectionOpen: Waits for an existing connection but won't start one.
|
|
30
34
|
// Use for operations that depend on a running kernel but shouldn't be the
|
|
31
35
|
// trigger to start it (e.g., saving, interrupting).
|
|
@@ -38,6 +42,7 @@ type Action =
|
|
|
38
42
|
| "throwError"
|
|
39
43
|
| "dropRequest"
|
|
40
44
|
| "startConnection"
|
|
45
|
+
| "startConnectionWithoutKernel"
|
|
41
46
|
| "waitForConnectionOpen"
|
|
42
47
|
| "serverOnly";
|
|
43
48
|
|
|
@@ -45,7 +50,7 @@ const ACTIONS: Record<keyof AllRequests, Action> = {
|
|
|
45
50
|
// These will start a connection if not already connected and then wait until the connection is open
|
|
46
51
|
sendComponentValues: "startConnection",
|
|
47
52
|
sendModelValue: "startConnection",
|
|
48
|
-
sendInstantiate: "
|
|
53
|
+
sendInstantiate: "startConnectionWithoutKernel",
|
|
49
54
|
sendRun: "startConnection",
|
|
50
55
|
sendDeleteCell: "startConnection",
|
|
51
56
|
sendRunScratchpad: "startConnection",
|
|
@@ -107,6 +112,9 @@ const ACTIONS: Record<keyof AllRequests, Action> = {
|
|
|
107
112
|
getEnvironmentInfo: "serverOnly",
|
|
108
113
|
getExportAvailability: "serverOnly",
|
|
109
114
|
|
|
115
|
+
// Session-scoped server operations
|
|
116
|
+
installExportRequirements: "startConnectionWithoutKernel",
|
|
117
|
+
|
|
110
118
|
// Home operations throw errors
|
|
111
119
|
getRecentFiles: "startConnection",
|
|
112
120
|
getWorkspaceFiles: "startConnection",
|
|
@@ -186,13 +194,12 @@ export function createLazyRequests(
|
|
|
186
194
|
await waitForKernelToBeInstantiated();
|
|
187
195
|
return request(...args);
|
|
188
196
|
|
|
197
|
+
case "startConnectionWithoutKernel":
|
|
189
198
|
case "startConnection":
|
|
190
199
|
// Start connection and wait for it to be open
|
|
191
200
|
await initOnce(runtimeManager);
|
|
192
201
|
await waitForConnectionOpen();
|
|
193
|
-
if (
|
|
194
|
-
// We don't need to wait for kernel to be instantiated if we are sending an instantiate request
|
|
195
|
-
// otherwise we will wait forever
|
|
202
|
+
if (action === "startConnection") {
|
|
196
203
|
await waitForKernelToBeInstantiated();
|
|
197
204
|
}
|
|
198
205
|
return request(...args);
|
|
@@ -417,6 +417,14 @@ export function createNetworkRequests(): EditRequests & RunRequests {
|
|
|
417
417
|
getExportAvailability: () => {
|
|
418
418
|
return getClient().GET("/api/export/availability").then(handleResponse);
|
|
419
419
|
},
|
|
420
|
+
installExportRequirements: (request) => {
|
|
421
|
+
return getClient()
|
|
422
|
+
.POST("/api/export/requirements/install", {
|
|
423
|
+
body: request,
|
|
424
|
+
params: getParams(),
|
|
425
|
+
})
|
|
426
|
+
.then(handleResponse);
|
|
427
|
+
},
|
|
420
428
|
exportAsHTML: async (request) => {
|
|
421
429
|
if (
|
|
422
430
|
process.env.NODE_ENV === "development" ||
|
|
@@ -84,6 +84,7 @@ export function createStaticRequests(): EditRequests & RunRequests {
|
|
|
84
84
|
getRunningNotebooks: throwNotInEditMode,
|
|
85
85
|
shutdownSession: throwNotInEditMode,
|
|
86
86
|
getExportAvailability: throwNotInEditMode,
|
|
87
|
+
installExportRequirements: throwNotInEditMode,
|
|
87
88
|
exportAsHTML: throwNotInEditMode,
|
|
88
89
|
exportAsIPYNB: throwNotInEditMode,
|
|
89
90
|
exportAsMarkdown: throwNotInEditMode,
|
|
@@ -65,6 +65,7 @@ export function createErrorToastingRequests(
|
|
|
65
65
|
getRunningNotebooks: "Failed to get running notebooks",
|
|
66
66
|
shutdownSession: "Failed to shutdown session",
|
|
67
67
|
getExportAvailability: "", // No toast
|
|
68
|
+
installExportRequirements: "Failed to install export requirements",
|
|
68
69
|
exportAsHTML: "Failed to export HTML",
|
|
69
70
|
exportAsIPYNB: "Failed to export ipynb",
|
|
70
71
|
exportAsMarkdown: "Failed to export Markdown",
|
|
@@ -29,6 +29,8 @@ export type ExportAsIPYNBRequest = schemas["ExportAsIPYNBRequest"];
|
|
|
29
29
|
export type ExportAsScriptRequest = schemas["ExportAsScriptRequest"];
|
|
30
30
|
export type ExportAsPDFRequest = schemas["ExportAsPDFRequest"];
|
|
31
31
|
export type ExportAvailabilityResponse = schemas["ExportAvailabilityResponse"];
|
|
32
|
+
export type InstallExportRequirementsRequest =
|
|
33
|
+
schemas["InstallExportRequirementsRequest"];
|
|
32
34
|
export type UpdateCellOutputsRequest = schemas["UpdateCellOutputsRequest"];
|
|
33
35
|
|
|
34
36
|
export interface ExportedFile<T extends BlobPart = BlobPart> {
|
|
@@ -223,6 +225,9 @@ export interface EditRequests {
|
|
|
223
225
|
) => Promise<RunningNotebooksResponse>;
|
|
224
226
|
// Export requests
|
|
225
227
|
getExportAvailability: () => Promise<ExportAvailabilityResponse>;
|
|
228
|
+
installExportRequirements: (
|
|
229
|
+
request: InstallExportRequirementsRequest,
|
|
230
|
+
) => Promise<ExportAvailabilityResponse>;
|
|
226
231
|
exportAsHTML: (request: ExportAsHTMLRequest) => Promise<ExportedFile<string>>;
|
|
227
232
|
exportAsIPYNB: (
|
|
228
233
|
request: ExportAsIPYNBRequest,
|
package/src/core/wasm/bridge.ts
CHANGED
|
@@ -675,6 +675,7 @@ export class PyodideBridge implements RunRequests, EditRequests {
|
|
|
675
675
|
getRunningNotebooks = throwNotImplemented;
|
|
676
676
|
shutdownSession = throwNotImplemented;
|
|
677
677
|
getExportAvailability = throwNotImplemented;
|
|
678
|
+
installExportRequirements = throwNotImplemented;
|
|
678
679
|
exportAsIPYNB = throwNotImplemented;
|
|
679
680
|
exportAsPDF = throwNotImplemented;
|
|
680
681
|
autoExportAsHTML = throwNotImplemented;
|