@marimo-team/islands 0.18.2 → 0.18.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/dist/{constants-DWBOe162.js → constants-D_G8vnDk.js} +5 -4
  2. package/dist/{formats-7RSCCoSI.js → formats-4m4HuHTj.js} +1 -1
  3. package/dist/{glide-data-editor-D-Ia_Jsv.js → glide-data-editor-DXF8E-QD.js} +2 -2
  4. package/dist/main.js +32 -29
  5. package/dist/{types-Dunk85GC.js → types-DclGb0Yh.js} +1 -1
  6. package/dist/{vega-component-kU4hFYYJ.js → vega-component-HUc7bIGs.js} +2 -2
  7. package/package.json +1 -1
  8. package/src/components/app-config/user-config-form.tsx +14 -1
  9. package/src/components/editor/chrome/components/contribute-snippet-button.tsx +22 -103
  10. package/src/components/editor/controls/duplicate-shortcut-banner.tsx +50 -0
  11. package/src/components/editor/controls/keyboard-shortcuts.tsx +25 -2
  12. package/src/components/editor/notebook-cell.tsx +4 -3
  13. package/src/components/editor/output/__tests__/ansi-reduce.test.ts +6 -6
  14. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +3 -3
  15. package/src/components/pages/home-page.tsx +6 -0
  16. package/src/components/scratchpad/scratchpad.tsx +2 -1
  17. package/src/core/constants.ts +10 -0
  18. package/src/core/layout/useTogglePresenting.ts +69 -25
  19. package/src/core/state/__mocks__/mocks.ts +1 -0
  20. package/src/hooks/__tests__/useDuplicateShortcuts.test.ts +449 -0
  21. package/src/hooks/useDuplicateShortcuts.ts +145 -0
  22. package/src/plugins/impl/NumberPlugin.tsx +1 -1
  23. package/src/plugins/impl/__tests__/NumberPlugin.test.tsx +1 -1
  24. package/src/plugins/layout/NavigationMenuPlugin.tsx +24 -22
  25. package/src/utils/__tests__/json-parser.test.ts +1 -1
@@ -64,9 +64,10 @@ const Constants = {
64
64
  accessToken: "access_token",
65
65
  viewAs: "view-as",
66
66
  showChrome: "show-chrome"
67
- };
67
+ }, CSSClasses = { outputArea: "output-area" };
68
68
  export {
69
- KnownQueryParams as n,
70
- debounce_default as r,
71
- Constants as t
69
+ debounce_default as i,
70
+ Constants as n,
71
+ KnownQueryParams as r,
72
+ CSSClasses as t
72
73
  };
@@ -9,7 +9,7 @@ import { a as cva, u as cn } from "./button-XnD6ylpt.js";
9
9
  import { s as Logger } from "./hotkeys-CwkyZ6ZF.js";
10
10
  import { t as require_jsx_runtime } from "./jsx-runtime-CTBg5pdT.js";
11
11
  import { b as atom, f as isIslands, l as store } from "./useTheme-ByTGDerd.js";
12
- import { n as KnownQueryParams } from "./constants-DWBOe162.js";
12
+ import { r as KnownQueryParams } from "./constants-D_G8vnDk.js";
13
13
  import { i as tableFromIPC } from "./loader-ZngagiXO.js";
14
14
  var CircleQuestionMark = createLucideIcon("circle-question-mark", [
15
15
  ["circle", {
@@ -8,7 +8,7 @@ import { n as Copy, r as toast, t as copyToClipboard } from "./copy-CzEthfGv.js"
8
8
  import "./Combination-DnWHe36P.js";
9
9
  import "./check-IicTB7sO.js";
10
10
  import { A as logNever, E as useOnMount, i as SelectContent, l as SelectTrigger, o as SelectItem, r as Select, t as Label, u as SelectValue } from "./label-BtLFsS7L.js";
11
- import { C as DropdownMenuSubTrigger, S as DropdownMenuSubContent, _ as DropdownMenuItem, a as Input, b as DropdownMenuSeparator, fn as Trash, h as DropdownMenuContent, hn as Pencil, ht as capitalize_default, m as DropdownMenu, mn as Plus, mt as marked, n as ErrorBoundary, pt as useNonce, t as BulkEdit, x as DropdownMenuSub, y as DropdownMenuPortal } from "./types-Dunk85GC.js";
11
+ import { C as DropdownMenuSubTrigger, S as DropdownMenuSubContent, _ as DropdownMenuItem, a as Input, b as DropdownMenuSeparator, fn as Trash, h as DropdownMenuContent, hn as Pencil, ht as capitalize_default, m as DropdownMenu, mn as Plus, mt as marked, n as ErrorBoundary, pt as useNonce, t as BulkEdit, x as DropdownMenuSub, y as DropdownMenuPortal } from "./types-DclGb0Yh.js";
12
12
  import "./clsx-D2KVTYnW.js";
13
13
  import { l as Events, t as Button } from "./button-XnD6ylpt.js";
14
14
  import { s as Logger } from "./hotkeys-CwkyZ6ZF.js";
@@ -25,7 +25,7 @@ import "./merge-DPdZQMPt.js";
25
25
  import "./_baseSlice-D44oUJcJ.js";
26
26
  import "./_hasUnicode-nuTfNJRy.js";
27
27
  import "./now-BA1FgVte.js";
28
- import "./constants-DWBOe162.js";
28
+ import "./constants-D_G8vnDk.js";
29
29
  import "./zod-Bvx56F8M.js";
30
30
  import "./invariant-Ctm_8TNZ.js";
31
31
  import "./once-DjP4Kbhy.js";
package/dist/main.js CHANGED
@@ -10,8 +10,8 @@ import { C as useLayoutEffect2, D as dispatchDiscreteCustomEvent, E as Primitive
10
10
  import { A as Badge, B as ListFilter, C as DEFAULT_COLOR_SCHEME, D as SCALE_TYPE_DESCRIPTIONS, E as EMPTY_VALUE$1, F as $5a387cc49350e6db$export$722debc0e56fea39, H as ChartPie, I as Type, L as ToggleLeft, M as startCase_default, N as $896ba0a80a8f4d36$export$85fd5fdf27bacc79, O as TIME_UNIT_DESCRIPTIONS, P as $fb18d541ea1ad717$export$ad991b66133851cf, R as Table$1, S as DEFAULT_AGGREGATION, T as DEFAULT_TIME_UNIT, U as ChartColumn, V as Hash, W as Calendar, _ 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 createReducerAndAtoms, 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, z as SquareFunction } from "./spec-D9VXxBJM.js";
11
11
  import { t as Check } from "./check-IicTB7sO.js";
12
12
  import { A as logNever, B as ChevronDown, C as useDirection, D as useOnUnmount, E as useOnMount, F as $18f2051aff69b9bf$export$a54013f0d02a8f82, I as $b5e257d569688ac6$export$535bd6ca7f90a273, M as $a916eb452884faea$export$b7a616150fdb9f44, O as usePrevious, P as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7, R as X, S as Trigger$5, T as clamp$2, _ as menuItemVariants, a as SelectGroup, b as menuSubTriggerVariants, c as SelectSeparator, d as NativeSelect, f as selectStyles, h as menuControlCheckVariants, i as SelectContent, k as assertNever, l as SelectTrigger, m as menuContentCommon, n as Primitive, o as SelectItem, p as MENU_ITEM_DISABLED, r as Select, s as SelectLabel, t as Label, u as SelectValue, v as menuLabelVariants, w as createCollection, x as Icon, y as menuSeparatorVariants } from "./label-BtLFsS7L.js";
13
- import { $ as $514c0188e459b4c0$export$9afb8bc826b033ea, $t as $65484d02dcb7eb3e$export$457c3d6518dd4c6f, A as Item2$2, At as $6db58dc88e78b024$export$2f817fcdc4b89ae0, B as SubTrigger, Bt as $458b0a5536c1a7cf$export$40bfa8c7b0832715, C as DropdownMenuSubTrigger, Ct as $e5be200c675c3b3a$export$fc1a364ae1f3ff10, D as CheckboxItem, Dt as $6c7bd7858deea686$export$cd11ab140839f11d, E as Arrow2, Et as $701a24aa0da5b062$export$ea18c227d4417cc3, F as RadioItem, Ft as $507fabe10e71c6fb$export$630ff653c5ada6a9, G as $3985021b0ad6602f$export$37fb8590cf2c088c, Gt as $df56164dff5785e2$export$4338b53315abf666, H as Item$2, Ht as $b4b717babfbb907b$export$bebd5a1431fec25d, I as Root3, It as $f6c31cce2adf654f$export$45712eceda6fad21, J as $a049562f99e7db0e$export$f9c6924e160136d1, Jt as $c87311424ea30a05$export$78551043582a6a98, K as $3985021b0ad6602f$export$f5b8910cec6cf069, Kt as $313b98861ee5dd6c$export$d6875122194c7b44, L as Separator, Lt as _class_private_field_init, M as Label$2, Mt as $6179b936705e76d3$export$ae780daf29e6d456, N as Portal$2, Nt as $9ab94262bd0047c7$export$420e68273165f4ec, O as Content2$3, Ot as $fca6afa0e843324b$export$87b761675e8eaa10, P as RadioGroup$2, Pt as $3ad3f6e1647bc98d$export$80f3e147d781571c, Q as $514c0188e459b4c0$export$5f1af8db9871e1d6, Qt as $7215afc6de606d6b$export$de79e2c695e052f3, R as Sub, Rt as $ae1eeba8b9eafd08$export$5165eccb35aaadb5, S as DropdownMenuSubContent, St as $e5be200c675c3b3a$export$dad6ae84456c676a, T as Anchor2, Tt as $f7dceffc5ad7768b$export$4e328f61c538687f, U as Root$6, Ut as $99facab73266f662$export$5add1d006293d136, V as createMenuScope, Vt as $b4b717babfbb907b$export$4c063cf1350e6fed, W as createRovingFocusGroupScope, Wt as $e9faafb641e167db$export$90fc3a17d93f704c, X as $ee014567cb39d3f0$export$f551688fc98f2e09, Xt as $c87311424ea30a05$export$a11b0059900ceec8, Y as $d3e0e05bdfcf66bd$export$c24727297075ec6a, Yt as $c87311424ea30a05$export$9ac100e40613ea10, Z as $ee014567cb39d3f0$export$ff05c3ac10437e03, Zt as $c87311424ea30a05$export$fedb369cb70207f1, _ as DropdownMenuItem, _n as ChevronRight, _t as $2baaea4c71418dea$export$294aa081a6c6f55d, a as Input, an as $431fbd86ca7dc216$export$b204af158042fbac, at as $64fa3d84918910a7$export$2881499e37b75b9a, b as DropdownMenuSeparator, bt as $e5be200c675c3b3a$export$a763b9476acd3eb, c as maxFractionalDigits, cn as $bdb11010cef70236$export$b4cc09c592e8fdb8, ct as $64fa3d84918910a7$export$9d4c57ee4c6ffdd8, d as prettyScientificNumber, dn as $f0a04ccd8dbdd83b$export$e5c5a5f917a5871c, dt as $64fa3d84918910a7$export$ef03459518577ad4, en as $3ef42575df84b30b$export$9d1611c77c2fe928, et as $d2b4bc8c273e7be6$export$24d547caef80ccd1, f as useDebounceControlledState, fn as Trash, ft as $64fa3d84918910a7$export$fabf2dc03a41866e, g as DropdownMenuGroup, gn as Circle, gt as $d2e8511e6f209edf$export$e908e06f4b8e3402, h as DropdownMenuContent, hn as Pencil, ht as capitalize_default, i as DebouncedNumberInput, in as $f4e2df6bd15f8569$export$98658e8c59125e6a, it as $f39a9eba43920ace$export$b5d7cc18bb8d2b59, j as ItemIndicator, jt as $5b160d28a433310d$export$c17fa47878dc55b6, k as Group$1, kt as $fca6afa0e843324b$export$f12b703ca79dfbb1, l as prettyEngineeringNumber, ln as $bdb11010cef70236$export$f680877a34711e37, lt as $64fa3d84918910a7$export$c245e6201fed2f75, m as DropdownMenu, mn as Plus, mt as marked, n as ErrorBoundary, nn as $d4ee10de306f2510$export$cd4e5573fbe2b576, nt as $01b77f81d0f07f68$export$75b6ee27786ba447, o as OnBlurredInput, on as $431fbd86ca7dc216$export$f21a1ffae260145a, ot as $64fa3d84918910a7$export$29f1550f4b0d4415, p as useDebouncedCallback, pn as Search, pt as useNonce, q as $a049562f99e7db0e$export$eb2fcfdbd7ba97d4, qt as $c87311424ea30a05$export$6446a186d09e379e, r as DebouncedInput, rn as $d4ee10de306f2510$export$e58f029f0fbfdb29, rt as $01b77f81d0f07f68$export$b04be29aa201d4f5, s as NumberField, sn as $ff5963eb1fccf552$export$e08e3b67e392101e, st as $64fa3d84918910a7$export$4d86445c2cf5e3, t as BulkEdit, tn as $d4ee10de306f2510$export$4282f70798064fe0, tt as $d2b4bc8c273e7be6$export$353f5b6fc5456de1, u as prettyNumber, un as $8ae05eaa5c114e9c$export$7f54fc3180508a52, ut as $64fa3d84918910a7$export$c62b8e45d58ddad9, v as DropdownMenuLabel, vt as $e93e671b31057976$export$b8473d3665f3a75a, w as DropdownMenuTrigger, wt as $319e236875307eab$export$a9b970dcc4ae71a9, x as DropdownMenuSub, xt as $e5be200c675c3b3a$export$aca958c65c314e6c, y as DropdownMenuPortal, yt as $e5be200c675c3b3a$export$75ee7c75d68f5b0e, z as SubContent, zt as $9446cca9a3875146$export$7d15b64cf5a3a4c4 } from "./types-Dunk85GC.js";
14
- import { C as CircleQuestionMark, S as isWasm, _ as appendQueryParams, a as AlertDescription, b as isStaticNotebook, c as toDate, d as millisecondsInHour, f as millisecondsInMinute, g as getRuntimeManager, h as asRemoteURL, i as Alert, l as constructFrom, m as millisecondsInWeek, n as useDeepCompareMemoize, o as AlertTitle, p as millisecondsInSecond, r as dequal, s as isValid, t as arrow, u as millisecondsInDay, v as isUrl, x as Deferred, y as require_cuid2 } from "./formats-7RSCCoSI.js";
13
+ import { $ as $514c0188e459b4c0$export$9afb8bc826b033ea, $t as $65484d02dcb7eb3e$export$457c3d6518dd4c6f, A as Item2$2, At as $6db58dc88e78b024$export$2f817fcdc4b89ae0, B as SubTrigger, Bt as $458b0a5536c1a7cf$export$40bfa8c7b0832715, C as DropdownMenuSubTrigger, Ct as $e5be200c675c3b3a$export$fc1a364ae1f3ff10, D as CheckboxItem, Dt as $6c7bd7858deea686$export$cd11ab140839f11d, E as Arrow2, Et as $701a24aa0da5b062$export$ea18c227d4417cc3, F as RadioItem, Ft as $507fabe10e71c6fb$export$630ff653c5ada6a9, G as $3985021b0ad6602f$export$37fb8590cf2c088c, Gt as $df56164dff5785e2$export$4338b53315abf666, H as Item$2, Ht as $b4b717babfbb907b$export$bebd5a1431fec25d, I as Root3, It as $f6c31cce2adf654f$export$45712eceda6fad21, J as $a049562f99e7db0e$export$f9c6924e160136d1, Jt as $c87311424ea30a05$export$78551043582a6a98, K as $3985021b0ad6602f$export$f5b8910cec6cf069, Kt as $313b98861ee5dd6c$export$d6875122194c7b44, L as Separator, Lt as _class_private_field_init, M as Label$2, Mt as $6179b936705e76d3$export$ae780daf29e6d456, N as Portal$2, Nt as $9ab94262bd0047c7$export$420e68273165f4ec, O as Content2$3, Ot as $fca6afa0e843324b$export$87b761675e8eaa10, P as RadioGroup$2, Pt as $3ad3f6e1647bc98d$export$80f3e147d781571c, Q as $514c0188e459b4c0$export$5f1af8db9871e1d6, Qt as $7215afc6de606d6b$export$de79e2c695e052f3, R as Sub, Rt as $ae1eeba8b9eafd08$export$5165eccb35aaadb5, S as DropdownMenuSubContent, St as $e5be200c675c3b3a$export$dad6ae84456c676a, T as Anchor2, Tt as $f7dceffc5ad7768b$export$4e328f61c538687f, U as Root$6, Ut as $99facab73266f662$export$5add1d006293d136, V as createMenuScope, Vt as $b4b717babfbb907b$export$4c063cf1350e6fed, W as createRovingFocusGroupScope, Wt as $e9faafb641e167db$export$90fc3a17d93f704c, X as $ee014567cb39d3f0$export$f551688fc98f2e09, Xt as $c87311424ea30a05$export$a11b0059900ceec8, Y as $d3e0e05bdfcf66bd$export$c24727297075ec6a, Yt as $c87311424ea30a05$export$9ac100e40613ea10, Z as $ee014567cb39d3f0$export$ff05c3ac10437e03, Zt as $c87311424ea30a05$export$fedb369cb70207f1, _ as DropdownMenuItem, _n as ChevronRight, _t as $2baaea4c71418dea$export$294aa081a6c6f55d, a as Input, an as $431fbd86ca7dc216$export$b204af158042fbac, at as $64fa3d84918910a7$export$2881499e37b75b9a, b as DropdownMenuSeparator, bt as $e5be200c675c3b3a$export$a763b9476acd3eb, c as maxFractionalDigits, cn as $bdb11010cef70236$export$b4cc09c592e8fdb8, ct as $64fa3d84918910a7$export$9d4c57ee4c6ffdd8, d as prettyScientificNumber, dn as $f0a04ccd8dbdd83b$export$e5c5a5f917a5871c, dt as $64fa3d84918910a7$export$ef03459518577ad4, en as $3ef42575df84b30b$export$9d1611c77c2fe928, et as $d2b4bc8c273e7be6$export$24d547caef80ccd1, f as useDebounceControlledState, fn as Trash, ft as $64fa3d84918910a7$export$fabf2dc03a41866e, g as DropdownMenuGroup, gn as Circle, gt as $d2e8511e6f209edf$export$e908e06f4b8e3402, h as DropdownMenuContent, hn as Pencil, ht as capitalize_default, i as DebouncedNumberInput, in as $f4e2df6bd15f8569$export$98658e8c59125e6a, it as $f39a9eba43920ace$export$b5d7cc18bb8d2b59, j as ItemIndicator, jt as $5b160d28a433310d$export$c17fa47878dc55b6, k as Group$1, kt as $fca6afa0e843324b$export$f12b703ca79dfbb1, l as prettyEngineeringNumber, ln as $bdb11010cef70236$export$f680877a34711e37, lt as $64fa3d84918910a7$export$c245e6201fed2f75, m as DropdownMenu, mn as Plus, mt as marked, n as ErrorBoundary, nn as $d4ee10de306f2510$export$cd4e5573fbe2b576, nt as $01b77f81d0f07f68$export$75b6ee27786ba447, o as OnBlurredInput, on as $431fbd86ca7dc216$export$f21a1ffae260145a, ot as $64fa3d84918910a7$export$29f1550f4b0d4415, p as useDebouncedCallback, pn as Search, pt as useNonce, q as $a049562f99e7db0e$export$eb2fcfdbd7ba97d4, qt as $c87311424ea30a05$export$6446a186d09e379e, r as DebouncedInput, rn as $d4ee10de306f2510$export$e58f029f0fbfdb29, rt as $01b77f81d0f07f68$export$b04be29aa201d4f5, s as NumberField, sn as $ff5963eb1fccf552$export$e08e3b67e392101e, st as $64fa3d84918910a7$export$4d86445c2cf5e3, t as BulkEdit, tn as $d4ee10de306f2510$export$4282f70798064fe0, tt as $d2b4bc8c273e7be6$export$353f5b6fc5456de1, u as prettyNumber, un as $8ae05eaa5c114e9c$export$7f54fc3180508a52, ut as $64fa3d84918910a7$export$c62b8e45d58ddad9, v as DropdownMenuLabel, vt as $e93e671b31057976$export$b8473d3665f3a75a, w as DropdownMenuTrigger, wt as $319e236875307eab$export$a9b970dcc4ae71a9, x as DropdownMenuSub, xt as $e5be200c675c3b3a$export$aca958c65c314e6c, y as DropdownMenuPortal, yt as $e5be200c675c3b3a$export$75ee7c75d68f5b0e, z as SubContent, zt as $9446cca9a3875146$export$7d15b64cf5a3a4c4 } from "./types-DclGb0Yh.js";
14
+ import { C as CircleQuestionMark, S as isWasm, _ as appendQueryParams, a as AlertDescription, b as isStaticNotebook, c as toDate, d as millisecondsInHour, f as millisecondsInMinute, g as getRuntimeManager, h as asRemoteURL, i as Alert, l as constructFrom, m as millisecondsInWeek, n as useDeepCompareMemoize, o as AlertTitle, p as millisecondsInSecond, r as dequal, s as isValid, t as arrow, u as millisecondsInDay, v as isUrl, x as Deferred, y as require_cuid2 } from "./formats-4m4HuHTj.js";
15
15
  import { n as clsx_default } from "./clsx-D2KVTYnW.js";
16
16
  import { a as cva, c as useComposedRefs, l as Events, n as buttonVariants, o as useEventListener, r as Slot$1, s as composeRefs, t as Button, u as cn } from "./button-XnD6ylpt.js";
17
17
  import { c as Functions, i as parseShortcut, l as throwNotImplemented, o as Objects, r as isPlatformMac, s as Logger, t as NOT_SET } from "./hotkeys-CwkyZ6ZF.js";
@@ -38,7 +38,7 @@ import "./_baseSlice-D44oUJcJ.js";
38
38
  import "./_hasUnicode-nuTfNJRy.js";
39
39
  import "./_arrayReduce-BdxKZ32o.js";
40
40
  import "./now-BA1FgVte.js";
41
- import { n as KnownQueryParams, r as debounce_default } from "./constants-DWBOe162.js";
41
+ import { i as debounce_default, r as KnownQueryParams, t as CSSClasses } from "./constants-D_G8vnDk.js";
42
42
  import { a as tooltipHandler, n as vegaLoadData, r as createBatchedLoader, t as parseCsvData } from "./loader-ZngagiXO.js";
43
43
  import { A as looseObject, B as union, C as any, D as discriminatedUnion, E as custom, F as optional, G as parse$3, H as safeParseAsync, I as record, J as prettifyError, K as parseAsync, L as strictObject, M as never, N as number$2, O as lazy$4, P as object$1, R as string$2, S as _null, T as boolean$2, U as ZodError$1, V as unknown, W as toJSONSchema, _ as ZodString$1, a as ZodIssueCode$1, b as _enum, c as ZodBoolean$1, d as ZodDiscriminatedUnion$1, f as ZodEnum$1, g as ZodOptional$1, h as ZodObject$1, i as string$3, j as nan, k as literal, l as ZodDate$1, m as ZodNumber$1, n as date, o as ZodAny$1, p as ZodLiteral$1, q as $ZodError, r as number$3, s as ZodArray$1, t as zod_default, u as ZodDefault$1, v as ZodType$1, w as array$2, x as _instanceof, y as ZodUnion$1, z as tuple } from "./zod-Bvx56F8M.js";
44
44
  import { t as invariant } from "./invariant-Ctm_8TNZ.js";
@@ -39479,29 +39479,32 @@ ${JSON.stringify(e2, null, 4)}`);
39479
39479
  }
39480
39480
  }, NavMenuComponent = (e) => {
39481
39481
  let r = (0, import_compiler_runtime$137.c)(13), { items: c, orientation: l } = e, d = _temp$36, f = _temp2$26, h = _temp3$17, g;
39482
- r[0] === l ? g = r[1] : (g = (e2) => "items" in e2 ? l === "horizontal" ? (0, import_jsx_runtime.jsxs)(NavigationMenuItem, {
39483
- children: [
39484
- (0, import_jsx_runtime.jsx)(NavigationMenuTrigger, {
39485
- children: renderHTML({
39486
- html: e2.label
39487
- })
39488
- }),
39489
- (0, import_jsx_runtime.jsx)(NavigationMenuContent, {
39490
- children: (0, import_jsx_runtime.jsx)(NavigationMenuList, {
39491
- children: (0, import_jsx_runtime.jsx)("ul", {
39492
- className: "grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px] ",
39493
- children: e2.items.map((e3) => (0, import_jsx_runtime.jsx)(ListItem, {
39494
- label: e3.label,
39495
- href: h(e3.href),
39496
- target: f(e3.href),
39497
- children: e3.description && renderHTML({
39498
- html: e3.description
39499
- })
39500
- }, e3.label))
39482
+ r[0] === l ? g = r[1] : (g = (e2) => "items" in e2 ? l === "horizontal" ? (0, import_jsx_runtime.jsx)(NavigationMenu, {
39483
+ orientation: "horizontal",
39484
+ children: (0, import_jsx_runtime.jsx)(NavigationMenuList, {
39485
+ children: (0, import_jsx_runtime.jsxs)(NavigationMenuItem, {
39486
+ children: [
39487
+ (0, import_jsx_runtime.jsx)(NavigationMenuTrigger, {
39488
+ children: renderHTML({
39489
+ html: e2.label
39490
+ })
39491
+ }),
39492
+ (0, import_jsx_runtime.jsx)(NavigationMenuContent, {
39493
+ children: (0, import_jsx_runtime.jsx)("ul", {
39494
+ className: "grid w-[400px] gap-3 p-4 md:w-[500px] md:grid-cols-2 lg:w-[600px] ",
39495
+ children: e2.items.map((e3) => (0, import_jsx_runtime.jsx)(ListItem, {
39496
+ label: e3.label,
39497
+ href: h(e3.href),
39498
+ target: f(e3.href),
39499
+ children: e3.description && renderHTML({
39500
+ html: e3.description
39501
+ })
39502
+ }, e3.label))
39503
+ })
39501
39504
  })
39502
- })
39505
+ ]
39503
39506
  })
39504
- ]
39507
+ })
39505
39508
  }, e2.label) : (0, import_jsx_runtime.jsxs)(NavigationMenuItem, {
39506
39509
  children: [
39507
39510
  (0, import_jsx_runtime.jsx)("div", {
@@ -69995,7 +69998,7 @@ Image URL: ${r.imageUrl}`)), contextToXml({
69995
69998
  function getVegaFieldTypes(e) {
69996
69999
  return !e || Object.keys(e).length === 0 ? "auto" : Objects.mapValues(e, (e2) => e2 === "date" || e2 === "time" ? "string" : e2 === "datetime" ? "date" : e2);
69997
70000
  }
69998
- var import_compiler_runtime$79 = require_compiler_runtime(), LazyDataEditor = import_react.lazy(() => import("./glide-data-editor-D-Ia_Jsv.js").then(async (m2) => {
70001
+ var import_compiler_runtime$79 = require_compiler_runtime(), LazyDataEditor = import_react.lazy(() => import("./glide-data-editor-DXF8E-QD.js").then(async (m2) => {
69999
70002
  await m2.__tla;
70000
70003
  return m2;
70001
70004
  }));
@@ -91903,7 +91906,7 @@ ${c}
91903
91906
  return true;
91904
91907
  }
91905
91908
  }
91906
- var LazyVegaComponent = import_react.lazy(() => import("./vega-component-kU4hFYYJ.js")), VegaPlugin = class {
91909
+ var LazyVegaComponent = import_react.lazy(() => import("./vega-component-HUc7bIGs.js")), VegaPlugin = class {
91907
91910
  constructor() {
91908
91911
  __publicField(this, "tagName", "marimo-vega");
91909
91912
  __publicField(this, "validator", object$1({
@@ -98401,7 +98404,7 @@ Defaulting to \`null\`.`;
98401
98404
  return Logger.warn("Failed to get version from mount config"), null;
98402
98405
  }
98403
98406
  }
98404
- const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.18.2"), showCodeInRunModeAtom = atom(true);
98407
+ const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.18.3"), showCodeInRunModeAtom = atom(true);
98405
98408
  atom(null);
98406
98409
  var VIRTUAL_FILE_REGEX = /\/@file\/([^\s"&'/]+)\.([\dA-Za-z]+)/g, VirtualFileTracker = class e {
98407
98410
  constructor() {
@@ -98701,7 +98704,7 @@ Defaulting to \`null\`.`;
98701
98704
  r[14] !== f || r[15] !== VY || r[16] !== c || r[17] !== q ? (e2 = (0, import_jsx_runtime.jsx)(OutputArea, {
98702
98705
  allowExpand: true,
98703
98706
  output: c,
98704
- className: "output-area",
98707
+ className: CSSClasses.outputArea,
98705
98708
  cellId: f,
98706
98709
  stale: q,
98707
98710
  loading: VY
@@ -98749,7 +98752,7 @@ Defaulting to \`null\`.`;
98749
98752
  r[45] !== f || r[46] !== VY || r[47] !== c || r[48] !== q || r[49] !== qY ? (JY = (0, import_jsx_runtime.jsx)(OutputArea, {
98750
98753
  allowExpand: qY,
98751
98754
  output: c,
98752
- className: "output-area",
98755
+ className: CSSClasses.outputArea,
98753
98756
  cellId: f,
98754
98757
  stale: q,
98755
98758
  loading: VY
@@ -15,7 +15,7 @@ import { t as require_jsx_runtime } from "./jsx-runtime-CTBg5pdT.js";
15
15
  import { t as require_react_dom } from "./react-dom-BZdwbVNI.js";
16
16
  import { m as useEvent_default } from "./useTheme-ByTGDerd.js";
17
17
  import { t as toString_default } from "./toString-DBXBHXIe.js";
18
- import { r as debounce_default, t as Constants } from "./constants-DWBOe162.js";
18
+ import { i as debounce_default, n as Constants } from "./constants-D_G8vnDk.js";
19
19
  import { t as memoizeLastValue } from "./once-DjP4Kbhy.js";
20
20
  var ChevronRight = createLucideIcon("chevron-right", [["path", {
21
21
  d: "m9 18 6-6-6-6",
@@ -2,7 +2,7 @@ import { s as __toESM } from "./chunk-BNovOVIE.js";
2
2
  import { t as require_react } from "./react-BSzAiXXz.js";
3
3
  import { t as require_compiler_runtime } from "./compiler-runtime-CNX0xYDF.js";
4
4
  import "./Combination-DnWHe36P.js";
5
- import { C as CircleQuestionMark, h as asRemoteURL, i as Alert, n as useDeepCompareMemoize, o as AlertTitle, s as isValid, t as arrow } from "./formats-7RSCCoSI.js";
5
+ import { C as CircleQuestionMark, h as asRemoteURL, i as Alert, n as useDeepCompareMemoize, o as AlertTitle, s as isValid, t as arrow } from "./formats-4m4HuHTj.js";
6
6
  import "./clsx-D2KVTYnW.js";
7
7
  import { l as Events } from "./button-XnD6ylpt.js";
8
8
  import { o as Objects, s as Logger } from "./hotkeys-CwkyZ6ZF.js";
@@ -18,7 +18,7 @@ import "./_baseUniq-CPOFUArp.js";
18
18
  import "./_baseIsEqual-CwglS7T6.js";
19
19
  import "./merge-DPdZQMPt.js";
20
20
  import "./now-BA1FgVte.js";
21
- import { r as debounce_default } from "./constants-DWBOe162.js";
21
+ import { i as debounce_default } from "./constants-D_G8vnDk.js";
22
22
  import { a as tooltipHandler, n as vegaLoadData } from "./loader-ZngagiXO.js";
23
23
  import { t as uniq_default } from "./uniq-CCIhWjDg.js";
24
24
  import "./zod-Bvx56F8M.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.18.2",
3
+ "version": "0.18.3",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -41,6 +41,7 @@ import {
41
41
  } from "@/core/config/config-schema";
42
42
  import { getAppWidths } from "@/core/config/widths";
43
43
  import { marimoVersionAtom } from "@/core/meta/state";
44
+ import { viewStateAtom } from "@/core/mode";
44
45
  import { useRequestClient } from "@/core/network/requests";
45
46
  import { isWasm } from "@/core/wasm/utils";
46
47
  import { useDebouncedCallback } from "@/hooks/useDebounce";
@@ -119,7 +120,19 @@ export const UserConfigForm: React.FC = () => {
119
120
  const [activeCategory, setActiveCategory] = useAtom(
120
121
  activeUserConfigCategoryAtom,
121
122
  );
122
- const capabilities = useAtomValue(capabilitiesAtom);
123
+
124
+ let capabilities = useAtomValue(capabilitiesAtom);
125
+ const isHome = useAtomValue(viewStateAtom).mode === "home";
126
+ // The home page does not fetch kernel capabilities, so we just turn them all on
127
+ if (isHome) {
128
+ capabilities = {
129
+ terminal: true,
130
+ pylsp: true,
131
+ ty: true,
132
+ basedpyright: true,
133
+ };
134
+ }
135
+
123
136
  const marimoVersion = useAtomValue(marimoVersionAtom);
124
137
  const { locale } = useLocale();
125
138
  const { saveUserConfig } = useRequestClient();
@@ -1,8 +1,7 @@
1
1
  /* Copyright 2024 Marimo. All rights reserved. */
2
2
 
3
- import { EditorView } from "@codemirror/view";
4
3
  import { Slot } from "@radix-ui/react-slot";
5
- import React, { type PropsWithChildren, useState } from "react";
4
+ import React, { type PropsWithChildren } from "react";
6
5
  import { useImperativeModal } from "@/components/modal/ImperativeModal";
7
6
  import { Button } from "@/components/ui/button";
8
7
  import {
@@ -12,12 +11,7 @@ import {
12
11
  DialogHeader,
13
12
  DialogTitle,
14
13
  } from "@/components/ui/dialog";
15
- import { Input } from "@/components/ui/input";
16
- import { Textarea } from "@/components/ui/textarea";
17
- import { toast } from "@/components/ui/use-toast";
18
14
  import { Constants } from "@/core/constants";
19
- import { LazyAnyLanguageCodeMirror } from "@/plugins/impl/code/LazyAnyLanguageCodeMirror";
20
- import { useTheme } from "@/theme/useTheme";
21
15
 
22
16
  export const ContributeSnippetButton: React.FC<PropsWithChildren> = ({
23
17
  children,
@@ -33,106 +27,31 @@ export const ContributeSnippetButton: React.FC<PropsWithChildren> = ({
33
27
  );
34
28
  };
35
29
 
36
- const extensions = [EditorView.lineWrapping];
37
-
38
30
  const ContributeSnippetModal: React.FC<{
39
31
  onClose: () => void;
40
32
  }> = ({ onClose }) => {
41
- const [code, setCode] = useState("");
42
- const { theme } = useTheme();
43
-
44
33
  return (
45
- <DialogContent className="w-fit">
46
- <form
47
- onSubmit={async (e) => {
48
- e.preventDefault();
49
-
50
- const formData = new FormData(e.target as HTMLFormElement);
51
- const title = formData.get("title");
52
- const description = formData.get("description");
53
- const code = formData.get("code");
54
-
55
- // Fire-and-forget we don't care about the response
56
- void fetch("https://marimo.io/api/suggest-snippet", {
57
- method: "POST",
58
- headers: {
59
- "Content-Type": "application/json",
60
- },
61
- body: JSON.stringify({
62
- title,
63
- description,
64
- code,
65
- }),
66
- });
67
- onClose();
68
- toast({
69
- title: "Snippet Submitted",
70
- description:
71
- "Thank you for contributing! We will review your snippet shortly.",
72
- });
73
- }}
74
- >
75
- <DialogHeader>
76
- <DialogTitle>Contribute a Snippet</DialogTitle>
77
- <DialogDescription>
78
- Have a useful snippet you want to share with the community? Submit
79
- it here or make a pull request{" "}
80
- <a
81
- href={Constants.githubPage}
82
- target="_blank"
83
- className="underline"
84
- >
85
- on GitHub
86
- </a>
87
- .
88
- </DialogDescription>
89
- </DialogHeader>
90
- <div className="flex flex-col gap-6 py-4">
91
- <Input
92
- id="title"
93
- name="title"
94
- autoFocus={true}
95
- placeholder="Title"
96
- required={true}
97
- autoComplete="off"
98
- />
99
- <Textarea
100
- id="description"
101
- name="description"
102
- autoFocus={true}
103
- placeholder="Description"
104
- rows={5}
105
- required={true}
106
- autoComplete="off"
107
- />
108
- <input type="hidden" name="code" value={code} />
109
- <LazyAnyLanguageCodeMirror
110
- theme={theme === "dark" ? "dark" : "light"}
111
- language="python"
112
- className="cm border rounded overflow-hidden"
113
- extensions={extensions}
114
- value={code}
115
- onChange={setCode}
116
- />
117
- </div>
118
- <DialogFooter>
119
- <Button
120
- data-testid="snippet-cancel-button"
121
- variant="secondary"
122
- onClick={onClose}
123
- >
124
- Cancel
125
- </Button>
126
- <Button
127
- data-testid="snippet-send-button"
128
- aria-label="Save"
129
- variant="default"
130
- type="submit"
131
- >
132
- Send
133
- </Button>
134
- </DialogFooter>
135
- </form>
34
+ <DialogContent className="max-w-md">
35
+ <DialogHeader>
36
+ <DialogTitle>Contribute a Snippet</DialogTitle>
37
+ <DialogDescription>
38
+ Have a useful snippet you want to share with the community? Make a
39
+ pull request{" "}
40
+ <a href={Constants.githubPage} target="_blank" className="underline">
41
+ on GitHub
42
+ </a>
43
+ .
44
+ </DialogDescription>
45
+ </DialogHeader>
46
+ <DialogFooter>
47
+ <Button
48
+ data-testid="snippet-close-button"
49
+ variant="default"
50
+ onClick={onClose}
51
+ >
52
+ Close
53
+ </Button>
54
+ </DialogFooter>
136
55
  </DialogContent>
137
56
  );
138
57
  };
@@ -0,0 +1,50 @@
1
+ /* Copyright 2024 Marimo. All rights reserved. */
2
+
3
+ import { AlertTriangleIcon } from "lucide-react";
4
+ import { KeyboardHotkeys } from "@/components/shortcuts/renderShortcut";
5
+ import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
6
+ import type { DuplicateGroup } from "@/hooks/useDuplicateShortcuts";
7
+
8
+ interface DuplicateShortcutBannerProps {
9
+ duplicates: DuplicateGroup[];
10
+ }
11
+
12
+ /**
13
+ * Banner component that warns about duplicate keyboard shortcuts.
14
+ * Displays a warning when multiple actions share the same key binding.
15
+ */
16
+ export const DuplicateShortcutBanner: React.FC<
17
+ DuplicateShortcutBannerProps
18
+ > = ({ duplicates }) => {
19
+ // Don't render if no duplicates
20
+ if (duplicates.length === 0) {
21
+ return null;
22
+ }
23
+
24
+ return (
25
+ <Alert variant="warning" className="mb-4">
26
+ <AlertTriangleIcon className="h-4 w-4" />
27
+ <AlertTitle>Duplicate shortcuts</AlertTitle>
28
+ <AlertDescription>
29
+ <p className="mb-2">
30
+ Multiple actions are assigned to the same keyboard shortcut:
31
+ </p>
32
+ <ul className="space-y-2">
33
+ {duplicates.map(({ key, actions }) => (
34
+ <li key={key} className="text-xs">
35
+ <div className="flex items-center gap-2 mb-1">
36
+ <KeyboardHotkeys shortcut={key} />
37
+ <span className="font-semibold">is used by:</span>
38
+ </div>
39
+ <ul className="ml-6 list-disc">
40
+ {actions.map(({ action, name }) => (
41
+ <li key={action}>{name}</li>
42
+ ))}
43
+ </ul>
44
+ </li>
45
+ ))}
46
+ </ul>
47
+ </AlertDescription>
48
+ </Alert>
49
+ );
50
+ };
@@ -1,7 +1,7 @@
1
1
  /* Copyright 2024 Marimo. All rights reserved. */
2
2
 
3
3
  import { atom, useAtom, useAtomValue } from "jotai";
4
- import { EditIcon, XIcon } from "lucide-react";
4
+ import { AlertTriangleIcon, EditIcon, XIcon } from "lucide-react";
5
5
  import { useState } from "react";
6
6
  import { Button } from "@/components/ui/button";
7
7
  import { Input } from "@/components/ui/input";
@@ -15,6 +15,7 @@ import {
15
15
  } from "@/core/hotkeys/hotkeys";
16
16
  import { isPlatformMac } from "@/core/hotkeys/shortcuts";
17
17
  import { useRequestClient } from "@/core/network/requests";
18
+ import { useDuplicateShortcuts } from "../../../hooks/useDuplicateShortcuts";
18
19
  import { useHotkey } from "../../../hooks/useHotkey";
19
20
  import { KeyboardHotkeys } from "../../shortcuts/renderShortcut";
20
21
  import {
@@ -25,6 +26,7 @@ import {
25
26
  DialogPortal,
26
27
  DialogTitle,
27
28
  } from "../../ui/dialog";
29
+ import { DuplicateShortcutBanner } from "./duplicate-shortcut-banner";
28
30
 
29
31
  export const keyboardShortcutsAtom = atom(false);
30
32
 
@@ -37,6 +39,10 @@ export const KeyboardShortcuts: React.FC = () => {
37
39
  const [config, setConfig] = useResolvedMarimoConfig();
38
40
  const hotkeys = useAtomValue(hotkeysAtom);
39
41
  const { saveUserConfig } = useRequestClient();
42
+ const { duplicates, hasDuplicate, getDuplicatesFor } = useDuplicateShortcuts(
43
+ hotkeys,
44
+ "Markdown",
45
+ );
40
46
 
41
47
  useHotkey("global.showHelp", () => setIsOpen((v) => !v));
42
48
 
@@ -214,6 +220,9 @@ export const KeyboardShortcuts: React.FC = () => {
214
220
  );
215
221
  }
216
222
 
223
+ const isDuplicate = hasDuplicate(action);
224
+ const duplicateActions = isDuplicate ? getDuplicatesFor(action) : [];
225
+
217
226
  return (
218
227
  <div
219
228
  key={action}
@@ -231,7 +240,20 @@ export const KeyboardShortcuts: React.FC = () => {
231
240
  <div className="w-3 h-3" />
232
241
  )}
233
242
  <KeyboardHotkeys className="justify-end" shortcut={hotkey.key} />
234
- <span>{hotkey.name.toLowerCase()}</span>
243
+ <div className="flex items-center gap-1">
244
+ <span>{hotkey.name.toLowerCase()}</span>
245
+ {isDuplicate && (
246
+ <div className="group relative inline-flex">
247
+ <AlertTriangleIcon className="w-3 h-3 text-(--yellow-11)" />
248
+ <div className="invisible group-hover:visible absolute left-0 top-5 z-10 w-max max-w-xs rounded-md bg-(--yellow-2) border border-(--yellow-7) p-2 text-xs text-(--yellow-11) shadow-md">
249
+ Also used by:{" "}
250
+ {duplicateActions
251
+ .map((a) => hotkeys.getHotkey(a).name.toLowerCase())
252
+ .join(", ")}
253
+ </div>
254
+ </div>
255
+ )}
256
+ </div>
235
257
  </div>
236
258
  );
237
259
  };
@@ -279,6 +301,7 @@ export const KeyboardShortcuts: React.FC = () => {
279
301
  <DialogHeader>
280
302
  <DialogTitle>Shortcuts</DialogTitle>
281
303
  </DialogHeader>
304
+ <DuplicateShortcutBanner duplicates={duplicates} />
282
305
  <div className="flex flex-row gap-3">
283
306
  <div className="w-1/2">
284
307
  {renderGroup("Editing")}
@@ -29,6 +29,7 @@ import { outputIsLoading, outputIsStale } from "@/core/cells/cell";
29
29
  import { isOutputEmpty } from "@/core/cells/outputs";
30
30
  import { autocompletionKeymap } from "@/core/codemirror/cm";
31
31
  import type { LanguageAdapterType } from "@/core/codemirror/language/types";
32
+ import { CSSClasses } from "@/core/constants";
32
33
  import { canCollapseOutline } from "@/core/dom/outline";
33
34
  import { isErrorMime } from "@/core/mime";
34
35
  import type { AppMode } from "@/core/mode";
@@ -349,7 +350,7 @@ const ReadonlyCellComponent = forwardRef(
349
350
  <OutputArea
350
351
  allowExpand={false}
351
352
  forceExpand={true}
352
- className="output-area"
353
+ className={CSSClasses.outputArea}
353
354
  cellId={cellId}
354
355
  output={cellRuntime.output}
355
356
  stale={outputIsStale(cellRuntime, cellData.edited)}
@@ -508,7 +509,7 @@ const EditableCellComponent = ({
508
509
  allowExpand={true}
509
510
  // Force expand when markdown is hidden
510
511
  forceExpand={isMarkdownCodeHidden}
511
- className="output-area"
512
+ className={CSSClasses.outputArea}
512
513
  cellId={cellId}
513
514
  output={cellRuntime.output}
514
515
  stale={isStaleCell}
@@ -1168,7 +1169,7 @@ const SetupCellComponent = ({
1168
1169
  <OutputArea
1169
1170
  allowExpand={true}
1170
1171
  forceExpand={true}
1171
- className="output-area"
1172
+ className={CSSClasses.outputArea}
1172
1173
  cellId={cellId}
1173
1174
  output={cellRuntime.output}
1174
1175
  stale={false}
@@ -534,13 +534,13 @@ describe("AnsiReducer streaming with append()", () => {
534
534
  describe("AnsiReducer color preservation", () => {
535
535
  const CASES = [
536
536
  // SGR sequences
537
- "\u001b[34mBlue text\u001b[m normal text\u001b[31mRed text\u001b[0m",
537
+ "\u001B[34mBlue text\u001B[m normal text\u001B[31mRed text\u001B[0m",
538
538
  // Complex SGR with parameters
539
- "\u001b[1;31mBold Red\u001b[0m \u001b[48;5;240mGray bg\u001b[0m",
539
+ "\u001B[1;31mBold Red\u001B[0m \u001B[48;5;240mGray bg\u001B[0m",
540
540
  // Character set selection
541
- "Text\u001b(BMore\u001b(0Graphics\u001b(B",
541
+ "Text\u001B(BMore\u001B(0Graphics\u001B(B",
542
542
  // Complex case
543
- "\u001b[34m[D 251201 15:32:24 cell_runner:695]\u001b(B\u001b[m Running post_execution hooks in context\n\u001b[34m[D 251201 15:32:24 hooks_post_execution:65]\u001b(B\u001b[m Acquiring graph lock to update cell import workspace\n\u001b[34m[D 251201 15:32:24 hooks_post_execution:67]\u001b(B\u001b[m Acquired graph lock to update import workspace.\n",
543
+ "\u001B[34m[D 251201 15:32:24 cell_runner:695]\u001B(B\u001B[m Running post_execution hooks in context\n\u001B[34m[D 251201 15:32:24 hooks_post_execution:65]\u001B(B\u001B[m Acquiring graph lock to update cell import workspace\n\u001B[34m[D 251201 15:32:24 hooks_post_execution:67]\u001B(B\u001B[m Acquired graph lock to update import workspace.\n",
544
544
  ];
545
545
 
546
546
  test.each(CASES)("preserves ANSI color codes", (input) => {
@@ -554,12 +554,12 @@ describe("AnsiReducer color preservation", () => {
554
554
  // Test that color codes work alongside cursor movements
555
555
  // Note: when cursor moves up, lines below are discarded (tqdm behavior)
556
556
  const result = reducer.reduce(
557
- "Line1\n\u001b[31mRed\u001b[0m\u001b[1A\u001b[32mGreen\u001b[0m",
557
+ "Line1\n\u001B[31mRed\u001B[0m\u001B[1A\u001B[32mGreen\u001B[0m",
558
558
  );
559
559
  // After moving up from row 1 to row 0, row 1 is discarded
560
560
  // Green is written at the end of row 0
561
561
  expect(result).toMatchInlineSnapshot(
562
- `"Line1 \u001b[32mGreen\u001b[0m"`,
562
+ `"Line1 \u001B[32mGreen\u001B[0m"`,
563
563
  );
564
564
  });
565
565
  });
@@ -29,7 +29,7 @@ import { isOutputEmpty } from "@/core/cells/outputs";
29
29
  import type { CellData, CellRuntimeState } from "@/core/cells/types";
30
30
  import { MarkdownLanguageAdapter } from "@/core/codemirror/language/languages/markdown";
31
31
  import { useResolvedMarimoConfig } from "@/core/config/config";
32
- import { KnownQueryParams } from "@/core/constants";
32
+ import { CSSClasses, KnownQueryParams } from "@/core/constants";
33
33
  import type { OutputMessage } from "@/core/kernel/messages";
34
34
  import { showCodeInRunModeAtom } from "@/core/meta/state";
35
35
  import { isErrorMime } from "@/core/mime";
@@ -339,7 +339,7 @@ const VerticalCell = memo(
339
339
  <OutputArea
340
340
  allowExpand={true}
341
341
  output={output}
342
- className="output-area"
342
+ className={CSSClasses.outputArea}
343
343
  cellId={cellId}
344
344
  stale={outputStale}
345
345
  loading={loading}
@@ -394,7 +394,7 @@ const VerticalCell = memo(
394
394
  <OutputArea
395
395
  allowExpand={mode === "edit"}
396
396
  output={output}
397
- className="output-area"
397
+ className={CSSClasses.outputArea}
398
398
  cellId={cellId}
399
399
  stale={outputStale}
400
400
  loading={loading}
@@ -169,6 +169,12 @@ const WorkspaceNotebooks: React.FC = () => {
169
169
  return (
170
170
  <WorkspaceRootContext value={workspace.root}>
171
171
  <div className="flex flex-col gap-2">
172
+ {workspace.hasMore && (
173
+ <Banner kind="warn" className="rounded p-4">
174
+ Showing first {workspace.fileCount} files. Your workspace has more
175
+ files.
176
+ </Banner>
177
+ )}
172
178
  <Header
173
179
  Icon={BookTextIcon}
174
180
  control={