@marimo-team/islands 0.25.2-dev12 → 0.25.2-dev4

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 (85) hide show
  1. package/dist/{ConnectedDataExplorerComponent-CqhQmp74.js → ConnectedDataExplorerComponent-C2d9ysUI.js} +11 -11
  2. package/dist/{ErrorBoundary-YddQ6YHW.js → ErrorBoundary-CHS5luyo.js} +8 -8
  3. package/dist/{abnfDiagram-VCTEODGH-aLGD44M7.js → abnfDiagram-VCTEODGH-AFhOQTt8.js} +2 -2
  4. package/dist/{any-language-editor-dqxlUDlT.js → any-language-editor-CycIVIeP.js} +3 -3
  5. package/dist/{architectureDiagram-5GKGNRK7-BGL5P81u.js → architectureDiagram-5GKGNRK7-BngksAAQ.js} +1 -1
  6. package/dist/{button-B0Xgl-Qn.js → button-DdXAm8iz.js} +0 -12
  7. package/dist/{capabilities-D7Ad8-zw.js → capabilities-B3ce_GNu.js} +1 -1
  8. package/dist/{cells-5ppES-Un.js → cells-Cv93oav_.js} +12 -12
  9. package/dist/{chat-ui-Dv2V95k6.js → chat-ui-fVyVOhYN.js} +15 -15
  10. package/dist/{check-DGZ74tV2.js → check-B7cIK6gb.js} +1 -1
  11. package/dist/{chunk-IMKFNOWR-Cm3RgLDj.js → chunk-IMKFNOWR-UOVZuZVn.js} +1 -1
  12. package/dist/{chunk-SHT3W25Y-DedDYSP5.js → chunk-SHT3W25Y-CrEPyWy1.js} +1 -1
  13. package/dist/{chunk-SVP7TREG-B2SFkCAL.js → chunk-SVP7TREG-uIyyySp6.js} +1 -1
  14. package/dist/{chunk-TICWLB2K-DB6hjNOL.js → chunk-TICWLB2K-DdXM3eg6.js} +1 -1
  15. package/dist/{classDiagram-ZZMXUADV-BwYhrSEX.js → classDiagram-ZZMXUADV-BiATbBE4.js} +2 -2
  16. package/dist/{classDiagram-v2-VYDZK3BY-HecM04TM.js → classDiagram-v2-VYDZK3BY-JnH97GYw.js} +2 -2
  17. package/dist/{code-visibility-C0zE3g0U.js → code-visibility-DOzR4Dbu.js} +6 -6
  18. package/dist/{common-BkjS959w.js → common-BH1qMx9b.js} +22 -22
  19. package/dist/{copy-icon-qmRg_VTX.js → copy-icon-CLdENY__.js} +3 -3
  20. package/dist/{cynefinDiagram-5FMLGOSQ-DzaZEqgD.js → cynefinDiagram-5FMLGOSQ-zknaAsGy.js} +1 -1
  21. package/dist/{dagre-GXQ25YYZ-Cjf5GjU3.js → dagre-GXQ25YYZ-BhMOoMGJ.js} +1 -1
  22. package/dist/{data-grid-overlay-editor-CqoIqvNa.js → data-grid-overlay-editor-C23bOAVI.js} +1 -1
  23. package/dist/{diagram-S7CK7UJ4-IhLt_khx.js → diagram-S7CK7UJ4-V5-Z-EDY.js} +1 -1
  24. package/dist/{diagram-UQ7AKVKN-CQc6KLPB.js → diagram-UQ7AKVKN-qw8AjDal.js} +1 -1
  25. package/dist/{diagram-VX7I27RA-DHmW9N1T.js → diagram-VX7I27RA-DfuqFb1E.js} +1 -1
  26. package/dist/{diagram-Z3DM3KII-zVKsg-Ty.js → diagram-Z3DM3KII-DpWwlYZB.js} +1 -1
  27. package/dist/{dialog-CILKhbsG.js → dialog-CgNq6y9-.js} +3 -3
  28. package/dist/{dropdown-menu-BaqM0t4N.js → dropdown-menu-CZy06LAq.js} +7 -7
  29. package/dist/{ebnfDiagram-PWID7BFC-DDd5hCRC.js → ebnfDiagram-PWID7BFC-C20OnNMZ.js} +2 -2
  30. package/dist/{erDiagram-RLTQ6QDP-D10NP0eI.js → erDiagram-RLTQ6QDP-DBXLWO9v.js} +1 -1
  31. package/dist/{error-banner-DzAmP0AQ.js → error-banner-B94dcDmP.js} +2 -2
  32. package/dist/{error-entries-B2Ux3Z2X.js → error-entries-DLl0XqoW.js} +2 -2
  33. package/dist/{feedback-button-BU771zKS.js → feedback-button-B6DzYbxQ.js} +10 -10
  34. package/dist/{flowDiagram-HODETNUW-DgcjSdPV.js → flowDiagram-HODETNUW-DL52nMkt.js} +2 -2
  35. package/dist/{formats-Q9gwlLyD.js → formats-Cl_67ghI.js} +3 -3
  36. package/dist/{glide-data-editor-D9TpbHEU.js → glide-data-editor-H0BN7EiD.js} +11 -11
  37. package/dist/{glide-utils-CzzWU59p.js → glide-utils-B3rUT5PI.js} +3 -3
  38. package/dist/{globals-nXV4QUKg.js → globals-C9VJ-IPA.js} +3 -3
  39. package/dist/{html-to-image-BZBwkkDG.js → html-to-image-CmkwfNkf.js} +11 -11
  40. package/dist/{infoDiagram-27XIBGKW-DrYu3UZC.js → infoDiagram-27XIBGKW-ntpxMfrq.js} +1 -1
  41. package/dist/{ishikawaDiagram-5VMMS53U-pmkGQJsA.js → ishikawaDiagram-5VMMS53U-BllIlHE5.js} +1 -1
  42. package/dist/{kanban-definition-UXKFOSKX-wWGD9VLW.js → kanban-definition-UXKFOSKX-GYtNMjtS.js} +1 -1
  43. package/dist/{label-MNhNNoN6.js → label-BslhXqL6.js} +2 -2
  44. package/dist/{loader-C9OUkMrj.js → loader-DEZSzvma.js} +1 -1
  45. package/dist/main.js +45 -65
  46. package/dist/{mermaid-Dfvntf3s.js → mermaid-Dnzoxjt1.js} +36 -36
  47. package/dist/{mindmap-definition-YA3MSWOX-C2f1VIBR.js → mindmap-definition-YA3MSWOX-Cth76xgH.js} +1 -1
  48. package/dist/{number-overlay-editor-BH4Uo_sZ.js → number-overlay-editor-MgsEqPLj.js} +1 -1
  49. package/dist/{pegDiagram-XKGWAZYB-D6v5dz4M.js → pegDiagram-XKGWAZYB-Cu4uOXii.js} +2 -2
  50. package/dist/{pieDiagram-E7YTZNPT-BwFAhpYD.js → pieDiagram-E7YTZNPT-Bh3eDa9s.js} +1 -1
  51. package/dist/{process-output-BSsWzfnY.js → process-output-CYN5E-iO.js} +4 -4
  52. package/dist/{railroadDiagram-O6MQD6OU-D6eOFr6Z.js → railroadDiagram-O6MQD6OU-DG-M6Rnc.js} +2 -2
  53. package/dist/{requirementDiagram-BXWQKSXE-CHYsMgDR.js → requirementDiagram-BXWQKSXE-DCwsThh0.js} +1 -1
  54. package/dist/{reveal-component-_A40NW1c.js → reveal-component-BNJLyBZU.js} +10 -10
  55. package/dist/{select-BcObMjGz.js → select-C6plhmZr.js} +4 -4
  56. package/dist/{sequenceDiagram-WJ2MYXX4-BPAknhBp.js → sequenceDiagram-WJ2MYXX4-CbXB1_PU.js} +1 -1
  57. package/dist/{spec-D62vWpMT.js → spec-DQBRQSba.js} +4 -4
  58. package/dist/{stateDiagram-D77RDMKH-Cq249IQ4.js → stateDiagram-D77RDMKH-A-Zf3Sb2.js} +2 -2
  59. package/dist/{stateDiagram-v2-MP3YSRHH-Dk5QgdXF.js → stateDiagram-v2-MP3YSRHH-D9YMnUGx.js} +2 -2
  60. package/dist/{swimlanes-42K2YHIH-Bh_S_HKD.js → swimlanes-42K2YHIH-B_pMf0J4.js} +1 -1
  61. package/dist/{swimlanesDiagram-VR7AAH4N-CbztusY8.js → swimlanesDiagram-VR7AAH4N-Ctgy-yGP.js} +2 -2
  62. package/dist/{swiper-component-DkV7T44B.js → swiper-component-IOUowglM.js} +2 -2
  63. package/dist/{timeline-definition-24CTP7MA-ByNMgBE7.js → timeline-definition-24CTP7MA-DTXFjTTM.js} +1 -1
  64. package/dist/{toDate-DWVp6uE1.js → toDate-C67bxMWn.js} +3 -3
  65. package/dist/{toast-DcoJGS3-.js → toast-DvY70eFX.js} +4 -4
  66. package/dist/{tooltip-Bi36DgYh.js → tooltip-qB8NlSqV.js} +2 -2
  67. package/dist/{use-restore-focus-ZgG5Br63.js → use-restore-focus-D5D9xEjZ.js} +1 -1
  68. package/dist/{useAsyncData-BD7NLQ3_.js → useAsyncData-BD6AStMt.js} +1 -1
  69. package/dist/{useDateFormatter-D8XWr8lL.js → useDateFormatter-BXQGu86d.js} +2 -2
  70. package/dist/{useDeepCompareMemoize-CawMGSRU.js → useDeepCompareMemoize-D_HNdyvI.js} +1 -1
  71. package/dist/{useIframeCapabilities-BUMBOpsM.js → useIframeCapabilities-CVtNkI3Y.js} +1 -1
  72. package/dist/{useLifecycle-3vGhRa1o.js → useLifecycle-DPgiiwwU.js} +3 -3
  73. package/dist/{useTheme-BOw801nZ.js → useTheme-DzXmYZ5V.js} +2 -2
  74. package/dist/{vega-component-9siY74NS.js → vega-component-tFOzgarw.js} +9 -9
  75. package/dist/{vennDiagram-4TSXK5OY-DY8CySdO.js → vennDiagram-4TSXK5OY-BPHjZo0R.js} +1 -1
  76. package/dist/{wardleyDiagram-VM6X3IG4-DYC1AFni.js → wardleyDiagram-VM6X3IG4-6fTLYBuD.js} +1 -1
  77. package/dist/{xychartDiagram-S5SC5T6Z-Df8LLnuY.js → xychartDiagram-S5SC5T6Z-BYjwjrzE.js} +1 -1
  78. package/package.json +1 -1
  79. package/src/components/editor/actions/useNotebookActions.tsx +0 -20
  80. package/src/core/edit-app.tsx +0 -16
  81. package/src/core/hotkeys/hotkeys.ts +0 -12
  82. package/src/plugins/impl/FileBrowserPlugin.tsx +15 -45
  83. package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +2 -85
  84. package/src/components/editor/actions/__tests__/useSetOutputsExpanded.test.ts +0 -42
  85. package/src/components/editor/actions/useSetOutputsExpanded.ts +0 -67
@@ -1,10 +1,10 @@
1
1
  import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
- import { g as t, h as n, r } from "./button-B0Xgl-Qn.js";
2
+ import { g as t, h as n, r } from "./button-DdXAm8iz.js";
3
3
  import { t as i } from "./react-ofJbxM4x.js";
4
4
  import { t as a } from "./compiler-runtime-Cj8ZWiNS.js";
5
- import { g as o } from "./tooltip-Bi36DgYh.js";
5
+ import { g as o } from "./tooltip-qB8NlSqV.js";
6
6
  import { t as s } from "./jsx-runtime-DgDPJV9S.js";
7
- import { E as c, w as l } from "./useTheme-BOw801nZ.js";
7
+ import { E as c, w as l } from "./useTheme-DzXmYZ5V.js";
8
8
  var u = o("calendar", [
9
9
  ["path", {
10
10
  d: "M8 2v4",
@@ -1,8 +1,8 @@
1
1
  import { a as e, r as t } from "./rolldown-runtime-Cb76FRpK.js";
2
- import { a as n, g as r, s as i } from "./button-B0Xgl-Qn.js";
2
+ import { a as n, g as r, s as i } from "./button-DdXAm8iz.js";
3
3
  import { t as a } from "./react-ofJbxM4x.js";
4
4
  import { t as o } from "./compiler-runtime-Cj8ZWiNS.js";
5
- import { C as s, F as c, L as l, M as u, O as d, P as f, S as p, j as m, v as h } from "./use-restore-focus-ZgG5Br63.js";
5
+ import { C as s, F as c, L as l, M as u, O as d, P as f, S as p, j as m, v as h } from "./use-restore-focus-D5D9xEjZ.js";
6
6
  import { l as g, t as _ } from "./_baseMerge-BiGRwuqv.js";
7
7
  //#region ../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/mergeWith.js
8
8
  var v = g(function(e, t, n, r) {
@@ -1,21 +1,21 @@
1
1
  import { a as e } from "./rolldown-runtime-Cb76FRpK.js";
2
- import { g as t, h as n, m as r, o as i } from "./button-B0Xgl-Qn.js";
2
+ import { g as t, h as n, m as r, o as i } from "./button-DdXAm8iz.js";
3
3
  import { t as a } from "./react-ofJbxM4x.js";
4
4
  import { t as o } from "./compiler-runtime-Cj8ZWiNS.js";
5
- import { t as s } from "./tooltip-Bi36DgYh.js";
6
- import { T as c, c as l } from "./toDate-DWVp6uE1.js";
5
+ import { t as s } from "./tooltip-qB8NlSqV.js";
6
+ import { T as c, c as l } from "./toDate-C67bxMWn.js";
7
7
  import { t as u } from "./jsx-runtime-DgDPJV9S.js";
8
- import { n as d } from "./error-banner-DzAmP0AQ.js";
8
+ import { n as d } from "./error-banner-B94dcDmP.js";
9
9
  import { t as f } from "./debounce-C3jyATpc.js";
10
- import { A as p, n as ee } from "./useTheme-BOw801nZ.js";
10
+ import { A as p, n as ee } from "./useTheme-DzXmYZ5V.js";
11
11
  import { c as m } from "./arrays-CN1djC4k.js";
12
12
  import { t as te } from "./objects-CzUgoMIF.js";
13
- import { t as h } from "./useAsyncData-BD7NLQ3_.js";
14
- import { a as ne, i as re, n as ie, t as g } from "./formats-Q9gwlLyD.js";
13
+ import { t as h } from "./useAsyncData-BD6AStMt.js";
14
+ import { a as ne, i as re, n as ie, t as g } from "./formats-Cl_67ghI.js";
15
15
  import { M as ae, n as oe } from "./vega-loader.browser-DNST6uVf.js";
16
16
  import { t as se } from "./react-vega-ewj7q_U5.js";
17
- import { a as ce, n as _ } from "./loader-C9OUkMrj.js";
18
- import { t as le } from "./useDeepCompareMemoize-CawMGSRU.js";
17
+ import { a as ce, n as _ } from "./loader-DEZSzvma.js";
18
+ import { t as le } from "./useDeepCompareMemoize-D_HNdyvI.js";
19
19
  import { t as ue } from "./semaphore-89jsoHtS.js";
20
20
  import { t as de } from "./use-vega-container-remeasure-4DwJbPWu.js";
21
21
  //#region src/plugins/impl/vega/fix-relative-url.ts
@@ -3,7 +3,7 @@ import { t } from "./src-CA_m4ONl.js";
3
3
  import { n } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
4
4
  import { $ as r, H as i, K as a, U as o, a as s, b as c, c as l, et as u, f as d, nt as f, tt as p, v as m, w as h, y as g } from "./chunk-DU6HZSFF-1TwWR6gh.js";
5
5
  import { t as _ } from "./rough.esm-CtV9AnV1.js";
6
- import { p as v } from "./mermaid-Dfvntf3s.js";
6
+ import { p as v } from "./mermaid-Dnzoxjt1.js";
7
7
  //#region ../node_modules/.pnpm/khroma@2.1.0/node_modules/khroma/dist/methods/transparentize.js
8
8
  var y = (e, t) => p(e, "a", -t), b = 1e-10;
9
9
  function x(e, t) {
@@ -2,7 +2,7 @@ import { i as e } from "./chunk-75Z2AOVW-C4AOleKf.js";
2
2
  import { n as t } from "./src-CA_m4ONl.js";
3
3
  import { n } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
4
4
  import { D as r, H as i, K as a, U as o, a as s, b as c, c as l, v as u, w as d, x as f, y as p } from "./chunk-DU6HZSFF-1TwWR6gh.js";
5
- import { p as m } from "./mermaid-Dfvntf3s.js";
5
+ import { p as m } from "./mermaid-Dnzoxjt1.js";
6
6
  import { n as h } from "./mermaid-parser.core-DxuSfYwJ.js";
7
7
  import { t as g } from "./chunk-JWPE2WC7-DJvv1t8U.js";
8
8
  //#region ../node_modules/.pnpm/mermaid@11.17.2/node_modules/mermaid/dist/chunks/mermaid.core/wardleyDiagram-VM6X3IG4.mjs
@@ -9,7 +9,7 @@ import { n as s } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
9
9
  import { D as c, H as l, K as u, U as d, a as f, b as p, c as m, f as h, v as g, w as _, y as v, z as y } from "./chunk-DU6HZSFF-1TwWR6gh.js";
10
10
  import "./chunk-PWAF6VOD-lNxB9k8z.js";
11
11
  import { t as b } from "./chunk-GMAD6QVW-vStrMz2P.js";
12
- import { p as x } from "./mermaid-Dfvntf3s.js";
12
+ import { p as x } from "./mermaid-Dnzoxjt1.js";
13
13
  //#region ../node_modules/.pnpm/d3-scale@4.0.2/node_modules/d3-scale/src/band.js
14
14
  function S() {
15
15
  var e = t().unknown(void 0), r = e.domain, i = e.range, o = 0, s = 1, c, l, u = !1, d = 0, f = 0, p = .5;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.25.2-dev12",
3
+ "version": "0.25.2-dev4",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -7,8 +7,6 @@ import {
7
7
  CheckIcon,
8
8
  ChevronDownCircleIcon,
9
9
  ChevronRightCircleIcon,
10
- ChevronsDownUpIcon,
11
- ChevronsUpDownIcon,
12
10
  ClipboardCopyIcon,
13
11
  CodeIcon,
14
12
  CommandIcon,
@@ -102,7 +100,6 @@ import type { ActionButton } from "./types";
102
100
  import { useCopyNotebook } from "./useCopyNotebook";
103
101
  import { useRestartKernel } from "./useRestartKernel";
104
102
  import { useSetCodeVisibility } from "./useSetCodeVisibility";
105
- import { useSetOutputsExpanded } from "./useSetOutputsExpanded";
106
103
 
107
104
  const NOOP_HANDLER = (event?: Event) => {
108
105
  event?.preventDefault();
@@ -121,7 +118,6 @@ export function useNotebookActions({
121
118
  const [viewState] = useAtom(viewStateAtom);
122
119
  const kioskMode = useAtomValue(kioskModeAtom);
123
120
  const setCodeVisibility = useSetCodeVisibility();
124
- const setOutputsExpanded = useSetOutputsExpanded();
125
121
  const [resolvedConfig] = useResolvedMarimoConfig();
126
122
  const capabilities = useAtomValue(capabilitiesAtom);
127
123
  const aiEnabled = useAtomValue(aiEnabledAtom);
@@ -600,22 +596,6 @@ export function useNotebookActions({
600
596
  handle: () => setCodeVisibility(true, "markdown"),
601
597
  redundant: true,
602
598
  },
603
- {
604
- icon: <ChevronsUpDownIcon size={14} strokeWidth={1.5} />,
605
- label: "Expand all outputs",
606
- hotkey: "global.expandAllOutputs",
607
- hidden: viewState.mode !== "edit",
608
- handle: () => setOutputsExpanded(true),
609
- redundant: true,
610
- },
611
- {
612
- icon: <ChevronsDownUpIcon size={14} strokeWidth={1.5} />,
613
- label: "Clamp all outputs",
614
- hotkey: "global.clampAllOutputs",
615
- hidden: viewState.mode !== "edit",
616
- handle: () => setOutputsExpanded(false),
617
- redundant: true,
618
- },
619
599
  {
620
600
  icon: <ChevronRightCircleIcon size={14} strokeWidth={1.5} />,
621
601
  label: "Collapse all sections",
@@ -23,7 +23,6 @@ import {
23
23
  useRunStaleCells,
24
24
  } from "../components/editor/cell/useRunCells";
25
25
  import { useSetCodeVisibility } from "../components/editor/actions/useSetCodeVisibility";
26
- import { useSetOutputsExpanded } from "../components/editor/actions/useSetOutputsExpanded";
27
26
  import { CellArray } from "../components/editor/renderers/cell-array";
28
27
  import { CellsRenderer } from "../components/editor/renderers/cells-renderer";
29
28
  import { useHotkey } from "../hooks/useHotkey";
@@ -116,7 +115,6 @@ export const EditApp: React.FC<AppProps> = ({
116
115
  const runAllCells = useRunAllCells();
117
116
  const togglePresenting = useTogglePresenting();
118
117
  const setCodeVisibility = useSetCodeVisibility();
119
- const setOutputsExpanded = useSetOutputsExpanded();
120
118
 
121
119
  // HOTKEYS
122
120
  useHotkey("global.runStale", () => {
@@ -143,20 +141,6 @@ export const EditApp: React.FC<AppProps> = ({
143
141
  useHotkey("global.hideAllMarkdownCode", () => {
144
142
  setCodeVisibility(true, "markdown");
145
143
  });
146
- useHotkey(
147
- "global.expandAllOutputs",
148
- () => {
149
- setOutputsExpanded(true);
150
- },
151
- { disabled: !isEditing },
152
- );
153
- useHotkey(
154
- "global.clampAllOutputs",
155
- () => {
156
- setOutputsExpanded(false);
157
- },
158
- { disabled: !isEditing },
159
- );
160
144
  useHotkey("global.collapseAllSections", () => {
161
145
  collapseAllCells();
162
146
  });
@@ -389,18 +389,6 @@ const DEFAULT_HOT_KEY = {
389
389
  group: "Editing",
390
390
  key: NOT_SET,
391
391
  },
392
- "global.expandAllOutputs": {
393
- name: "Expand all outputs",
394
- group: "Editing",
395
- key: NOT_SET,
396
- additionalKeywords: ["show full output", "unclamp"],
397
- },
398
- "global.clampAllOutputs": {
399
- name: "Clamp all outputs",
400
- group: "Editing",
401
- key: NOT_SET,
402
- additionalKeywords: ["collapse outputs", "shrink outputs"],
403
- },
404
392
  "global.collapseAllSections": {
405
393
  name: "Collapse all sections",
406
394
  group: "Editing",
@@ -1,6 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import { type LucideIcon, ChevronRightIcon, CornerLeftUp } from "lucide-react";
3
+ import { type LucideIcon, CornerLeftUp } from "lucide-react";
4
4
  import { type JSX, useEffect, useLayoutEffect, useRef, useState } from "react";
5
5
  import { z } from "zod";
6
6
  import {
@@ -12,6 +12,7 @@ import { Spinner } from "@/components/icons/spinner";
12
12
  import { Button } from "@/components/ui/button";
13
13
  import { Checkbox } from "@/components/ui/checkbox";
14
14
  import { Label } from "@/components/ui/label";
15
+ import { NativeSelect } from "@/components/ui/native-select";
15
16
  import { Table, TableBody, TableCell, TableRow } from "@/components/ui/table";
16
17
  import { toast } from "@/components/ui/use-toast";
17
18
  import { RANDOM_ID_ATTR } from "@/core/dom/ui-element-constants";
@@ -471,19 +472,12 @@ export const FileBrowser = ({
471
472
  //
472
473
  // Assumes that path contains at least one delimiter, which is true
473
474
  // only if this is an absolute path.
474
- const { protocol, parentDirectories } = getProtocolAndParentDirectories({
475
+ const { parentDirectories } = getProtocolAndParentDirectories({
475
476
  path,
476
477
  delimiter,
477
478
  initialPath,
478
479
  restrictNavigation,
479
480
  });
480
- const breadcrumbs = parentDirectories.toReversed().map((dir) => ({
481
- path: dir,
482
- name:
483
- dir === protocol
484
- ? protocol
485
- : (dir.split(delimiter).findLast(Boolean) ?? dir),
486
- }));
487
481
 
488
482
  const selectionKindLabel =
489
483
  selectionMode === "all"
@@ -521,42 +515,18 @@ export const FileBrowser = ({
521
515
  <div>
522
516
  {error && <Banner kind="danger">{error.message}</Banner>}
523
517
  {renderHeader()}
524
- <nav aria-label="Current directory" className="mt-2">
525
- <ol className="flex flex-wrap items-center gap-0.5 text-sm">
526
- {breadcrumbs.map((crumb, index) => {
527
- const isCurrent = index === breadcrumbs.length - 1;
528
- return (
529
- <li key={crumb.path} className="flex items-center gap-0.5">
530
- {index > 0 && (
531
- <ChevronRightIcon
532
- size={14}
533
- className="text-muted-foreground shrink-0"
534
- aria-hidden={true}
535
- />
536
- )}
537
- <button
538
- type="button"
539
- title={crumb.path}
540
- aria-current={isCurrent ? "page" : undefined}
541
- onClick={() => {
542
- if (!isCurrent) {
543
- setNewPath(crumb.path);
544
- }
545
- }}
546
- className={cn(
547
- "rounded px-1 focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring",
548
- isCurrent
549
- ? "font-medium cursor-default"
550
- : "text-muted-foreground hover:bg-accent hover:text-foreground",
551
- )}
552
- >
553
- {crumb.name}
554
- </button>
555
- </li>
556
- );
557
- })}
558
- </ol>
559
- </nav>
518
+ <NativeSelect
519
+ className="mt-2 w-full"
520
+ placeholder={path}
521
+ value={path}
522
+ onChange={(e) => setNewPath(e.target.value)}
523
+ >
524
+ {parentDirectories.map((dir) => (
525
+ <option value={dir} key={dir}>
526
+ {dir}
527
+ </option>
528
+ ))}
529
+ </NativeSelect>
560
530
 
561
531
  {data && typeof data.total_count === "number" && (
562
532
  <div className="text-xs text-muted-foreground mt-1 px-1">
@@ -1,12 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import {
4
- fireEvent,
5
- render,
6
- screen,
7
- waitFor,
8
- within,
9
- } from "@testing-library/react";
3
+ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
10
4
  import { beforeAll, describe, expect, it, vi } from "vitest";
11
5
  import { SetupMocks } from "@/__mocks__/common";
12
6
  import { initialModeAtom } from "@/core/mode";
@@ -193,7 +187,7 @@ describe("FileBrowserPlugin keyboard accessibility", () => {
193
187
  const docsRow = docs.closest('[role="row"]')!;
194
188
  fireEvent.keyDown(docsRow, { key: "ArrowDown" }); // move active off the parent
195
189
  fireEvent.click(docs); // navigate into "docs"
196
- await within(screen.getByRole("grid")).findByText("docs"); // listing reloads (mock returns same files)
190
+ await screen.findByText("docs"); // listing reloads (mock returns same files)
197
191
  const rows = screen.getAllByRole("row");
198
192
  expect(rows[0]).toHaveAttribute("tabindex", "0");
199
193
  // the focused row must match the only tabbable row
@@ -367,80 +361,3 @@ describe("FileBrowserPlugin keyboard accessibility", () => {
367
361
  function rowFor(name: string): HTMLElement {
368
362
  return screen.getByText(name).closest('[role="row"]') as HTMLElement;
369
363
  }
370
-
371
- describe("FileBrowserPlugin breadcrumbs", () => {
372
- function breadcrumbs() {
373
- return within(
374
- screen.getByRole("navigation", { name: "Current directory" }),
375
- );
376
- }
377
-
378
- it("renders a crumb per ancestor with the current directory last", async () => {
379
- renderBrowser();
380
- await screen.findByText("docs");
381
- const items = breadcrumbs().getAllByRole("listitem");
382
- expect(items.map((li) => li.textContent)).toEqual(["/", "home", "user"]);
383
- expect(breadcrumbs().getByRole("button", { name: "user" })).toHaveAttribute(
384
- "aria-current",
385
- "page",
386
- );
387
- expect(
388
- breadcrumbs().getByRole("button", { name: "home" }),
389
- ).not.toHaveAttribute("aria-current");
390
- });
391
-
392
- it("keeps focus on a crumb after navigating to it", async () => {
393
- const { listDirectory } = renderBrowser();
394
- await screen.findByText("docs");
395
- const home = breadcrumbs().getByRole("button", { name: "home" });
396
- home.focus();
397
- fireEvent.click(home);
398
- await waitFor(() =>
399
- expect(listDirectory).toHaveBeenLastCalledWith({ path: "/home" }),
400
- );
401
- const current = breadcrumbs().getByRole("button", { name: "home" });
402
- expect(current).toHaveAttribute("aria-current", "page");
403
- expect(current).toBe(home);
404
- expect(current).toHaveFocus();
405
- });
406
-
407
- it("does not reload when the current crumb is clicked", async () => {
408
- const { listDirectory } = renderBrowser();
409
- await screen.findByText("docs");
410
- fireEvent.click(breadcrumbs().getByRole("button", { name: "user" }));
411
- expect(listDirectory).toHaveBeenCalledTimes(1);
412
- });
413
-
414
- it("navigates to an ancestor when a crumb is clicked", async () => {
415
- const { listDirectory } = renderBrowser();
416
- await screen.findByText("docs");
417
- fireEvent.click(breadcrumbs().getByRole("button", { name: "home" }));
418
- await waitFor(() =>
419
- expect(listDirectory).toHaveBeenLastCalledWith({ path: "/home" }),
420
- );
421
- fireEvent.click(breadcrumbs().getByRole("button", { name: "/" }));
422
- await waitFor(() =>
423
- expect(listDirectory).toHaveBeenLastCalledWith({ path: "/" }),
424
- );
425
- });
426
-
427
- it("hides ancestors outside the initial path when navigation is restricted", async () => {
428
- render(
429
- <FileBrowser
430
- initialPath="/home/user"
431
- filetypes={[]}
432
- selectionMode="all"
433
- multiple={true}
434
- label={null}
435
- restrictNavigation={true}
436
- value={[]}
437
- setValue={vi.fn()}
438
- host={document.createElement("div")}
439
- list_directory={mockListDirectory(FILES)}
440
- />,
441
- );
442
- await screen.findByText("docs");
443
- const items = breadcrumbs().getAllByRole("listitem");
444
- expect(items.map((li) => li.textContent)).toEqual(["user"]);
445
- });
446
- });
@@ -1,42 +0,0 @@
1
- /* Copyright 2026 Marimo. All rights reserved. */
2
-
3
- import { describe, expect, it } from "vitest";
4
- import { MockNotebook } from "@/__mocks__/notebook";
5
- import type { OutputMessage } from "@/core/kernel/messages";
6
- import { outputExpansionConfigs } from "../useSetOutputsExpanded";
7
-
8
- const output: OutputMessage = {
9
- channel: "output",
10
- mimetype: "text/plain",
11
- data: "hello",
12
- timestamp: 0,
13
- };
14
-
15
- describe("outputExpansionConfigs", () => {
16
- const [withOutput, withoutOutput, expanded, expandedWithoutOutput] =
17
- MockNotebook.cellIds();
18
- const notebook = MockNotebook.notebookState({
19
- cellData: {
20
- [withOutput]: {},
21
- [withoutOutput]: {},
22
- [expanded]: { config: { expand_output: true } },
23
- [expandedWithoutOutput]: { config: { expand_output: true } },
24
- },
25
- cellRuntime: {
26
- [withOutput]: { output },
27
- [expanded]: { output },
28
- },
29
- });
30
-
31
- it("expands clamped cells with output and skips cells without output", () => {
32
- expect(outputExpansionConfigs(notebook, true)).toEqual({
33
- [withOutput]: { expand_output: true },
34
- });
35
- });
36
-
37
- it("clamps expanded cells with output and skips cells without output", () => {
38
- expect(outputExpansionConfigs(notebook, false)).toEqual({
39
- [expanded]: { expand_output: false },
40
- });
41
- });
42
- });
@@ -1,67 +0,0 @@
1
- /* Copyright 2026 Marimo. All rights reserved. */
2
-
3
- import { useCallback } from "react";
4
- import {
5
- getNotebook,
6
- type NotebookState,
7
- useCellActions,
8
- } from "@/core/cells/cells";
9
- import type { CellId } from "@/core/cells/ids";
10
- import { isOutputEmpty } from "@/core/cells/outputs";
11
- import { useRequestClient } from "@/core/network/requests";
12
- import type { CellConfig } from "@/core/network/types";
13
- import { Objects } from "@/utils/objects";
14
-
15
- /**
16
- * The `expand_output` config changes needed to expand or clamp every output.
17
- *
18
- * Both actions skip cells without output, so their source isn't annotated
19
- * with a config that has no effect.
20
- */
21
- export function outputExpansionConfigs(
22
- notebook: NotebookState,
23
- expanded: boolean,
24
- ): Record<CellId, Partial<CellConfig>> {
25
- const configs: Record<CellId, Partial<CellConfig>> = {};
26
- for (const cellId of notebook.cellIds.inOrderIds) {
27
- const cell = notebook.cellData[cellId];
28
- if (
29
- cell === undefined ||
30
- (cell.config.expand_output ?? false) === expanded
31
- ) {
32
- continue;
33
- }
34
- if (isOutputEmpty(notebook.cellRuntime[cellId]?.output)) {
35
- continue;
36
- }
37
- configs[cellId] = { expand_output: expanded };
38
- }
39
- return configs;
40
- }
41
-
42
- /**
43
- * Hook returning a callback that shows every cell's output in full, or clamps
44
- * every output to a fixed height, by setting each cell's `expand_output` config.
45
- */
46
- export const useSetOutputsExpanded = () => {
47
- const { updateCellConfig } = useCellActions();
48
- const { saveCellConfig } = useRequestClient();
49
-
50
- return useCallback(
51
- async (expanded: boolean) => {
52
- const newConfigs = outputExpansionConfigs(getNotebook(), expanded);
53
-
54
- const entries = Objects.entries(newConfigs);
55
- if (entries.length === 0) {
56
- return;
57
- }
58
-
59
- await saveCellConfig({ configs: newConfigs });
60
-
61
- for (const [cellId, config] of entries) {
62
- updateCellConfig({ cellId, config });
63
- }
64
- },
65
- [updateCellConfig, saveCellConfig],
66
- );
67
- };