@marimo-team/islands 0.25.3-dev17 → 0.25.3-dev170

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 (547) hide show
  1. package/dist/{ConnectedDataExplorerComponent-CNMliVzw.js → ConnectedDataExplorerComponent-BbSXV-Xa.js} +21 -19
  2. package/dist/{ErrorBoundary-jaGao4LA.js → ErrorBoundary-NE86qEWZ.js} +18 -18
  3. package/dist/{abnfDiagram-VCTEODGH-D-Ez91gV.js → abnfDiagram-VCTEODGH-D7n07nXf.js} +2 -2
  4. package/dist/any-language-editor-3E24SnCV.js +75 -0
  5. package/dist/{architectureDiagram-5GKGNRK7-CTpcNtO8.js → architectureDiagram-5GKGNRK7-D6CjRib5.js} +1 -1
  6. package/dist/{arrays-CN1djC4k.js → arrays-R6JsImiT.js} +8 -0
  7. package/dist/assets/__vite-browser-external-DVeFf2e7.js +1 -0
  8. package/dist/assets/worker-C1pfNBsx.js +113 -0
  9. package/dist/{button-CvjkwdSk.js → button-BQRdqQi1.js} +199 -192
  10. package/dist/{capabilities-CQ5IjhzL.js → capabilities-CI4xUPsp.js} +2 -2
  11. package/dist/{chat-ui-DaHynk8g.js → chat-ui-CC7GekpG.js} +1144 -1143
  12. package/dist/{check-EDwSwP89.js → check-SpOMoCLP.js} +1 -1
  13. package/dist/{chunk-IMKFNOWR-DGxi-zeo.js → chunk-IMKFNOWR-6dtPz7uS.js} +1 -1
  14. package/dist/{chunk-SHT3W25Y-CV9J3rAB.js → chunk-SHT3W25Y-BwnFNKDA.js} +1 -1
  15. package/dist/{chunk-SVP7TREG-BL-9Fqgg.js → chunk-SVP7TREG-D2eV4vBJ.js} +1 -1
  16. package/dist/{chunk-TICWLB2K-Cu_XMjDM.js → chunk-TICWLB2K-BDs4-_-r.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-DCJnf_8v.js} +2 -2
  19. package/dist/{classDiagram-v2-VYDZK3BY-B7FXJ1Cp.js → classDiagram-v2-VYDZK3BY-BOmSzPBD.js} +2 -2
  20. package/dist/{code-visibility-Bub8tnaA.js → code-visibility-Bzvc6ajl.js} +25 -25
  21. package/dist/{common-CdT0nyN1.js → common-Ciw4zkh2.js} +6933 -6754
  22. package/dist/{copy-icon-Ft7t9bqz.js → copy-icon-C1trdvVt.js} +3 -3
  23. package/dist/{cynefinDiagram-5FMLGOSQ-CH96rwba.js → cynefinDiagram-5FMLGOSQ-Bln_Soky.js} +1 -1
  24. package/dist/{dagre-GXQ25YYZ-BD3PmpFY.js → dagre-GXQ25YYZ-D-nf7WzW.js} +1 -1
  25. package/dist/{data-grid-overlay-editor-Dbcss6_2.js → data-grid-overlay-editor-AQREmxI7.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-PsgSMkY2.js} +1 -1
  28. package/dist/{diagram-UQ7AKVKN-muQtNZc4.js → diagram-UQ7AKVKN-DfwfUuSw.js} +1 -1
  29. package/dist/{diagram-VX7I27RA-CdhuZAqR.js → diagram-VX7I27RA-C9_e-oMc.js} +1 -1
  30. package/dist/{diagram-Z3DM3KII-BD8mXjOj.js → diagram-Z3DM3KII-CWLa5tuY.js} +1 -1
  31. package/dist/{dialog-CEBFZNyc.js → dialog-DgeqyrEZ.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-B6ftyzOg.js} +1277 -1229
  34. package/dist/{ebnfDiagram-PWID7BFC-BIN1sweE.js → ebnfDiagram-PWID7BFC-B1QRM58v.js} +2 -2
  35. package/dist/{erDiagram-RLTQ6QDP-Ctp5cfoN.js → erDiagram-RLTQ6QDP-DJK_FqvW.js} +1 -1
  36. package/dist/{error-banner-D-WCIiMt.js → error-banner-D40pmfQQ.js} +83 -83
  37. package/dist/{error-entries-Bv6bZPF3.js → error-entries-DgK3wUJR.js} +5728 -5638
  38. package/dist/{feedback-button-B3Wrnsf_.js → feedback-button-8a6SETmT.js} +23 -23
  39. package/dist/{flowDiagram-HODETNUW-3EfLrlFb.js → flowDiagram-HODETNUW-Uxc25XSJ.js} +2 -2
  40. package/dist/{formats-27CW_UP4.js → formats-DQCyPd5Z.js} +3 -3
  41. package/dist/{ganttDiagram-EL5Y4UJY-BQT16JSc.js → ganttDiagram-EL5Y4UJY-Dh_4cBJZ.js} +2 -2
  42. package/dist/{glide-data-editor-BDYKJdqK.js → glide-data-editor-B70oke_v.js} +370 -368
  43. package/dist/{glide-utils-DJyqh0EM.js → glide-utils-Dz_F4pAY.js} +16 -16
  44. package/dist/{globals-DGTE1S0_.js → globals-Cxd5hNlI.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-Bf8QMGi4.js → html-to-image-D4yG5Ru0.js} +631 -594
  47. package/dist/{infoDiagram-27XIBGKW-DipQoHxl.js → infoDiagram-27XIBGKW-DmjxqwL0.js} +1 -1
  48. package/dist/{ishikawaDiagram-5VMMS53U-DgFMjSGz.js → ishikawaDiagram-5VMMS53U-NgCLHqQi.js} +1 -1
  49. package/dist/{kanban-definition-UXKFOSKX-w1ACVjgl.js → kanban-definition-UXKFOSKX-CZaG-iam.js} +1 -1
  50. package/dist/{label-BDKF3Afc.js → label-D9_-zSg-.js} +3 -3
  51. package/dist/{linear-Cnaq3Tfb.js → linear-DWERh7eI.js} +121 -73
  52. package/dist/{loader-BQOfjTIJ.js → loader-DOVB0Syl.js} +12 -12
  53. package/dist/main.js +7689 -7342
  54. package/dist/{mermaid-CHo49Yv-.js → mermaid-CSvw7c71.js} +38 -38
  55. package/dist/mermaid-HWGCJPDP-Du3-HPQA.js +2 -0
  56. package/dist/{mindmap-definition-YA3MSWOX-CrT0KSfX.js → mindmap-definition-YA3MSWOX-DJYQBDH_.js} +1 -1
  57. package/dist/{number-overlay-editor-S8UJY0i5.js → number-overlay-editor-ChK-SKUk.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-CHKO_dAe.js} +2 -2
  61. package/dist/{pieDiagram-E7YTZNPT-BfxJ_XCc.js → pieDiagram-E7YTZNPT-DVevbMAo.js} +1 -1
  62. package/dist/precisionRound-DhAzeRcm.js +49 -0
  63. package/dist/{process-output-BZg56CCb.js → process-output-DxvBAeL3.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-Detj1kcB.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-BLFD0T_Z.js} +1 -1
  68. package/dist/{reveal-component-De4Pvf4V.js → reveal-component-CXMXeDZD.js} +14 -14
  69. package/dist/{select-BButFi-d.js → select-CkF_GBxO.js} +537 -458
  70. package/dist/{sequenceDiagram-WJ2MYXX4-CXFMnxGh.js → sequenceDiagram-WJ2MYXX4-BZBgatQV.js} +1 -1
  71. package/dist/{spec-BwarBpUJ.js → spec-Mnkn3XEr.js} +41 -11
  72. package/dist/{stateDiagram-D77RDMKH-DQeA_CwI.js → stateDiagram-D77RDMKH-4BZW9-6_.js} +2 -2
  73. package/dist/{stateDiagram-v2-MP3YSRHH-BxxQucm1.js → stateDiagram-v2-MP3YSRHH-C4sKC8Iq.js} +2 -2
  74. package/dist/style.css +1 -1
  75. package/dist/{swimlanes-42K2YHIH-Do6L-cYg.js → swimlanes-42K2YHIH-SL5yeGe2.js} +1 -1
  76. package/dist/{swimlanesDiagram-VR7AAH4N-DUzPvSVU.js → swimlanesDiagram-VR7AAH4N-DqPmAYUv.js} +2 -2
  77. package/dist/{swiper-component-DKntyn8p.js → swiper-component-BkCm-kLg.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-BfXUMWkq.js} +1 -1
  80. package/dist/{toDate-UtiwmnH2.js → toDate-TMubKIVL.js} +37 -36
  81. package/dist/{toast-B9UMEi8u.js → toast-Btbve3Lm.js} +231 -213
  82. package/dist/{tooltip-BO1REbqs.js → tooltip-CJ4Rqasp.js} +327 -303
  83. package/dist/{use-restore-focus-BEM7sFWl.js → use-restore-focus-CmGwRNId.js} +1482 -1433
  84. package/dist/{useAsyncData-Deh5kszT.js → useAsyncData-DjMGFzFy.js} +15 -14
  85. package/dist/{useDateFormatter-D8XruNGG.js → useDateFormatter-eCL_SdeG.js} +2 -2
  86. package/dist/{useDeepCompareMemoize-DXwzRINI.js → useDeepCompareMemoize-BQR5TJot.js} +1 -1
  87. package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-CSdWn6NP.js} +1 -1
  88. package/dist/{useLifecycle-j7D9uD1o.js → useLifecycle-C_GvKWbQ.js} +28 -25
  89. package/dist/{useTheme-CRnjkku0.js → useTheme-Bns2gJZ6.js} +224 -220
  90. package/dist/{vega-component-BeF9dfyO.js → vega-component-BsVptuhz.js} +148 -148
  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-CH65znGa.js} +1 -1
  94. package/dist/{wardleyDiagram-VM6X3IG4-48cUWkfA.js → wardleyDiagram-VM6X3IG4-z9pWKb2_.js} +1 -1
  95. package/dist/{xychartDiagram-S5SC5T6Z-CswYgYeu.js → xychartDiagram-S5SC5T6Z-MxyaWjjq.js} +2 -2
  96. package/package.json +16 -16
  97. package/src/__mocks__/requests.ts +0 -1
  98. package/src/__tests__/module-entry.test.ts +44 -0
  99. package/src/__tests__/mount.test.ts +1 -21
  100. package/src/__tests__/{host-imports.test.ts → replica-imports.test.ts} +12 -11
  101. package/src/components/ai/__tests__/ai-model-dropdown.test.tsx +63 -0
  102. package/src/components/ai/ai-model-dropdown.tsx +11 -6
  103. package/src/components/app-config/ai-config.tsx +7 -2
  104. package/src/components/app-config/user-config-form.tsx +35 -0
  105. package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
  106. package/src/components/chat/acp/__tests__/session-tabs.test.tsx +43 -0
  107. package/src/components/chat/acp/__tests__/state.test.ts +2 -2
  108. package/src/components/chat/acp/blocks.tsx +3 -2
  109. package/src/components/chat/acp/session-tabs.tsx +8 -3
  110. package/src/components/chat/chat-components.tsx +2 -0
  111. package/src/components/chat/chat-panel.tsx +9 -8
  112. package/src/components/chat/chat-utils.ts +4 -8
  113. package/src/components/data-table/TableBottomBar.tsx +4 -1
  114. package/src/components/data-table/TableTopBar.tsx +2 -0
  115. package/src/components/data-table/__tests__/chart-spec-model.test.ts +195 -195
  116. package/src/components/data-table/__tests__/column-explorer.test.tsx +27 -1
  117. package/src/components/data-table/__tests__/columns.test.tsx +105 -0
  118. package/src/components/data-table/__tests__/context-menu-interaction.test.tsx +130 -0
  119. package/src/components/data-table/__tests__/data-table.test.tsx +1 -0
  120. package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
  121. package/src/components/data-table/__tests__/export-actions.test.tsx +105 -0
  122. package/src/components/data-table/__tests__/keyboard-selection.test.tsx +188 -0
  123. package/src/components/data-table/__tests__/pagination.test.tsx +28 -1
  124. package/src/components/data-table/__tests__/search-highlight.test.tsx +109 -0
  125. package/src/components/data-table/__tests__/url-detector.test.tsx +74 -0
  126. package/src/components/data-table/cell-selection/feature.ts +2 -2
  127. package/src/components/data-table/cell-selection/types.ts +2 -2
  128. package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
  129. package/src/components/data-table/charts/__tests__/spec-snapshot.test.ts +20 -20
  130. package/src/components/data-table/charts/__tests__/spec.test.ts +78 -52
  131. package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
  132. package/src/components/data-table/charts/chart-spec/spec.ts +68 -43
  133. package/src/components/data-table/charts/charts.tsx +40 -30
  134. package/src/components/data-table/charts/storage.ts +16 -5
  135. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
  136. package/src/components/data-table/column-summary/chart-spec-model.tsx +23 -16
  137. package/src/components/data-table/column-summary/column-summary.tsx +2 -4
  138. package/src/components/data-table/column-visibility-dropdown.tsx +8 -13
  139. package/src/components/data-table/columns.tsx +45 -46
  140. package/src/components/data-table/context-menu.tsx +36 -20
  141. package/src/components/data-table/data-table.tsx +17 -1
  142. package/src/components/data-table/date-popover.tsx +6 -4
  143. package/src/components/data-table/export-actions.tsx +76 -48
  144. package/src/components/data-table/pagination.tsx +44 -33
  145. package/src/components/data-table/range-focus/atoms.ts +4 -6
  146. package/src/components/data-table/range-focus/use-cell-range-selection.ts +65 -38
  147. package/src/components/data-table/range-focus/use-scroll-into-view.ts +21 -2
  148. package/src/components/data-table/renderers.tsx +16 -7
  149. package/src/components/data-table/row-viewer-panel/__tests__/row-viewer.test.tsx +24 -1
  150. package/src/components/data-table/row-viewer-panel/row-viewer.tsx +4 -4
  151. package/src/components/data-table/search-highlight.tsx +79 -0
  152. package/src/components/data-table/types.ts +1 -0
  153. package/src/components/data-table/url-detector.tsx +49 -9
  154. package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
  155. package/src/components/datasources/__tests__/column-preview.test.tsx +98 -5
  156. package/src/components/datasources/__tests__/datasources-interactions.test.tsx +181 -0
  157. package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
  158. package/src/components/datasources/__tests__/utils.test.ts +57 -6
  159. package/src/components/datasources/column-preview.tsx +13 -4
  160. package/src/components/datasources/datasources.tsx +51 -39
  161. package/src/components/datasources/utils.ts +32 -23
  162. package/src/components/debugger/debugger-code.tsx +5 -0
  163. package/src/components/dependency-graph/dependency-graph-tree.tsx +8 -8
  164. package/src/components/dependency-graph/elements.ts +24 -21
  165. package/src/components/dependency-graph/panels.tsx +2 -1
  166. package/src/components/dependency-graph/utils/__tests__/layout.test.ts +18 -11
  167. package/src/components/editor/SortableCell.tsx +1 -3
  168. package/src/{core/attachments/__tests__/toast.test.tsx → components/editor/__tests__/agent-toast.test.tsx} +1 -1
  169. package/src/components/editor/__tests__/data-attributes.test.tsx +6 -2
  170. package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
  171. package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
  172. package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +24 -0
  173. package/src/components/editor/actions/pair-with-agent-modal.tsx +18 -15
  174. package/src/components/editor/actions/useRestartKernel.tsx +1 -1
  175. package/src/components/editor/ai/add-cell-with-ai.tsx +3 -3
  176. package/src/components/editor/ai/ai-completion-editor.tsx +1 -0
  177. package/src/components/editor/alerts/__tests__/connection-notice.test.tsx +1 -1
  178. package/src/components/editor/alerts/connection-notice.tsx +1 -1
  179. package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
  180. package/src/components/editor/app-container.tsx +1 -1
  181. package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +1 -1
  182. package/src/components/editor/cell/CreateCellButton.tsx +10 -12
  183. package/src/components/editor/cell/DeleteButton.tsx +3 -2
  184. package/src/components/editor/cell/RunButton.tsx +2 -2
  185. package/src/components/editor/cell/StagedAICell.tsx +10 -2
  186. package/src/components/editor/cell/StopButton.tsx +2 -2
  187. package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
  188. package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
  189. package/src/components/editor/cell/code/cell-editor.tsx +9 -16
  190. package/src/components/editor/cell/code/language-toggle.tsx +8 -7
  191. package/src/components/editor/cell/collapse.tsx +5 -3
  192. package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
  193. package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +1 -1
  194. package/src/components/editor/chrome/components/feedback-button.tsx +1 -1
  195. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +31 -2
  196. package/src/components/editor/chrome/panels/__tests__/runtime-details.test.tsx +1 -1
  197. package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +1 -1
  198. package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
  199. package/src/components/editor/chrome/panels/outline/__tests__/outline-keyboard.test.tsx +84 -0
  200. package/src/components/editor/chrome/panels/outline/floating-outline.tsx +39 -14
  201. package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +3 -2
  202. package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
  203. package/src/components/editor/chrome/panels/secrets-panel.tsx +1 -0
  204. package/src/components/editor/chrome/panels/snippets-panel.tsx +5 -1
  205. package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +9 -18
  206. package/src/components/editor/chrome/wrapper/__tests__/document-sync-status.test.tsx +92 -0
  207. package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +58 -1
  208. package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +4 -4
  209. package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +1 -1
  210. package/src/components/editor/chrome/wrapper/footer-items/document-sync-status.tsx +54 -0
  211. package/src/components/editor/chrome/wrapper/footer-items/lsp-status.tsx +1 -1
  212. package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +1 -1
  213. package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
  214. package/src/components/editor/chrome/wrapper/footer.tsx +2 -0
  215. package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +12 -2
  216. package/src/components/editor/chrome/wrapper/storage.ts +1 -1
  217. package/src/components/editor/connections/components.tsx +1 -1
  218. package/src/components/editor/controls/Controls.tsx +2 -2
  219. package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
  220. package/src/components/editor/controls/__tests__/keyboard-shortcuts.test.tsx +61 -0
  221. package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +1 -1
  222. package/src/components/editor/controls/command-palette.tsx +22 -10
  223. package/src/components/editor/controls/keyboard-shortcuts.tsx +14 -5
  224. package/src/components/editor/dynamic-favicon.tsx +21 -40
  225. package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +9 -23
  226. package/src/components/editor/errors/send-error-report-button.tsx +3 -6
  227. package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
  228. package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +47 -0
  229. package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
  230. package/src/components/editor/file-tree/file-explorer.tsx +45 -8
  231. package/src/components/editor/file-tree/file-name-input.tsx +1 -0
  232. package/src/components/editor/file-tree/file-viewer.tsx +4 -2
  233. package/src/components/editor/file-tree/use-file-search.ts +35 -21
  234. package/src/components/editor/header/__tests__/status.test.tsx +5 -3
  235. package/src/components/editor/header/app-header.tsx +1 -1
  236. package/src/components/editor/header/status.tsx +40 -20
  237. package/src/components/editor/links/__tests__/cell-link.test.tsx +146 -0
  238. package/src/components/editor/links/cell-link.tsx +14 -5
  239. package/src/components/editor/navigation/focus-utils.ts +4 -4
  240. package/src/components/editor/notebook-banner.tsx +1 -0
  241. package/src/components/editor/notebook-cell.tsx +12 -3
  242. package/src/components/editor/output/MarimoErrorOutput.tsx +2 -1
  243. package/src/components/editor/output/MarimoTracebackOutput.tsx +19 -17
  244. package/src/components/editor/output/Outputs.css +8 -0
  245. package/src/components/editor/output/__tests__/traceback.test.tsx +27 -1
  246. package/src/components/editor/output/ansi-reduce.ts +33 -20
  247. package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
  248. package/src/components/editor/package-alert.tsx +14 -7
  249. package/src/components/editor/renderers/grid-layout/grid-layout.tsx +12 -6
  250. package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
  251. package/src/components/home/components.tsx +17 -31
  252. package/src/components/icons/__tests__/large-spinner.test.tsx +39 -0
  253. package/src/components/icons/large-spinner.tsx +3 -14
  254. package/src/components/icons/spinner.tsx +1 -1
  255. package/src/components/mcp/mcp-status-indicator.tsx +1 -1
  256. package/src/components/pages/__tests__/home-page.test.tsx +116 -0
  257. package/src/components/pages/home-page.tsx +164 -91
  258. package/src/components/scratchpad/scratchpad.test.tsx +95 -0
  259. package/src/components/scratchpad/scratchpad.tsx +16 -3
  260. package/src/components/slides/reveal-component.tsx +4 -2
  261. package/src/components/slides/slide-cell-view.tsx +1 -1
  262. package/src/components/slides/slide-form.tsx +1 -0
  263. package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
  264. package/src/components/tracing/tracing.tsx +45 -41
  265. package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
  266. package/src/components/ui/__tests__/range-slider.test.tsx +165 -0
  267. package/src/components/ui/alert-dialog.tsx +1 -1
  268. package/src/components/ui/draggable-popover.tsx +24 -2
  269. package/src/components/ui/range-slider.tsx +22 -9
  270. package/src/core/ai/__tests__/staged-cells.test.ts +8 -5
  271. package/src/core/ai/context/providers/datasource.ts +6 -2
  272. package/src/core/ai/staged-cells.ts +7 -2
  273. package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +3 -15
  274. package/src/core/ai/tools/base.ts +16 -7
  275. package/src/core/ai/tools/edit-notebook-tool.ts +61 -48
  276. package/src/core/ai/tools/registry.ts +13 -8
  277. package/src/core/ai/tools/sample-tool.ts +6 -7
  278. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -0
  279. package/src/core/cells/__tests__/cell.test.ts +39 -0
  280. package/src/core/cells/__tests__/cells.test.ts +3 -298
  281. package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
  282. package/src/core/cells/__tests__/document.test.ts +410 -0
  283. package/src/core/cells/__tests__/flush-document.test.ts +40 -0
  284. package/src/core/cells/__tests__/notebook-outline.test.ts +108 -0
  285. package/src/core/cells/__tests__/session.test.ts +117 -36
  286. package/src/core/cells/__tests__/with-document-save.test.ts +67 -0
  287. package/src/core/cells/cell.ts +14 -3
  288. package/src/core/cells/cells.ts +30 -159
  289. package/src/core/cells/columns.ts +38 -0
  290. package/src/core/cells/document.ts +360 -0
  291. package/src/core/cells/pending-delete-service.ts +2 -6
  292. package/src/core/cells/session.ts +1 -1
  293. package/src/core/cells/types.ts +22 -1
  294. package/src/core/codemirror/__tests__/setup.test.ts +29 -29
  295. package/src/core/codemirror/ai/__tests__/resources.test.ts +117 -0
  296. package/src/core/codemirror/ai/resources.ts +1 -1
  297. package/src/core/codemirror/cells/__tests__/extensions.test.ts +42 -1
  298. package/src/core/codemirror/cells/extensions.ts +21 -3
  299. package/src/core/codemirror/format.ts +6 -5
  300. package/src/core/codemirror/keymaps/vim.ts +2 -6
  301. package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
  302. package/src/core/codemirror/language/__tests__/utils.test.ts +187 -15
  303. package/src/core/codemirror/language/cell-code.ts +114 -0
  304. package/src/core/codemirror/language/extension.ts +52 -35
  305. package/src/core/codemirror/language/languages/markdown.ts +8 -6
  306. package/src/core/codemirror/language/languages/python.ts +16 -10
  307. package/src/core/codemirror/language/languages/sql/sql.ts +16 -24
  308. package/src/core/codemirror/language/panel/panel.tsx +1 -0
  309. package/src/core/codemirror/language/types.ts +7 -7
  310. package/src/core/codemirror/language/utils.ts +9 -39
  311. package/src/core/codemirror/lsp/notebook-lsp.ts +6 -5
  312. package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
  313. package/src/core/codemirror/readonly/extension.ts +2 -2
  314. package/src/core/codemirror/rtc/extension.ts +24 -13
  315. package/src/core/codemirror/rtc/loro/awareness.ts +34 -19
  316. package/src/core/codemirror/rtc/loro/sync.ts +1 -0
  317. package/src/core/codemirror/utils.ts +1 -0
  318. package/src/core/config/__tests__/config-schema.test.ts +5 -3
  319. package/src/core/config/config-schema.ts +3 -0
  320. package/src/core/datasets/__tests__/data-source-discovery.test.ts +5 -5
  321. package/src/core/datasets/data-source-discovery.ts +4 -6
  322. package/src/core/edit-app.tsx +6 -5
  323. package/src/core/errors/error-entries.ts +3 -0
  324. package/src/core/export/hooks.ts +1 -1
  325. package/src/core/export/layout.ts +2 -2
  326. package/src/core/hotkeys/actions.ts +2 -4
  327. package/src/core/islands/__tests__/bootstrap.test.ts +16 -42
  328. package/src/core/islands/__tests__/bridge.test.ts +31 -26
  329. package/src/core/islands/bootstrap.ts +22 -52
  330. package/src/core/islands/bridge.ts +31 -21
  331. package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
  332. package/src/core/islands/worker/__tests__/controller.test.ts +62 -4
  333. package/src/core/islands/worker/controller.ts +4 -10
  334. package/src/core/islands/worker/worker.tsx +33 -33
  335. package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
  336. package/src/core/network/__tests__/connection.test.ts +1 -1
  337. package/src/core/network/connection-notice.ts +1 -1
  338. package/src/core/network/connection.ts +5 -3
  339. package/src/core/network/requests-lazy.ts +1 -2
  340. package/src/core/network/requests-network.ts +0 -9
  341. package/src/core/network/requests-static.ts +0 -1
  342. package/src/core/network/requests-toasting.tsx +0 -1
  343. package/src/core/network/types.ts +0 -5
  344. package/src/core/network/useConnectionNotice.ts +8 -2
  345. package/src/core/notebook/attachments.ts +38 -0
  346. package/src/core/notebook/document/__tests__/codemirror.test.ts +547 -0
  347. package/src/core/notebook/document/__tests__/draft.test.ts +322 -0
  348. package/src/core/notebook/document/__tests__/fixtures.ts +92 -0
  349. package/src/core/notebook/document/__tests__/hold.test.ts +88 -0
  350. package/src/core/notebook/document/__tests__/hooks.test.tsx +391 -0
  351. package/src/core/notebook/document/__tests__/lifecycle-scenarios.test.ts +61 -0
  352. package/src/core/notebook/document/__tests__/model.test.ts +247 -0
  353. package/src/core/notebook/document/__tests__/protocol-fixtures.ts +38 -0
  354. package/src/core/notebook/document/__tests__/recovery-scenarios.test.ts +230 -0
  355. package/src/core/notebook/document/__tests__/scenario-fixture.ts +43 -0
  356. package/src/core/notebook/document/__tests__/scenarios.test.ts +205 -0
  357. package/src/core/notebook/document/__tests__/state.test.ts +438 -0
  358. package/src/core/notebook/document/__tests__/submission.test.ts +203 -0
  359. package/src/core/notebook/document/__tests__/test-host.test.ts +92 -0
  360. package/src/core/notebook/document/__tests__/test-host.ts +247 -0
  361. package/src/core/notebook/document/__tests__/test-notebook.ts +149 -0
  362. package/src/core/notebook/document/__tests__/user.ts +61 -0
  363. package/src/core/notebook/document/codemirror.ts +216 -0
  364. package/src/core/notebook/document/draft.ts +472 -0
  365. package/src/core/notebook/document/hooks.tsx +118 -0
  366. package/src/core/notebook/document/index.ts +23 -0
  367. package/src/core/notebook/document/model.ts +105 -0
  368. package/src/core/notebook/document/select.ts +41 -0
  369. package/src/core/notebook/document/state.ts +374 -0
  370. package/src/core/notebook/document/sync.ts +418 -0
  371. package/src/core/notebook/index.ts +18 -0
  372. package/src/core/notebook/replica/AGENTS.md +11 -0
  373. package/src/core/notebook/replica/__tests__/attachments.test.ts +56 -0
  374. package/src/core/notebook/replica/__tests__/document.test.ts +126 -0
  375. package/src/core/notebook/replica/__tests__/fixtures.ts +79 -0
  376. package/src/core/notebook/replica/__tests__/replica.test.ts +550 -0
  377. package/src/core/notebook/replica/backend.ts +19 -0
  378. package/src/core/notebook/replica/connection.ts +42 -0
  379. package/src/core/notebook/replica/index.ts +13 -0
  380. package/src/core/notebook/replica/replica.ts +286 -0
  381. package/src/core/notebook/replica/resources/attachments.ts +22 -0
  382. package/src/core/notebook/replica/resources/document.ts +101 -0
  383. package/src/core/packages/__tests__/useSandboxController.test.tsx +1 -1
  384. package/src/core/packages/useSandboxController.ts +1 -1
  385. package/src/core/run-app.tsx +47 -44
  386. package/src/core/runtime/__tests__/adapter.test.ts +1 -1
  387. package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
  388. package/src/core/runtime/__tests__/runtime.test.ts +32 -58
  389. package/src/core/runtime/adapter.ts +1 -1
  390. package/src/core/runtime/config.ts +2 -2
  391. package/src/core/runtime/runtime.ts +38 -42
  392. package/src/core/runtime/types.ts +0 -2
  393. package/src/core/saving/filename.ts +1 -1
  394. package/src/core/saving/save-component.tsx +10 -4
  395. package/src/core/saving/useAutoSave.ts +1 -1
  396. package/src/core/session/__tests__/backend.test.ts +235 -0
  397. package/src/core/session/__tests__/useNotebookReplica.hook.test.tsx +183 -0
  398. package/src/core/session/__tests__/useNotebookSession.hook.test.tsx +669 -0
  399. package/src/core/session/active-notebook.ts +11 -0
  400. package/src/core/session/backend.ts +125 -0
  401. package/src/core/{websocket → session}/types.ts +2 -2
  402. package/src/core/session/useNotebookReplica.ts +72 -0
  403. package/src/core/{websocket → session}/useNotebookSession.tsx +56 -43
  404. package/src/core/state/__tests__/jotai.test.tsx +108 -0
  405. package/src/core/state/jotai.ts +1 -1
  406. package/src/core/static/__tests__/files.test.ts +38 -10
  407. package/src/core/static/files.ts +2 -0
  408. package/src/core/{websocket → transports}/__tests__/connection-state.test.ts +1 -13
  409. package/src/core/transports/__tests__/server.test.ts +408 -0
  410. package/src/core/transports/__tests__/static.test.ts +175 -0
  411. package/src/core/transports/__tests__/wasm.test.ts +166 -0
  412. package/src/core/{websocket → transports}/connection-state.ts +9 -16
  413. package/src/core/transports/server.ts +152 -0
  414. package/src/core/transports/static.ts +84 -0
  415. package/src/core/transports/wasm.ts +97 -0
  416. package/src/core/wasm/__tests__/bridge.test.ts +213 -50
  417. package/src/core/wasm/__tests__/worker.test.ts +187 -0
  418. package/src/core/wasm/bridge.ts +75 -53
  419. package/src/core/wasm/rpc.ts +15 -3
  420. package/src/core/wasm/store.ts +3 -3
  421. package/src/core/wasm/worker/bootstrap.ts +55 -51
  422. package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
  423. package/src/core/wasm/worker/save-worker.ts +9 -10
  424. package/src/core/wasm/worker/types.ts +29 -18
  425. package/src/core/wasm/worker/worker.ts +88 -44
  426. package/src/css/globals.css +10 -0
  427. package/src/hooks/__tests__/useAsyncData.test.tsx +148 -0
  428. package/src/hooks/__tests__/useDebounce.test.tsx +51 -0
  429. package/src/hooks/__tests__/useDeepCompareMemoize.test.tsx +39 -0
  430. package/src/hooks/__tests__/useDelayElapsed.test.tsx +28 -0
  431. package/src/hooks/__tests__/useInternalStateWithSync.test.tsx +20 -0
  432. package/src/hooks/__tests__/useScript.test.tsx +77 -0
  433. package/src/hooks/__tests__/useStateForKey.test.tsx +257 -0
  434. package/src/hooks/useAsyncData.ts +3 -3
  435. package/src/hooks/useDataSourceDiscovery.ts +6 -4
  436. package/src/hooks/useDebounce.ts +6 -10
  437. package/src/hooks/useDeepCompareMemoize.ts +1 -1
  438. package/src/hooks/useDelayElapsed.ts +14 -10
  439. package/src/hooks/useElapsedTime.ts +3 -3
  440. package/src/hooks/useEventListener.ts +1 -2
  441. package/src/hooks/useInputHistory.ts +4 -7
  442. package/src/hooks/useInternalStateWithSync.ts +6 -6
  443. package/src/hooks/useResizeObserver.ts +4 -7
  444. package/src/hooks/useScript.ts +67 -70
  445. package/src/hooks/useStateForKey.ts +93 -0
  446. package/src/mount.tsx +1 -5
  447. package/src/plugins/__tests__/plugin-object-schemas.test.ts +104 -0
  448. package/src/plugins/core/registerReactComponent.tsx +1 -1
  449. package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
  450. package/src/plugins/impl/DataEditorPlugin.tsx +1 -1
  451. package/src/plugins/impl/DataTablePlugin.tsx +69 -37
  452. package/src/plugins/impl/DropdownPlugin.tsx +2 -6
  453. package/src/plugins/impl/FileBrowserPlugin.tsx +4 -16
  454. package/src/plugins/impl/FormPlugin.tsx +1 -1
  455. package/src/plugins/impl/RangeSliderPlugin.tsx +16 -2
  456. package/src/plugins/impl/RefreshPlugin.tsx +1 -0
  457. package/src/plugins/impl/SliderPlugin.tsx +6 -8
  458. package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +387 -1
  459. package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
  460. package/src/plugins/impl/__tests__/RangeSliderPlugin.test.tsx +109 -0
  461. package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
  462. package/src/plugins/impl/anywidget/__tests__/registry.test.ts +153 -0
  463. package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
  464. package/src/plugins/impl/anywidget/model.ts +3 -1
  465. package/src/plugins/impl/anywidget/registry.ts +18 -14
  466. package/src/plugins/impl/anywidget/runtime.ts +21 -9
  467. package/src/plugins/impl/anywidget/widget-binding.ts +160 -82
  468. package/src/plugins/impl/chat/__tests__/chat-prompts.test.tsx +93 -0
  469. package/src/plugins/impl/chat/chat-ui.tsx +14 -11
  470. package/src/plugins/impl/code/any-language-editor.tsx +2 -2
  471. package/src/plugins/impl/data-editor/glide-data-editor.tsx +8 -5
  472. package/src/plugins/impl/data-editor/glide-utils.ts +3 -1
  473. package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
  474. package/src/plugins/impl/data-explorer/components/column-summary.tsx +4 -2
  475. package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
  476. package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -2
  477. package/src/plugins/impl/data-frames/__tests__/sidebar.test.tsx +160 -0
  478. package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +66 -66
  479. package/src/plugins/impl/data-frames/panel.tsx +43 -16
  480. package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
  481. package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
  482. package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
  483. package/src/plugins/impl/panel/utils.ts +17 -0
  484. package/src/plugins/impl/plotly/PlotlyPlugin.tsx +2 -5
  485. package/src/plugins/impl/plotly/selection.ts +25 -19
  486. package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
  487. package/src/plugins/impl/vega/make-selectable.ts +4 -7
  488. package/src/plugins/layout/RoutesPlugin.tsx +1 -1
  489. package/src/stories/__tests__/editor-story.test.tsx +33 -0
  490. package/src/stories/button.stories.tsx +1 -0
  491. package/src/stories/cell.stories.tsx +1 -1
  492. package/src/stories/data-table.stories.tsx +31 -0
  493. package/src/stories/editor.stories.tsx +24 -17
  494. package/src/stories/form-wrapper.stories.tsx +2 -2
  495. package/src/stories/layout/vertical/one-column.stories.tsx +1 -1
  496. package/src/stories/runtime-story.tsx +1 -1
  497. package/src/stories/select.stories.tsx +2 -2
  498. package/src/stories/switchable-multi-select.stories.tsx +1 -1
  499. package/src/utils/__tests__/arrays.test.ts +35 -0
  500. package/src/utils/__tests__/batch-requests.test.ts +3 -3
  501. package/src/utils/__tests__/{createReducer.test.ts → createReducer.test.tsx} +29 -0
  502. package/src/utils/__tests__/numbers.test.ts +105 -1
  503. package/src/utils/__tests__/objects.test.ts +21 -0
  504. package/src/utils/arrays.ts +11 -2
  505. package/src/utils/blob.ts +1 -1
  506. package/src/utils/createReducer.ts +53 -26
  507. package/src/utils/maps.ts +0 -3
  508. package/src/utils/numbers.ts +79 -18
  509. package/src/utils/objects.ts +4 -9
  510. package/src/utils/once.ts +19 -19
  511. package/src/utils/tracer.ts +9 -5
  512. package/src/utils/zod-utils.ts +1 -3
  513. package/dist/any-language-editor-DZ_YTVus.js +0 -76
  514. package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
  515. package/dist/assets/worker-HPY9fbhz.js +0 -114
  516. package/dist/mermaid-HWGCJPDP-ByCsZnYF.js +0 -2
  517. package/dist/precisionRound-DMIVQrt2.js +0 -97
  518. package/src/core/attachments/state.ts +0 -21
  519. package/src/core/cells/__tests__/apply-transaction.test.ts +0 -991
  520. package/src/core/cells/__tests__/document-changes.test.ts +0 -1140
  521. package/src/core/cells/__tests__/document-roundtrip.test.ts +0 -392
  522. package/src/core/cells/document-changes.ts +0 -944
  523. package/src/core/host/AGENTS.md +0 -6
  524. package/src/core/host/__tests__/events.test.ts +0 -46
  525. package/src/core/host/__tests__/notebook-client.test.ts +0 -191
  526. package/src/core/host/__tests__/protocol.test.ts +0 -214
  527. package/src/core/host/connection.ts +0 -81
  528. package/src/core/host/events.ts +0 -60
  529. package/src/core/host/notebook-client.ts +0 -226
  530. package/src/core/host/protocol.ts +0 -1943
  531. package/src/core/state/__tests__/jotai.test.ts +0 -25
  532. package/src/core/wasm/worker/message-buffer.ts +0 -33
  533. package/src/core/websocket/__tests__/createConnectionTransport.test.ts +0 -49
  534. package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +0 -140
  535. package/src/core/websocket/__tests__/useNotebookSession.hook.test.tsx +0 -883
  536. package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
  537. package/src/core/websocket/transports/__tests__/sse.test.ts +0 -335
  538. package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
  539. package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
  540. package/src/core/websocket/transports/basic.ts +0 -102
  541. package/src/core/websocket/transports/create.ts +0 -31
  542. package/src/core/websocket/transports/sse.ts +0 -308
  543. package/src/core/websocket/transports/transport.ts +0 -50
  544. package/src/core/websocket/transports/ws.ts +0 -98
  545. package/src/core/websocket/useNotebookClient.ts +0 -80
  546. /package/src/{core/attachments/toast.ts → components/editor/agent-toast.ts} +0 -0
  547. /package/src/core/{websocket → session}/connection-utils.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  import { closeCompletion, completionStatus } from "@codemirror/autocomplete";
4
- import { type Extension, Prec } from "@codemirror/state";
4
+ import { type Extension, Prec, Transaction } from "@codemirror/state";
5
5
  import {
6
6
  EditorView,
7
7
  type KeyBinding,
@@ -325,6 +325,11 @@ function cellKeymaps({
325
325
  function cellCodeEditing(hotkeys: HotkeyProvider): Extension[] {
326
326
  const onChangePlugin = EditorView.updateListener.of((update) => {
327
327
  if (update.docChanged) {
328
+ // Loro already applied a collaborator's change here. The client that
329
+ // typed it syncs it to the document.
330
+ if (isCollaboratorUpdate(update.transactions)) {
331
+ return;
332
+ }
328
333
  // Check if the doc update was a formatting change
329
334
  // e.g. changing from python to markdown
330
335
  const isFormattingChange = update.transactions.some((tr) =>
@@ -350,6 +355,14 @@ function cellCodeEditing(hotkeys: HotkeyProvider): Extension[] {
350
355
  return [onChangePlugin, formatKeymapExtension(hotkeys)];
351
356
  }
352
357
 
358
+ /** Whether every transaction in an update arrived from a collaborator through Loro. */
359
+ function isCollaboratorUpdate(transactions: readonly Transaction[]): boolean {
360
+ return (
361
+ transactions.length > 0 &&
362
+ transactions.every((tr) => tr.annotation(loroSyncAnnotation) !== undefined)
363
+ );
364
+ }
365
+
353
366
  const MARKDOWN_AUTORUN_USER_EVENTS = ["input", "delete", "undo", "redo"];
354
367
 
355
368
  function shouldAutorunMarkdownUpdate({
@@ -382,8 +395,12 @@ function shouldAutorunMarkdownUpdate({
382
395
  }
383
396
 
384
397
  return transactions.some((tr) => {
385
- // Ignore RTC sync changes to avoid duplicate runs from remote edits.
386
- if (tr.annotation(loroSyncAnnotation) !== undefined) {
398
+ // Ignore remote changes to avoid duplicate runs. The client that made the
399
+ // edit runs it.
400
+ if (
401
+ tr.annotation(Transaction.remote) ||
402
+ tr.annotation(loroSyncAnnotation) !== undefined
403
+ ) {
387
404
  return false;
388
405
  }
389
406
 
@@ -463,5 +480,6 @@ export function cellBundle({
463
480
  }
464
481
 
465
482
  export const exportedForTesting = {
483
+ isCollaboratorUpdate,
466
484
  shouldAutorunMarkdownUpdate,
467
485
  };
@@ -18,10 +18,8 @@ import { cellIdState } from "./config/extension";
18
18
  import { languageAdapterState } from "./language/extension";
19
19
  import { SCHEMA_CACHE } from "./language/languages/sql/completion-store";
20
20
  import { isKnownDialect } from "./language/languages/sql/utils";
21
- import {
22
- getEditorCodeAsPython,
23
- updateEditorCodeFromPython,
24
- } from "./language/utils";
21
+ import { prepareCellCodeUpdate } from "./language/cell-code";
22
+ import { getEditorCodeAsPython } from "./language/utils";
25
23
  import { replaceEditorContent } from "./replace-editor-content";
26
24
 
27
25
  export const formattingChangeEffect = StateEffect.define<boolean>();
@@ -62,7 +60,10 @@ export async function formatEditorViews(views: Record<CellId, EditorView>) {
62
60
  code: formattedCode,
63
61
  formattingChange: true,
64
62
  });
65
- updateEditorCodeFromPython(view, formattedCode);
63
+ const update = prepareCellCodeUpdate(view.state, formattedCode);
64
+ if (update) {
65
+ view.dispatch(update);
66
+ }
66
67
  }
67
68
  }
68
69
 
@@ -369,7 +369,7 @@ class CodeMirrorVimSync {
369
369
  // We use onIdle to keep the focused editor snappy
370
370
  onIdle(() => {
371
371
  if (!skipBroadcast) {
372
- this.broadcastModeChange(instance, e.mode, e.subMode);
372
+ this.broadcastModeChange(instance, e.mode);
373
373
  }
374
374
  this.isBroadcasting = false;
375
375
  });
@@ -380,11 +380,7 @@ class CodeMirrorVimSync {
380
380
  this.instances.delete(instance);
381
381
  }
382
382
 
383
- public broadcastModeChange(
384
- originInstance: EditorView,
385
- mode: string,
386
- subMode?: string,
387
- ) {
383
+ public broadcastModeChange(originInstance: EditorView, mode: string) {
388
384
  invariant(
389
385
  "exitInsertMode" in Vim,
390
386
  "Vim does not have an exitInsertMode method",
@@ -42,12 +42,14 @@ const adapter = new SQLLanguageAdapter();
42
42
  const TEST_ENGINE = "test_engine" as ConnectionName;
43
43
 
44
44
  const TEST_EXTENSION_ARGS = [
45
- {} as CellId,
46
- {} as CompletionConfig,
47
- {} as HotkeyProvider,
48
- {} as PlaceholderType,
49
- {} as LSPConfig & {
50
- diagnostics: DiagnosticsConfig;
45
+ {
46
+ cellId: {} as CellId,
47
+ completionConfig: {} as CompletionConfig,
48
+ hotkeys: {} as HotkeyProvider,
49
+ placeholderType: {} as PlaceholderType,
50
+ lspConfig: {} as LSPConfig & {
51
+ diagnostics: DiagnosticsConfig;
52
+ },
51
53
  },
52
54
  ] as const;
53
55
 
@@ -930,15 +932,15 @@ describe("SQL analysis features", () => {
930
932
 
931
933
  it("reports semantic diagnostics as warnings", async () => {
932
934
  const adapter = new SQLLanguageAdapter();
933
- const extensions = adapter.getExtension(
934
- {} as CellId,
935
- {} as CompletionConfig,
936
- {} as HotkeyProvider,
937
- {} as PlaceholderType,
938
- {
935
+ const extensions = adapter.getExtension({
936
+ cellId: {} as CellId,
937
+ completionConfig: {} as CompletionConfig,
938
+ hotkeys: {} as HotkeyProvider,
939
+ placeholderType: {} as PlaceholderType,
940
+ lspConfig: {
939
941
  diagnostics: { sql_linter: true },
940
942
  } as LSPConfig & { diagnostics: DiagnosticsConfig },
941
- );
943
+ });
942
944
  const state = EditorState.create({
943
945
  doc: "SELECT missing FROM users",
944
946
  extensions: [languageMetadataField.init(() => metadata), ...extensions],
@@ -963,15 +965,15 @@ describe("SQL analysis features", () => {
963
965
 
964
966
  it("does not report unknown tables", async () => {
965
967
  const adapter = new SQLLanguageAdapter();
966
- const extensions = adapter.getExtension(
967
- {} as CellId,
968
- {} as CompletionConfig,
969
- {} as HotkeyProvider,
970
- {} as PlaceholderType,
971
- {
968
+ const extensions = adapter.getExtension({
969
+ cellId: {} as CellId,
970
+ completionConfig: {} as CompletionConfig,
971
+ hotkeys: {} as HotkeyProvider,
972
+ placeholderType: {} as PlaceholderType,
973
+ lspConfig: {
972
974
  diagnostics: { sql_linter: true },
973
975
  } as LSPConfig & { diagnostics: DiagnosticsConfig },
974
- );
976
+ });
975
977
  const state = EditorState.create({
976
978
  doc: "SELECT missing FROM users; SELECT * FROM unknown_table",
977
979
  extensions: [languageMetadataField.init(() => metadata), ...extensions],
@@ -1,23 +1,35 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import { EditorState } from "@codemirror/state";
3
+ import { history, redo, undo } from "@codemirror/commands";
4
+ import { EditorSelection, EditorState, StateEffect } from "@codemirror/state";
4
5
  import { EditorView } from "@codemirror/view";
5
- import { describe, expect, it } from "vitest";
6
+ import { afterEach, describe, expect, it } from "vitest";
6
7
  import { cellId } from "@/__tests__/branded";
7
8
  import { OverridingHotkeyProvider } from "@/core/hotkeys/hotkeys";
8
9
  import { cellConfigExtension } from "../../config/extension";
9
- import { adaptiveLanguageConfiguration, switchLanguage } from "../extension";
10
+ import { prepareCellCodeUpdate } from "../cell-code";
11
+ import { languageMetadataField } from "../metadata";
10
12
  import {
11
- getEditorCodeAsPython,
12
- splitEditor,
13
- updateEditorCodeFromPython,
14
- } from "../utils";
13
+ adaptiveLanguageConfiguration,
14
+ languageAdapterState,
15
+ switchLanguage,
16
+ } from "../extension";
17
+ import { getEditorCodeAsPython, splitEditor } from "../utils";
18
+
19
+ const views: EditorView[] = [];
20
+
21
+ afterEach(() => {
22
+ for (const view of views.splice(0)) {
23
+ view.destroy();
24
+ }
25
+ });
15
26
 
16
27
  function createEditor(doc: string) {
17
- return new EditorView({
28
+ const view = new EditorView({
18
29
  state: EditorState.create({
19
30
  doc,
20
31
  extensions: [
32
+ history(),
21
33
  adaptiveLanguageConfiguration({
22
34
  completionConfig: {
23
35
  activate_on_typing: true,
@@ -50,6 +62,8 @@ function createEditor(doc: string) {
50
62
  ],
51
63
  }),
52
64
  });
65
+ views.push(view);
66
+ return view;
53
67
  }
54
68
 
55
69
  describe("getEditorCodeAsPython", () => {
@@ -72,14 +86,172 @@ describe("getEditorCodeAsPython", () => {
72
86
  });
73
87
  });
74
88
 
75
- describe("updateEditorCodeFromPython", () => {
76
- it("should update the editor code with the provided Python code", () => {
77
- const mockEditor = createEditor("");
78
- const pythonCode = "print('Hello, World!')";
79
- const result = updateEditorCodeFromPython(mockEditor, pythonCode);
80
- expect(result).toEqual(pythonCode);
81
- expect(mockEditor.state.doc.toString()).toEqual(pythonCode);
89
+ describe("prepareCellCodeUpdate transactions", () => {
90
+ it("applies text and metadata together, including metadata-only undo", () => {
91
+ const view = createEditor('mo.md(r"hi")');
92
+ switchLanguage(view, { language: "markdown" });
93
+ const observed: Array<{ text: string; prefix: string }> = [];
94
+ view.dispatch({
95
+ effects: StateEffect.appendConfig.of(
96
+ EditorView.updateListener.of((update) => {
97
+ if (
98
+ update.transactions.some(
99
+ (tr) => tr.effects.length > 0 || tr.docChanged,
100
+ )
101
+ ) {
102
+ observed.push({
103
+ text: update.state.doc.toString(),
104
+ prefix: update.state.field(languageMetadataField).quotePrefix,
105
+ });
106
+ }
107
+ }),
108
+ ),
109
+ });
110
+ observed.length = 0;
111
+
112
+ view.dispatch(prepareCellCodeUpdate(view.state, 'mo.md(f"hi")')!);
113
+ expect(observed).toEqual([{ text: "hi", prefix: "f" }]);
114
+ expect(undo(view)).toBe(true);
115
+ expect(view.state.field(languageMetadataField).quotePrefix).toBe("r");
116
+ expect(redo(view)).toBe(true);
117
+ expect(view.state.field(languageMetadataField).quotePrefix).toBe("f");
118
+ });
119
+
120
+ it("clears incompatible history while applying a language fallback atomically", () => {
121
+ const view = createEditor('mo.md("hi")');
122
+ switchLanguage(view, { language: "markdown" });
123
+ view.dispatch({ changes: { from: 2, insert: "!" } });
124
+ const observed: Array<{ text: string; language: string }> = [];
125
+ view.dispatch({
126
+ effects: StateEffect.appendConfig.of(
127
+ EditorView.updateListener.of((update) => {
128
+ observed.push({
129
+ text: update.state.doc.toString(),
130
+ language: update.state.field(languageAdapterState).type,
131
+ });
132
+ }),
133
+ ),
134
+ });
135
+ observed.length = 0;
136
+
137
+ view.dispatch(prepareCellCodeUpdate(view.state, "x = 1")!);
138
+ expect(observed).toEqual([{ text: "x = 1", language: "python" }]);
139
+ expect(undo(view)).toBe(false);
140
+ view.dispatch({ changes: { from: 5, insert: "0" } });
141
+ expect(undo(view)).toBe(true);
142
+ expect(view.state.doc.toString()).toBe("x = 1");
82
143
  });
144
+
145
+ it("maps the selection through separate edits and keeps the update undoable", () => {
146
+ const view = createEditor("a = 1\nb = 2\nc = 3");
147
+ view.dispatch({ selection: EditorSelection.range(6, 11) });
148
+ view.dispatch(
149
+ prepareCellCodeUpdate(view.state, "alpha = 1\nb = 2\ncharlie = 3")!,
150
+ );
151
+ expect(
152
+ view.state.sliceDoc(
153
+ view.state.selection.main.from,
154
+ view.state.selection.main.to,
155
+ ),
156
+ ).toBe("b = 2");
157
+ expect(undo(view)).toBe(true);
158
+ expect(view.state.doc.toString()).toBe("a = 1\nb = 2\nc = 3");
159
+ });
160
+
161
+ it.each(["mo.md()", 'mo.md("hi")', 'df = mo.sql("SELECT 1")'])(
162
+ "keeps Python mode when receiving %s",
163
+ (code) => {
164
+ const view = createEditor("mo.md");
165
+ view.dispatch(prepareCellCodeUpdate(view.state, code)!);
166
+ expect({
167
+ language: view.state.field(languageAdapterState).type,
168
+ code: view.state.doc.toString(),
169
+ }).toEqual({ language: "python", code });
170
+ },
171
+ );
172
+
173
+ it.each([
174
+ {
175
+ language: "markdown",
176
+ initial: 'mo.md("hi")',
177
+ next: 'mo.md("bye")',
178
+ text: "bye",
179
+ },
180
+ {
181
+ language: "sql",
182
+ initial: 'df = mo.sql("SELECT 1")',
183
+ next: 'df = mo.sql("SELECT 2")',
184
+ text: "SELECT 2",
185
+ },
186
+ ] as const)(
187
+ "preserves compatible $language mode",
188
+ ({ language, initial, next, text }) => {
189
+ const view = createEditor(initial);
190
+ switchLanguage(view, { language });
191
+ view.dispatch(prepareCellCodeUpdate(view.state, next)!);
192
+ expect({
193
+ language: view.state.field(languageAdapterState).type,
194
+ code: view.state.doc.toString(),
195
+ }).toEqual({ language, code: text });
196
+ },
197
+ );
198
+
199
+ it.each([
200
+ {
201
+ language: "markdown",
202
+ initial: 'mo.md("hi")',
203
+ next: 'df = mo.sql("SELECT 1")',
204
+ },
205
+ {
206
+ language: "sql",
207
+ initial: 'df = mo.sql("SELECT 1")',
208
+ next: 'mo.md("hi")',
209
+ },
210
+ { language: "markdown", initial: 'mo.md("hi")', next: "x = 1" },
211
+ ] as const)(
212
+ "falls back from $language to Python for $next",
213
+ ({ language, initial, next }) => {
214
+ const view = createEditor(initial);
215
+ switchLanguage(view, { language });
216
+ view.dispatch(prepareCellCodeUpdate(view.state, next)!);
217
+ expect({
218
+ language: view.state.field(languageAdapterState).type,
219
+ code: view.state.doc.toString(),
220
+ }).toEqual({ language: "python", code: next });
221
+ },
222
+ );
223
+ });
224
+
225
+ describe("prepareCellCodeUpdate", () => {
226
+ it("does not normalize an editor that already represents the source", () => {
227
+ const view = createEditor('mo.md("hi")');
228
+ switchLanguage(view, { language: "markdown" });
229
+ expect(prepareCellCodeUpdate(view.state, 'mo.md("hi")')).toBeNull();
230
+ view.dispatch({ changes: { from: 2, insert: "\n " } });
231
+ const source = getEditorCodeAsPython(view);
232
+ expect(prepareCellCodeUpdate(view.state, source)).toBeNull();
233
+ expect(view.state.doc.toString()).toBe("hi\n ");
234
+ });
235
+
236
+ it.each(["", 'mo.md(f"hi {x}")'])(
237
+ "prepares initialization from %j without mutating the editor",
238
+ (initial) => {
239
+ const view = createEditor(initial);
240
+ const update = prepareCellCodeUpdate(view.state, 'mo.md(f"hi {x}")', {
241
+ initialize: true,
242
+ });
243
+ expect(view.state.doc.toString()).toBe(initial);
244
+ expect(view.state.field(languageAdapterState).type).toBe("python");
245
+ expect(update).not.toBeNull();
246
+ if (update) {
247
+ view.dispatch(update);
248
+ }
249
+ expect(view.state.doc.toString()).toBe("hi {x}");
250
+ expect(view.state.field(languageAdapterState).type).toBe("markdown");
251
+ expect(view.state.field(languageMetadataField).quotePrefix).toBe("f");
252
+ expect(undo(view)).toBe(false);
253
+ },
254
+ );
83
255
  });
84
256
 
85
257
  describe("splitEditor", () => {
@@ -0,0 +1,114 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { diff } from "@codemirror/merge";
4
+ import {
5
+ type EditorState,
6
+ type StateEffect,
7
+ Transaction,
8
+ type TransactionSpec,
9
+ } from "@codemirror/state";
10
+ import { suppressSignatureHelp } from "@marimo-team/codemirror-languageserver";
11
+ import { dequal } from "dequal";
12
+ import {
13
+ languageAdapterFromCode,
14
+ languageAdapterState,
15
+ languageConfigurationEffects,
16
+ } from "./extension";
17
+ import { LanguageAdapters } from "./LanguageAdapters";
18
+ import { sqlDialectEffect } from "./languages/sql/sql";
19
+ import { languageMetadataField, setLanguageMetadata } from "./metadata";
20
+
21
+ /** The Python source represented by the editor's text and language metadata. */
22
+ export function getCellCode(state: EditorState): string {
23
+ const text = state.doc.toString();
24
+ const adapter = state.field(languageAdapterState, false);
25
+ return adapter
26
+ ? adapter.transformOut(
27
+ text,
28
+ state.field(languageMetadataField, false) ?? {},
29
+ )[0]
30
+ : text;
31
+ }
32
+
33
+ /** Account for adapters normalizing quotes and whitespace when reading source. */
34
+ export function editorShowsCellCode(
35
+ state: EditorState,
36
+ source: string,
37
+ ): boolean {
38
+ if (getCellCode(state) === source) {
39
+ return true;
40
+ }
41
+ const adapter = state.field(languageAdapterState, false);
42
+ if (!adapter?.isSupported(source)) {
43
+ return false;
44
+ }
45
+ const [text, , metadata] = adapter.transformIn(source);
46
+ return (
47
+ text === state.doc.toString() &&
48
+ dequal(metadata, state.field(languageMetadataField, false))
49
+ );
50
+ }
51
+
52
+ /**
53
+ * Prepare one update to the editor's text, language, and metadata.
54
+ * Existing editors keep a compatible mode; only initial loading infers one.
55
+ * The caller decides whether this is a local edit or a remote synchronization.
56
+ */
57
+ export function prepareCellCodeUpdate(
58
+ state: EditorState,
59
+ source: string,
60
+ { initialize = false }: { initialize?: boolean } = {},
61
+ ): TransactionSpec | null {
62
+ const current = state.field(languageAdapterState, false);
63
+ let target = current;
64
+ if (current) {
65
+ if (initialize) {
66
+ target = languageAdapterFromCode(source);
67
+ } else if (!current.isSupported(source)) {
68
+ target = LanguageAdapters.python;
69
+ }
70
+ }
71
+ const languageChanged = target?.type !== current?.type;
72
+ if (!languageChanged && editorShowsCellCode(state, source)) {
73
+ return null;
74
+ }
75
+
76
+ const effects: StateEffect<unknown>[] = [];
77
+ let text = source;
78
+ if (target) {
79
+ if (languageChanged) {
80
+ effects.push(...languageConfigurationEffects(state, target));
81
+ }
82
+ const [inner, , metadata] = target.transformIn(source);
83
+ text = inner;
84
+ const metadataChanged = !dequal(
85
+ metadata,
86
+ state.field(languageMetadataField, false),
87
+ );
88
+ if (metadataChanged) {
89
+ effects.push(setLanguageMetadata.of(metadata));
90
+ }
91
+ if (target.type === "sql" && (languageChanged || metadataChanged)) {
92
+ effects.push(sqlDialectEffect(metadata.engine));
93
+ }
94
+ }
95
+
96
+ // Match the merge view's scan limit so large rewrites stay bounded. The diff
97
+ // maps selections, folds, and diagnostics through each individual edit.
98
+ const changes = diff(state.doc.toString(), text, { scanLimit: 500 }).map(
99
+ (change) => ({
100
+ from: change.fromA,
101
+ to: change.toA,
102
+ insert: text.slice(change.fromB, change.toB),
103
+ }),
104
+ );
105
+ return {
106
+ changes,
107
+ effects,
108
+ annotations: [
109
+ suppressSignatureHelp.of(true),
110
+ // History was reset with the language; the previous text uses another representation.
111
+ ...(languageChanged ? [Transaction.addToHistory.of(false)] : []),
112
+ ],
113
+ };
114
+ }
@@ -1,11 +1,13 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import { history } from "@codemirror/commands";
3
+ import { history, historyField, invertedEffects } from "@codemirror/commands";
4
4
  import {
5
5
  Compartment,
6
6
  EditorSelection,
7
+ EditorState,
7
8
  StateEffect,
8
9
  StateField,
10
+ Transaction,
9
11
  } from "@codemirror/state";
10
12
  import { type EditorView, keymap, showPanel } from "@codemirror/view";
11
13
  import type { CellId } from "@/core/cells/ids";
@@ -25,11 +27,10 @@ import {
25
27
  placeholderState,
26
28
  } from "../config/extension";
27
29
  import type { PlaceholderType } from "../config/types";
28
- import { historyCompartment } from "../editing/extensions";
29
30
  import { formattingChangeEffect } from "../format";
30
31
  import { createPanel } from "../react-dom/createPanel";
31
32
  import { getLanguageAdapters, LanguageAdapters } from "./LanguageAdapters";
32
- import { initializeSQLDialect } from "./languages/sql/sql";
33
+ import { sqlDialectEffect } from "./languages/sql/sql";
33
34
  import type { LanguageMetadata } from "./metadata";
34
35
  import { languageMetadataField, setLanguageMetadata } from "./metadata";
35
36
  import { LanguagePanelComponent } from "./panel/panel";
@@ -42,6 +43,32 @@ import { getEditorCodeAsPython } from "./utils";
42
43
  */
43
44
  const languageCompartment = new Compartment();
44
45
 
46
+ /** Reconfigure a language and discard history written in its previous representation. */
47
+ export function languageConfigurationEffects(
48
+ state: EditorState,
49
+ language: LanguageAdapter,
50
+ ): StateEffect<unknown>[] {
51
+ const extensions = language.getExtension({
52
+ cellId: state.facet(cellIdState),
53
+ completionConfig: state.facet(completionConfigState),
54
+ hotkeys: state.facet(hotkeysProviderState),
55
+ placeholderType: state.facet(placeholderState),
56
+ lspConfig: state.facet(lspConfigState),
57
+ });
58
+ if (state.field(historyField, false) !== undefined) {
59
+ // A fresh initializer resets the history in the same transaction as the language.
60
+ extensions.push(
61
+ historyField.init(() =>
62
+ EditorState.create({ extensions: [history()] }).field(historyField),
63
+ ),
64
+ );
65
+ }
66
+ return [
67
+ setLanguageAdapter.of(language),
68
+ languageCompartment.reconfigure(extensions),
69
+ ];
70
+ }
71
+
45
72
  /**
46
73
  * State effect to set the language adapter.
47
74
  */
@@ -129,11 +156,6 @@ function updateLanguageAdapterAndCode({
129
156
  }) {
130
157
  const currentLanguage = view.state.field(languageAdapterState);
131
158
  const code = view.state.doc.toString();
132
- const completionConfig = view.state.facet(completionConfigState);
133
- const hotkeysProvider = view.state.facet(hotkeysProviderState);
134
- const placeholderType = view.state.facet(placeholderState);
135
- const cellId = view.state.facet(cellIdState);
136
- const lspConfig = view.state.facet(lspConfigState);
137
159
  let metadata = view.state.field(languageMetadataField);
138
160
  let cursor = view.state.selection.main.head;
139
161
 
@@ -164,22 +186,15 @@ function updateLanguageAdapterAndCode({
164
186
  // Update the state
165
187
  view.dispatch({
166
188
  effects: [
167
- setLanguageAdapter.of(nextLanguage),
189
+ ...languageConfigurationEffects(view.state, nextLanguage),
168
190
  setLanguageMetadata.of(metadata),
169
- languageCompartment.reconfigure(
170
- nextLanguage.getExtension(
171
- cellId,
172
- completionConfig,
173
- hotkeysProvider,
174
- placeholderType,
175
- lspConfig,
176
- ),
177
- ),
178
- // Clear history
179
- historyCompartment.reconfigure([]),
191
+ ...(nextLanguage.type === "sql"
192
+ ? [sqlDialectEffect(metadata.engine)]
193
+ : []),
180
194
  // Let downstream extensions know that this is a formatting change
181
195
  formattingChangeEffect.of(true),
182
196
  ],
197
+ annotations: Transaction.addToHistory.of(false),
183
198
  changes: opts.keepCodeAsIs
184
199
  ? undefined
185
200
  : {
@@ -189,16 +204,6 @@ function updateLanguageAdapterAndCode({
189
204
  },
190
205
  selection: opts.keepCodeAsIs ? undefined : EditorSelection.cursor(cursor),
191
206
  });
192
-
193
- // Add history back
194
- view.dispatch({
195
- effects: [historyCompartment.reconfigure([history()])],
196
- });
197
-
198
- // Initialize SQL dialect if switching to SQL
199
- if (nextLanguage.type === "sql") {
200
- initializeSQLDialect(view);
201
- }
202
207
  }
203
208
 
204
209
  /**
@@ -218,16 +223,28 @@ export function adaptiveLanguageConfiguration(opts: {
218
223
  // Language adapter
219
224
  languageToggleKeymaps(),
220
225
  languageCompartment.of(
221
- LanguageAdapters.python.getExtension(
226
+ LanguageAdapters.python.getExtension({
222
227
  cellId,
223
228
  completionConfig,
224
229
  hotkeys,
225
230
  placeholderType,
226
231
  lspConfig,
227
- ),
232
+ }),
228
233
  ),
229
234
  languageAdapterState,
230
235
  languageMetadataField,
236
+ invertedEffects.of((tr) => {
237
+ if (!tr.effects.some((effect) => effect.is(setLanguageMetadata))) {
238
+ return [];
239
+ }
240
+ const metadata = tr.startState.field(languageMetadataField);
241
+ return [
242
+ setLanguageMetadata.of(metadata),
243
+ ...(tr.startState.field(languageAdapterState).type === "sql"
244
+ ? [sqlDialectEffect(metadata.engine)]
245
+ : []),
246
+ ];
247
+ }),
231
248
  ];
232
249
  }
233
250
 
@@ -323,12 +340,12 @@ export function reconfigureLanguageEffect(
323
340
  }
324
341
 
325
342
  return languageCompartment.reconfigure(
326
- language.getExtension(
343
+ language.getExtension({
327
344
  cellId,
328
345
  completionConfig,
329
- hotkeysProvider,
346
+ hotkeys: hotkeysProvider,
330
347
  placeholderType,
331
348
  lspConfig,
332
- ),
349
+ }),
333
350
  );
334
351
  }