@marimo-team/frontend 0.25.3-dev91 → 0.25.3-dev93

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 (157) hide show
  1. package/dist/assets/{CellStatus-DYRvLOiP.js → CellStatus-CplYFNTy.js} +1 -1
  2. package/dist/assets/{ConnectedDataExplorerComponent-D9UK8o9A.js → ConnectedDataExplorerComponent-Dft8R6l5.js} +1 -1
  3. package/dist/assets/{ErrorBoundary-BKQo68Df.js → ErrorBoundary-CdGuz4a_.js} +2 -2
  4. package/dist/assets/{JsonOutput-DryOywaN.js → JsonOutput-Csbov8Fx.js} +3 -3
  5. package/dist/assets/{MarimoErrorOutput-XrTcOYTI.js → MarimoErrorOutput-czclLlOn.js} +1 -1
  6. package/dist/assets/{RenderHTML-DaVbCAsb.js → RenderHTML-CNDedpS4.js} +1 -1
  7. package/dist/assets/{RunButton-D3ScLvwb.js → RunButton-CRfdOxVd.js} +1 -1
  8. package/dist/assets/__vite-browser-external-8vDMR0Kk.js +1 -0
  9. package/dist/assets/__vite-browser-external-mKcnhO20.js +1 -0
  10. package/dist/assets/{add-cell-with-ai-BKk0pvon.js → add-cell-with-ai-BAIX7r0P.js} +1 -1
  11. package/dist/assets/{add-connection-dialog-CNIwGJVL.js → add-connection-dialog-DrDuM-tI.js} +1 -1
  12. package/dist/assets/{agent-panel-6t16-QG0.js → agent-panel-CoXq_rlA.js} +1 -1
  13. package/dist/assets/{ai-model-dropdown-prnCk5hq.js → ai-model-dropdown-COvWn46z.js} +2 -2
  14. package/dist/assets/{app-config-button-O_yI5nzB.js → app-config-button-CtxoYG4F.js} +1 -1
  15. package/dist/assets/{blob-FjxwDE1i.js → blob-DCjrjZKW.js} +1 -1
  16. package/dist/assets/{cache-panel-Byolv2ht.js → cache-panel-CbWZcBu0.js} +1 -1
  17. package/dist/assets/{cell-editor-CM_kQ_VW.js → cell-editor-BnL0Sorl.js} +1 -1
  18. package/dist/assets/{cell-link-D8EbRFJJ.js → cell-link-BFbgKiRH.js} +1 -1
  19. package/dist/assets/{cells-DfF1DLV_.js → cells-yOs72eZm.js} +2 -2
  20. package/dist/assets/{chat-display-BtQI9LeB.js → chat-display-DwRM41t_.js} +1 -1
  21. package/dist/assets/{chat-panel-tuUN0wet.js → chat-panel-DeTEdjxF.js} +1 -1
  22. package/dist/assets/{chat-ui-Bb-HxAv4.js → chat-ui-D6XucD07.js} +1 -1
  23. package/dist/assets/{code-visibility-ny5n3-GH.js → code-visibility-DYDagVy7.js} +1 -1
  24. package/dist/assets/{column-preview-CqFSXTtf.js → column-preview-DXM8SqGY.js} +1 -1
  25. package/dist/assets/{command-palette-CkDj29px.js → command-palette-CA6yfNLb.js} +1 -1
  26. package/dist/assets/{common-D2oGA09G.js → common-B-ZYnO1x.js} +1 -1
  27. package/dist/assets/{components-CJRBUI2s.js → components-CBE8cOLK.js} +1 -1
  28. package/dist/assets/{components-DrU8dOzy.js → components-DCo7mAWO.js} +1 -1
  29. package/dist/assets/{components-1zsrzJ_K.js → components-vu2jLG08.js} +1 -1
  30. package/dist/assets/{config-BWKfkUWA.js → config-CD1IuZFJ.js} +1 -1
  31. package/dist/assets/{config-CP8Y8_R0.js → config-DMz7oN0r.js} +1 -1
  32. package/dist/assets/{config-DGX7JYor.js → config-DpY86_Yq.js} +1 -1
  33. package/dist/assets/{createReducer-HKXUbqyz.js → createReducer-CaI_Oa0v.js} +1 -1
  34. package/dist/assets/{datasource-rV_-mqbc.js → datasource-BakEOWsf.js} +1 -1
  35. package/dist/assets/{dependency-graph-panel-By-cv0Nw.js → dependency-graph-panel-DCGB3_id.js} +1 -1
  36. package/dist/assets/{documentation-panel-DHMjvOPt.js → documentation-panel-CpGZ2Dfn.js} +1 -1
  37. package/dist/assets/{download-CMTzX3rG.js → download-CV1k4XQ4.js} +1 -1
  38. package/dist/assets/{edit-page-Bgkov1Jy.js → edit-page-By7n2M84.js} +5 -5
  39. package/dist/assets/{error-entries-BGCjRkVy.js → error-entries-JgrZYMbe.js} +1 -1
  40. package/dist/assets/{error-panel-BDTFHLEt.js → error-panel-DS7HWph-.js} +1 -1
  41. package/dist/assets/feedback-button-Dgs_HOOC.js +1 -0
  42. package/dist/assets/{feedback-button-C-ScLxY2.js → feedback-button-eYsTCK-g.js} +1 -1
  43. package/dist/assets/{file-explorer-panel-B9jBSwhj.js → file-explorer-panel-BTLwwwD4.js} +1 -1
  44. package/dist/assets/{file-name-input-DIvrcC82.js → file-name-input-BaR4h2Ud.js} +1 -1
  45. package/dist/assets/{floating-outline-DJnZ45VA.js → floating-outline-Drd73Quo.js} +1 -1
  46. package/dist/assets/{gallery-page-CHJD1mdU.js → gallery-page-DXUD11Rm.js} +1 -1
  47. package/dist/assets/{glide-data-editor-BsE9Em-a.js → glide-data-editor-DqBBoQBl.js} +1 -1
  48. package/dist/assets/{home-page-CCbdig5p.js → home-page-DrRto2-v.js} +1 -1
  49. package/dist/assets/{hooks-yjSoxKTw.js → hooks-D25kP4Sr.js} +1 -1
  50. package/dist/assets/{index-0pnwTVch.js → index-vBuAUWEe.js} +6 -6
  51. package/dist/assets/{input-BZdRe7pb.js → input-DmHMEZGh.js} +1 -1
  52. package/dist/assets/kiosk-mode-DFS6HopF.js +1 -0
  53. package/dist/assets/{layout-B2MJFBFp.js → layout-DLHIGZTK.js} +3 -3
  54. package/dist/assets/links-DX2w97N9.js +1 -0
  55. package/dist/assets/{logs-panel-B34vxRV7.js → logs-panel-D5AAD2s9.js} +1 -1
  56. package/dist/assets/{markdown-renderer-CkN_xAjW.js → markdown-renderer--CwVm4kJ.js} +1 -1
  57. package/dist/assets/{mermaid-B6mqMm5_.js → mermaid-BKXlWk4F.js} +1 -1
  58. package/dist/assets/{name-cell-input-eyYneuGK.js → name-cell-input-BFKZaNI5.js} +1 -1
  59. package/dist/assets/{outline-panel-rpjpMDYX.js → outline-panel-qcwRnl0R.js} +1 -1
  60. package/dist/assets/{package-data-dv4FBHxR.js → package-data-CKPmBDtg.js} +1 -1
  61. package/dist/assets/{packages-panel-gXdFgCro.js → packages-panel-DnSryNcz.js} +1 -1
  62. package/dist/assets/{panel-accordion-state-CImIsdc8.js → panel-accordion-state-BwJpDMVt.js} +1 -1
  63. package/dist/assets/{panels-DI8gAi31.js → panels-Aqzwb3UR.js} +1 -1
  64. package/dist/assets/{process-output-BClx23Jv.js → process-output-DuUfHYSr.js} +1 -1
  65. package/dist/assets/{readonly-code-display-JC_YsLL_.js → readonly-code-display-BY-9I_Yk.js} +1 -1
  66. package/dist/assets/{readonly-python-code-DeBED4OB.js → readonly-python-code-DSyr-yE2.js} +1 -1
  67. package/dist/assets/{renderShortcut-H60uiHBp.js → renderShortcut-rUwGqKgC.js} +1 -1
  68. package/dist/assets/{requests-lt0JK8Jt.js → requests-BIFR-h4M.js} +1 -1
  69. package/dist/assets/requests-DuLJN9Tf.js +1 -0
  70. package/dist/assets/{reveal-component-BoGgZrdo.js → reveal-component-C_Lb7Mom.js} +1 -1
  71. package/dist/assets/{run-page-DnvqkxCy.js → run-page-ZTw-kCU-.js} +1 -1
  72. package/dist/assets/{runs-6lJxKV1w.js → runs-C49hleBy.js} +1 -1
  73. package/dist/assets/{runtime-details-state-7JHj3efu.js → runtime-details-state-B7gpnuXx.js} +1 -1
  74. package/dist/assets/{save-worker-BbUSwZRG.js → save-worker-pCkSHhuz.js} +1 -1
  75. package/dist/assets/{scratchpad-panel-DZDmNIPw.js → scratchpad-panel-D2IHkKoG.js} +1 -1
  76. package/dist/assets/{secrets-panel-Dh3v7XPE.js → secrets-panel-bcfEKxRx.js} +1 -1
  77. package/dist/assets/{session-B8Y-GJnS.js → session-CMLIzZKw.js} +1 -1
  78. package/dist/assets/session-panel-cOSO3WCX.js +1 -0
  79. package/dist/assets/{snippets-panel-BNjtDbnR.js → snippets-panel-BNadUJLU.js} +1 -1
  80. package/dist/assets/{state-BY4_P6ko.js → state-3mcyTS9q.js} +1 -1
  81. package/dist/assets/{state-C0irhlOZ.js → state-B_MCKzBL.js} +1 -1
  82. package/dist/assets/state-BaYudep3.js +3 -0
  83. package/dist/assets/{state-DaWgt-rn.js → state-C5WAeuTu.js} +1 -1
  84. package/dist/assets/{state-Ck7FMD5A.js → state-Cv2JW3l9.js} +1 -1
  85. package/dist/assets/{state-DhaPGGBO.js → state-_1LTGJQM.js} +1 -1
  86. package/dist/assets/{switch-IoWE8PbW.js → switch-DYjBfpNJ.js} +1 -1
  87. package/dist/assets/{terminal-BwLC9HS5.js → terminal-Ca-kubKb.js} +1 -1
  88. package/dist/assets/{tracing-Ch4LR62-.js → tracing-DbTgS4u9.js} +1 -1
  89. package/dist/assets/{tracing-panel-B8fX4PhX.js → tracing-panel-CjlrpXPy.js} +2 -2
  90. package/dist/assets/{tree-actions-Zg3Ycse4.js → tree-actions-C_KYlaSv.js} +1 -1
  91. package/dist/assets/{useAddCell-BX9lq_0J.js → useAddCell-C0J8quGE.js} +1 -1
  92. package/dist/assets/{useAsyncData-DhhdOGGd.js → useAsyncData-qvoPYHtx.js} +1 -1
  93. package/dist/assets/{useBoolean-WABMLM83.js → useBoolean-Dd2nWXFJ.js} +1 -1
  94. package/dist/assets/{useCellActionButton-D7Ruyes-.js → useCellActionButton-CbkOj6BE.js} +1 -1
  95. package/dist/assets/{useDebounce-k9QTpQ9-.js → useDebounce-DwTQ_1Pu.js} +1 -1
  96. package/dist/assets/{useDeepCompareMemoize-DFIVN9dn.js → useDeepCompareMemoize-B2DVK2De.js} +1 -1
  97. package/dist/assets/{useDeleteCell-AbkQI6-c.js → useDeleteCell-DHkF5wgS.js} +1 -1
  98. package/dist/assets/{useDependencyPanelTab-B0b2KkvS.js → useDependencyPanelTab--yXJW6X5.js} +1 -1
  99. package/dist/assets/{useEvent-Dfcbgjhg.js → useEvent-BDjgaBtz.js} +1 -1
  100. package/dist/assets/{useInstallPackage-CWcPxSLP.js → useInstallPackage-wcDq9hYT.js} +1 -1
  101. package/dist/assets/{useNotebookActions-DJuAUAGI.js → useNotebookActions-dJQalORg.js} +1 -1
  102. package/dist/assets/{useRunCells-CV81rge-.js → useRunCells-C_IwVJR_.js} +1 -1
  103. package/dist/assets/{useSplitCell-BTwCB3JS.js → useSplitCell-Ci4MEUj8.js} +1 -1
  104. package/dist/assets/{useTheme-DLtPc-39.js → useTheme-BAA27lh7.js} +1 -1
  105. package/dist/assets/{vega-component-CY6HmM06.js → vega-component-BeyxAJad.js} +1 -1
  106. package/dist/assets/{worker-DTQ7oH2A.js → worker-bSCjCvwz.js} +1 -1
  107. package/dist/assets/{write-secret-modal-7DzehGyr.js → write-secret-modal-BEx-EUlh.js} +1 -1
  108. package/dist/index.html +40 -40
  109. package/package.json +1 -1
  110. package/src/components/chat/acp/__tests__/state.test.ts +2 -2
  111. package/src/components/data-table/cell-selection/feature.ts +2 -2
  112. package/src/components/data-table/cell-selection/types.ts +2 -2
  113. package/src/components/data-table/column-summary/column-summary.tsx +2 -4
  114. package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
  115. package/src/components/datasources/datasources.tsx +35 -21
  116. package/src/components/editor/SortableCell.tsx +1 -3
  117. package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
  118. package/src/components/editor/chrome/wrapper/storage.ts +1 -1
  119. package/src/components/editor/output/MarimoTracebackOutput.tsx +1 -1
  120. package/src/components/icons/spinner.tsx +1 -1
  121. package/src/components/ui/alert-dialog.tsx +1 -1
  122. package/src/core/ai/context/providers/datasource.ts +6 -2
  123. package/src/core/cells/session.ts +1 -1
  124. package/src/core/codemirror/__tests__/setup.test.ts +1 -1
  125. package/src/core/codemirror/keymaps/vim.ts +2 -6
  126. package/src/core/codemirror/language/languages/markdown.ts +1 -1
  127. package/src/core/codemirror/language/languages/python.ts +3 -3
  128. package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
  129. package/src/core/state/__tests__/jotai.test.tsx +108 -0
  130. package/src/core/state/jotai.ts +1 -1
  131. package/src/core/wasm/bridge.ts +2 -2
  132. package/src/core/wasm/store.ts +3 -3
  133. package/src/core/wasm/worker/bootstrap.ts +1 -1
  134. package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
  135. package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
  136. package/src/plugins/impl/RangeSliderPlugin.tsx +0 -1
  137. package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
  138. package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
  139. package/src/plugins/impl/data-frames/DataFramePlugin.tsx +0 -1
  140. package/src/plugins/impl/panel/PanelPlugin.tsx +1 -1
  141. package/src/plugins/impl/vega/make-selectable.ts +1 -1
  142. package/src/plugins/layout/RoutesPlugin.tsx +1 -1
  143. package/src/stories/form-wrapper.stories.tsx +2 -2
  144. package/src/stories/select.stories.tsx +2 -2
  145. package/src/stories/switchable-multi-select.stories.tsx +1 -1
  146. package/src/utils/__tests__/batch-requests.test.ts +3 -3
  147. package/src/utils/blob.ts +1 -1
  148. package/src/utils/zod-utils.ts +1 -3
  149. package/dist/assets/__vite-browser-external-CYO_P3S8.js +0 -1
  150. package/dist/assets/__vite-browser-external-FeDVGZU8.js +0 -1
  151. package/dist/assets/feedback-button-CLRAP9DE.js +0 -1
  152. package/dist/assets/kiosk-mode-BGmMSc7A.js +0 -1
  153. package/dist/assets/links-CXcpNIM0.js +0 -1
  154. package/dist/assets/requests-CgSY1X4a.js +0 -1
  155. package/dist/assets/session-panel-B1QB5LN7.js +0 -1
  156. package/dist/assets/state-DUP4ToPd.js +0 -3
  157. package/src/core/state/__tests__/jotai.test.ts +0 -25
@@ -702,7 +702,40 @@ const SchemaNode: React.FC<SchemaNodeProps> = (props) => {
702
702
  );
703
703
  };
704
704
 
705
- const TableList: React.FC<{
705
+ // Kept outside the component because the React Compiler does not yet
706
+ // support try/finally inside component bodies.
707
+ async function loadTableList(
708
+ sqlTableContext: SQLTableContext,
709
+ addTableList: ReturnType<typeof useDataSourceActions>["addTableList"],
710
+ setLoading: (loading: boolean) => void,
711
+ ) {
712
+ setLoading(true);
713
+ try {
714
+ const { engine, database, schema, schemaPath } = sqlTableContext;
715
+ const previewTableList = await PreviewSQLTableList.request({
716
+ engine: engine,
717
+ database: database,
718
+ schema: schema,
719
+ schemaPath: schemaPath ?? [],
720
+ });
721
+
722
+ if (!previewTableList?.tables) {
723
+ throw new Error("No tables available");
724
+ }
725
+
726
+ addTableList({
727
+ tables: previewTableList.tables,
728
+ sqlTableContext: sqlTableContext,
729
+ });
730
+ } finally {
731
+ setLoading(false);
732
+ }
733
+ }
734
+
735
+ /**
736
+ * This is exported for testing purposes only.
737
+ */
738
+ export const TableList: React.FC<{
706
739
  tables: DataTable[];
707
740
  sqlTableContext?: SQLTableContext;
708
741
  searchValue?: string;
@@ -731,26 +764,7 @@ const TableList: React.FC<{
731
764
  // resets tablesResolved to false).
732
765
  const { isPending, error } = useAsyncData(async () => {
733
766
  if (!tablesResolved && sqlTableContext) {
734
- setTablesLoading(true);
735
-
736
- const { engine, database, schema, schemaPath } = sqlTableContext;
737
- const previewTableList = await PreviewSQLTableList.request({
738
- engine: engine,
739
- database: database,
740
- schema: schema,
741
- schemaPath: schemaPath ?? [],
742
- });
743
-
744
- if (!previewTableList?.tables) {
745
- setTablesLoading(false);
746
- throw new Error("No tables available");
747
- }
748
-
749
- addTableList({
750
- tables: previewTableList.tables,
751
- sqlTableContext: sqlTableContext,
752
- });
753
- setTablesLoading(false);
767
+ await loadTableList(sqlTableContext, addTableList, setTablesLoading);
754
768
  }
755
769
  }, [tablesResolved, sqlTableContext]);
756
770
 
@@ -71,7 +71,6 @@ export const SortableCell = React.forwardRef(
71
71
  return (
72
72
  <SortableCellInternal
73
73
  ref={ref}
74
- cellId={cellId}
75
74
  canMoveX={canMoveX}
76
75
  {...props}
77
76
  attributes={attributes}
@@ -86,7 +85,7 @@ export const SortableCell = React.forwardRef(
86
85
  );
87
86
  SortableCell.displayName = "SortableCell";
88
87
 
89
- interface SortableCellInternalProps extends Props {
88
+ interface SortableCellInternalProps extends Omit<Props, "cellId"> {
90
89
  children: React.ReactNode;
91
90
  attributes: DraggableAttributes;
92
91
  listeners: SyntheticListenerMap | undefined;
@@ -99,7 +98,6 @@ interface SortableCellInternalProps extends Props {
99
98
  const SortableCellInternal = React.forwardRef(
100
99
  (
101
100
  {
102
- cellId,
103
101
  canMoveX,
104
102
  children,
105
103
  attributes,
@@ -26,13 +26,7 @@ import { isWasm } from "@/core/wasm/utils";
26
26
  import { cn } from "@/utils/cn";
27
27
  import { FooterItem } from "../footer-item";
28
28
 
29
- interface RuntimeSettingsProps {
30
- className?: string;
31
- }
32
-
33
- export const RuntimeSettings: React.FC<RuntimeSettingsProps> = ({
34
- className,
35
- }) => {
29
+ export const RuntimeSettings: React.FC = () => {
36
30
  const { saveUserConfig } = useRequestClient();
37
31
  const [config, setUserConfig] = useResolvedMarimoConfig();
38
32
 
@@ -15,7 +15,7 @@ let storedValue: string | null = null;
15
15
  */
16
16
  export function createStorage(location: "left" | "bottom"): PanelGroupStorage {
17
17
  return {
18
- getItem(name) {
18
+ getItem(_name) {
19
19
  if (!storedValue) {
20
20
  return storedValue ?? null;
21
21
  }
@@ -274,7 +274,7 @@ export const replaceTracebackFilenames = (domNode: DOMNode) => {
274
274
  return (
275
275
  <div
276
276
  className="inline-block cursor-pointer text-destructive hover:underline"
277
- onClick={(_) => {
277
+ onClick={() => {
278
278
  getRequestClient().openFile({
279
279
  path: info.filePath,
280
280
  lineNumber: info.lineNumber,
@@ -25,7 +25,7 @@ const spinnerVariants = cva("animate-spin", {
25
25
  const Spinner = React.forwardRef<
26
26
  SVGSVGElement,
27
27
  React.SVGProps<SVGSVGElement> & VariantProps<typeof spinnerVariants>
28
- >(({ className, children, centered, size, ...props }, ref) => (
28
+ >(({ className, children: _children, centered, size, ...props }, ref) => (
29
29
  <Loader2Icon
30
30
  ref={ref}
31
31
  className={cn(spinnerVariants({ centered, size }), className)}
@@ -28,7 +28,7 @@ AlertDialogPortal.displayName = AlertDialogPrimitive.Portal.displayName;
28
28
  const AlertDialogOverlay = React.forwardRef<
29
29
  React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
30
30
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
31
- >(({ className, children, ...props }, ref) => (
31
+ >(({ className, children: _children, ...props }, ref) => (
32
32
  <AlertDialogPrimitive.Overlay
33
33
  className={cn(
34
34
  "fixed inset-0 z-50 bg-background/80 backdrop-blur-xs transition-opacity animate-in fade-in",
@@ -98,8 +98,12 @@ export class DatasourceContextProvider extends AIContextProvider<DatasourceConte
98
98
  public formatContext(item: DatasourceContextItem): string {
99
99
  const data = item.data;
100
100
  // Remove certain fields that are not needed in the context
101
- const { name, display_name, source, ...filteredDatasource } =
102
- data.connection;
101
+ const {
102
+ name,
103
+ display_name: _displayName,
104
+ source: _source,
105
+ ...filteredDatasource
106
+ } = data.connection;
103
107
 
104
108
  let datasource = filteredDatasource;
105
109
  const isInternalEngine = INTERNAL_SQL_ENGINES.has(name as ConnectionName);
@@ -56,7 +56,7 @@ function mergeSessionAndNotebookCells(
56
56
  return {
57
57
  cellIds,
58
58
  sessionCellData: new Map(
59
- cellIds.map((id, idx) => [id, null] as [CellId, SessionCell | null]),
59
+ cellIds.map((id) => [id, null] as [CellId, SessionCell | null]),
60
60
  ),
61
61
  notebookCellData: new Map(
62
62
  cellIds.map(
@@ -100,7 +100,7 @@ function getDuplicateKeymaps(state: EditorState) {
100
100
  (keymap) => keymap,
101
101
  );
102
102
  const duplicates = Objects.fromEntries(
103
- Object.entries(groupBy).filter(([key, value]) => value.length > 1),
103
+ Object.entries(groupBy).filter(([_key, value]) => value.length > 1),
104
104
  );
105
105
  return duplicates;
106
106
  }
@@ -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",
@@ -73,7 +73,7 @@ export class MarkdownLanguageAdapter implements LanguageAdapter<MarkdownLanguage
73
73
  _cellId: CellId,
74
74
  _completionConfig: CompletionConfig,
75
75
  hotkeys: HotkeyProvider,
76
- _: PlaceholderType,
76
+ _placeholderType: PlaceholderType,
77
77
  ): Extension[] {
78
78
  const markdownLanguageData = markdown().language.data;
79
79
  let view: EditorView | undefined;
@@ -157,7 +157,7 @@ const pylspClient = once((lspConfig: LSPConfig) => {
157
157
  return notebookClient;
158
158
  });
159
159
 
160
- const tyLspClient = once((_: LSPConfig) => {
160
+ const tyLspClient = once((_config: LSPConfig) => {
161
161
  // oxlint-disable-next-line prefer-const -- reassigned after closure capture
162
162
  let resyncCallback: (() => Promise<void>) | undefined;
163
163
 
@@ -176,7 +176,7 @@ const tyLspClient = once((_: LSPConfig) => {
176
176
  const notebookClient = new NotebookLanguageServerClient(
177
177
  new LanguageServerClient({
178
178
  ...lspClientOpts,
179
- getWorkspaceConfiguration: (_) => [{ disableLanguageServices: true }],
179
+ getWorkspaceConfiguration: () => [{ disableLanguageServices: true }],
180
180
  }),
181
181
  {},
182
182
  );
@@ -226,7 +226,7 @@ const pyreflyClient = once(
226
226
  },
227
227
  );
228
228
 
229
- const pyrightClient = once((_: LSPConfig) => {
229
+ const pyrightClient = once((_config: LSPConfig) => {
230
230
  // oxlint-disable-next-line prefer-const -- reassigned after closure capture
231
231
  let resyncCallback: (() => Promise<void>) | undefined;
232
232
 
@@ -25,7 +25,7 @@ describe("RuntimeState", () => {
25
25
 
26
26
  beforeEach(() => {
27
27
  vi.clearAllMocks();
28
- mockSendComponentValues = vi.fn((args) => Promise.resolve(null));
28
+ mockSendComponentValues = vi.fn(() => Promise.resolve(null));
29
29
  uiElementRegistry = UIElementRegistry.INSTANCE;
30
30
  uiElementRegistry.entries.clear();
31
31
 
@@ -0,0 +1,108 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { act, renderHook } from "@testing-library/react";
4
+ import { atom, Provider } from "jotai";
5
+ import type React from "react";
6
+ import { describe, expect, it, vi } from "vitest";
7
+ import { store, useJotaiEffect, waitFor } from "../jotai";
8
+
9
+ const wrapper = ({ children }: { children: React.ReactNode }) => (
10
+ <Provider store={store}>{children}</Provider>
11
+ );
12
+
13
+ describe("waitFor function", () => {
14
+ it("should resolve when the atom satisfies the predicate", async () => {
15
+ const testAtom = atom(0);
16
+ store.set(testAtom, 10);
17
+
18
+ const result = await waitFor(testAtom, (value) => value === 10);
19
+ expect(result).toBe(10);
20
+ });
21
+
22
+ it("should resolve when the atom changes to satisfy the predicate", async () => {
23
+ const testAtom = atom(0);
24
+
25
+ setTimeout(() => store.set(testAtom, 15), 5);
26
+ setTimeout(() => store.set(testAtom, 20), 10);
27
+
28
+ const result = await waitFor(testAtom, (value) => value === 20);
29
+ expect(result).toBe(20);
30
+ });
31
+ });
32
+
33
+ describe("useJotaiEffect", () => {
34
+ it("calls the effect with the new and previous values", () => {
35
+ const testAtom = atom(0);
36
+ const effect = vi.fn();
37
+ renderHook(() => useJotaiEffect(testAtom, effect), { wrapper });
38
+
39
+ act(() => store.set(testAtom, 1));
40
+ act(() => store.set(testAtom, 2));
41
+
42
+ expect(effect.mock.calls).toEqual([
43
+ [1, 0],
44
+ [2, 1],
45
+ ]);
46
+ });
47
+
48
+ it("calls only the latest callback after a rerender", () => {
49
+ const testAtom = atom(0);
50
+ const first = vi.fn();
51
+ const second = vi.fn();
52
+ const { rerender } = renderHook(
53
+ ({ effect }) => useJotaiEffect(testAtom, effect),
54
+ { initialProps: { effect: first }, wrapper },
55
+ );
56
+
57
+ rerender({ effect: second });
58
+ act(() => store.set(testAtom, 1));
59
+
60
+ expect(first).not.toHaveBeenCalled();
61
+ expect(second).toHaveBeenCalledTimes(1);
62
+ });
63
+
64
+ it("subscribes once per rerender with an inline callback", () => {
65
+ const testAtom = atom(0);
66
+ const calls: number[] = [];
67
+ const { rerender } = renderHook(
68
+ () => useJotaiEffect(testAtom, (value) => calls.push(value)),
69
+ { wrapper },
70
+ );
71
+
72
+ rerender();
73
+ rerender();
74
+ act(() => store.set(testAtom, 1));
75
+
76
+ expect(calls).toEqual([1]);
77
+ });
78
+
79
+ it("stops listening to the previous atom when the atom changes", () => {
80
+ const firstAtom = atom(0);
81
+ const secondAtom = atom(0);
82
+ const effect = vi.fn();
83
+ const { rerender } = renderHook(
84
+ ({ target }) => useJotaiEffect(target, effect),
85
+ { initialProps: { target: firstAtom }, wrapper },
86
+ );
87
+
88
+ rerender({ target: secondAtom });
89
+ act(() => store.set(firstAtom, 1));
90
+ expect(effect).not.toHaveBeenCalled();
91
+
92
+ act(() => store.set(secondAtom, 1));
93
+ expect(effect).toHaveBeenCalledTimes(1);
94
+ });
95
+
96
+ it("unsubscribes on unmount", () => {
97
+ const testAtom = atom(0);
98
+ const effect = vi.fn();
99
+ const { unmount } = renderHook(() => useJotaiEffect(testAtom, effect), {
100
+ wrapper,
101
+ });
102
+
103
+ unmount();
104
+ act(() => store.set(testAtom, 1));
105
+
106
+ expect(effect).not.toHaveBeenCalled();
107
+ });
108
+ });
@@ -42,7 +42,7 @@ export function useJotaiEffect<T>(
42
42
  const store = useStore();
43
43
  useEffect(() => {
44
44
  let prevValue = store.get(atom);
45
- store.sub(atom, () => {
45
+ return store.sub(atom, () => {
46
46
  const value = store.get(atom);
47
47
  effect(value, prevValue);
48
48
  prevValue = value;
@@ -407,7 +407,7 @@ export class PyodideBridge implements RunRequests, EditRequests {
407
407
  return response as Snippets;
408
408
  };
409
409
 
410
- public openFile: EditRequests["openFile"] = async ({ path }) => {
410
+ public openFile: EditRequests["openFile"] = async () => {
411
411
  const url = createShareableLink({
412
412
  code: null,
413
413
  baseUrl: window.location.origin,
@@ -451,7 +451,7 @@ export class PyodideBridge implements RunRequests, EditRequests {
451
451
  return null;
452
452
  };
453
453
 
454
- public sendInstantiate: RunRequests["sendInstantiate"] = async (request) => {
454
+ public sendInstantiate: RunRequests["sendInstantiate"] = async () => {
455
455
  return null;
456
456
  };
457
457
 
@@ -41,7 +41,7 @@ const urlFileStore: FileStore = {
41
41
  };
42
42
 
43
43
  export const domElementFileStore: FileStore = {
44
- saveFile(contents: string) {
44
+ saveFile(_contents: string) {
45
45
  // Do nothing
46
46
  },
47
47
  readFile() {
@@ -54,7 +54,7 @@ export const domElementFileStore: FileStore = {
54
54
  };
55
55
 
56
56
  const remoteDefaultFileStore: FileStore = {
57
- saveFile(contents: string) {
57
+ saveFile(_contents: string) {
58
58
  // Do nothing
59
59
  },
60
60
  readFile() {
@@ -79,7 +79,7 @@ export const mountConfigFileStore: FileStore = {
79
79
  };
80
80
 
81
81
  const emptyFileStore: FileStore = {
82
- saveFile(contents: string) {
82
+ saveFile(_contents: string) {
83
83
  // Do nothing
84
84
  },
85
85
  readFile() {
@@ -85,7 +85,7 @@ export class DefaultWasmController implements WasmController {
85
85
  packages: [
86
86
  "micropip",
87
87
  "msgspec",
88
- getMarimoWheel(opts.version),
88
+ getMarimoWheel(),
89
89
  "Markdown",
90
90
  "pymdown-extensions",
91
91
  "narwhals",
@@ -1,6 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- export function getMarimoWheel(version: string) {
3
+ export function getMarimoWheel() {
4
4
  if (import.meta.env.DEV && import.meta.env.VITE_WASM_MARIMO_PREBUILT_WHEEL) {
5
5
  return "marimo-base";
6
6
  }
@@ -71,7 +71,7 @@ const CodeEditorComponent = (props: CodeEditorComponentProps) => {
71
71
  });
72
72
 
73
73
  const handleChange = useEvent((newValue: string) => {
74
- setLocalValue((_) => newValue);
74
+ setLocalValue(newValue);
75
75
  if (typeof props.debounce === "number") {
76
76
  setValueDebounced(newValue);
77
77
  } else if (!props.debounce) {
@@ -74,7 +74,6 @@ const RangeSliderComponent = ({
74
74
  start,
75
75
  stop,
76
76
  step,
77
- steps,
78
77
  debounce,
79
78
  orientation,
80
79
  showValue,
@@ -47,7 +47,7 @@ const ConnectedDataExplorerComponent = (props: DataTableProps): JSX.Element => {
47
47
  // Subscribe to the store
48
48
  const unsub = store.sub(chartSpecAtom, () => {
49
49
  const value = store.get(chartSpecAtom);
50
- const { schema, ...withoutSchema } = value;
50
+ const { schema: _schema, ...withoutSchema } = value;
51
51
  props.setValue(withoutSchema);
52
52
  });
53
53
 
@@ -47,7 +47,7 @@ const { valueAtom: chartSpecAtom, useActions } = createReducerAndAtoms(
47
47
  },
48
48
  set: (state, next: ChartSpec) => {
49
49
  // remove schema
50
- const { schema, ...rest } = next;
50
+ const { schema: _schema, ...rest } = next;
51
51
  return { ...state, ...rest };
52
52
  },
53
53
  },
@@ -192,7 +192,6 @@ const EMPTY: Transformations = {
192
192
  export const DataFrameComponent = memo(
193
193
  ({
194
194
  columns,
195
- dataframeName,
196
195
  pageSize,
197
196
  showDownload,
198
197
  lazy,
@@ -78,7 +78,7 @@ type T = Record<string, unknown>;
78
78
 
79
79
  // oxlint-disable-next-line typescript/consistent-type-definitions
80
80
  type PluginFunctions = {
81
- send_to_widget: <T>(req: {
81
+ send_to_widget: (req: {
82
82
  message?: unknown;
83
83
  buffers?: unknown;
84
84
  }) => Promise<null | undefined>;
@@ -219,7 +219,7 @@ function removeSpecificParamsFromNestedSpecs(
219
219
  }
220
220
 
221
221
  if (filteredParams.length === 0) {
222
- const { params, ...rest } = spec;
222
+ const { params: _params, ...rest } = spec;
223
223
  return rest as SpecWithParams;
224
224
  }
225
225
 
@@ -56,7 +56,7 @@ const RoutesComponent = ({
56
56
 
57
57
  useEffect(() => {
58
58
  // Listen for route changes
59
- const listener = (e: PopStateEvent | HashChangeEvent) => {
59
+ const listener = () => {
60
60
  handleFindMatch(window.location);
61
61
  };
62
62
  window.addEventListener("hashchange", listener);
@@ -20,7 +20,7 @@ type Story = StoryObj<typeof FormWrapper>;
20
20
  const props: FormWrapperProps<string> = {
21
21
  currentValue: "currentValue",
22
22
  newValue: "currentValue",
23
- setValue: (v) => {
23
+ setValue: () => {
24
24
  toast({
25
25
  title: "Form submitted",
26
26
  });
@@ -133,7 +133,7 @@ export const Validate: Story = {
133
133
  <FormWrapper
134
134
  {...props}
135
135
  shouldValidate={true}
136
- validate={async ({ value }) => {
136
+ validate={async () => {
137
137
  const random = Math.random();
138
138
  if (random < 0.8) {
139
139
  return `Failed to validate. Random number was ${random}`;
@@ -24,7 +24,7 @@ export default meta;
24
24
  type Story = StoryObj;
25
25
 
26
26
  export const Primary: Story = {
27
- render: (args, ctx) => (
27
+ render: () => (
28
28
  <Select>
29
29
  <SelectTrigger className="w-64">
30
30
  <SelectValue placeholder="Select a fruit" />
@@ -63,7 +63,7 @@ export const Primary: Story = {
63
63
  };
64
64
 
65
65
  export const Clearable: Story = {
66
- render: (args, ctx) => {
66
+ render: () => {
67
67
  const [value, setValue] = useState<string>("");
68
68
  return (
69
69
  <>
@@ -15,7 +15,7 @@ export default meta;
15
15
  type Story = StoryObj;
16
16
 
17
17
  export const Primary: Story = {
18
- render: (args, ctx) => {
18
+ render: () => {
19
19
  const [value, setValue] = useState<string[]>([]);
20
20
  return (
21
21
  <TooltipProvider>
@@ -8,7 +8,7 @@ async function sleep(ms: number) {
8
8
 
9
9
  describe("batch", () => {
10
10
  it("should return the same promise for calls with the same key", async () => {
11
- const loader = vi.fn().mockImplementation(async (arg) => {
11
+ const loader = vi.fn().mockImplementation(async () => {
12
12
  await sleep(10);
13
13
  return "response";
14
14
  });
@@ -25,7 +25,7 @@ describe("batch", () => {
25
25
  });
26
26
 
27
27
  it("should call loader again after the first promise resolves", async () => {
28
- const loader = vi.fn().mockImplementation(async (arg) => {
28
+ const loader = vi.fn().mockImplementation(async () => {
29
29
  await sleep(10);
30
30
  return "response";
31
31
  });
@@ -40,7 +40,7 @@ describe("batch", () => {
40
40
  });
41
41
 
42
42
  it("should handle different keys separately", async () => {
43
- const loader = vi.fn().mockImplementation(async (arg) => {
43
+ const loader = vi.fn().mockImplementation(async () => {
44
44
  await sleep(10);
45
45
  return "response";
46
46
  });
package/src/utils/blob.ts CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  type DataURLString,
6
6
  } from "./json/base64";
7
7
 
8
- export function serializeBlob<T>(blob: Blob): Promise<DataURLString> {
8
+ export function serializeBlob(blob: Blob): Promise<DataURLString> {
9
9
  return new Promise<DataURLString>((resolve, reject) => {
10
10
  const reader = new FileReader();
11
11
  reader.onload = (event) => {
@@ -2,9 +2,7 @@
2
2
 
3
3
  import z from "zod";
4
4
 
5
- export function isZodArray<T>(
6
- schema: z.ZodType,
7
- ): schema is z.ZodArray<z.ZodType> {
5
+ export function isZodArray(schema: z.ZodType): schema is z.ZodArray<z.ZodType> {
8
6
  return schema instanceof z.ZodArray;
9
7
  }
10
8
 
@@ -1 +0,0 @@
1
- import{t as e}from"./save-worker-BbUSwZRG.js";var t=e(((e,t)=>{t.exports={}}));export default t();
@@ -1 +0,0 @@
1
- import{t as e}from"./worker-DTQ7oH2A.js";var t=e(((e,t)=>{t.exports={}}));export default t();
@@ -1 +0,0 @@
1
- import{n as e}from"./feedback-button-C-ScLxY2.js";export{e as FeedbackModal};
@@ -1 +0,0 @@
1
- import{l as e}from"./useEvent-Dfcbgjhg.js";import{m as t}from"./session-B8Y-GJnS.js";var n=n=>{let{children:r}=n;return e(t)?null:r},r=n=>{let{children:r}=n;return e(t)?r:null};export{r as n,n as t};
@@ -1 +0,0 @@
1
- import{l as e}from"./session-B8Y-GJnS.js";function t(t){window.open(e(`?file=${encodeURIComponent(t)}`).toString(),`_blank`)}export{t};
@@ -1 +0,0 @@
1
- import{f as e}from"./useEvent-Dfcbgjhg.js";var t=e(null);export{t};