@marimo-team/frontend 0.25.2-dev66 → 0.25.2-dev89

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 (153) hide show
  1. package/dist/assets/{CellStatus-CRFBVGjI.js → CellStatus-Bj7PvY_u.js} +1 -1
  2. package/dist/assets/{ErrorBoundary-BKmN7zye.js → ErrorBoundary-CG6gtgym.js} +2 -2
  3. package/dist/assets/{JsonOutput-nqqzL-n0.js → JsonOutput-NVH7GWyC.js} +1 -1
  4. package/dist/assets/{MarimoErrorOutput-DCu6fm2y.js → MarimoErrorOutput-z5iFryzf.js} +1 -1
  5. package/dist/assets/{RenderHTML-DRMkieKn.js → RenderHTML-C7QcdAgB.js} +1 -1
  6. package/dist/assets/{RunButton-CPZWjCL9.js → RunButton-A__3wcpF.js} +1 -1
  7. package/dist/assets/{add-cell-with-ai-D20NyZO4.js → add-cell-with-ai-Wyt6GBhk.js} +1 -1
  8. package/dist/assets/{add-connection-dialog-pQcdKIlO.js → add-connection-dialog-bl8dqCVs.js} +1 -1
  9. package/dist/assets/{agent-panel-tNErBgmq.js → agent-panel-BcoO8S6Q.js} +1 -1
  10. package/dist/assets/{ai-model-dropdown-BIeRPKed.js → ai-model-dropdown-CvJsRj9y.js} +1 -1
  11. package/dist/assets/{api-DYL9A86_.js → api-DVLtXyp7.js} +1 -1
  12. package/dist/assets/{app-config-button-DkNGV0b1.js → app-config-button-C7QrZbqr.js} +1 -1
  13. package/dist/assets/{blob-BIYte8oT.js → blob-Bx8A10xl.js} +1 -1
  14. package/dist/assets/{cell-editor-C5RTy4Y0.js → cell-editor-CevZDS63.js} +4 -4
  15. package/dist/assets/cell-link-DC1UZQr_.js +1 -0
  16. package/dist/assets/{cells-h5u00Nz8.js → cells-CxY8RSp7.js} +2 -2
  17. package/dist/assets/{chat-display-DzTkUWMw.js → chat-display-YETh6yXV.js} +1 -1
  18. package/dist/assets/{chat-panel-CKqEpnjN.js → chat-panel-DyaePe7B.js} +1 -1
  19. package/dist/assets/{chat-ui-CGzOsYVb.js → chat-ui-D_QL46qM.js} +1 -1
  20. package/dist/assets/code-visibility-DNzJgrTz.js +1 -0
  21. package/dist/assets/{column-preview-DtrgJzVI.js → column-preview-sL_Jo0hX.js} +1 -1
  22. package/dist/assets/{command-palette-BKYGTfS5.js → command-palette-DMQFuWz1.js} +1 -1
  23. package/dist/assets/{common-BMeq0Bqi.js → common-Cy3lJDvJ.js} +1 -1
  24. package/dist/assets/{components-CWcf8098.js → components-D9ZIJGG8.js} +1 -1
  25. package/dist/assets/{config-BAnYSdpO.js → config-D_c_6ce1.js} +1 -1
  26. package/dist/assets/{datasource-BLHGFSsT.js → datasource-Tst92Pzi.js} +1 -1
  27. package/dist/assets/{dependency-graph-panel-C8X3Nn8W.js → dependency-graph-panel-BwMayTyZ.js} +1 -1
  28. package/dist/assets/{documentation-panel-C8wrSKlX.js → documentation-panel-OMUbXgKW.js} +1 -1
  29. package/dist/assets/{download-CUgiCx7s.js → download-CPMAf7re.js} +1 -1
  30. package/dist/assets/{edit-page-CqPNBpAP.js → edit-page-DD1NFkiu.js} +6 -6
  31. package/dist/assets/{error-entries-DQD4A9cx.js → error-entries-DBpwg0GC.js} +1 -1
  32. package/dist/assets/{error-panel-BJYkwYEY.js → error-panel-ByOEJuZN.js} +1 -1
  33. package/dist/assets/{feedback-button-DbTjGwcX.js → feedback-button-7KY7nL-j.js} +2 -2
  34. package/dist/assets/feedback-button-DxjoRfo3.js +1 -0
  35. package/dist/assets/{file-explorer-panel-BQi88S1o.js → file-explorer-panel-B92ugwxr.js} +1 -1
  36. package/dist/assets/{file-name-input-DPJSxW_X.js → file-name-input-DZehOHLA.js} +1 -1
  37. package/dist/assets/{floating-outline-3PlTr0K1.js → floating-outline-K7cVdOlC.js} +1 -1
  38. package/dist/assets/{gallery-page-BqvVmwde.js → gallery-page-DoriMrLH.js} +1 -1
  39. package/dist/assets/{glide-data-editor-CAa14cIr.js → glide-data-editor-DWyeHe3u.js} +1 -1
  40. package/dist/assets/{home-page-Bg-WqjiD.js → home-page-BcJJsD_Q.js} +1 -1
  41. package/dist/assets/{hooks-DLBvBo8c.js → hooks-DNPsQf79.js} +1 -1
  42. package/dist/assets/index-B7ZZVUcj.css +2 -0
  43. package/dist/assets/{index-BtV91sqJ.js → index-CqJKdR1j.js} +5 -5
  44. package/dist/assets/{layout-mWXZofX2.js → layout-BaluekG6.js} +3 -3
  45. package/dist/assets/{logs-panel-IKL6F2OX.js → logs-panel-OkoO5mbN.js} +1 -1
  46. package/dist/assets/{markdown-renderer-DHvAXF8E.js → markdown-renderer-mDlWBE1M.js} +1 -1
  47. package/dist/assets/{name-cell-input-j4eGLLyd.js → name-cell-input-D_Q2IhP9.js} +1 -1
  48. package/dist/assets/{outline-panel-CprDWmxn.js → outline-panel-Dy2cmYDF.js} +1 -1
  49. package/dist/assets/packages-panel-CIvhx0hb.js +1 -0
  50. package/dist/assets/{panel-accordion-state-8xXVhawu.js → panel-accordion-state-BI4SU22L.js} +1 -1
  51. package/dist/assets/panels-CO6Clgel.js +4 -0
  52. package/dist/assets/{process-output-DOmeJ1VR.js → process-output-Crm0vqbi.js} +1 -1
  53. package/dist/assets/{readonly-code-display-xvH6MyT6.js → readonly-code-display-CNbw6v1-.js} +1 -1
  54. package/dist/assets/{readonly-python-code-D4YGmSvB.js → readonly-python-code-DcYhdd1B.js} +1 -1
  55. package/dist/assets/{reveal-component-CDUG1x74.js → reveal-component-DeZTBbnn.js} +1 -1
  56. package/dist/assets/{run-page-BAqLgcq9.js → run-page-BNEg-Ro9.js} +1 -1
  57. package/dist/assets/runtime-details-state-lxXYwJcI.js +1 -0
  58. package/dist/assets/{scratchpad-panel-BFbUuzdn.js → scratchpad-panel-lDJWcpVs.js} +1 -1
  59. package/dist/assets/{session-panel-BdN43Lzi.js → session-panel-BqutyoYd.js} +1 -1
  60. package/dist/assets/{snippets-panel-5_jR08Zd.js → snippets-panel-YttkYAW9.js} +1 -1
  61. package/dist/assets/state-B2ZbImvm.js +1 -0
  62. package/dist/assets/{state-BxJ_FX3k.js → state-B85OOscw.js} +1 -1
  63. package/dist/assets/{state-7os84dnI.js → state-sbCCk7ZP.js} +1 -1
  64. package/dist/assets/{terminal-DHWTOXu3.js → terminal-3hxM6K9q.js} +1 -1
  65. package/dist/assets/{tracing-CRkNpBaH.js → tracing-DZYfCw6p.js} +1 -1
  66. package/dist/assets/{tracing-panel-DV2-2TUI.js → tracing-panel-BUPJ77jB.js} +2 -2
  67. package/dist/assets/{tree-actions-CShqSonp.js → tree-actions-D5clvgKl.js} +1 -1
  68. package/dist/assets/{useAddCell-DesMfnE4.js → useAddCell-Bhv6GT3m.js} +1 -1
  69. package/dist/assets/{useBoolean-BofUVeKg.js → useBoolean-Co-_MyFz.js} +1 -1
  70. package/dist/assets/{useCellActionButton-BO5SFMxA.js → useCellActionButton-DwAUf_Cn.js} +1 -1
  71. package/dist/assets/{useDeleteCell-DSbUjpSC.js → useDeleteCell-BKN7t4DH.js} +1 -1
  72. package/dist/assets/{useDependencyPanelTab-JIFiQrr2.js → useDependencyPanelTab-CbcGEmqM.js} +1 -1
  73. package/dist/assets/{useInstallPackage-CCQcFc6U.js → useInstallPackage-HTUlGg0U.js} +1 -1
  74. package/dist/assets/{useNotebookActions-CjjED3t-.js → useNotebookActions-pXzVjrlk.js} +1 -1
  75. package/dist/assets/{useRunCells-Bx3wXUWO.js → useRunCells-zMO43eNR.js} +1 -1
  76. package/dist/assets/{useSplitCell-BRmQP02b.js → useSplitCell-xEtFLByO.js} +1 -1
  77. package/dist/assets/{vega-component-C28fL5fD.js → vega-component-Chbfi__Q.js} +1 -1
  78. package/dist/index.html +24 -24
  79. package/package.json +1 -1
  80. package/src/__tests__/mount.test.ts +6 -6
  81. package/src/components/editor/actions/useRestartKernel.tsx +2 -2
  82. package/src/components/editor/alerts/__tests__/connection-notice.test.tsx +224 -17
  83. package/src/components/editor/alerts/connection-details.tsx +61 -0
  84. package/src/components/editor/alerts/connection-notice.tsx +46 -53
  85. package/src/components/editor/alerts/startup-progress.tsx +73 -129
  86. package/src/components/editor/app-container.tsx +2 -2
  87. package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +2 -2
  88. package/src/components/editor/cell/CreateCellButton.tsx +2 -2
  89. package/src/components/editor/cell/DeleteButton.tsx +2 -2
  90. package/src/components/editor/cell/RunButton.tsx +3 -3
  91. package/src/components/editor/cell/StopButton.tsx +2 -2
  92. package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +4 -4
  93. package/src/components/editor/chrome/components/feedback-button.tsx +3 -3
  94. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +8 -8
  95. package/src/components/editor/chrome/panels/__tests__/{sandbox-details.test.tsx → runtime-details.test.tsx} +94 -22
  96. package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +4 -4
  97. package/src/components/editor/chrome/panels/packages-panel.tsx +8 -29
  98. package/src/components/editor/chrome/panels/{sandbox-details-state.ts → runtime-details-state.ts} +1 -1
  99. package/src/components/editor/chrome/panels/{sandbox-panel.tsx → runtime-panel.tsx} +38 -66
  100. package/src/components/editor/chrome/panels/runtime-status-toggle.tsx +56 -0
  101. package/src/components/editor/chrome/panels/sandbox-controller.tsx +2 -2
  102. package/src/components/editor/chrome/wrapper/app-chrome.tsx +3 -3
  103. package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +2 -2
  104. package/src/components/editor/controls/Controls.tsx +3 -3
  105. package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +2 -2
  106. package/src/components/editor/header/__tests__/status.test.tsx +4 -4
  107. package/src/components/editor/header/app-header.tsx +2 -2
  108. package/src/components/editor/header/status.tsx +3 -3
  109. package/src/components/ui/progress-stages.tsx +114 -0
  110. package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +106 -5
  111. package/src/core/codemirror/lsp/notebook-lsp.ts +16 -2
  112. package/src/core/codemirror/readonly/__tests__/extension.test.ts +6 -6
  113. package/src/core/codemirror/readonly/extension.ts +2 -2
  114. package/src/core/datasets/__tests__/data-source-discovery.test.ts +2 -2
  115. package/src/core/edit-app.tsx +5 -1
  116. package/src/core/export/hooks.ts +2 -2
  117. package/src/core/network/__tests__/connection.test.ts +3 -3
  118. package/src/core/network/connection-notice.ts +5 -5
  119. package/src/core/network/connection.ts +9 -9
  120. package/src/core/network/requests-lazy.ts +2 -2
  121. package/src/core/packages/__tests__/useSandboxController.test.tsx +2 -2
  122. package/src/core/packages/useSandboxController.ts +6 -6
  123. package/src/core/runtime/__tests__/adapter.test.ts +6 -6
  124. package/src/core/runtime/adapter.ts +7 -7
  125. package/src/core/runtime/config.ts +2 -2
  126. package/src/core/saving/filename.ts +2 -2
  127. package/src/core/saving/save-component.tsx +5 -5
  128. package/src/core/saving/useAutoSave.ts +2 -2
  129. package/src/core/websocket/__tests__/useMarimoKernelConnection.hook.test.tsx +30 -25
  130. package/src/core/websocket/__tests__/useMarimoKernelConnection.test.ts +5 -5
  131. package/src/core/websocket/connection-utils.ts +21 -21
  132. package/src/core/websocket/types.ts +8 -9
  133. package/src/core/websocket/useMarimoKernelConnection.tsx +21 -21
  134. package/src/mount.tsx +2 -2
  135. package/src/plugins/core/__test__/registerReactComponent.test.ts +55 -0
  136. package/src/plugins/core/registerReactComponent.tsx +3 -1
  137. package/src/stories/cell.stories.tsx +2 -2
  138. package/src/stories/layout/vertical/one-column.stories.tsx +5 -5
  139. package/src/stories/progress-stages.stories.tsx +62 -0
  140. package/src/stories/runtime-existing.stories.tsx +44 -0
  141. package/src/stories/runtime-maintenance.stories.tsx +40 -0
  142. package/src/stories/runtime-pixi.stories.tsx +28 -0
  143. package/src/stories/{sandbox.stories.tsx → runtime-story.tsx} +191 -152
  144. package/src/stories/runtime-uv.stories.tsx +56 -0
  145. package/dist/assets/cell-link-BeZAiE1D.js +0 -1
  146. package/dist/assets/code-visibility-B5QjA0ie.js +0 -1
  147. package/dist/assets/feedback-button-JqvnTSfN.js +0 -1
  148. package/dist/assets/index-CF8Gfz1R.css +0 -2
  149. package/dist/assets/packages-panel-CDDChziK.js +0 -1
  150. package/dist/assets/panels-CU7deLqc.js +0 -4
  151. package/dist/assets/sandbox-panel-D5bRunTM.js +0 -1
  152. package/dist/assets/state-Bo8h64Rn.js +0 -1
  153. package/src/components/editor/chrome/panels/sandbox-toggle.tsx +0 -52
@@ -84,7 +84,7 @@ import { isWasm } from "../wasm/utils";
84
84
  import {
85
85
  type ConnectionStatus,
86
86
  WebSocketClosedReason,
87
- WebSocketState,
87
+ ConnectionState,
88
88
  } from "./types";
89
89
 
90
90
  const SUPPORTS_LAZY_KERNELS = true;
@@ -116,7 +116,7 @@ export function classifyCloseEvent(event: { reason?: string }): CloseDecision {
116
116
  return {
117
117
  kind: "gave-up",
118
118
  status: {
119
- state: WebSocketState.CLOSED,
119
+ state: ConnectionState.CLOSED,
120
120
  code: WebSocketClosedReason.KERNEL_DISCONNECTED,
121
121
  reason: "kernel not found",
122
122
  },
@@ -128,7 +128,7 @@ export function classifyCloseEvent(event: { reason?: string }): CloseDecision {
128
128
  return {
129
129
  kind: "terminal",
130
130
  status: {
131
- state: WebSocketState.CLOSED,
131
+ state: ConnectionState.CLOSED,
132
132
  code: WebSocketClosedReason.KERNEL_DISCONNECTED,
133
133
  reason: "kernel not found",
134
134
  },
@@ -138,7 +138,7 @@ export function classifyCloseEvent(event: { reason?: string }): CloseDecision {
138
138
  return {
139
139
  kind: "terminal",
140
140
  status: {
141
- state: WebSocketState.CLOSED,
141
+ state: ConnectionState.CLOSED,
142
142
  code: WebSocketClosedReason.KERNEL_DISCONNECTED,
143
143
  reason: "not authorized",
144
144
  },
@@ -148,7 +148,7 @@ export function classifyCloseEvent(event: { reason?: string }): CloseDecision {
148
148
  return {
149
149
  kind: "terminal",
150
150
  status: {
151
- state: WebSocketState.CLOSED,
151
+ state: ConnectionState.CLOSED,
152
152
  code: WebSocketClosedReason.KERNEL_DISCONNECTED,
153
153
  reason: "kiosk mode is not available for this session",
154
154
  },
@@ -158,7 +158,7 @@ export function classifyCloseEvent(event: { reason?: string }): CloseDecision {
158
158
  return {
159
159
  kind: "terminal",
160
160
  status: {
161
- state: WebSocketState.CLOSED,
161
+ state: ConnectionState.CLOSED,
162
162
  code: WebSocketClosedReason.KERNEL_STARTUP_ERROR,
163
163
  reason: "Failed to start kernel sandbox",
164
164
  },
@@ -175,7 +175,7 @@ export function classifyCloseEvent(event: { reason?: string }): CloseDecision {
175
175
 
176
176
  return {
177
177
  kind: "retry",
178
- status: { state: WebSocketState.CONNECTING },
178
+ status: { state: ConnectionState.CONNECTING },
179
179
  };
180
180
  }
181
181
 
@@ -256,17 +256,17 @@ export function useMarimoKernelConnection(opts: {
256
256
  const { phase } = msg.data;
257
257
  updateStartupProgress(msg.data);
258
258
  setConnection((previous) =>
259
- previous.state === WebSocketState.OPEN ||
260
- (previous.state === WebSocketState.CONNECTING &&
259
+ previous.state === ConnectionState.OPEN ||
260
+ (previous.state === ConnectionState.CONNECTING &&
261
261
  previous.phase === phase)
262
262
  ? previous
263
- : { state: WebSocketState.CONNECTING, phase },
263
+ : { state: ConnectionState.CONNECTING, phase },
264
264
  );
265
265
  return;
266
266
  }
267
267
  case "kernel-ready": {
268
268
  setKernelStartupError(null);
269
- setConnection({ state: WebSocketState.OPEN });
269
+ setConnection({ state: ConnectionState.OPEN });
270
270
  setInitialRunCompleted(
271
271
  Boolean(msg.data.resumed || msg.data.auto_instantiated),
272
272
  );
@@ -481,7 +481,7 @@ export function useMarimoKernelConnection(opts: {
481
481
 
482
482
  case "reconnected":
483
483
  setKernelStartupError(null);
484
- setConnection({ state: WebSocketState.OPEN });
484
+ setConnection({ state: ConnectionState.OPEN });
485
485
  return;
486
486
 
487
487
  case "focus-cell":
@@ -526,12 +526,12 @@ export function useMarimoKernelConnection(opts: {
526
526
  }
527
527
  shouldTryReconnecting.current = true;
528
528
  setKernelStartupError(null);
529
- setConnection({ state: WebSocketState.CONNECTING });
529
+ setConnection({ state: ConnectionState.CONNECTING });
530
530
  const healthy = await runtimeManager.reconcileFromHealth();
531
531
  if (!healthy) {
532
532
  shouldTryReconnecting.current = false;
533
533
  setConnection({
534
- state: WebSocketState.CLOSED,
534
+ state: ConnectionState.CLOSED,
535
535
  code: WebSocketClosedReason.KERNEL_DISCONNECTED,
536
536
  reason: "kernel not found",
537
537
  });
@@ -607,17 +607,17 @@ export function useMarimoKernelConnection(opts: {
607
607
  setConnection((previous) => {
608
608
  const status = decision.status;
609
609
  if (
610
- status.state === WebSocketState.CLOSED &&
610
+ status.state === ConnectionState.CLOSED &&
611
611
  status.code === WebSocketClosedReason.KERNEL_STARTUP_ERROR &&
612
- (previous.state === WebSocketState.CONNECTING ||
613
- previous.state === WebSocketState.CLOSED)
612
+ (previous.state === ConnectionState.CONNECTING ||
613
+ previous.state === ConnectionState.CLOSED)
614
614
  ) {
615
615
  return { ...status, phase: previous.phase };
616
616
  }
617
617
  if (
618
- status.state === WebSocketState.CONNECTING &&
619
- (previous.state === WebSocketState.OPEN ||
620
- (previous.state === WebSocketState.CONNECTING &&
618
+ status.state === ConnectionState.CONNECTING &&
619
+ (previous.state === ConnectionState.OPEN ||
620
+ (previous.state === ConnectionState.CONNECTING &&
621
621
  previous.phase === "reconnecting"))
622
622
  ) {
623
623
  return { ...status, phase: "reconnecting" };
@@ -642,7 +642,7 @@ export function useMarimoKernelConnection(opts: {
642
642
  onError: (e) => {
643
643
  Logger.warn("WebSocket error", e);
644
644
  setConnection({
645
- state: WebSocketState.CLOSED,
645
+ state: ConnectionState.CLOSED,
646
646
  code: WebSocketClosedReason.KERNEL_DISCONNECTED,
647
647
  reason: "kernel not found",
648
648
  });
package/src/mount.tsx CHANGED
@@ -62,7 +62,7 @@ import {
62
62
  import { maybeRegisterVSCodeBindings } from "./core/vscode/vscode-bindings";
63
63
  import type { FileStore } from "./core/wasm/store";
64
64
  import { notebookFileStore } from "./core/wasm/store";
65
- import { WebSocketState } from "./core/websocket/types";
65
+ import { ConnectionState } from "./core/websocket/types";
66
66
  import {
67
67
  handleWidgetMessage,
68
68
  WIDGET_REGISTRY,
@@ -359,7 +359,7 @@ function initStore(options: unknown) {
359
359
  });
360
360
  // If the remote runtime is not lazy, start it in CONNECTING
361
361
  if (!firstRuntimeConfig.lazy && !isStaticNotebook()) {
362
- store.set(connectionAtom, { state: WebSocketState.CONNECTING });
362
+ store.set(connectionAtom, { state: ConnectionState.CONNECTING });
363
363
  }
364
364
  } else {
365
365
  store.set(runtimeConfigAtom, {
@@ -32,6 +32,61 @@ function makePlugin(tagName: string) {
32
32
  };
33
33
  }
34
34
 
35
+ describe("stylesheet copying", () => {
36
+ afterEach(() => {
37
+ delete (Document.prototype as Partial<Document>).adoptedStyleSheets;
38
+ vi.restoreAllMocks();
39
+ vi.unstubAllGlobals();
40
+ });
41
+
42
+ test.each([
43
+ {
44
+ name: "linked stylesheet",
45
+ href: "http://localhost/assets/index.css",
46
+ title: "marimo-linked-test",
47
+ expectedBaseURL: "http://localhost/assets/index.css",
48
+ },
49
+ {
50
+ name: "inline stylesheet",
51
+ href: null,
52
+ title: "marimo-inline-test",
53
+ expectedBaseURL: document.baseURI,
54
+ },
55
+ ])(
56
+ "preserves the base URL of a $name",
57
+ ({ href, title, expectedBaseURL }) => {
58
+ const constructedStyleSheet = {
59
+ replaceSync: vi.fn(),
60
+ } as unknown as CSSStyleSheet;
61
+ const constructor = vi.fn(function () {
62
+ return constructedStyleSheet;
63
+ });
64
+ constructor.prototype.replace = vi.fn();
65
+ vi.stubGlobal("CSSStyleSheet", constructor);
66
+ Object.defineProperty(Document.prototype, "adoptedStyleSheets", {
67
+ configurable: true,
68
+ value: [],
69
+ });
70
+
71
+ const source = {
72
+ cssRules: [],
73
+ href,
74
+ ownerNode: null,
75
+ title,
76
+ } as unknown as CSSStyleSheet;
77
+ vi.spyOn(document, "styleSheets", "get").mockReturnValue([
78
+ source,
79
+ ] as unknown as StyleSheetList);
80
+
81
+ const tag = uniqueTag("stylesheet-base-url");
82
+ registerReactComponent(makePlugin(tag));
83
+ document.createElement(tag);
84
+
85
+ expect(constructor).toHaveBeenCalledWith({ baseURL: expectedBaseURL });
86
+ },
87
+ );
88
+ });
89
+
35
90
  describe("isCustomMarimoElement", () => {
36
91
  test("returns false for null", () => {
37
92
  expect(isCustomMarimoElement(null)).toBe(false);
@@ -519,7 +519,9 @@ export function registerReactComponent<T>(plugin: IPlugin<T, unknown>): void {
519
519
  if (!styleSheetCache.has(sheetUniqueKey)) {
520
520
  // We need to create a new stylesheet because we can't use the same
521
521
  // stylesheet otherwise the browser will throw an error.
522
- const newSheet = new CSSStyleSheet();
522
+ const newSheet = new CSSStyleSheet({
523
+ baseURL: sheet.href ?? document.baseURI,
524
+ });
523
525
  try {
524
526
  newSheet.replaceSync(
525
527
  Array.from(sheet.cssRules)
@@ -14,7 +14,7 @@ import { connectionAtom } from "@/core/network/connection";
14
14
  import { requestClientAtom } from "@/core/network/requests";
15
15
  import { resolveRequestClient } from "@/core/network/resolve";
16
16
  import type { CellConfig } from "@/core/network/types";
17
- import { WebSocketState } from "@/core/websocket/types";
17
+ import { ConnectionState } from "@/core/websocket/types";
18
18
  import { MultiColumn } from "@/utils/id-tree";
19
19
  import type { Milliseconds, Seconds } from "@/utils/time";
20
20
  import { Cell as EditorCell } from "../components/editor/notebook-cell";
@@ -84,7 +84,7 @@ const Cell: React.FC<{
84
84
 
85
85
  const store = createStore();
86
86
  store.set(notebookAtom, notebook);
87
- store.set(connectionAtom, { state: WebSocketState.OPEN });
87
+ store.set(connectionAtom, { state: ConnectionState.OPEN });
88
88
  store.set(requestClientAtom, resolveRequestClient());
89
89
  return (
90
90
  <Provider store={store}>
@@ -11,7 +11,7 @@ import { showCodeInRunModeAtom } from "@/core/meta/state";
11
11
  import { connectionAtom } from "@/core/network/connection";
12
12
  import { requestClientAtom } from "@/core/network/requests";
13
13
  import { resolveRequestClient } from "@/core/network/resolve";
14
- import { WebSocketState } from "@/core/websocket/types";
14
+ import { ConnectionState } from "@/core/websocket/types";
15
15
  import { MultiColumn } from "@/utils/id-tree";
16
16
  import type { Milliseconds, Seconds } from "@/utils/time";
17
17
  import { CellArray } from "../../../components/editor/renderers/cell-array";
@@ -105,7 +105,7 @@ const EditModeCodeShown = () => {
105
105
 
106
106
  const store = createStore();
107
107
  store.set(notebookAtom, notebook);
108
- store.set(connectionAtom, { state: WebSocketState.OPEN });
108
+ store.set(connectionAtom, { state: ConnectionState.OPEN });
109
109
  store.set(requestClientAtom, resolveRequestClient());
110
110
  store.set(showCodeInRunModeAtom, true);
111
111
 
@@ -130,7 +130,7 @@ const EditModeCodeHidden = () => {
130
130
 
131
131
  const store = createStore();
132
132
  store.set(notebookAtom, notebook);
133
- store.set(connectionAtom, { state: WebSocketState.OPEN });
133
+ store.set(connectionAtom, { state: ConnectionState.OPEN });
134
134
  store.set(requestClientAtom, resolveRequestClient());
135
135
  store.set(showCodeInRunModeAtom, true);
136
136
 
@@ -155,7 +155,7 @@ const ReadModeCodeShown = () => {
155
155
 
156
156
  const store = createStore();
157
157
  store.set(notebookAtom, notebook);
158
- store.set(connectionAtom, { state: WebSocketState.OPEN });
158
+ store.set(connectionAtom, { state: ConnectionState.OPEN });
159
159
  store.set(requestClientAtom, resolveRequestClient());
160
160
  store.set(showCodeInRunModeAtom, true);
161
161
 
@@ -174,7 +174,7 @@ const ReadModeCodeHidden = () => {
174
174
 
175
175
  const store = createStore();
176
176
  store.set(notebookAtom, notebook);
177
- store.set(connectionAtom, { state: WebSocketState.OPEN });
177
+ store.set(connectionAtom, { state: ConnectionState.OPEN });
178
178
  store.set(requestClientAtom, resolveRequestClient());
179
179
  store.set(showCodeInRunModeAtom, true);
180
180
 
@@ -0,0 +1,62 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import type { Meta, StoryObj } from "@storybook/react-vite";
3
+ import {
4
+ ProgressStages,
5
+ type ProgressState,
6
+ } from "@/components/ui/progress-stages";
7
+
8
+ function ProgressStagesStory({
9
+ state,
10
+ completedStage,
11
+ }: {
12
+ state: ProgressState;
13
+ completedStage: boolean;
14
+ }) {
15
+ return (
16
+ <div className="w-80 space-y-6">
17
+ <p className="text-sm text-muted-foreground">
18
+ Isolated stage styling. For the actual notebook and sidebar, use the
19
+ walkthroughs under Runtime.
20
+ </p>
21
+ <ProgressStages
22
+ label="Example stages"
23
+ stages={[
24
+ ...(completedStage
25
+ ? [
26
+ {
27
+ id: "previous",
28
+ state: "succeeded" as const,
29
+ title: "Previous stage",
30
+ description: "This stage has finished.",
31
+ },
32
+ ]
33
+ : []),
34
+ {
35
+ id: "current",
36
+ state,
37
+ title: "Current stage",
38
+ description: "Change the state using the Storybook controls.",
39
+ },
40
+ ]}
41
+ />
42
+ </div>
43
+ );
44
+ }
45
+
46
+ const meta = {
47
+ title: "UI Primitives/ProgressStages",
48
+ component: ProgressStagesStory,
49
+ parameters: { layout: "centered" },
50
+ args: { state: "running", completedStage: true },
51
+ argTypes: {
52
+ state: {
53
+ control: "radio",
54
+ options: ["waiting", "running", "succeeded", "failed"],
55
+ },
56
+ },
57
+ } satisfies Meta<typeof ProgressStagesStory>;
58
+ export default meta;
59
+ type Story = StoryObj<typeof meta>;
60
+
61
+ export const MultipleStages: Story = {};
62
+ export const SingleStage: Story = { args: { completedStage: false } };
@@ -0,0 +1,44 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import type { Meta, StoryObj } from "@storybook/react-vite";
3
+ import { type RuntimeStory, runtimeStoryMeta } from "./runtime-story";
4
+
5
+ const meta = {
6
+ ...runtimeStoryMeta,
7
+ title: "Runtime/Existing environment",
8
+ args: { ...runtimeStoryMeta.args, backend: null, phase: "starting" },
9
+ } satisfies Meta<typeof RuntimeStory>;
10
+ export default meta;
11
+ type Story = StoryObj<typeof meta>;
12
+
13
+ export const Walkthrough: Story = {
14
+ name: "Walkthrough",
15
+ args: { manual: true, detailsOpen: true },
16
+ };
17
+ export const NotebookConnecting: Story = {
18
+ name: "Notebook — connecting",
19
+ args: {},
20
+ };
21
+ export const NotebookFailed: Story = {
22
+ name: "Notebook — failure and retry",
23
+ args: { phase: "failed" },
24
+ };
25
+ export const EmptyNotebook: Story = {
26
+ name: "Empty notebook — connecting",
27
+ args: { existingCells: false },
28
+ };
29
+ export const DetailsConnecting: Story = {
30
+ name: "Sidebar — connecting",
31
+ args: { surface: "packages" },
32
+ };
33
+ export const DetailsFailed: Story = {
34
+ name: "Sidebar — failure details",
35
+ args: { surface: "packages", phase: "failed" },
36
+ };
37
+ export const Ready: Story = {
38
+ name: "Sidebar — ready",
39
+ args: { surface: "packages", phase: "ready" },
40
+ };
41
+ export const Completion: Story = {
42
+ name: "Automatic completion",
43
+ args: { interactive: true },
44
+ };
@@ -0,0 +1,40 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import type { Meta, StoryObj } from "@storybook/react-vite";
3
+ import { type RuntimeStory, runtimeStoryMeta } from "./runtime-story";
4
+
5
+ const meta = {
6
+ ...runtimeStoryMeta,
7
+ title: "Runtime/Sandbox maintenance",
8
+ args: { ...runtimeStoryMeta.args, backend: "uv", surface: "packages" },
9
+ } satisfies Meta<typeof RuntimeStory>;
10
+ export default meta;
11
+ type Story = StoryObj<typeof meta>;
12
+
13
+ export const Syncing: Story = {
14
+ name: "Sync — in progress",
15
+ args: { phase: "syncing" },
16
+ };
17
+ export const SyncFailed: Story = {
18
+ name: "Sync — failed",
19
+ args: { phase: "sync-failed" },
20
+ };
21
+ export const Synced: Story = {
22
+ name: "Sync — completed",
23
+ args: { phase: "synced" },
24
+ };
25
+ export const RestartRequired: Story = {
26
+ name: "Sync — restart required",
27
+ args: { phase: "restart-required" },
28
+ };
29
+ export const ManifestEditor: Story = {
30
+ name: "Manifest — edit",
31
+ args: { surface: "manifest", phase: "failed" },
32
+ };
33
+ export const ManifestSyncFailed: Story = {
34
+ name: "Manifest — sync failed",
35
+ args: { surface: "manifest", phase: "failed", saveResult: "failure" },
36
+ };
37
+ export const ManifestChanged: Story = {
38
+ name: "Manifest — changed on disk",
39
+ args: { surface: "manifest", phase: "failed", saveResult: "stale" },
40
+ };
@@ -0,0 +1,28 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import type { Meta, StoryObj } from "@storybook/react-vite";
3
+ import { type RuntimeStory, runtimeStoryMeta } from "./runtime-story";
4
+
5
+ const meta = {
6
+ ...runtimeStoryMeta,
7
+ title: "Runtime/pixi sandbox",
8
+ args: { ...runtimeStoryMeta.args, backend: "pixi" },
9
+ } satisfies Meta<typeof RuntimeStory>;
10
+ export default meta;
11
+ type Story = StoryObj<typeof meta>;
12
+
13
+ export const Walkthrough: Story = {
14
+ name: "Walkthrough",
15
+ args: { manual: true, detailsOpen: true },
16
+ };
17
+ export const Ready: Story = {
18
+ name: "Sidebar — ready",
19
+ args: { surface: "packages", phase: "ready" },
20
+ };
21
+ export const Completion: Story = {
22
+ name: "Notebook — automatic completion",
23
+ args: { interactive: true },
24
+ };
25
+ export const EmptyCompletion: Story = {
26
+ name: "Empty notebook — automatic completion",
27
+ args: { interactive: true, existingCells: false },
28
+ };