@marimo-team/frontend 0.20.0 → 0.20.2

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 (67) hide show
  1. package/dist/assets/{CellStatus-C-x2V01u.js → CellStatus-CXzj7sRm.js} +1 -1
  2. package/dist/assets/{JsonOutput-GcxmOJYP.js → JsonOutput-Cf8A51yY.js} +1 -1
  3. package/dist/assets/{MarimoErrorOutput-DXW0JM3_.js → MarimoErrorOutput-DDh0mN6J.js} +1 -1
  4. package/dist/assets/{RenderHTML-Daud0S_p.js → RenderHTML-BtyszmRY.js} +1 -1
  5. package/dist/assets/{add-cell-with-ai-tKFEu3DZ.js → add-cell-with-ai-BCTdiv0p.js} +1 -1
  6. package/dist/assets/{add-database-form-CzPD2bTj.js → add-database-form-Be5HSGc6.js} +1 -1
  7. package/dist/assets/{agent-panel-CQbchvK2.js → agent-panel-2Q2T5S16.js} +1 -1
  8. package/dist/assets/{ai-model-dropdown-CKWg_XHD.js → ai-model-dropdown-BC0cdhi9.js} +1 -1
  9. package/dist/assets/{app-config-button-R5x8Kgdf.js → app-config-button-DmKmnxml.js} +1 -1
  10. package/dist/assets/{cell-editor-Dwrvpw6E.js → cell-editor-DW3vX0Hr.js} +1 -1
  11. package/dist/assets/{cell-link-Bhvw0on1.js → cell-link-HggHOhac.js} +1 -1
  12. package/dist/assets/{cells-3SLwRjPd.js → cells-BvQJ_wGv.js} +1 -1
  13. package/dist/assets/{chat-display-CjlWzBMp.js → chat-display-Bvu3qbng.js} +1 -1
  14. package/dist/assets/{chat-panel-C7GNMsJo.js → chat-panel-BGfg1SLf.js} +1 -1
  15. package/dist/assets/{column-preview-3XIyjT9T.js → column-preview-CJ3a0IPi.js} +1 -1
  16. package/dist/assets/{command-zI_q-_PG.js → command-D2UvWA5R.js} +1 -1
  17. package/dist/assets/{command-palette-CqYF4pMC.js → command-palette-D8rmVaQE.js} +1 -1
  18. package/dist/assets/{common-DORX-NKD.js → common-CdY4MV1-.js} +1 -1
  19. package/dist/assets/{datasource-BNFc5bM1.js → datasource-ow4Y3Yl7.js} +1 -1
  20. package/dist/assets/{dependency-graph-panel--665IS5c.js → dependency-graph-panel-G7LHU1W_.js} +1 -1
  21. package/dist/assets/{documentation-panel-CaE2ohYn.js → documentation-panel-C1BKTYu6.js} +1 -1
  22. package/dist/assets/{download-BWdagSya.js → download-FoG6dAm7.js} +1 -1
  23. package/dist/assets/{edit-page-D3xQ9L_f.js → edit-page-qkwPqNNl.js} +3 -3
  24. package/dist/assets/{error-panel-CUvQCWJt.js → error-panel-Cse2qyD7.js} +1 -1
  25. package/dist/assets/{file-explorer-panel-DeybZaOo.js → file-explorer-panel-I8XsTAeG.js} +1 -1
  26. package/dist/assets/{floating-outline-2m6YWlpq.js → floating-outline-D3kzMiv3.js} +1 -1
  27. package/dist/assets/{focus-DyBJP5Y2.js → focus-CPRFg4kn.js} +1 -1
  28. package/dist/assets/{form-B3o-gHpb.js → form-DISpbGyw.js} +1 -1
  29. package/dist/assets/{globals-rTjtfYVE.js → globals-g_NWGBtF.js} +1 -1
  30. package/dist/assets/{home-page-Dd3yQLeM.js → home-page-DFksLw4j.js} +1 -1
  31. package/dist/assets/{hooks-C44T-jvI.js → hooks-DDDn7T5i.js} +1 -1
  32. package/dist/assets/{html-to-image-BODKgB04.js → html-to-image-DvPYLUI8.js} +1 -1
  33. package/dist/assets/{index-CUYYOT3v.js → index-xckvhXGM.js} +18 -18
  34. package/dist/assets/{kiosk-mode-DBQu1lzt.js → kiosk-mode-DChTDQjX.js} +1 -1
  35. package/dist/assets/{layout-DvylFImy.js → layout-W7LHtlpD.js} +1 -1
  36. package/dist/assets/{logs-panel-HEDRaCpU.js → logs-panel-WG80bH91.js} +1 -1
  37. package/dist/assets/{markdown-renderer-DKn81PWh.js → markdown-renderer-Dyy86-0S.js} +1 -1
  38. package/dist/assets/{mode-CuFbHwND.js → mode-COhtYT4e.js} +1 -1
  39. package/dist/assets/{name-cell-input-CIs7Aqay.js → name-cell-input-Cga4BASx.js} +1 -1
  40. package/dist/assets/{outline-panel-B2F8-xpS.js → outline-panel-oVyrH0zg.js} +1 -1
  41. package/dist/assets/{packages-panel-CPc1z9d4.js → packages-panel-CAj1iddH.js} +1 -1
  42. package/dist/assets/{panels-Dh7M-Zzp.js → panels-BP4rsYL6.js} +1 -1
  43. package/dist/assets/{process-output-BpbC_Aow.js → process-output-WvCcApgB.js} +1 -1
  44. package/dist/assets/{readonly-python-code-D3Z8uYT4.js → readonly-python-code-ZwGAfelJ.js} +1 -1
  45. package/dist/assets/{run-page-DwpujfMt.js → run-page-BsDIxokV.js} +1 -1
  46. package/dist/assets/{scratchpad-panel-BlFZic7K.js → scratchpad-panel-Bl5zLNBf.js} +1 -1
  47. package/dist/assets/{session-panel-C40jAnsp.js → session-panel-C2uwzFbP.js} +1 -1
  48. package/dist/assets/{snippets-panel-DQ_FNiaw.js → snippets-panel-DE-LV-IU.js} +1 -1
  49. package/dist/assets/{state-EtDJEfA8.js → state-D0hcaf71.js} +1 -1
  50. package/dist/assets/{switch-KP9aBLRd.js → switch-C3e8vdXY.js} +1 -1
  51. package/dist/assets/{textarea-BeKvrxrf.js → textarea-DIGVRG-E.js} +1 -1
  52. package/dist/assets/{tracing-DXW2T0PZ.js → tracing-h7TdA1_p.js} +1 -1
  53. package/dist/assets/{tracing-panel-BakKzZZ8.js → tracing-panel-Babikkit.js} +2 -2
  54. package/dist/assets/{types-BWsfSnQV.js → types-B0GfsfZC.js} +1 -1
  55. package/dist/assets/{useAddCell-Bxc74D8L.js → useAddCell-DWpYLvcR.js} +1 -1
  56. package/dist/assets/{useCellActionButton-CYbF-pxP.js → useCellActionButton-Db9MI9XQ.js} +1 -1
  57. package/dist/assets/{useDeleteCell-MooOUPWp.js → useDeleteCell-87_Oh8sv.js} +1 -1
  58. package/dist/assets/{useDependencyPanelTab-BJ-miHJJ.js → useDependencyPanelTab-BloSVZ6I.js} +1 -1
  59. package/dist/assets/{useNotebookActions-CMrugtYC.js → useNotebookActions-_M_GKcKV.js} +1 -1
  60. package/dist/assets/{useRunCells-DQIUBAoK.js → useRunCells-DCLlGGDx.js} +1 -1
  61. package/dist/assets/{useSplitCell-DPGiPYwq.js → useSplitCell-BGRLlxZG.js} +1 -1
  62. package/dist/assets/{utilities.esm-BHFwaIGQ.js → utilities.esm-C57m8aJQ.js} +1 -1
  63. package/dist/index.html +30 -30
  64. package/package.json +1 -1
  65. package/src/core/codemirror/extensions.ts +2 -7
  66. package/src/plugins/impl/matplotlib/__tests__/matplotlib-renderer.test.ts +37 -2
  67. package/src/plugins/impl/matplotlib/matplotlib-renderer.ts +31 -8
@@ -3,8 +3,14 @@ import { describe, expect, it } from "vitest";
3
3
  import type { Data } from "../matplotlib-renderer";
4
4
  import { visibleForTesting } from "../matplotlib-renderer";
5
5
 
6
- const { pixelToData, dataToPixel, pointInPolygon, clampToAxes, isPointInBox } =
7
- visibleForTesting;
6
+ const {
7
+ pixelToData,
8
+ dataToPixel,
9
+ pointInPolygon,
10
+ clampToAxes,
11
+ isPointInBox,
12
+ isInAxes,
13
+ } = visibleForTesting;
8
14
 
9
15
  // A simple axes geometry for testing:
10
16
  // axes occupy pixels [100, 50] to [500, 350] (400px wide, 300px tall)
@@ -150,3 +156,32 @@ describe("isPointInBox", () => {
150
156
  expect(isPointInBox({ x: 5, y: 30 }, boxEnd, boxStart)).toBe(false);
151
157
  });
152
158
  });
159
+
160
+ describe("isInAxes", () => {
161
+ it("returns true for a point inside the axes", () => {
162
+ expect(isInAxes({ x: 300, y: 200 }, LINEAR_AXES)).toBe(true);
163
+ });
164
+
165
+ it("returns true for a point on the boundary", () => {
166
+ expect(isInAxes({ x: 100, y: 50 }, LINEAR_AXES)).toBe(true); // top-left
167
+ expect(isInAxes({ x: 500, y: 350 }, LINEAR_AXES)).toBe(true); // bottom-right
168
+ expect(isInAxes({ x: 100, y: 350 }, LINEAR_AXES)).toBe(true); // bottom-left
169
+ expect(isInAxes({ x: 500, y: 50 }, LINEAR_AXES)).toBe(true); // top-right
170
+ });
171
+
172
+ it("returns false for a point left of axes", () => {
173
+ expect(isInAxes({ x: 99, y: 200 }, LINEAR_AXES)).toBe(false);
174
+ });
175
+
176
+ it("returns false for a point right of axes", () => {
177
+ expect(isInAxes({ x: 501, y: 200 }, LINEAR_AXES)).toBe(false);
178
+ });
179
+
180
+ it("returns false for a point above axes", () => {
181
+ expect(isInAxes({ x: 300, y: 49 }, LINEAR_AXES)).toBe(false);
182
+ });
183
+
184
+ it("returns false for a point below axes", () => {
185
+ expect(isInAxes({ x: 300, y: 351 }, LINEAR_AXES)).toBe(false);
186
+ });
187
+ });
@@ -257,6 +257,11 @@ function isPointInBox(
257
257
  return pt.x >= minX && pt.x <= maxX && pt.y >= minY && pt.y <= maxY;
258
258
  }
259
259
 
260
+ function isInAxes(pt: PixelPoint, g: AxesGeometry): boolean {
261
+ const [axLeft, axTop, axRight, axBottom] = g.axesPixelBounds;
262
+ return pt.x >= axLeft && pt.x <= axRight && pt.y >= axTop && pt.y <= axBottom;
263
+ }
264
+
260
265
  export const visibleForTesting = {
261
266
  createScale,
262
267
  pixelToData,
@@ -264,6 +269,7 @@ export const visibleForTesting = {
264
269
  pointInPolygon,
265
270
  clampToAxes,
266
271
  isPointInBox,
272
+ isInAxes,
267
273
  };
268
274
 
269
275
  export class MatplotlibRenderer {
@@ -330,10 +336,7 @@ export class MatplotlibRenderer {
330
336
  const prev = this.#state;
331
337
  this.#state = state;
332
338
 
333
- if (state.chartBase64 !== this.#currentChartBase64) {
334
- this.#loadImage(state.chartBase64);
335
- return;
336
- }
339
+ let needsRedraw = false;
337
340
 
338
341
  // Update canvas dimensions if changed
339
342
  if (state.width !== prev.width || state.height !== prev.height) {
@@ -342,15 +345,20 @@ export class MatplotlibRenderer {
342
345
  this.#canvas.height = state.height * dpr;
343
346
  this.#canvas.style.width = `${state.width}px`;
344
347
  this.#canvas.style.height = `${state.height}px`;
348
+ needsRedraw = true;
349
+ }
350
+
351
+ if (state.chartBase64 !== this.#currentChartBase64) {
352
+ this.#loadImage(state.chartBase64);
353
+ return;
345
354
  }
346
355
 
347
356
  // Redraw if style props changed or dimensions changed
348
357
  if (
358
+ needsRedraw ||
349
359
  state.selectionColor !== prev.selectionColor ||
350
360
  state.selectionOpacity !== prev.selectionOpacity ||
351
- state.strokeWidth !== prev.strokeWidth ||
352
- state.width !== prev.width ||
353
- state.height !== prev.height
361
+ state.strokeWidth !== prev.strokeWidth
354
362
  ) {
355
363
  this.#drawCanvas();
356
364
  }
@@ -364,6 +372,15 @@ export class MatplotlibRenderer {
364
372
  // Clear selection on new chart
365
373
  this.#interaction = { type: "idle" };
366
374
 
375
+ // Clear stale image so old content doesn't linger while new image loads
376
+ this.#image = null;
377
+ const ctx = this.#canvas.getContext("2d");
378
+ if (ctx) {
379
+ const dpr = globalThis.devicePixelRatio ?? 1;
380
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
381
+ ctx.clearRect(0, 0, this.#state.width, this.#state.height);
382
+ }
383
+
367
384
  const img = new Image();
368
385
  img.onload = () => {
369
386
  if (generation !== this.#imageGeneration) {
@@ -557,6 +574,9 @@ export class MatplotlibRenderer {
557
574
 
558
575
  // Shift+click -> start lasso
559
576
  if (e.shiftKey) {
577
+ if (!isInAxes(pt, this.#state)) {
578
+ return;
579
+ }
560
580
  this.#interaction = {
561
581
  type: "lasso",
562
582
  points: [clampToAxes(pt, this.#state)],
@@ -609,7 +629,10 @@ export class MatplotlibRenderer {
609
629
  this.#clearSelection();
610
630
  }
611
631
 
612
- // Start new box selection
632
+ // Start new box selection (only inside axes)
633
+ if (!isInAxes(pt, this.#state)) {
634
+ return;
635
+ }
613
636
  const clamped = clampToAxes(pt, this.#state);
614
637
  this.#interaction = {
615
638
  type: "box",