@marimo-team/islands 0.21.2-dev6 → 0.21.2-dev61

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 (152) hide show
  1. package/dist/{ConnectedDataExplorerComponent-D0GoOd_c.js → ConnectedDataExplorerComponent-DrWDbHRV.js} +1 -1
  2. package/dist/{any-language-editor-DlsjUw_l.js → any-language-editor-BRpxklRq.js} +1 -1
  3. package/dist/{copy-DIK6DiIA.js → copy-BjkXCUxP.js} +12 -2
  4. package/dist/{esm-BLobyqMs.js → esm-No_6eSQS.js} +1 -1
  5. package/dist/{glide-data-editor-pZyd9UJ_.js → glide-data-editor-858wsVkd.js} +1 -1
  6. package/dist/main.js +821 -417
  7. package/dist/{spec-Bfvf9Hre.js → spec-oVDndBz4.js} +25 -16
  8. package/dist/style.css +1 -1
  9. package/package.json +1 -1
  10. package/src/__mocks__/notebook.ts +9 -9
  11. package/src/__mocks__/requests.ts +1 -0
  12. package/src/__tests__/branded.ts +20 -0
  13. package/src/components/app-config/user-config-form.tsx +5 -4
  14. package/src/components/data-table/__tests__/utils.test.ts +138 -1
  15. package/src/components/data-table/charts/__tests__/storage.test.ts +7 -7
  16. package/src/components/data-table/context-menu.tsx +9 -5
  17. package/src/components/data-table/data-table.tsx +3 -0
  18. package/src/components/data-table/range-focus/__tests__/atoms.test.ts +8 -2
  19. package/src/components/data-table/range-focus/__tests__/test-utils.ts +2 -0
  20. package/src/components/data-table/range-focus/__tests__/utils.test.ts +82 -8
  21. package/src/components/data-table/range-focus/atoms.ts +2 -2
  22. package/src/components/data-table/range-focus/utils.ts +50 -12
  23. package/src/components/data-table/types.ts +7 -0
  24. package/src/components/data-table/utils.ts +87 -0
  25. package/src/components/editor/__tests__/data-attributes.test.tsx +8 -8
  26. package/src/components/editor/ai/__tests__/completion-utils.test.ts +15 -15
  27. package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap +2 -2
  28. package/src/components/editor/connections/storage/as-code.ts +2 -2
  29. package/src/components/editor/file-tree/file-explorer.tsx +16 -2
  30. package/src/components/editor/file-tree/file-viewer.tsx +17 -3
  31. package/src/components/editor/navigation/__tests__/clipboard.test.ts +2 -2
  32. package/src/components/editor/navigation/__tests__/selection.test.ts +7 -6
  33. package/src/components/editor/navigation/__tests__/state.test.ts +8 -7
  34. package/src/components/editor/output/MarimoErrorOutput.tsx +7 -7
  35. package/src/components/editor/output/__tests__/traceback.test.tsx +4 -4
  36. package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +4 -4
  37. package/src/components/editor/renderers/vertical-layout/useFocusFirstEditor.ts +8 -1
  38. package/src/components/storage/storage-file-viewer.tsx +35 -1
  39. package/src/components/storage/storage-inspector.tsx +9 -4
  40. package/src/components/storage/storage-snippets.ts +3 -3
  41. package/src/components/tracing/tracing.tsx +3 -1
  42. package/src/components/ui/range-slider.tsx +108 -1
  43. package/src/core/ai/__tests__/staged-cells.test.ts +9 -8
  44. package/src/core/ai/context/providers/__tests__/cell-output.test.ts +31 -31
  45. package/src/core/ai/context/providers/__tests__/datasource.test.ts +3 -3
  46. package/src/core/ai/context/providers/__tests__/tables.test.ts +3 -2
  47. package/src/core/ai/context/providers/__tests__/variable.test.ts +84 -63
  48. package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +10 -9
  49. package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +6 -6
  50. package/src/core/ai/tools/edit-notebook-tool.ts +3 -3
  51. package/src/core/cells/__tests__/add-missing-import.test.ts +3 -3
  52. package/src/core/cells/__tests__/apply-transaction.test.ts +279 -0
  53. package/src/core/cells/__tests__/cells.test.ts +198 -135
  54. package/src/core/cells/__tests__/document-changes.test.ts +575 -0
  55. package/src/core/cells/__tests__/document-roundtrip.test.ts +376 -0
  56. package/src/core/cells/__tests__/focus.test.ts +5 -4
  57. package/src/core/cells/__tests__/logs.test.ts +13 -12
  58. package/src/core/cells/__tests__/pending-delete-service.test.tsx +3 -3
  59. package/src/core/cells/__tests__/runs.test.ts +22 -21
  60. package/src/core/cells/__tests__/scrollCellIntoView.test.ts +8 -7
  61. package/src/core/cells/__tests__/session.test.ts +23 -22
  62. package/src/core/cells/cells.ts +29 -4
  63. package/src/core/cells/document-changes.ts +644 -0
  64. package/src/core/cells/ids.ts +5 -5
  65. package/src/core/cells/logs.ts +2 -2
  66. package/src/core/cells/runs.ts +6 -8
  67. package/src/core/codemirror/__tests__/format.test.ts +34 -36
  68. package/src/core/codemirror/__tests__/setup.test.ts +2 -2
  69. package/src/core/codemirror/cells/__tests__/extensions.test.ts +114 -0
  70. package/src/core/codemirror/cells/__tests__/traceback-decorations.test.ts +33 -32
  71. package/src/core/codemirror/cells/extensions.ts +66 -23
  72. package/src/core/codemirror/completion/__tests__/keymap.test.ts +15 -35
  73. package/src/core/codemirror/completion/keymap.ts +14 -4
  74. package/src/core/codemirror/copilot/__tests__/getCodes.test.ts +12 -13
  75. package/src/core/codemirror/language/__tests__/utils.test.ts +3 -3
  76. package/src/core/codemirror/language/embedded/__tests__/embedded-python.test.ts +7 -8
  77. package/src/core/codemirror/language/languages/python.ts +4 -0
  78. package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +4 -3
  79. package/src/core/codemirror/lsp/notebook-lsp.ts +28 -2
  80. package/src/core/codemirror/reactive-references/__tests__/analyzer.test.ts +7 -6
  81. package/src/core/codemirror/reactive-references/analyzer.ts +2 -2
  82. package/src/core/codemirror/rtc/loro/__tests__/sync.test.ts +52 -0
  83. package/src/core/codemirror/rtc/loro/sync.ts +1 -0
  84. package/src/core/datasets/__tests__/data-source.test.ts +5 -6
  85. package/src/core/datasets/state.ts +1 -1
  86. package/src/core/errors/__tests__/errors.test.ts +2 -1
  87. package/src/core/export/__tests__/hooks.test.ts +37 -36
  88. package/src/core/islands/bridge.ts +1 -0
  89. package/src/core/islands/main.ts +4 -7
  90. package/src/core/kernel/__tests__/handlers.test.ts +5 -4
  91. package/src/core/kernel/handlers.ts +7 -4
  92. package/src/core/network/DeferredRequestRegistry.ts +2 -2
  93. package/src/core/network/__tests__/CachingRequestRegistry.test.ts +9 -10
  94. package/src/core/network/__tests__/DeferredRequestRegistry.test.ts +4 -6
  95. package/src/core/network/requests-lazy.ts +1 -0
  96. package/src/core/network/requests-network.ts +9 -0
  97. package/src/core/network/requests-static.ts +1 -0
  98. package/src/core/network/requests-toasting.tsx +1 -0
  99. package/src/core/network/types.ts +5 -0
  100. package/src/core/static/__tests__/virtual-file-tracker.test.ts +8 -8
  101. package/src/core/static/virtual-file-tracker.ts +1 -1
  102. package/src/core/storage/__tests__/state.test.ts +31 -21
  103. package/src/core/storage/state.ts +1 -1
  104. package/src/core/variables/__tests__/state.test.ts +6 -6
  105. package/src/core/variables/types.ts +2 -2
  106. package/src/core/wasm/__tests__/state.test.ts +8 -8
  107. package/src/core/wasm/bridge.ts +1 -0
  108. package/src/core/websocket/useMarimoKernelConnection.tsx +31 -16
  109. package/src/css/app/fonts.css +6 -6
  110. package/src/css/md-tooltip.css +4 -39
  111. package/src/css/md.css +7 -0
  112. package/src/fonts/Fira_Mono/FiraMono-Bold.woff2 +0 -0
  113. package/src/fonts/Fira_Mono/FiraMono-Medium.woff2 +0 -0
  114. package/src/fonts/Fira_Mono/FiraMono-Regular.woff2 +0 -0
  115. package/src/fonts/Lora/Lora-VariableFont_wght.woff2 +0 -0
  116. package/src/fonts/PT_Sans/PTSans-Bold.woff2 +0 -0
  117. package/src/fonts/PT_Sans/PTSans-Regular.woff2 +0 -0
  118. package/src/plugins/core/RenderHTML.tsx +17 -0
  119. package/src/plugins/core/__test__/RenderHTML.test.ts +45 -0
  120. package/src/plugins/core/sanitize-html.ts +25 -18
  121. package/src/plugins/impl/DataTablePlugin.tsx +23 -2
  122. package/src/plugins/impl/SliderPlugin.tsx +1 -3
  123. package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +120 -0
  124. package/src/plugins/impl/anywidget/model.ts +1 -2
  125. package/src/stories/cell.stories.tsx +8 -8
  126. package/src/stories/layout/vertical/one-column.stories.tsx +9 -8
  127. package/src/stories/log-viewer.stories.tsx +8 -8
  128. package/src/stories/variables.stories.tsx +2 -2
  129. package/src/utils/__tests__/download.test.tsx +21 -20
  130. package/src/utils/copy.ts +18 -5
  131. package/src/utils/createReducer.ts +26 -11
  132. package/src/utils/download.ts +4 -3
  133. package/src/utils/html-to-image.ts +6 -0
  134. package/src/utils/json/base64.ts +3 -3
  135. package/src/utils/traceback.ts +5 -3
  136. package/src/fonts/Fira_Mono/FiraMono-Bold.ttf +0 -0
  137. package/src/fonts/Fira_Mono/FiraMono-Medium.ttf +0 -0
  138. package/src/fonts/Fira_Mono/FiraMono-Regular.ttf +0 -0
  139. package/src/fonts/Lora/Lora-Italic-VariableFont_wght.ttf +0 -0
  140. package/src/fonts/Lora/Lora-VariableFont_wght.ttf +0 -0
  141. package/src/fonts/Lora/static/Lora-Bold.ttf +0 -0
  142. package/src/fonts/Lora/static/Lora-BoldItalic.ttf +0 -0
  143. package/src/fonts/Lora/static/Lora-Italic.ttf +0 -0
  144. package/src/fonts/Lora/static/Lora-Medium.ttf +0 -0
  145. package/src/fonts/Lora/static/Lora-MediumItalic.ttf +0 -0
  146. package/src/fonts/Lora/static/Lora-Regular.ttf +0 -0
  147. package/src/fonts/Lora/static/Lora-SemiBold.ttf +0 -0
  148. package/src/fonts/Lora/static/Lora-SemiBoldItalic.ttf +0 -0
  149. package/src/fonts/PT_Sans/PTSans-Bold.ttf +0 -0
  150. package/src/fonts/PT_Sans/PTSans-BoldItalic.ttf +0 -0
  151. package/src/fonts/PT_Sans/PTSans-Italic.ttf +0 -0
  152. package/src/fonts/PT_Sans/PTSans-Regular.ttf +0 -0
@@ -27,6 +27,13 @@ type ReducerActions<RH extends ReducerHandlers<any>> = {
27
27
  : never;
28
28
  };
29
29
 
30
+ /** Helper for typing middleware that receives dispatched actions. */
31
+ export type DispatchedActionOf<T> = {
32
+ [Key in keyof T]: T[Key] extends (payload: infer P) => any
33
+ ? { type: Key; payload: P }
34
+ : never;
35
+ }[keyof T & string];
36
+
30
37
  export interface ReducerCreatorResult<
31
38
  State,
32
39
  RH extends ReducerHandlers<State>,
@@ -80,21 +87,20 @@ export function createReducerAndAtoms<
80
87
  State,
81
88
  RH extends ReducerHandlers<NoInfer<State>>,
82
89
  >(initialState: () => State, reducers: RH, middleware?: Middleware<State>[]) {
90
+ const allMiddleware = [...(middleware ?? [])];
91
+ const addMiddleware = (mw: Middleware<State>) => {
92
+ allMiddleware.push(mw);
93
+ };
83
94
  const { reducer, createActions } = createReducer(initialState, reducers);
84
95
 
85
96
  const reducerWithMiddleware = (state: State, action: ReducerAction<any>) => {
86
97
  try {
87
98
  const newState = reducer(state, action);
88
- if (middleware) {
89
- for (const mw of middleware) {
90
- try {
91
- mw(state, newState, action);
92
- } catch (error) {
93
- Logger.error(
94
- `Error in middleware for action ${action.type}:`,
95
- error,
96
- );
97
- }
99
+ for (const mw of allMiddleware) {
100
+ try {
101
+ mw(state, newState, action);
102
+ } catch (error) {
103
+ Logger.error(`Error in middleware for action ${action.type}:`, error);
98
104
  }
99
105
  }
100
106
  return newState;
@@ -108,9 +114,17 @@ export function createReducerAndAtoms<
108
114
  // map of SetAtom => Actions
109
115
  const actionsMap = new WeakMap();
110
116
 
111
- function useActions(): ReducerActions<RH> {
117
+ function useActions(
118
+ options: { skipMiddleware?: boolean } = {},
119
+ ): ReducerActions<RH> {
112
120
  const setState = useSetAtom(valueAtom);
113
121
 
122
+ if (options.skipMiddleware === true) {
123
+ return createActions((action: ReducerAction<any>) => {
124
+ setState((state: State) => reducer(state, action));
125
+ });
126
+ }
127
+
114
128
  if (!actionsMap.has(setState)) {
115
129
  actionsMap.set(
116
130
  setState,
@@ -126,6 +140,7 @@ export function createReducerAndAtoms<
126
140
 
127
141
  return {
128
142
  reducer: reducerWithMiddleware,
143
+ addMiddleware,
129
144
  createActions,
130
145
  valueAtom,
131
146
  useActions,
@@ -156,10 +156,11 @@ export async function downloadHTMLAsImage(opts: {
156
156
  // Get screenshot
157
157
  const dataUrl = await toPng(element);
158
158
  downloadByURL(dataUrl, Filenames.toPNG(filename));
159
- } catch {
159
+ } catch (error) {
160
+ Logger.error("Error downloading as PNG", error);
160
161
  toast({
161
- title: "Error",
162
- description: "Failed to download as PNG.",
162
+ title: "Failed to download as PNG",
163
+ description: prettyError(error),
163
164
  variant: "danger",
164
165
  });
165
166
  } finally {
@@ -140,6 +140,11 @@ export const necessaryStyleProperties = [
140
140
  "cursor",
141
141
  ];
142
142
 
143
+ // 1x1 transparent PNG as a fallback for images that fail to embed (e.g., cross-origin).
144
+ // Without this, failed embeds leave external URLs in the cloned DOM, which taints the canvas.
145
+ const TRANSPARENT_PIXEL =
146
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQI12NgAAIABQABNjN9GQAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAA0lEQVQI12P4z8BQDwAEgAF/QualIQAAAABJRU5ErkJggg==";
147
+
143
148
  /**
144
149
  * Default options for html-to-image conversions.
145
150
  * These handle common edge cases like filtering out toolbars and logging errors.
@@ -162,6 +167,7 @@ export const defaultHtmlToImageOptions: HtmlToImageOptions = {
162
167
  return true;
163
168
  }
164
169
  },
170
+ imagePlaceholder: TRANSPARENT_PIXEL,
165
171
  onImageErrorHandler: (event) => {
166
172
  Logger.error("Error loading image:", event);
167
173
  },
@@ -1,5 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import type { components } from "@marimo-team/marimo-api";
3
4
  import type { NotificationMessageData } from "@/core/kernel/messages";
4
5
  import type { TypedString } from "../typed";
5
6
 
@@ -11,9 +12,9 @@ export type JsonString<T = unknown> = TypedString<"Json"> & {
11
12
  };
12
13
 
13
14
  /**
14
- * A base64-encoded string.
15
+ * A base64-encoded string — derived from the generated OpenAPI schema.
15
16
  */
16
- export type Base64String = TypedString<"Base64">;
17
+ export type Base64String = components["schemas"]["Base64String"];
17
18
 
18
19
  /**
19
20
  * A data URL string.
@@ -120,7 +121,6 @@ export function dataViewToBase64(dataView: DataView): Base64String {
120
121
  export function safeExtractSetUIElementMessageBuffers(
121
122
  notification: NotificationMessageData<"send-ui-element-message">,
122
123
  ): readonly DataView[] {
123
- // @ts-expect-error - TypeScript doesn't know that these strings are actually base64 strings
124
124
  const strs: Base64String[] = notification.buffers ?? [];
125
125
  return strs.map(base64ToDataView);
126
126
  }
@@ -98,10 +98,12 @@ export function getTracebackInfo(domNode: DOMNode): TracebackInfo | null {
98
98
  10,
99
99
  );
100
100
  if (domNode.firstChild.nodeValue?.includes("__marimo__")) {
101
- const cellId = /__marimo__cell_(\w+)_/.exec(
101
+ const maybeCellId = /__marimo__cell_(\w+)_/.exec(
102
102
  domNode.firstChild.nodeValue,
103
- )?.[1] as CellId;
104
- if (cellId && lineNumber) {
103
+ )?.[1];
104
+ if (maybeCellId && lineNumber) {
105
+ // @ts-expect-error - Custom parser above will return valid cell ids
106
+ const cellId: CellId = maybeCellId;
105
107
  return { kind: "cell", cellId, lineNumber };
106
108
  }
107
109
  } else {
Binary file
Binary file
Binary file