@marimo-team/frontend 0.25.3-dev96 → 0.25.3-dev98

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 (90) hide show
  1. package/dist/assets/{CellStatus-Dc8AR1al.js → CellStatus-fK4n2NPc.js} +1 -1
  2. package/dist/assets/{ErrorBoundary-DBQW23V4.js → ErrorBoundary-CAEGdoFW.js} +2 -2
  3. package/dist/assets/{JsonOutput-nLzWQ-0V.js → JsonOutput-CyAKmZDD.js} +1 -1
  4. package/dist/assets/{MarimoErrorOutput-DAFgeK_G.js → MarimoErrorOutput-CgZvP0p0.js} +1 -1
  5. package/dist/assets/{RenderHTML-DwolbpuI.js → RenderHTML-DQvxDDNS.js} +1 -1
  6. package/dist/assets/{RunButton-BN3_mnoU.js → RunButton-BBDnDL6G.js} +1 -1
  7. package/dist/assets/{add-cell-with-ai-CRbG5cTT.js → add-cell-with-ai-Clg5FELx.js} +1 -1
  8. package/dist/assets/{add-connection-dialog-CzCmVM_b.js → add-connection-dialog-BqdWmD-7.js} +1 -1
  9. package/dist/assets/{agent-panel-zpTxANfi.js → agent-panel-5RxG5Y82.js} +3 -3
  10. package/dist/assets/{ai-model-dropdown-DL56ImUU.js → ai-model-dropdown-Bvl1ktQq.js} +1 -1
  11. package/dist/assets/{app-config-button-BRBtaFi_.js → app-config-button-0QTeQ2Mv.js} +1 -1
  12. package/dist/assets/{blob-CuL-H1JC.js → blob-5VcB8K_t.js} +1 -1
  13. package/dist/assets/{cell-editor-C6QIY1Q-.js → cell-editor-Byw5y-oI.js} +1 -1
  14. package/dist/assets/{cell-link-C9tkvy6x.js → cell-link-C5yYyzuF.js} +1 -1
  15. package/dist/assets/{cells-B23_t5uX.js → cells-D_11MjVB.js} +13 -13
  16. package/dist/assets/{chat-display-DSezZ1qo.js → chat-display-BCR_ySiV.js} +1 -1
  17. package/dist/assets/{chat-panel-CocbwA2Q.js → chat-panel-RPRvBsaU.js} +1 -1
  18. package/dist/assets/{chat-ui-DXvDBccG.js → chat-ui-CGviVaRA.js} +2 -2
  19. package/dist/assets/{column-preview-BUQ_YMaE.js → column-preview-xe533-Cn.js} +1 -1
  20. package/dist/assets/{command-palette-HbIlNTLD.js → command-palette-BB9bWdWp.js} +1 -1
  21. package/dist/assets/{common-XXWicvmo.js → common-CaeItbcI.js} +1 -1
  22. package/dist/assets/{components-D1a5GeNf.js → components-G6frbw0c.js} +1 -1
  23. package/dist/assets/{datasource-Qo_t5PqI.js → datasource-deuXnlU-.js} +1 -1
  24. package/dist/assets/{dependency-graph-panel-DHrm4LUL.js → dependency-graph-panel-CIykLnJe.js} +1 -1
  25. package/dist/assets/{documentation-panel-BoNI3vXT.js → documentation-panel-2PQ8kQLa.js} +1 -1
  26. package/dist/assets/{download-Cm3InGht.js → download-dK52bLxZ.js} +1 -1
  27. package/dist/assets/{edit-page-BVkC2MyU.js → edit-page-C2phWLKH.js} +5 -5
  28. package/dist/assets/{error-entries-DEkB-8EY.js → error-entries-3GVk2KjS.js} +1 -1
  29. package/dist/assets/{error-panel-D7GInT--.js → error-panel-CzDRGPeC.js} +1 -1
  30. package/dist/assets/{feedback-button-sC38i-D1.js → feedback-button-C5NgWpFg.js} +1 -1
  31. package/dist/assets/feedback-button-CONwLFpw.js +1 -0
  32. package/dist/assets/{file-explorer-panel-2XFMubVM.js → file-explorer-panel-B50xDnTZ.js} +1 -1
  33. package/dist/assets/{file-name-input-DPs3KKM-.js → file-name-input-DqwMSgGU.js} +1 -1
  34. package/dist/assets/{floating-outline-C7MSAu6q.js → floating-outline-ChmAuvxz.js} +1 -1
  35. package/dist/assets/{gallery-page-B3fJlerH.js → gallery-page-CiL8aMS1.js} +1 -1
  36. package/dist/assets/{glide-data-editor-DrhzXms_.js → glide-data-editor-CqRclBkp.js} +1 -1
  37. package/dist/assets/{home-page-CajAhF9Q.js → home-page-BgZVl4dP.js} +1 -1
  38. package/dist/assets/{hooks-DteA-neM.js → hooks-DM5n7Osw.js} +1 -1
  39. package/dist/assets/{index-YQHSwyF3.js → index-vCxv6WVQ.js} +18 -18
  40. package/dist/assets/{layout-DEFRD3k3.js → layout-BpP8nTjb.js} +4 -4
  41. package/dist/assets/{logs-panel-BpM3pLdf.js → logs-panel-B5eVAZtH.js} +1 -1
  42. package/dist/assets/{markdown-renderer-C5aIPuRT.js → markdown-renderer-BWUzqkJM.js} +1 -1
  43. package/dist/assets/{name-cell-input-Dd8oSXnd.js → name-cell-input-DXW68gRW.js} +1 -1
  44. package/dist/assets/{outline-panel-kFr3Fo2d.js → outline-panel-DPxJhJ_A.js} +1 -1
  45. package/dist/assets/{packages-panel-Ce_wBuIJ.js → packages-panel-gBE2FWQr.js} +1 -1
  46. package/dist/assets/{panel-accordion-state-BO2rN4A5.js → panel-accordion-state-CCF5Gxnc.js} +1 -1
  47. package/dist/assets/{panels-Cy18qaTN.js → panels-BQYMF6p_.js} +1 -1
  48. package/dist/assets/{process-output-CDhnnF3f.js → process-output-Cw9IDcKQ.js} +1 -1
  49. package/dist/assets/{readonly-code-display-ChOK6mhE.js → readonly-code-display-DYcZQ28T.js} +1 -1
  50. package/dist/assets/{readonly-python-code-CVwB1OHZ.js → readonly-python-code-RFuQP50v.js} +1 -1
  51. package/dist/assets/{reveal-component-DE-4w0ik.js → reveal-component-yRrDmCQz.js} +2 -2
  52. package/dist/assets/{run-page-C6qwGqj6.js → run-page-CY65WUOu.js} +1 -1
  53. package/dist/assets/{runtime-details-state-BRSVs8um.js → runtime-details-state-pobtu6TO.js} +1 -1
  54. package/dist/assets/scratchpad-panel-H44_pvb_.js +1 -0
  55. package/dist/assets/{session-panel-B0CkZ3wl.js → session-panel-Bnd1iXkO.js} +1 -1
  56. package/dist/assets/{snippets-panel-CN-U1niV.js → snippets-panel-DKApxKx9.js} +1 -1
  57. package/dist/assets/{state-BRL89qqy.js → state-Bl9BiY_s.js} +1 -1
  58. package/dist/assets/{state-BoRCcWOg.js → state-Dv059B3A.js} +1 -1
  59. package/dist/assets/{tracing-CqxmObxN.js → tracing-Clwy4SlW.js} +1 -1
  60. package/dist/assets/{tracing-panel-Bn8xJSPi.js → tracing-panel-BwjLG_aC.js} +2 -2
  61. package/dist/assets/{tree-actions-DoPCJTpj.js → tree-actions-BZNTQ12N.js} +1 -1
  62. package/dist/assets/{useAddCell-DKb7o70l.js → useAddCell-Cjuqk2YR.js} +1 -1
  63. package/dist/assets/{useCellActionButton-CSNFulkR.js → useCellActionButton-MoWLvuGe.js} +1 -1
  64. package/dist/assets/{useDeleteCell-BPQ6Xcbj.js → useDeleteCell-BC-MW7d1.js} +1 -1
  65. package/dist/assets/{useDependencyPanelTab-4SMlwjEg.js → useDependencyPanelTab-CZU7i-B3.js} +1 -1
  66. package/dist/assets/{useNotebookActions-B4kq9-P4.js → useNotebookActions-wFxVdRXQ.js} +1 -1
  67. package/dist/assets/{useRunCells-BV6nl_Ok.js → useRunCells-ByaWxoIt.js} +1 -1
  68. package/dist/assets/{useSplitCell-Ca364Rrx.js → useSplitCell-YJIystwv.js} +1 -1
  69. package/dist/index.html +20 -20
  70. package/package.json +1 -1
  71. package/src/components/chat/acp/blocks.tsx +2 -2
  72. package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
  73. package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
  74. package/src/components/data-table/charts/charts.tsx +21 -6
  75. package/src/components/data-table/charts/storage.ts +16 -5
  76. package/src/components/editor/output/ansi-reduce.ts +6 -0
  77. package/src/components/editor/output/console/ConsoleOutput.tsx +11 -7
  78. package/src/components/editor/package-alert.tsx +4 -4
  79. package/src/components/scratchpad/scratchpad.tsx +2 -2
  80. package/src/components/slides/reveal-component.tsx +4 -2
  81. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -0
  82. package/src/core/cells/__tests__/cell.test.ts +39 -0
  83. package/src/core/cells/__tests__/cells.test.ts +3 -1
  84. package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
  85. package/src/core/cells/cell.ts +14 -3
  86. package/src/core/cells/cells.ts +1 -0
  87. package/src/core/cells/types.ts +10 -1
  88. package/src/plugins/impl/chat/chat-ui.tsx +1 -1
  89. package/dist/assets/feedback-button-Cz9BdS49.js +0 -1
  90. package/dist/assets/scratchpad-panel--SxH2dnk.js +0 -1
@@ -1 +1 @@
1
- import{f as e,t,u as n}from"./useEvent-BDjgaBtz.js";import{D as r,da as i,dt as a,h as o,ia as s,ri as c}from"./cells-B23_t5uX.js";import{t as l}from"./compiler-runtime-BrajqUja.js";import{g as u}from"./useEventListener-CjDeLqFC.js";import{o as d}from"./dist-qhAY4L2r.js";import{r as f}from"./requests-BIFR-h4M.js";var p=l(),m=e(!1);function h(){let e=(0,p.c)(2),n=v(),r;return e[0]===n?r=e[1]:(r=()=>n(i(o())),e[0]=n,e[1]=r),t(r)}function g(e){let n=(0,p.c)(3),r=v(),i;return n[0]!==e||n[1]!==r?(i=()=>{e!==void 0&&r([e])},n[0]=e,n[1]=r,n[2]=i):i=n[2],t(i)}function _(){let e=(0,p.c)(2),n=v(),r;return e[0]===n?r=e[1]:(r=()=>n(s(o())),e[0]=n,e[1]=r),t(r)}function v(){let e=(0,p.c)(4),{prepareForRun:i}=r(),{sendRun:a}=f(),s=n(m),c;return e[0]!==i||e[1]!==a||e[2]!==s?(c=async e=>{if(e.length===0)return;let t=o();return s(!0),y({cellIds:e,sendRun:a,prepareForRun:i,notebook:t})},e[0]=i,e[1]=a,e[2]=s,e[3]=c):c=e[3],t(c)}async function y({cellIds:e,sendRun:t,prepareForRun:n,notebook:r}){if(e.length===0)return;let{cellHandles:i,cellData:o}=r,s=[];for(let t of e){let e=i[t]?.current?.editorView,r;e?(c(e)!==`markdown`&&d(e),r=a(e)):r=o[t]?.code||``,s.push(r),n({cellId:t})}await t({cellIds:e,codes:s}).catch(e=>{u.error(e)})}export{v as a,g as i,y as n,h as o,_ as r,m as t};
1
+ import{f as e,t,u as n}from"./useEvent-BDjgaBtz.js";import{D as r,da as i,dt as a,h as o,ia as s,ri as c}from"./cells-D_11MjVB.js";import{t as l}from"./compiler-runtime-BrajqUja.js";import{g as u}from"./useEventListener-CjDeLqFC.js";import{o as d}from"./dist-qhAY4L2r.js";import{r as f}from"./requests-BIFR-h4M.js";var p=l(),m=e(!1);function h(){let e=(0,p.c)(2),n=v(),r;return e[0]===n?r=e[1]:(r=()=>n(i(o())),e[0]=n,e[1]=r),t(r)}function g(e){let n=(0,p.c)(3),r=v(),i;return n[0]!==e||n[1]!==r?(i=()=>{e!==void 0&&r([e])},n[0]=e,n[1]=r,n[2]=i):i=n[2],t(i)}function _(){let e=(0,p.c)(2),n=v(),r;return e[0]===n?r=e[1]:(r=()=>n(s(o())),e[0]=n,e[1]=r),t(r)}function v(){let e=(0,p.c)(4),{prepareForRun:i}=r(),{sendRun:a}=f(),s=n(m),c;return e[0]!==i||e[1]!==a||e[2]!==s?(c=async e=>{if(e.length===0)return;let t=o();return s(!0),y({cellIds:e,sendRun:a,prepareForRun:i,notebook:t})},e[0]=i,e[1]=a,e[2]=s,e[3]=c):c=e[3],t(c)}async function y({cellIds:e,sendRun:t,prepareForRun:n,notebook:r}){if(e.length===0)return;let{cellHandles:i,cellData:o}=r,s=[];for(let t of e){let e=i[t]?.current?.editorView,r;e?(c(e)!==`markdown`&&d(e),r=a(e)):r=o[t]?.code||``,s.push(r),n({cellId:t})}await t({cellIds:e,codes:s}).catch(e=>{u.error(e)})}export{v as a,g as i,y as n,h as o,_ as r,m as t};
@@ -1 +1 @@
1
- import{t as e}from"./useEvent-BDjgaBtz.js";import{D as t,dt as n,f as r}from"./cells-B23_t5uX.js";import{t as i}from"./compiler-runtime-BrajqUja.js";import{t as a}from"./jsx-runtime-B74pBk57.js";import{r as o}from"./useDeleteCell-BPQ6Xcbj.js";import{t as s}from"./use-toast-Wu434mLr.js";var c=i(),l=a();function u(){let i=(0,c.c)(3),{splitCell:a,undoSplitCell:u}=t(),d;return i[0]!==a||i[1]!==u?(d=e=>{let t=r(e.cellId);if(!t)return;let i=n(t);a(e);let{dismiss:c}=s({title:`Cell split`,action:(0,l.jsx)(o,{"data-testid":`undo-split-button`,size:`sm`,variant:`outline`,onClick:()=>{u({...e,snapshot:i}),d()},children:`Undo`})}),d=c},i[0]=a,i[1]=u,i[2]=d):d=i[2],e(d)}export{u as t};
1
+ import{t as e}from"./useEvent-BDjgaBtz.js";import{D as t,dt as n,f as r}from"./cells-D_11MjVB.js";import{t as i}from"./compiler-runtime-BrajqUja.js";import{t as a}from"./jsx-runtime-B74pBk57.js";import{r as o}from"./useDeleteCell-BC-MW7d1.js";import{t as s}from"./use-toast-Wu434mLr.js";var c=i(),l=a();function u(){let i=(0,c.c)(3),{splitCell:a,undoSplitCell:u}=t(),d;return i[0]!==a||i[1]!==u?(d=e=>{let t=r(e.cellId);if(!t)return;let i=n(t);a(e);let{dismiss:c}=s({title:`Cell split`,action:(0,l.jsx)(o,{"data-testid":`undo-split-button`,size:`sm`,variant:`outline`,onClick:()=>{u({...e,snapshot:i}),d()},children:`Undo`})}),d=c},i[0]=a,i[1]=u,i[2]=d):d=i[2],e(d)}export{u as t};
package/dist/index.html CHANGED
@@ -66,7 +66,7 @@
66
66
  <marimo-server-token data-token="{{ server_token }}" hidden></marimo-server-token>
67
67
  <!-- /TODO -->
68
68
  <title>{{ title }}</title>
69
- <script type="module" crossorigin src="./assets/index-YQHSwyF3.js"></script>
69
+ <script type="module" crossorigin src="./assets/index-vCxv6WVQ.js"></script>
70
70
  <link rel="modulepreload" crossorigin href="./assets/rolldown-runtime-B0Z9INg1.js">
71
71
  <link rel="modulepreload" crossorigin href="./assets/react-DVplv7_D.js">
72
72
  <link rel="modulepreload" crossorigin href="./assets/compiler-runtime-BrajqUja.js">
@@ -139,7 +139,7 @@
139
139
  <link rel="modulepreload" crossorigin href="./assets/useTheme-BAA27lh7.js">
140
140
  <link rel="modulepreload" crossorigin href="./assets/useAsyncData-qvoPYHtx.js">
141
141
  <link rel="modulepreload" crossorigin href="./assets/purify.es--06brOip.js">
142
- <link rel="modulepreload" crossorigin href="./assets/cells-B23_t5uX.js">
142
+ <link rel="modulepreload" crossorigin href="./assets/cells-D_11MjVB.js">
143
143
  <link rel="modulepreload" crossorigin href="./assets/coerce-DWjFeXOY.js">
144
144
  <link rel="modulepreload" crossorigin href="./assets/get-DjNf4SIX.js">
145
145
  <link rel="modulepreload" crossorigin href="./assets/_hasPath-BmRQipI0.js">
@@ -154,40 +154,40 @@
154
154
  <link rel="modulepreload" crossorigin href="./assets/copy-KlhazlhB.js">
155
155
  <link rel="modulepreload" crossorigin href="./assets/micromark-factory-space-D9Dr-k4J.js">
156
156
  <link rel="modulepreload" crossorigin href="./assets/chunk-YOKDWASO-BIpRENEC.js">
157
- <link rel="modulepreload" crossorigin href="./assets/markdown-renderer-C5aIPuRT.js">
157
+ <link rel="modulepreload" crossorigin href="./assets/markdown-renderer-BWUzqkJM.js">
158
158
  <link rel="modulepreload" crossorigin href="./assets/copy-Djr5m5ac.js">
159
159
  <link rel="modulepreload" crossorigin href="./assets/copy-icon-8-a5vovc.js">
160
- <link rel="modulepreload" crossorigin href="./assets/useRunCells-BV6nl_Ok.js">
161
- <link rel="modulepreload" crossorigin href="./assets/RenderHTML-DwolbpuI.js">
162
- <link rel="modulepreload" crossorigin href="./assets/blob-CuL-H1JC.js">
160
+ <link rel="modulepreload" crossorigin href="./assets/useRunCells-ByaWxoIt.js">
161
+ <link rel="modulepreload" crossorigin href="./assets/RenderHTML-DQvxDDNS.js">
162
+ <link rel="modulepreload" crossorigin href="./assets/blob-5VcB8K_t.js">
163
163
  <link rel="modulepreload" crossorigin href="./assets/kbd-pdKBv96t.js">
164
164
  <link rel="modulepreload" crossorigin href="./assets/useInstallPackage-wcDq9hYT.js">
165
165
  <link rel="modulepreload" crossorigin href="./assets/share-BZW3tzEX.js">
166
166
  <link rel="modulepreload" crossorigin href="./assets/events-CbeVJ6OD.js">
167
- <link rel="modulepreload" crossorigin href="./assets/state-BRL89qqy.js">
168
- <link rel="modulepreload" crossorigin href="./assets/ErrorBoundary-DBQW23V4.js">
167
+ <link rel="modulepreload" crossorigin href="./assets/state-Bl9BiY_s.js">
168
+ <link rel="modulepreload" crossorigin href="./assets/ErrorBoundary-CAEGdoFW.js">
169
169
  <link rel="modulepreload" crossorigin href="./assets/chevron-right-eAtVhbNZ.js">
170
170
  <link rel="modulepreload" crossorigin href="./assets/dropdown-menu-DS6umAnH.js">
171
171
  <link rel="modulepreload" crossorigin href="./assets/html-to-image-D_0rd3_B.js">
172
- <link rel="modulepreload" crossorigin href="./assets/download-Cm3InGht.js">
172
+ <link rel="modulepreload" crossorigin href="./assets/download-dK52bLxZ.js">
173
173
  <link rel="modulepreload" crossorigin href="./assets/switch-DYjBfpNJ.js">
174
174
  <link rel="modulepreload" crossorigin href="./assets/tabs-CY8E4r9U.js">
175
175
  <link rel="modulepreload" crossorigin href="./assets/table-DG7Ap4H4.js">
176
176
  <link rel="modulepreload" crossorigin href="./assets/eye-off-CxVozGAC.js">
177
177
  <link rel="modulepreload" crossorigin href="./assets/refresh-cw-Qw1f8Jhy.js">
178
- <link rel="modulepreload" crossorigin href="./assets/tree-actions-DoPCJTpj.js">
178
+ <link rel="modulepreload" crossorigin href="./assets/tree-actions-BZNTQ12N.js">
179
179
  <link rel="modulepreload" crossorigin href="./assets/ellipsis-63DyBLHQ.js">
180
180
  <link rel="modulepreload" crossorigin href="./assets/external-link-UrX9KO36.js">
181
181
  <link rel="modulepreload" crossorigin href="./assets/spinner-DyNE-o8o.js">
182
182
  <link rel="modulepreload" crossorigin href="./assets/message-circle-C3rKm8_a.js">
183
183
  <link rel="modulepreload" crossorigin href="./assets/hat-glasses-C8RhSVii.js">
184
184
  <link rel="modulepreload" crossorigin href="./assets/package-GSoSTiIK.js">
185
- <link rel="modulepreload" crossorigin href="./assets/datasource-Qo_t5PqI.js">
186
- <link rel="modulepreload" crossorigin href="./assets/error-entries-DEkB-8EY.js">
185
+ <link rel="modulepreload" crossorigin href="./assets/datasource-deuXnlU-.js">
186
+ <link rel="modulepreload" crossorigin href="./assets/error-entries-3GVk2KjS.js">
187
187
  <link rel="modulepreload" crossorigin href="./assets/alert-DTaqCu_d.js">
188
- <link rel="modulepreload" crossorigin href="./assets/state-BoRCcWOg.js">
189
- <link rel="modulepreload" crossorigin href="./assets/cell-link-C9tkvy6x.js">
190
- <link rel="modulepreload" crossorigin href="./assets/MarimoErrorOutput-DAFgeK_G.js">
188
+ <link rel="modulepreload" crossorigin href="./assets/state-Dv059B3A.js">
189
+ <link rel="modulepreload" crossorigin href="./assets/cell-link-C5yYyzuF.js">
190
+ <link rel="modulepreload" crossorigin href="./assets/MarimoErrorOutput-CgZvP0p0.js">
191
191
  <link rel="modulepreload" crossorigin href="./assets/useDateFormatter-DA-62E-Y.js">
192
192
  <link rel="modulepreload" crossorigin href="./assets/en-US-Buu61juQ.js">
193
193
  <link rel="modulepreload" crossorigin href="./assets/isValid-q_Ad80ug.js">
@@ -207,7 +207,7 @@
207
207
  <link rel="modulepreload" crossorigin href="./assets/table-vrvqpuKJ.js">
208
208
  <link rel="modulepreload" crossorigin href="./assets/react-resizable-panels.browser.esm-Dbe0MrFr.js">
209
209
  <link rel="modulepreload" crossorigin href="./assets/useStateForKey-CGMJQT8x.js">
210
- <link rel="modulepreload" crossorigin href="./assets/JsonOutput-nLzWQ-0V.js">
210
+ <link rel="modulepreload" crossorigin href="./assets/JsonOutput-CyAKmZDD.js">
211
211
  <link rel="modulepreload" crossorigin href="./assets/chart-no-axes-column-C4_v6fQW.js">
212
212
  <link rel="modulepreload" crossorigin href="./assets/square-function-_W_Lo0P4.js">
213
213
  <link rel="modulepreload" crossorigin href="./assets/spec-uCpVvaAR.js">
@@ -221,11 +221,11 @@
221
221
  <link rel="modulepreload" crossorigin href="./assets/file-icons-CdJgUy-I.js">
222
222
  <link rel="modulepreload" crossorigin href="./assets/globe-UdPdIbF7.js">
223
223
  <link rel="modulepreload" crossorigin href="./assets/esm-CI_o7NhW.js">
224
- <link rel="modulepreload" crossorigin href="./assets/useAddCell-DKb7o70l.js">
225
- <link rel="modulepreload" crossorigin href="./assets/readonly-python-code-CVwB1OHZ.js">
224
+ <link rel="modulepreload" crossorigin href="./assets/useAddCell-Cjuqk2YR.js">
225
+ <link rel="modulepreload" crossorigin href="./assets/readonly-python-code-RFuQP50v.js">
226
226
  <link rel="modulepreload" crossorigin href="./assets/data-grid-types-DgHVN_Zz.js">
227
227
  <link rel="modulepreload" crossorigin href="./assets/glide-utils-HFqhvWHI.js">
228
- <link rel="modulepreload" crossorigin href="./assets/column-preview-BUQ_YMaE.js">
228
+ <link rel="modulepreload" crossorigin href="./assets/column-preview-xe533-Cn.js">
229
229
  <link rel="modulepreload" crossorigin href="./assets/square-BPmgQFnh.js">
230
230
  <link rel="modulepreload" crossorigin href="./assets/triangle-alert-DmIqR8sY.js">
231
231
  <link rel="modulepreload" crossorigin href="./assets/prop-types-Djf4O40e.js">
@@ -238,7 +238,7 @@
238
238
  <link rel="modulepreload" crossorigin href="./assets/useDeepCompareMemoize-B2DVK2De.js">
239
239
  <link rel="modulepreload" crossorigin href="./assets/useDelayElapsed-BlsDT4TV.js">
240
240
  <link rel="modulepreload" crossorigin href="./assets/pathUtils-DPmlLd-r.js">
241
- <link rel="modulepreload" crossorigin href="./assets/floating-outline-C7MSAu6q.js">
241
+ <link rel="modulepreload" crossorigin href="./assets/floating-outline-ChmAuvxz.js">
242
242
  <link rel="stylesheet" crossorigin href="./assets/cells-0PFKL3SH.css">
243
243
  <link rel="stylesheet" crossorigin href="./assets/markdown-renderer-DjIHoF9Z.css">
244
244
  <link rel="stylesheet" crossorigin href="./assets/JsonOutput-B0GmlMnR.css">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/frontend",
3
- "version": "0.25.3-dev96",
3
+ "version": "0.25.3-dev98",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -328,9 +328,9 @@ export const PlansBlock = (props: { data: PlanNotificationEvent[] }) => {
328
328
  </span>
329
329
  </div>
330
330
  <ul className="flex flex-col gap-1">
331
- {plans.map((item, index) => (
331
+ {plans.map((item) => (
332
332
  <li
333
- key={`${item.status}-${index}`}
333
+ key={item.content}
334
334
  className={`
335
335
  flex items-center gap-2 px-2 py-1 rounded
336
336
  `}
@@ -10,13 +10,27 @@ import { cellId } from "@/__tests__/branded";
10
10
  import { LazyVegaEmbed } from "@/components/charts/lazy";
11
11
  import { vegaLoader } from "@/plugins/impl/vega/loader";
12
12
  import { ChartPanel, TablePanel, type TablePanelProps } from "../charts";
13
- import { getChartTabName, tabsStorageAtom } from "../storage";
13
+ import { createTabId, getChartTabName, tabsStorageAtom } from "../storage";
14
14
  import { ChartType, NONE_VALUE } from "../types";
15
+ import { TOO_MANY_ROWS } from "../../types";
15
16
 
16
17
  vi.mock("@/components/charts/lazy", () => ({
17
18
  LazyVegaEmbed: vi.fn(() => null),
18
19
  }));
19
20
 
21
+ vi.mock("../components/chart-items", async (importOriginal) => ({
22
+ ...(await importOriginal<typeof import("../components/chart-items")>()),
23
+ ChartTypeSelect: ({
24
+ onValueChange,
25
+ }: {
26
+ onValueChange: (value: string) => void;
27
+ }) => (
28
+ <button type="button" onClick={() => onValueChange("line")}>
29
+ Change chart type
30
+ </button>
31
+ ),
32
+ }));
33
+
20
34
  beforeAll(() => {
21
35
  SetupMocks.resizeObserver();
22
36
  });
@@ -38,6 +52,7 @@ describe("ChartPanel", () => {
38
52
  id,
39
53
  [
40
54
  {
55
+ id: createTabId(),
41
56
  tabName,
42
57
  chartType: ChartType.BAR,
43
58
  config: {
@@ -283,4 +298,62 @@ describe("ChartPanel", () => {
283
298
  });
284
299
  },
285
300
  );
301
+ it("keeps panel state when a chart type change renames the tab", async () => {
302
+ const store = createStore();
303
+ const id = cellId("rename-keeps-state");
304
+ const tabName = getChartTabName(0, ChartType.BAR);
305
+ store.set(
306
+ tabsStorageAtom,
307
+ new Map([
308
+ [
309
+ id,
310
+ [
311
+ {
312
+ id: createTabId(),
313
+ tabName,
314
+ chartType: ChartType.BAR,
315
+ config: {
316
+ general: {
317
+ xColumn: { field: "value", type: "number" },
318
+ yColumn: {
319
+ field: "value",
320
+ type: "integer",
321
+ aggregate: NONE_VALUE,
322
+ },
323
+ },
324
+ },
325
+ },
326
+ ],
327
+ ],
328
+ ]),
329
+ );
330
+ const sample = [{ value: 1 }];
331
+ const props: TablePanelProps = {
332
+ cellId: id,
333
+ data: sample,
334
+ dataTable: <div />,
335
+ totalRows: TOO_MANY_ROWS,
336
+ columns: 1,
337
+ displayHeader: true,
338
+ fieldTypes: [["value", ["number", "float64"]]],
339
+ };
340
+ const { getByRole, findByRole, queryByRole } = render(
341
+ <Provider store={store}>
342
+ <Tooltip.Provider>
343
+ <TablePanel {...props} />
344
+ </Tooltip.Provider>
345
+ </Provider>,
346
+ );
347
+ fireEvent.click(getByRole("tab", { name: tabName }));
348
+ fireEvent.click(await findByRole("button", { name: "Proceed" }));
349
+ await waitFor(() => {
350
+ expect(queryByRole("button", { name: "Proceed" })).toBeNull();
351
+ });
352
+
353
+ fireEvent.click(getByRole("button", { name: "Change chart type" }));
354
+
355
+ const renamed = getChartTabName(0, ChartType.LINE);
356
+ await findByRole("tab", { name: renamed });
357
+ expect(queryByRole("button", { name: "Proceed" })).toBeNull();
358
+ });
286
359
  });
@@ -16,7 +16,7 @@ import { cellId } from "@/__tests__/branded";
16
16
  import { availableStorage } from "@/utils/storage/storage";
17
17
  import { ChartSchema } from "../schemas";
18
18
  import type { TabName } from "../storage";
19
- import { KEY, tabsStorageAtom } from "../storage";
19
+ import { createTabId, KEY, tabsStorageAtom } from "../storage";
20
20
  import { ChartType } from "../types";
21
21
 
22
22
  describe("Chart Transforms Storage", () => {
@@ -39,6 +39,7 @@ describe("Chart Transforms Storage", () => {
39
39
  const store = getDefaultStore();
40
40
  const cid = cellId("cell-1");
41
41
  const tabData = {
42
+ id: createTabId(),
42
43
  tabName: "Tab 1" as TabName,
43
44
  chartType: ChartType.LINE,
44
45
  config: ChartSchema.parse({
@@ -63,6 +64,7 @@ describe("Chart Transforms Storage", () => {
63
64
  const store = getDefaultStore();
64
65
  const cid = cellId("cell-1");
65
66
  const tabData1 = {
67
+ id: createTabId(),
66
68
  tabName: "Tab 1" as TabName,
67
69
  chartType: ChartType.LINE,
68
70
  config: ChartSchema.parse({
@@ -73,6 +75,7 @@ describe("Chart Transforms Storage", () => {
73
75
  }),
74
76
  };
75
77
  const tabData2 = {
78
+ id: createTabId(),
76
79
  tabName: "Tab 2" as TabName,
77
80
  chartType: ChartType.BAR,
78
81
  config: ChartSchema.parse({
@@ -48,7 +48,12 @@ import { HeatmapForm } from "./forms/heatmap";
48
48
  import { PieForm } from "./forms/pie";
49
49
  import { LazyChart } from "./lazy-chart";
50
50
  import { ChartSchema, type ChartSchemaType, getChartDefaults } from "./schemas";
51
- import { getChartTabName, type TabName, tabsStorageAtom } from "./storage";
51
+ import {
52
+ createTabId,
53
+ getChartTabName,
54
+ type TabName,
55
+ tabsStorageAtom,
56
+ } from "./storage";
52
57
  import { ChartType } from "./types";
53
58
 
54
59
  const NEW_CHART_TYPE = "bar" as ChartType;
@@ -114,7 +119,12 @@ export const TablePanel: React.FC<TablePanelProps> = ({
114
119
  const tabName = getChartTabName(0, NEW_CHART_TYPE);
115
120
  const newTabs = new Map(tabsMap);
116
121
  newTabs.set(cellId, [
117
- { tabName, chartType: NEW_CHART_TYPE, config: getChartDefaults() },
122
+ {
123
+ id: createTabId(),
124
+ tabName,
125
+ chartType: NEW_CHART_TYPE,
126
+ config: getChartDefaults(),
127
+ },
118
128
  ]);
119
129
  saveTabsMap(newTabs);
120
130
  setTabCounter(1);
@@ -135,6 +145,7 @@ export const TablePanel: React.FC<TablePanelProps> = ({
135
145
  newTabs.set(cellId, [
136
146
  ...tabs,
137
147
  {
148
+ id: createTabId(),
138
149
  tabName,
139
150
  chartType: NEW_CHART_TYPE,
140
151
  config: getChartDefaults(),
@@ -233,9 +244,9 @@ export const TablePanel: React.FC<TablePanelProps> = ({
233
244
  >
234
245
  Table
235
246
  </TabsTrigger>
236
- {tabs.map((tab, idx) => (
247
+ {tabs.map((tab) => (
237
248
  <TabsTrigger
238
- key={idx}
249
+ key={tab.id}
239
250
  className="text-xs"
240
251
  value={tab.tabName}
241
252
  onClick={() => setSelectedTab(tab.tabName)}
@@ -263,7 +274,7 @@ export const TablePanel: React.FC<TablePanelProps> = ({
263
274
  <TabsContent className="mt-1 overflow-hidden" value={DEFAULT_TAB_NAME}>
264
275
  {dataTable}
265
276
  </TabsContent>
266
- {tabs.map((tab, idx) => {
277
+ {tabs.map((tab) => {
267
278
  const saveChart = (formValues: ChartSchemaType) => {
268
279
  saveTabChart({
269
280
  tabName: tab.tabName,
@@ -275,7 +286,11 @@ export const TablePanel: React.FC<TablePanelProps> = ({
275
286
  saveTabChartType(tab.tabName, chartType);
276
287
  };
277
288
  return (
278
- <TabsContent key={idx} value={tab.tabName} className="h-[400px] mt-0">
289
+ <TabsContent
290
+ key={tab.id}
291
+ value={tab.tabName}
292
+ className="h-[400px] mt-0"
293
+ >
279
294
  <ChartPanel
280
295
  tableData={data}
281
296
  chartConfig={tab.config}
@@ -7,13 +7,16 @@ import { Logger } from "@/utils/Logger";
7
7
  import { NotebookScopedLocalStorage } from "@/utils/storage/typed";
8
8
  import { capitalize } from "@/utils/strings";
9
9
  import type { TypedString } from "@/utils/typed";
10
+ import { generateUUID } from "@/utils/uuid";
10
11
  import { ChartSchema, type ChartSchemaType } from "./schemas";
11
12
  import type { ChartType } from "./types";
12
13
 
13
14
  export type TabName = TypedString<"TabName">;
15
+ export type TabId = TypedString<"TabId">;
14
16
  export const KEY = "marimo:charts:v2";
15
17
 
16
18
  interface TabStorage {
19
+ id: TabId;
17
20
  tabName: TabName; // unique within cell
18
21
  chartType: ChartType;
19
22
  config: ChartSchemaType;
@@ -21,11 +24,15 @@ interface TabStorage {
21
24
 
22
25
  type TabStorageMap = Map<CellId, TabStorage[]>;
23
26
 
24
- const TabStorageSchema = z.object({
25
- tabName: z.string().transform((name) => name as TabName),
26
- chartType: z.string().transform((type) => type as ChartType),
27
- config: ChartSchema,
28
- });
27
+ const TabStorageSchema = z
28
+ .object({
29
+ id: z.string().optional(),
30
+ tabName: z.string().transform((name) => name as TabName),
31
+ chartType: z.string().transform((type) => type as ChartType),
32
+ config: ChartSchema,
33
+ })
34
+ // Stored tabs without an id use their name, which is unique within a cell.
35
+ .transform((tab) => ({ ...tab, id: (tab.id ?? tab.tabName) as TabId }));
29
36
  const TabStorageEntriesSchema = z.array(
30
37
  z.tuple([
31
38
  z.string().transform((name) => name as CellId),
@@ -64,6 +71,10 @@ export const tabsStorageAtom = atomWithStorage<TabStorageMap>(
64
71
  mapStorage,
65
72
  );
66
73
 
74
+ export function createTabId(): TabId {
75
+ return generateUUID() as TabId;
76
+ }
77
+
67
78
  /**
68
79
  * Convenience function to get the tab name for a given tab number and chart type
69
80
  */
@@ -358,6 +358,7 @@ export class AnsiReducer {
358
358
 
359
359
  export type StringOutputMessage = Omit<OutputMessage, "data"> & {
360
360
  data: string;
361
+ id?: number;
361
362
  };
362
363
 
363
364
  /**
@@ -369,6 +370,7 @@ export class StatefulOutputMessage implements OutputMessage {
369
370
  public readonly channel: OutputMessage["channel"];
370
371
  public readonly timestamp: OutputMessage["timestamp"];
371
372
  public readonly code: OutputMessage["code"];
373
+ public readonly id: StringOutputMessage["id"];
372
374
  private ansiReducer = new AnsiReducer();
373
375
  private _data: string;
374
376
 
@@ -385,6 +387,7 @@ export class StatefulOutputMessage implements OutputMessage {
385
387
  message.timestamp,
386
388
  ansiReducer,
387
389
  message.code,
390
+ message.id,
388
391
  );
389
392
  }
390
393
 
@@ -394,11 +397,13 @@ export class StatefulOutputMessage implements OutputMessage {
394
397
  timestamp: OutputMessage["timestamp"],
395
398
  ansiReducer: AnsiReducer,
396
399
  code: OutputMessage["code"],
400
+ id: StringOutputMessage["id"],
397
401
  ) {
398
402
  this.mimetype = mimetype;
399
403
  this.channel = channel;
400
404
  this.timestamp = timestamp;
401
405
  this.code = code;
406
+ this.id = id;
402
407
  this.ansiReducer = ansiReducer;
403
408
  this._data = this.ansiReducer.render();
404
409
  }
@@ -411,6 +416,7 @@ export class StatefulOutputMessage implements OutputMessage {
411
416
  this.timestamp,
412
417
  this.ansiReducer,
413
418
  this.code,
419
+ this.id,
414
420
  );
415
421
  }
416
422
 
@@ -16,8 +16,7 @@ import { Tooltip } from "@/components/ui/tooltip";
16
16
  import type { CellId } from "@/core/cells/ids";
17
17
  import { isInternalCellName } from "@/core/cells/names";
18
18
  import { useExpandedConsoleOutput } from "@/core/cells/outputs";
19
- import type { WithResponse } from "@/core/cells/types";
20
- import type { OutputMessage } from "@/core/kernel/messages";
19
+ import type { ConsoleOutputMessage } from "@/core/cells/types";
21
20
  import {
22
21
  type UseInputHistoryReturn,
23
22
  useInputHistory,
@@ -73,7 +72,7 @@ interface Props {
73
72
  cellId: CellId;
74
73
  cellName: string;
75
74
  className?: string;
76
- consoleOutputs: WithResponse<OutputMessage>[];
75
+ consoleOutputs: ConsoleOutputMessage[];
77
76
  stale: boolean;
78
77
  interrupted: boolean;
79
78
  debuggerActive: boolean;
@@ -241,19 +240,24 @@ const ConsoleOutputInternal = (props: Props): React.ReactNode => {
241
240
  return null;
242
241
  }
243
242
 
243
+ const originalIdx = consoleOutputs.length - idx - 1;
244
+ // Outputs render in reverse, so the reversed index shifts on every
245
+ // new line. The assigned id survives collapse and truncation. The
246
+ // original position is the fallback for outputs without one.
247
+ const key = output.id ?? `position-${originalIdx}`;
248
+
244
249
  if (output.channel === "stdin") {
245
250
  invariant(
246
251
  typeof output.data === "string",
247
252
  "Expected data to be a string",
248
253
  );
249
254
 
250
- const originalIdx = consoleOutputs.length - idx - 1;
251
255
  const isPassword = output.mimetype === "text/password";
252
256
 
253
257
  if (output.response == null && lastStdInputIdx === idx) {
254
258
  return (
255
259
  <StdInput
256
- key={idx}
260
+ key={key}
257
261
  output={output.data}
258
262
  isPdb={isPdb}
259
263
  isPassword={isPassword}
@@ -268,7 +272,7 @@ const ConsoleOutputInternal = (props: Props): React.ReactNode => {
268
272
 
269
273
  return (
270
274
  <StdInputWithResponse
271
- key={idx}
275
+ key={key}
272
276
  output={output.data}
273
277
  response={output.response}
274
278
  isPassword={isPassword}
@@ -278,7 +282,7 @@ const ConsoleOutputInternal = (props: Props): React.ReactNode => {
278
282
  }
279
283
 
280
284
  return (
281
- <React.Fragment key={idx}>
285
+ <React.Fragment key={key}>
282
286
  <OutputRenderer
283
287
  cellId={cellId}
284
288
  onRefactorWithAI={onRefactorWithAI}
@@ -172,12 +172,12 @@ export const PackageAlert: React.FC = () => {
172
172
  <p>The following packages were not found:</p>
173
173
  <table className="list-disc ml-2 mt-1">
174
174
  <tbody>
175
- {packageAlert.packages.map((pkg, index) => {
175
+ {packageAlert.packages.map((pkg) => {
176
176
  const parsed = parsePackageSpecifier(pkg);
177
177
  const currentExtras = selectedExtras[pkg] || parsed.extras;
178
178
 
179
179
  return (
180
- <tr className="font-mono text-sm" key={index}>
180
+ <tr className="font-mono text-sm" key={pkg}>
181
181
  <td className="pr-2 py-1 align-middle">
182
182
  <BoxIcon size="1rem" />
183
183
  </td>
@@ -296,7 +296,7 @@ export const PackageAlert: React.FC = () => {
296
296
  </>
297
297
  )}
298
298
  <ul className="list-disc ml-2 mt-1">
299
- {Object.entries(packageAlert.packages).map(([pkg, st], index) => (
299
+ {Object.entries(packageAlert.packages).map(([pkg, st]) => (
300
300
  <li
301
301
  className={cn(
302
302
  "flex items-center gap-1 font-mono text-sm",
@@ -307,7 +307,7 @@ export const PackageAlert: React.FC = () => {
307
307
  status === "failed" &&
308
308
  "text-muted-foreground",
309
309
  )}
310
- key={index}
310
+ key={pkg}
311
311
  >
312
312
  <ProgressIcon status={st} />
313
313
  {pkg}
@@ -135,9 +135,9 @@ export const ScratchPad: React.FC = () => {
135
135
  return (
136
136
  <div className="absolute inset-0 z-100 bg-background p-3 border-none overflow-auto">
137
137
  <div className="overflow-auto flex flex-col gap-3">
138
- {history.map((item, index) => (
138
+ {history.map((item) => (
139
139
  <div
140
- key={index}
140
+ key={item}
141
141
  className="border rounded-md hover:shadow-sm cursor-pointer hover:border-input overflow-hidden"
142
142
  onClick={() => handleSelectHistoryItem(item)}
143
143
  >
@@ -404,13 +404,15 @@ const SubslideView = ({
404
404
  if (block.isFragment) {
405
405
  const cumulative = cumulativeByBlock.get(i);
406
406
  return (
407
- <Fragment key={i} as="div">
407
+ <Fragment key={block.cells[0].id} as="div">
408
408
  {rendered}
409
409
  {cumulative && <NotesAside text={cumulative} />}
410
410
  </Fragment>
411
411
  );
412
412
  }
413
- return <ReactFragment key={i}>{rendered}</ReactFragment>;
413
+ return (
414
+ <ReactFragment key={block.cells[0].id}>{rendered}</ReactFragment>
415
+ );
414
416
  })}
415
417
  </div>
416
418
  </SlideScrollContainer>
@@ -139,6 +139,7 @@ exports[`cell reducer > can initialize stdin > second stdin requested 1`] = `
139
139
  {
140
140
  "channel": "stdin",
141
141
  "data": "what is your name?",
142
+ "id": 2,
142
143
  "mimetype": "text/plain",
143
144
  "response": "Marimo!",
144
145
  "timestamp": 2,
@@ -146,6 +147,7 @@ exports[`cell reducer > can initialize stdin > second stdin requested 1`] = `
146
147
  {
147
148
  "channel": "stdin",
148
149
  "data": "how old are you?",
150
+ "id": 3,
149
151
  "mimetype": "text/plain",
150
152
  "timestamp": 3,
151
153
  },
@@ -189,6 +191,7 @@ exports[`cell reducer > can initialize stdin > stdin answered 1`] = `
189
191
  {
190
192
  "channel": "stdin",
191
193
  "data": "what is your name?",
194
+ "id": 2,
192
195
  "mimetype": "text/plain",
193
196
  "response": "Marimo!",
194
197
  "timestamp": 2,
@@ -233,6 +236,7 @@ exports[`cell reducer > can initialize stdin > stdin requested 1`] = `
233
236
  {
234
237
  "channel": "stdin",
235
238
  "data": "what is your name?",
239
+ "id": 2,
236
240
  "mimetype": "text/plain",
237
241
  "timestamp": 2,
238
242
  },
@@ -219,6 +219,45 @@ describe("transitionCell serialization", () => {
219
219
  });
220
220
  });
221
221
 
222
+ describe("transitionCell console output ids", () => {
223
+ const output = (
224
+ data: string,
225
+ channel: OutputMessage["channel"] = "stdout",
226
+ ): OutputMessage => ({
227
+ channel,
228
+ mimetype: "text/plain",
229
+ data,
230
+ timestamp: 0,
231
+ });
232
+
233
+ it("assigns increasing ids to appended outputs", () => {
234
+ let cell = createCellRuntimeState({ status: "running" });
235
+ cell = transitionCell(cell, { console: output("a") } as CellMessage);
236
+ cell = transitionCell(cell, {
237
+ console: output("b", "stderr"),
238
+ } as CellMessage);
239
+ expect(cell.consoleOutputs.map((o) => o.id)).toEqual([1, 2]);
240
+ });
241
+
242
+ it("continues from the surviving maximum after a collapse", () => {
243
+ let cell = createCellRuntimeState({ status: "running" });
244
+ cell = transitionCell(cell, { console: output("a") } as CellMessage);
245
+ cell = transitionCell(cell, { console: output("b") } as CellMessage);
246
+ expect(cell.consoleOutputs.map((o) => o.id)).toEqual([1]);
247
+ cell = transitionCell(cell, {
248
+ console: output("c", "stderr"),
249
+ } as CellMessage);
250
+ expect(cell.consoleOutputs.map((o) => o.id)).toEqual([1, 2]);
251
+ });
252
+
253
+ it("assigns ids when the kernel replaces the whole console", () => {
254
+ const cell = transitionCell(createCellRuntimeState({ status: "running" }), {
255
+ console: [output("a"), output("b", "stderr")],
256
+ } as CellMessage);
257
+ expect(cell.consoleOutputs.map((o) => o.id)).toEqual([1, 2]);
258
+ });
259
+ });
260
+
222
261
  describe("transitionCell stdin resolution", () => {
223
262
  describe.each([
224
263
  {