@marimo-team/islands 0.25.3-dev10 → 0.25.3-dev100

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 (336) hide show
  1. package/dist/{ConnectedDataExplorerComponent-CNMliVzw.js → ConnectedDataExplorerComponent-Dhf5EGs5.js} +14 -14
  2. package/dist/{ErrorBoundary-BsqSMK9Y.js → ErrorBoundary-GScQVnJ8.js} +8 -8
  3. package/dist/{abnfDiagram-VCTEODGH-D-Ez91gV.js → abnfDiagram-VCTEODGH-Di400kYu.js} +2 -2
  4. package/dist/any-language-editor-k2B8YI3Y.js +75 -0
  5. package/dist/{architectureDiagram-5GKGNRK7-CTpcNtO8.js → architectureDiagram-5GKGNRK7-BdTJcsNJ.js} +1 -1
  6. package/dist/{arrays-CN1djC4k.js → arrays-R6JsImiT.js} +8 -0
  7. package/dist/assets/__vite-browser-external-35VXYmnw.js +1 -0
  8. package/dist/assets/{worker-HPY9fbhz.js → worker-Dq8y-WM5.js} +2 -2
  9. package/dist/{button-CvjkwdSk.js → button-BxB3RDjN.js} +1 -1
  10. package/dist/{capabilities-CQ5IjhzL.js → capabilities-BgR0osfN.js} +2 -2
  11. package/dist/{chat-ui-0lKdOoQ3.js → chat-ui-BIgPxfPP.js} +1141 -1141
  12. package/dist/{check-EDwSwP89.js → check-P35dc2dH.js} +1 -1
  13. package/dist/{chunk-IMKFNOWR-DGxi-zeo.js → chunk-IMKFNOWR-mtD7aJBw.js} +1 -1
  14. package/dist/{chunk-SHT3W25Y-CV9J3rAB.js → chunk-SHT3W25Y-DybB1ShH.js} +1 -1
  15. package/dist/{chunk-SVP7TREG-BL-9Fqgg.js → chunk-SVP7TREG-DNhhdCex.js} +1 -1
  16. package/dist/{chunk-TICWLB2K-Cu_XMjDM.js → chunk-TICWLB2K-NhAQhlDf.js} +1 -1
  17. package/dist/{chunk-YOKDWASO-DPZk8vhS.js → chunk-YOKDWASO-DKplTrBY.js} +20 -20
  18. package/dist/{classDiagram-ZZMXUADV-BXXV13Hq.js → classDiagram-ZZMXUADV-GTL0l5xS.js} +2 -2
  19. package/dist/{classDiagram-v2-VYDZK3BY-B7FXJ1Cp.js → classDiagram-v2-VYDZK3BY-BWrM2ruI.js} +2 -2
  20. package/dist/{code-visibility-CXQvUXHT.js → code-visibility-DnqM5oW_.js} +6 -6
  21. package/dist/{common-CuD-CAC-.js → common-D2HSo8Gy.js} +5550 -5451
  22. package/dist/{copy-icon-Ft7t9bqz.js → copy-icon-CPoxUG7G.js} +3 -3
  23. package/dist/{cynefinDiagram-5FMLGOSQ-CH96rwba.js → cynefinDiagram-5FMLGOSQ-CX22wa7c.js} +1 -1
  24. package/dist/{dagre-GXQ25YYZ-BD3PmpFY.js → dagre-GXQ25YYZ-Df6Pp-cl.js} +1 -1
  25. package/dist/{data-grid-overlay-editor-DgeyYmC1.js → data-grid-overlay-editor-BgIMQs9G.js} +5 -5
  26. package/dist/{data-grid-types-BH_r7g7l.js → data-grid-types-0PJ-9N5n.js} +1 -1
  27. package/dist/{diagram-S7CK7UJ4-BsSJJldB.js → diagram-S7CK7UJ4-CctU9kVx.js} +1 -1
  28. package/dist/{diagram-UQ7AKVKN-muQtNZc4.js → diagram-UQ7AKVKN-FVHjCF9j.js} +1 -1
  29. package/dist/{diagram-VX7I27RA-CdhuZAqR.js → diagram-VX7I27RA-BSDbwFFv.js} +1 -1
  30. package/dist/{diagram-Z3DM3KII-BD8mXjOj.js → diagram-Z3DM3KII-BX8kW7Nc.js} +1 -1
  31. package/dist/{dialog-CEBFZNyc.js → dialog-C1PcpCqX.js} +3 -3
  32. package/dist/{dist-DpBpA_n1.js → dist-Lm-D-Vr6.js} +3 -3
  33. package/dist/{dropdown-menu-CP_qCYHC.js → dropdown-menu-B_7xD2X4.js} +177 -169
  34. package/dist/{ebnfDiagram-PWID7BFC-BIN1sweE.js → ebnfDiagram-PWID7BFC-DtapdLet.js} +2 -2
  35. package/dist/{erDiagram-RLTQ6QDP-Ctp5cfoN.js → erDiagram-RLTQ6QDP-BAru9jHt.js} +1 -1
  36. package/dist/{error-banner-D-WCIiMt.js → error-banner-Sl2FlSJ4.js} +2 -2
  37. package/dist/{error-entries-DSvFWT_M.js → error-entries-TAO6kEhF.js} +797 -784
  38. package/dist/{feedback-button-DZMj9PF3.js → feedback-button-BXcB6llx.js} +29 -29
  39. package/dist/{flowDiagram-HODETNUW-3EfLrlFb.js → flowDiagram-HODETNUW-CjaeFeea.js} +2 -2
  40. package/dist/{formats-CeOmU1MU.js → formats-V8ifA0Bk.js} +3 -3
  41. package/dist/{ganttDiagram-EL5Y4UJY-BQT16JSc.js → ganttDiagram-EL5Y4UJY-Dh_4cBJZ.js} +2 -2
  42. package/dist/{glide-data-editor-g_L8FLAC.js → glide-data-editor-S-_J-7SO.js} +370 -368
  43. package/dist/{glide-utils-DJyqh0EM.js → glide-utils-Bt8_pBa2.js} +16 -16
  44. package/dist/{globals-CYGlmBXb.js → globals-D4vBwcD6.js} +3 -3
  45. package/dist/{highlighted-body-KPVGNVTW-zwjq21tf.js → highlighted-body-KPVGNVTW-3Ziwfz-V.js} +2 -2
  46. package/dist/{html-to-image-B8s5SgGm.js → html-to-image-CWdayGZU.js} +29 -29
  47. package/dist/{infoDiagram-27XIBGKW-DipQoHxl.js → infoDiagram-27XIBGKW-B1hmUggC.js} +1 -1
  48. package/dist/{ishikawaDiagram-5VMMS53U-DgFMjSGz.js → ishikawaDiagram-5VMMS53U-DUeT3t-d.js} +1 -1
  49. package/dist/{kanban-definition-UXKFOSKX-w1ACVjgl.js → kanban-definition-UXKFOSKX-DEUnNNgc.js} +1 -1
  50. package/dist/{label-BDKF3Afc.js → label-BRnUC0NX.js} +2 -2
  51. package/dist/{linear-Cnaq3Tfb.js → linear-DWERh7eI.js} +121 -73
  52. package/dist/{loader-BQOfjTIJ.js → loader-Bm8cy3e8.js} +12 -12
  53. package/dist/main.js +3236 -3019
  54. package/dist/{mermaid-CHo49Yv-.js → mermaid-B0fXpsNP.js} +38 -38
  55. package/dist/mermaid-HWGCJPDP-Du3-HPQA.js +2 -0
  56. package/dist/{mindmap-definition-YA3MSWOX-CrT0KSfX.js → mindmap-definition-YA3MSWOX-CPexlhDQ.js} +1 -1
  57. package/dist/{number-overlay-editor-9VRv-pdj.js → number-overlay-editor-CUrUm7Np.js} +3 -3
  58. package/dist/{objects-CzUgoMIF.js → objects-DCmMvZtn.js} +1 -3
  59. package/dist/{once-BtE-wKRL.js → once-eG8Vmvjd.js} +1 -1
  60. package/dist/{pegDiagram-XKGWAZYB-BqvywNJA.js → pegDiagram-XKGWAZYB-CMpp1OOQ.js} +2 -2
  61. package/dist/{pieDiagram-E7YTZNPT-BfxJ_XCc.js → pieDiagram-E7YTZNPT-DlMWg5t1.js} +1 -1
  62. package/dist/precisionRound-DhAzeRcm.js +49 -0
  63. package/dist/{process-output-CKRXyszb.js → process-output-DD-oSvZk.js} +4 -4
  64. package/dist/{quadrantDiagram-AXDQQJYC-Ccw0xMjN.js → quadrantDiagram-AXDQQJYC-Blrm7V7_.js} +1 -1
  65. package/dist/{railroadDiagram-O6MQD6OU-8vFLVTPu.js → railroadDiagram-O6MQD6OU-DBJfseeO.js} +2 -2
  66. package/dist/{react-vega-BED0DjiB.js → react-vega-C4T9Rb_w.js} +12284 -12270
  67. package/dist/{requirementDiagram-BXWQKSXE-a_MxGvxe.js → requirementDiagram-BXWQKSXE-BC7V639r.js} +1 -1
  68. package/dist/{reveal-component-C87mv9Mn.js → reveal-component-CFzdsOg8.js} +23 -23
  69. package/dist/{select-BButFi-d.js → select-B0LRDH0g.js} +4 -4
  70. package/dist/{sequenceDiagram-WJ2MYXX4-CXFMnxGh.js → sequenceDiagram-WJ2MYXX4-CgesU6F-.js} +1 -1
  71. package/dist/{spec-BwarBpUJ.js → spec-CcT0slVc.js} +4 -4
  72. package/dist/{stateDiagram-D77RDMKH-DQeA_CwI.js → stateDiagram-D77RDMKH-lH_BUhs3.js} +2 -2
  73. package/dist/{stateDiagram-v2-MP3YSRHH-BxxQucm1.js → stateDiagram-v2-MP3YSRHH-8LL6FrBe.js} +2 -2
  74. package/dist/style.css +1 -1
  75. package/dist/{swimlanes-42K2YHIH-Do6L-cYg.js → swimlanes-42K2YHIH-Cuf9B9kE.js} +1 -1
  76. package/dist/{swimlanesDiagram-VR7AAH4N-DUzPvSVU.js → swimlanesDiagram-VR7AAH4N-BoMMtOPh.js} +2 -2
  77. package/dist/{swiper-component-DKntyn8p.js → swiper-component-DfhRvAFi.js} +2 -2
  78. package/dist/{time-BieKwdYS.js → time-BaMbJs4z.js} +18 -18
  79. package/dist/{timeline-definition-24CTP7MA-D3c46WM5.js → timeline-definition-24CTP7MA-yzzw4TF4.js} +1 -1
  80. package/dist/{toDate-vIXljnsr.js → toDate-DKH0_kMo.js} +29 -31
  81. package/dist/{toast-B9UMEi8u.js → toast-CFWpihJU.js} +4 -4
  82. package/dist/{tooltip-BO1REbqs.js → tooltip-CKO1pHJo.js} +2 -2
  83. package/dist/{use-restore-focus-BEM7sFWl.js → use-restore-focus-DBCITLeF.js} +1 -1
  84. package/dist/{useAsyncData-Deh5kszT.js → useAsyncData-D0mLJstx.js} +15 -14
  85. package/dist/{useDateFormatter-D8XruNGG.js → useDateFormatter-c_yJtkAe.js} +2 -2
  86. package/dist/{useDeepCompareMemoize-DXwzRINI.js → useDeepCompareMemoize-BpPWi3G3.js} +1 -1
  87. package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-BkdeVdXC.js} +1 -1
  88. package/dist/{useLifecycle-j7D9uD1o.js → useLifecycle-Dum8WSXq.js} +3 -3
  89. package/dist/{useTheme-CRnjkku0.js → useTheme-CfeaVw5D.js} +6 -6
  90. package/dist/{vega-component-DTG6zxaY.js → vega-component-DgytCKrL.js} +147 -147
  91. package/dist/{vega-embed-container-BNHE18G9.js → vega-embed-container--LYZqguO.js} +2 -2
  92. package/dist/{vega-loader.browser-DNST6uVf.js → vega-loader.browser-B9Pz0EGP.js} +298 -507
  93. package/dist/{vennDiagram-4TSXK5OY-BSZD8JcZ.js → vennDiagram-4TSXK5OY-eJOrTqqC.js} +1 -1
  94. package/dist/{wardleyDiagram-VM6X3IG4-48cUWkfA.js → wardleyDiagram-VM6X3IG4-TILPvee6.js} +1 -1
  95. package/dist/{xychartDiagram-S5SC5T6Z-CswYgYeu.js → xychartDiagram-S5SC5T6Z-DUPvRwwJ.js} +2 -2
  96. package/package.json +7 -7
  97. package/src/__tests__/host-imports.test.ts +1 -0
  98. package/src/components/app-config/ai-config.tsx +7 -2
  99. package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
  100. package/src/components/chat/acp/__tests__/state.test.ts +2 -2
  101. package/src/components/chat/acp/blocks.tsx +2 -2
  102. package/src/components/chat/chat-components.tsx +2 -0
  103. package/src/components/chat/chat-panel.tsx +9 -8
  104. package/src/components/chat/chat-utils.ts +4 -8
  105. package/src/components/data-table/__tests__/column-explorer.test.tsx +27 -1
  106. package/src/components/data-table/__tests__/columns.test.tsx +105 -0
  107. package/src/components/data-table/__tests__/context-menu-interaction.test.tsx +130 -0
  108. package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
  109. package/src/components/data-table/__tests__/export-actions.test.tsx +105 -0
  110. package/src/components/data-table/__tests__/search-highlight.test.tsx +109 -0
  111. package/src/components/data-table/__tests__/url-detector.test.tsx +74 -0
  112. package/src/components/data-table/cell-selection/feature.ts +2 -2
  113. package/src/components/data-table/cell-selection/types.ts +2 -2
  114. package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
  115. package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
  116. package/src/components/data-table/charts/charts.tsx +35 -25
  117. package/src/components/data-table/charts/storage.ts +16 -5
  118. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
  119. package/src/components/data-table/column-summary/column-summary.tsx +2 -4
  120. package/src/components/data-table/column-visibility-dropdown.tsx +8 -13
  121. package/src/components/data-table/columns.tsx +45 -46
  122. package/src/components/data-table/context-menu.tsx +36 -20
  123. package/src/components/data-table/data-table.tsx +7 -1
  124. package/src/components/data-table/date-popover.tsx +6 -4
  125. package/src/components/data-table/export-actions.tsx +76 -48
  126. package/src/components/data-table/row-viewer-panel/row-viewer.tsx +2 -2
  127. package/src/components/data-table/search-highlight.tsx +79 -0
  128. package/src/components/data-table/types.ts +1 -0
  129. package/src/components/data-table/url-detector.tsx +49 -9
  130. package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
  131. package/src/components/datasources/__tests__/column-preview.test.tsx +63 -2
  132. package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
  133. package/src/components/datasources/column-preview.tsx +8 -2
  134. package/src/components/datasources/datasources.tsx +47 -35
  135. package/src/components/debugger/debugger-code.tsx +5 -0
  136. package/src/components/dependency-graph/panels.tsx +2 -1
  137. package/src/components/editor/SortableCell.tsx +1 -3
  138. package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
  139. package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +24 -0
  140. package/src/components/editor/actions/pair-with-agent-modal.tsx +18 -15
  141. package/src/components/editor/ai/add-cell-with-ai.tsx +3 -3
  142. package/src/components/editor/ai/ai-completion-editor.tsx +1 -0
  143. package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
  144. package/src/components/editor/cell/CreateCellButton.tsx +8 -10
  145. package/src/components/editor/cell/DeleteButton.tsx +1 -0
  146. package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
  147. package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
  148. package/src/components/editor/cell/code/cell-editor.tsx +1 -1
  149. package/src/components/editor/cell/code/language-toggle.tsx +8 -7
  150. package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
  151. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +30 -1
  152. package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
  153. package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
  154. package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +12 -18
  155. package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +58 -1
  156. package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
  157. package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +12 -2
  158. package/src/components/editor/chrome/wrapper/storage.ts +1 -1
  159. package/src/components/editor/connections/components.tsx +1 -1
  160. package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
  161. package/src/components/editor/controls/command-palette.tsx +22 -10
  162. package/src/components/editor/dynamic-favicon.tsx +21 -40
  163. package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +12 -23
  164. package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
  165. package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
  166. package/src/components/editor/file-tree/file-explorer.tsx +10 -5
  167. package/src/components/editor/file-tree/file-viewer.tsx +4 -2
  168. package/src/components/editor/file-tree/use-file-search.ts +35 -21
  169. package/src/components/editor/notebook-banner.tsx +1 -0
  170. package/src/components/editor/output/MarimoTracebackOutput.tsx +2 -2
  171. package/src/components/editor/output/ansi-reduce.ts +6 -0
  172. package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
  173. package/src/components/editor/package-alert.tsx +6 -4
  174. package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
  175. package/src/components/home/components.tsx +17 -31
  176. package/src/components/icons/__tests__/large-spinner.test.tsx +39 -0
  177. package/src/components/icons/large-spinner.tsx +3 -14
  178. package/src/components/icons/spinner.tsx +1 -1
  179. package/src/components/mcp/mcp-status-indicator.tsx +1 -1
  180. package/src/components/pages/__tests__/home-page.test.tsx +116 -0
  181. package/src/components/pages/home-page.tsx +164 -91
  182. package/src/components/scratchpad/scratchpad.tsx +2 -2
  183. package/src/components/slides/reveal-component.tsx +4 -2
  184. package/src/components/slides/slide-cell-view.tsx +1 -1
  185. package/src/components/slides/slide-form.tsx +1 -0
  186. package/src/components/tracing/tracing.tsx +2 -2
  187. package/src/components/ui/alert-dialog.tsx +1 -1
  188. package/src/core/ai/context/providers/datasource.ts +6 -2
  189. package/src/core/attachments/state.ts +5 -8
  190. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -0
  191. package/src/core/cells/__tests__/cell.test.ts +39 -0
  192. package/src/core/cells/__tests__/cells.test.ts +3 -1
  193. package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
  194. package/src/core/cells/__tests__/notebook-outline.test.ts +113 -0
  195. package/src/core/cells/cell.ts +14 -3
  196. package/src/core/cells/cells.ts +3 -1
  197. package/src/core/cells/pending-delete-service.ts +2 -6
  198. package/src/core/cells/session.ts +1 -1
  199. package/src/core/cells/types.ts +10 -1
  200. package/src/core/codemirror/__tests__/setup.test.ts +1 -1
  201. package/src/core/codemirror/keymaps/vim.ts +2 -6
  202. package/src/core/codemirror/language/languages/markdown.ts +1 -1
  203. package/src/core/codemirror/language/languages/python.ts +3 -3
  204. package/src/core/codemirror/language/panel/panel.tsx +1 -0
  205. package/src/core/datasets/__tests__/data-source-discovery.test.ts +4 -4
  206. package/src/core/datasets/data-source-discovery.ts +4 -6
  207. package/src/core/document/__tests__/draft.test.ts +322 -0
  208. package/src/core/document/__tests__/fixtures.ts +92 -0
  209. package/src/core/document/__tests__/model.test.ts +483 -0
  210. package/src/core/document/__tests__/state.test.ts +446 -0
  211. package/src/core/document/__tests__/submission.test.ts +346 -0
  212. package/src/core/document/draft.ts +472 -0
  213. package/src/core/document/index.ts +10 -0
  214. package/src/core/document/model.ts +53 -0
  215. package/src/core/document/state.ts +401 -0
  216. package/src/core/document/sync.ts +359 -0
  217. package/src/core/edit-app.tsx +2 -2
  218. package/src/core/host/AGENTS.md +12 -2
  219. package/src/core/host/__tests__/attachments.test.ts +56 -0
  220. package/src/core/host/__tests__/document.test.ts +126 -0
  221. package/src/core/host/__tests__/fixtures.ts +41 -0
  222. package/src/core/host/__tests__/notebook-client.test.ts +570 -0
  223. package/src/core/host/connection.ts +42 -0
  224. package/src/core/host/notebook-client.ts +297 -0
  225. package/src/core/host/resources/attachments.ts +22 -0
  226. package/src/core/host/resources/document.ts +101 -0
  227. package/src/core/hotkeys/actions.ts +2 -4
  228. package/src/core/islands/__tests__/bootstrap.test.ts +0 -26
  229. package/src/core/islands/bootstrap.ts +0 -1
  230. package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
  231. package/src/core/network/connection.ts +4 -2
  232. package/src/core/network/useConnectionNotice.ts +8 -2
  233. package/src/core/run-app.tsx +2 -2
  234. package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
  235. package/src/core/runtime/__tests__/runtime.test.ts +18 -17
  236. package/src/core/runtime/runtime.ts +26 -30
  237. package/src/core/state/__tests__/jotai.test.tsx +108 -0
  238. package/src/core/state/jotai.ts +1 -1
  239. package/src/core/static/files.ts +2 -0
  240. package/src/core/wasm/bridge.ts +2 -10
  241. package/src/core/wasm/store.ts +3 -3
  242. package/src/core/wasm/worker/bootstrap.ts +1 -1
  243. package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
  244. package/src/core/websocket/__tests__/{useMarimoKernelConnection.test.ts → connection-state.test.ts} +15 -29
  245. package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +223 -0
  246. package/src/core/websocket/__tests__/useNotebookSession.hook.test.tsx +606 -0
  247. package/src/core/websocket/connection-state.ts +60 -0
  248. package/src/core/websocket/state.ts +7 -0
  249. package/src/core/websocket/transports/__tests__/notebook.test.ts +502 -0
  250. package/src/core/websocket/transports/notebook.ts +213 -0
  251. package/src/core/websocket/types.ts +9 -39
  252. package/src/core/websocket/useNotebookClient.ts +89 -0
  253. package/src/core/websocket/{useMarimoKernelConnection.tsx → useNotebookSession.tsx} +53 -233
  254. package/src/css/globals.css +5 -0
  255. package/src/hooks/__tests__/useAsyncData.test.tsx +148 -0
  256. package/src/hooks/__tests__/useDebounce.test.tsx +51 -0
  257. package/src/hooks/__tests__/useDeepCompareMemoize.test.tsx +39 -0
  258. package/src/hooks/__tests__/useDelayElapsed.test.tsx +28 -0
  259. package/src/hooks/__tests__/useInternalStateWithSync.test.tsx +20 -0
  260. package/src/hooks/__tests__/useScript.test.tsx +77 -0
  261. package/src/hooks/__tests__/useStateForKey.test.tsx +257 -0
  262. package/src/hooks/useAsyncData.ts +3 -3
  263. package/src/hooks/useDataSourceDiscovery.ts +6 -4
  264. package/src/hooks/useDebounce.ts +5 -8
  265. package/src/hooks/useDeepCompareMemoize.ts +1 -1
  266. package/src/hooks/useDelayElapsed.ts +14 -10
  267. package/src/hooks/useElapsedTime.ts +3 -3
  268. package/src/hooks/useInputHistory.ts +4 -7
  269. package/src/hooks/useInternalStateWithSync.ts +6 -6
  270. package/src/hooks/useResizeObserver.ts +4 -7
  271. package/src/hooks/useScript.ts +67 -70
  272. package/src/hooks/useStateForKey.ts +93 -0
  273. package/src/plugins/core/registerReactComponent.tsx +1 -1
  274. package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
  275. package/src/plugins/impl/DataTablePlugin.tsx +14 -15
  276. package/src/plugins/impl/DropdownPlugin.tsx +2 -6
  277. package/src/plugins/impl/FileBrowserPlugin.tsx +4 -16
  278. package/src/plugins/impl/FormPlugin.tsx +1 -1
  279. package/src/plugins/impl/RangeSliderPlugin.tsx +0 -1
  280. package/src/plugins/impl/RefreshPlugin.tsx +1 -0
  281. package/src/plugins/impl/SliderPlugin.tsx +6 -8
  282. package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +117 -1
  283. package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
  284. package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
  285. package/src/plugins/impl/anywidget/__tests__/registry.test.ts +2 -0
  286. package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
  287. package/src/plugins/impl/anywidget/runtime.ts +21 -9
  288. package/src/plugins/impl/anywidget/widget-binding.ts +160 -82
  289. package/src/plugins/impl/chat/__tests__/chat-prompts.test.tsx +93 -0
  290. package/src/plugins/impl/chat/chat-ui.tsx +12 -10
  291. package/src/plugins/impl/code/any-language-editor.tsx +2 -2
  292. package/src/plugins/impl/data-editor/glide-data-editor.tsx +8 -5
  293. package/src/plugins/impl/data-editor/glide-utils.ts +3 -1
  294. package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
  295. package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
  296. package/src/plugins/impl/data-frames/DataFramePlugin.tsx +0 -1
  297. package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
  298. package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
  299. package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
  300. package/src/plugins/impl/panel/utils.ts +17 -0
  301. package/src/plugins/impl/vega/make-selectable.ts +4 -7
  302. package/src/plugins/layout/RoutesPlugin.tsx +1 -1
  303. package/src/stories/__tests__/editor-story.test.tsx +33 -0
  304. package/src/stories/button.stories.tsx +1 -0
  305. package/src/stories/editor.stories.tsx +24 -17
  306. package/src/stories/form-wrapper.stories.tsx +2 -2
  307. package/src/stories/select.stories.tsx +2 -2
  308. package/src/stories/switchable-multi-select.stories.tsx +1 -1
  309. package/src/utils/__tests__/arrays.test.ts +35 -0
  310. package/src/utils/__tests__/batch-requests.test.ts +3 -3
  311. package/src/utils/__tests__/numbers.test.ts +48 -1
  312. package/src/utils/__tests__/objects.test.ts +21 -0
  313. package/src/utils/arrays.ts +10 -0
  314. package/src/utils/blob.ts +1 -1
  315. package/src/utils/numbers.ts +28 -17
  316. package/src/utils/objects.ts +3 -7
  317. package/src/utils/once.ts +19 -19
  318. package/src/utils/zod-utils.ts +1 -3
  319. package/dist/any-language-editor-DZ_YTVus.js +0 -76
  320. package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
  321. package/dist/mermaid-HWGCJPDP-ByCsZnYF.js +0 -2
  322. package/dist/precisionRound-DMIVQrt2.js +0 -97
  323. package/src/core/host/__tests__/protocol.test.ts +0 -214
  324. package/src/core/host/protocol.ts +0 -1943
  325. package/src/core/state/__tests__/jotai.test.ts +0 -25
  326. package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +0 -789
  327. package/src/core/websocket/__tests__/useWebSocket.test.ts +0 -49
  328. package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
  329. package/src/core/websocket/transports/__tests__/sse.test.ts +0 -338
  330. package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
  331. package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
  332. package/src/core/websocket/transports/basic.ts +0 -102
  333. package/src/core/websocket/transports/sse.ts +0 -308
  334. package/src/core/websocket/transports/transport.ts +0 -61
  335. package/src/core/websocket/transports/ws.ts +0 -98
  336. package/src/core/websocket/useWebSocket.tsx +0 -88
@@ -0,0 +1,213 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import {
4
+ type NotebookTransport,
5
+ sse,
6
+ StreamStopped,
7
+ type StreamUrl,
8
+ } from "@marimo-team/client";
9
+ import { jsonParseWithSpecialChar } from "@/utils/json/json-parser";
10
+ import { PyodideBridge } from "../../wasm/bridge";
11
+ import { isWasm } from "../../wasm/utils";
12
+ import { classifyCloseEvent } from "../connection-state";
13
+
14
+ /** The server can be slow to accept when many notebooks are open. */
15
+ const CONNECT_MS = 10_000;
16
+
17
+ /**
18
+ * The error that ends a stream on this close, or none to retry.
19
+ *
20
+ * `cause` is the connection status the editor shows.
21
+ */
22
+ function stopOn(close: { code?: number; reason?: string }) {
23
+ const decision = classifyCloseEvent(close);
24
+ if (decision.kind === "retry") {
25
+ return undefined;
26
+ }
27
+ const reason = "reason" in decision.status ? decision.status.reason : "";
28
+ return new StreamStopped(reason, { cause: decision.status });
29
+ }
30
+
31
+ /** Read a URL provider, stopping the stream when it gives up. */
32
+ async function resolve(url: StreamUrl): Promise<URL | undefined> {
33
+ try {
34
+ return new URL(typeof url === "function" ? await url() : url);
35
+ } catch (error) {
36
+ if (error instanceof StreamStopped) {
37
+ throw error;
38
+ }
39
+ return undefined;
40
+ }
41
+ }
42
+
43
+ /** A resume cursor and replica belong to the session that produced them. */
44
+ function withSessionIdentity(
45
+ url: StreamUrl,
46
+ connect: (target: URL) => NotebookTransport,
47
+ ): NotebookTransport {
48
+ let previous: string | undefined;
49
+ return async (attempt, handlers) => {
50
+ const target = await resolve(url);
51
+ if (target === undefined || attempt.signal.aborted) {
52
+ return;
53
+ }
54
+ target.searchParams.delete("cursor");
55
+ const identity = new URL(target);
56
+ identity.searchParams.delete("access_token");
57
+ identity.searchParams.sort();
58
+ identity.hash = "";
59
+ const key = identity.toString();
60
+ let { cursor } = attempt;
61
+ if (previous !== undefined && previous !== key) {
62
+ // Reset both the stream's cursor and its subscribers' state.
63
+ handlers.message({ event: "reset", data: {} });
64
+ cursor = null;
65
+ }
66
+ previous = key;
67
+ if (!attempt.signal.aborted) {
68
+ return connect(target)({ ...attempt, cursor }, handlers);
69
+ }
70
+ };
71
+ }
72
+
73
+ /**
74
+ * Follow a marimo session over its WebSocket route.
75
+ *
76
+ * Each attempt opens one socket with the cursor as a query parameter. The
77
+ * editor's close policy decides which closes end the stream.
78
+ *
79
+ * TODO: Notice a connection that died without closing, such as after a laptop
80
+ * sleeps. `/sse` sends a heartbeat that its silence limit relies on, and
81
+ * `/ws` drops it. Sending it on `/ws` would let this transport close a
82
+ * silent socket.
83
+ */
84
+ export function websocket(url: StreamUrl): NotebookTransport {
85
+ return withSessionIdentity(
86
+ url,
87
+ (target) =>
88
+ async ({ cursor, signal }, { open, message }) => {
89
+ if (cursor !== null) {
90
+ target.searchParams.set("cursor", cursor);
91
+ }
92
+ await new Promise<void>((settle, reject) => {
93
+ const socket = new WebSocket(target);
94
+ const timeout = setTimeout(() => socket.close(), CONNECT_MS);
95
+ const abort = () => socket.close();
96
+ signal.addEventListener("abort", abort, { once: true });
97
+ socket.addEventListener("open", () => {
98
+ clearTimeout(timeout);
99
+ open();
100
+ });
101
+ socket.addEventListener("message", ({ data }) =>
102
+ // marimo's parser reads `NaN`. A message it cannot read arrives as an
103
+ // empty object, which `NotebookEvents` rejects as not an event.
104
+ message(jsonParseWithSpecialChar(String(data))),
105
+ );
106
+ socket.addEventListener("close", (event) => {
107
+ clearTimeout(timeout);
108
+ signal.removeEventListener("abort", abort);
109
+ const stopped = signal.aborted ? undefined : stopOn(event);
110
+ if (stopped === undefined) {
111
+ settle();
112
+ } else {
113
+ reject(stopped);
114
+ }
115
+ });
116
+ });
117
+ },
118
+ );
119
+ }
120
+
121
+ /**
122
+ * Follow a marimo session over its server-sent events route.
123
+ *
124
+ * The session's `close` frames carry the same reasons as WebSocket closes.
125
+ * marimo's parser decodes tagged bigints and non-finite numbers in every frame.
126
+ */
127
+ export function sessionSse(
128
+ url: StreamUrl,
129
+ headers: () => Record<string, string>,
130
+ ): NotebookTransport {
131
+ return withSessionIdentity(url, (target) =>
132
+ sse(target, {
133
+ parseData: jsonParseWithSpecialChar,
134
+ fetch: (input, init) => {
135
+ const sent = new Headers(init?.headers);
136
+ for (const [name, value] of Object.entries(headers())) {
137
+ sent.set(name, value);
138
+ }
139
+ return globalThis.fetch(input, { ...init, headers: sent });
140
+ },
141
+ stop: (frame) =>
142
+ frame.event === "close"
143
+ ? stopOn(frame.data as { code?: number; reason?: string })
144
+ : undefined,
145
+ }),
146
+ );
147
+ }
148
+
149
+ /** A connection that opens and delivers nothing, for static notebooks. */
150
+ const idle: NotebookTransport = ({ signal }, { open }) =>
151
+ new Promise((settle) => {
152
+ open();
153
+ signal.addEventListener("abort", () => settle(), { once: true });
154
+ });
155
+
156
+ /**
157
+ * Follow the notebook running in the WASM worker.
158
+ *
159
+ * The worker sends marimo notifications as `{ data: notification }`, which
160
+ * arrive as `marimo` events.
161
+ */
162
+ export function pyodide(
163
+ attach: (consumer: (message: MessageEvent<string>) => void) => void,
164
+ ): NotebookTransport {
165
+ return ({ signal }, { open, message }) =>
166
+ new Promise((settle) => {
167
+ open();
168
+ attach(({ data }) => {
169
+ if (signal.aborted) {
170
+ return;
171
+ }
172
+ const value = jsonParseWithSpecialChar(data);
173
+ // The worker sends notifications without the host's event envelope.
174
+ message(
175
+ typeof value === "object" &&
176
+ value !== null &&
177
+ !("event" in value) &&
178
+ "data" in value
179
+ ? { event: "marimo", data: { marimo: value.data } }
180
+ : value,
181
+ );
182
+ });
183
+ signal.addEventListener("abort", () => settle(), { once: true });
184
+ });
185
+ }
186
+
187
+ /** How the editor follows its notebook. */
188
+ export interface NotebookTransportOptions {
189
+ static: boolean;
190
+ transportType: "websocket" | "sse";
191
+ /** The session route, read before each connection. */
192
+ url: StreamUrl;
193
+ /** The runtime's headers, read before each request. */
194
+ headers: () => Record<string, string>;
195
+ }
196
+
197
+ /** Choose the transport for the editor's notebook. */
198
+ export function createNotebookTransport(
199
+ options: NotebookTransportOptions,
200
+ ): NotebookTransport {
201
+ if (options.static) {
202
+ return idle;
203
+ }
204
+ if (isWasm()) {
205
+ return pyodide((consumer) =>
206
+ PyodideBridge.INSTANCE.attachMessageConsumer(consumer),
207
+ );
208
+ }
209
+ if (options.transportType === "sse") {
210
+ return sessionSse(options.url, options.headers);
211
+ }
212
+ return websocket(options.url);
213
+ }
@@ -1,47 +1,17 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import type { ConnectionStatus as HostConnectionStatus } from "../host/connection";
3
4
  import type { NotificationMessageData } from "../kernel/messages";
4
5
 
6
+ export {
7
+ ConnectionState,
8
+ ConnectionClosedReason as WebSocketClosedReason,
9
+ } from "../host/connection";
10
+
5
11
  export type ConnectionPhase =
6
12
  | NotificationMessageData<"startup-progress">["phase"]
7
13
  | "reconnecting";
8
14
 
9
- export const ConnectionState = {
10
- NOT_STARTED: "NOT_STARTED",
11
- CONNECTING: "CONNECTING",
12
- OPEN: "OPEN",
13
- CLOSING: "CLOSING",
14
- CLOSED: "CLOSED",
15
- } as const;
16
-
17
- export type ConnectionState =
18
- (typeof ConnectionState)[keyof typeof ConnectionState];
19
-
20
- export const WebSocketClosedReason = {
21
- KERNEL_DISCONNECTED: "KERNEL_DISCONNECTED",
22
- KERNEL_STARTUP_ERROR: "KERNEL_STARTUP_ERROR",
23
- } as const;
24
-
25
- export type WebSocketClosedReason =
26
- (typeof WebSocketClosedReason)[keyof typeof WebSocketClosedReason];
27
-
28
- export type ConnectionStatus =
29
- | {
30
- state: typeof ConnectionState.CLOSED;
31
- code: WebSocketClosedReason;
32
- /**
33
- * Human-readable reason for closing the connection.
34
- */
35
- reason: string;
36
- phase?: ConnectionPhase;
37
- }
38
- | {
39
- state: typeof ConnectionState.CONNECTING;
40
- phase?: ConnectionPhase;
41
- }
42
- | {
43
- state:
44
- | typeof ConnectionState.OPEN
45
- | typeof ConnectionState.CLOSING
46
- | typeof ConnectionState.NOT_STARTED;
47
- };
15
+ export type ConnectionStatus = HostConnectionStatus & {
16
+ phase?: ConnectionPhase;
17
+ };
@@ -0,0 +1,89 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { StreamStopped } from "@marimo-team/client";
4
+ import { useStore } from "jotai";
5
+ import { useEffect, useMemo } from "react";
6
+ import useEvent from "react-use-event-hook";
7
+ import type {
8
+ NotificationMessage,
9
+ NotificationPayload,
10
+ } from "../kernel/messages";
11
+ import {
12
+ createNotebookClient,
13
+ type NotebookClient,
14
+ } from "../host/notebook-client";
15
+ import { notebookClientAtom } from "./state";
16
+ import {
17
+ createNotebookTransport,
18
+ type NotebookTransportOptions,
19
+ } from "./transports/notebook";
20
+
21
+ type Options = Omit<NotebookTransportOptions, "url"> & {
22
+ /** The session route, read before each connection. */
23
+ url: () => string;
24
+ /** Wait until the host can accept a connection. */
25
+ waitUntilReady: () => Promise<void>;
26
+ checkHealth: () => Promise<boolean>;
27
+ onNotification: (notification: NotificationPayload) => void;
28
+ };
29
+
30
+ export function useNotebookClient(options: Options): NotebookClient {
31
+ const store = useStore();
32
+ const { static: isStatic, transportType } = options;
33
+ const controller = useMemo(() => createNotebookClient(store), [store]);
34
+ const url = useEvent(options.url);
35
+ const headers = useEvent(options.headers);
36
+ const waitUntilReady = useEvent(options.waitUntilReady);
37
+ const checkHealth = useEvent(options.checkHealth);
38
+ const onNotification = useEvent(options.onNotification);
39
+
40
+ useEffect(() => {
41
+ const lifetime = new AbortController();
42
+ let needsInitialReadiness = true;
43
+ store.set(notebookClientAtom, controller.client);
44
+ controller.connect({
45
+ transport: createNotebookTransport({
46
+ static: isStatic,
47
+ transportType,
48
+ url: async () => {
49
+ if (needsInitialReadiness) {
50
+ // Explicit retries check current health, even if startup failed.
51
+ needsInitialReadiness = false;
52
+ try {
53
+ await waitUntilReady();
54
+ } catch (error) {
55
+ throw new StreamStopped("Healthy connection never made", {
56
+ cause: error,
57
+ });
58
+ }
59
+ }
60
+ return url();
61
+ },
62
+ headers,
63
+ }),
64
+ signal: lifetime.signal,
65
+ checkHealth,
66
+ // The host validates the envelope, not the native notification contents.
67
+ onNotification: (notification) =>
68
+ onNotification({ data: notification as NotificationMessage }),
69
+ });
70
+ return () => {
71
+ lifetime.abort();
72
+ if (store.get(notebookClientAtom) === controller.client) {
73
+ store.set(notebookClientAtom, null);
74
+ }
75
+ };
76
+ }, [
77
+ controller,
78
+ store,
79
+ isStatic,
80
+ transportType,
81
+ url,
82
+ headers,
83
+ waitUntilReady,
84
+ checkHealth,
85
+ onNotification,
86
+ ]);
87
+
88
+ return controller.client;
89
+ }