@marimo-team/islands 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.
package/dist/main.js
CHANGED
|
@@ -73400,7 +73400,7 @@ Image URL: ${r.imageUrl}`)), contextToXml({
|
|
|
73400
73400
|
return Logger.warn("Failed to get version from mount config"), null;
|
|
73401
73401
|
}
|
|
73402
73402
|
}
|
|
73403
|
-
const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.20.
|
|
73403
|
+
const marimoVersionAtom = atom(getVersionFromMountConfig() || "0.20.2"), showCodeInRunModeAtom = atom(true);
|
|
73404
73404
|
atom(null);
|
|
73405
73405
|
var import_compiler_runtime$88 = require_compiler_runtime();
|
|
73406
73406
|
function useKeydownOnElement(e, r) {
|
|
@@ -94128,6 +94128,10 @@ ${c}
|
|
|
94128
94128
|
let d = Math.min(r.x, c.x), f = Math.max(r.x, c.x), _ = Math.min(r.y, c.y), v = Math.max(r.y, c.y);
|
|
94129
94129
|
return e.x >= d && e.x <= f && e.y >= _ && e.y <= v;
|
|
94130
94130
|
}
|
|
94131
|
+
function isInAxes(e, r) {
|
|
94132
|
+
let [c, d, f, _] = r.axesPixelBounds;
|
|
94133
|
+
return e.x >= c && e.x <= f && e.y >= d && e.y <= _;
|
|
94134
|
+
}
|
|
94131
94135
|
var MatplotlibRenderer = (_k = class {
|
|
94132
94136
|
constructor(e, r) {
|
|
94133
94137
|
__privateAdd(this, _MatplotlibRenderer_instances);
|
|
@@ -94259,6 +94263,7 @@ ${c}
|
|
|
94259
94263
|
__privateGet(this, _e8).setPointerCapture(e.pointerId), __privateGet(this, _t5).focus();
|
|
94260
94264
|
let r = __privateGet(this, _d2).call(this, e), c = __privateGet(this, _r2);
|
|
94261
94265
|
if (e.shiftKey) {
|
|
94266
|
+
if (!isInAxes(r, __privateGet(this, _n4))) return;
|
|
94262
94267
|
__privateSet(this, _r2, {
|
|
94263
94268
|
type: "lasso",
|
|
94264
94269
|
points: [
|
|
@@ -94307,7 +94312,7 @@ ${c}
|
|
|
94307
94312
|
});
|
|
94308
94313
|
return;
|
|
94309
94314
|
}
|
|
94310
|
-
__privateGet(this, _h2).call(this) && __privateGet(this, _m).call(this);
|
|
94315
|
+
if (__privateGet(this, _h2).call(this) && __privateGet(this, _m).call(this), !isInAxes(r, __privateGet(this, _n4))) return;
|
|
94311
94316
|
let d = clampToAxes(r, __privateGet(this, _n4));
|
|
94312
94317
|
__privateSet(this, _r2, {
|
|
94313
94318
|
type: "box",
|
|
@@ -94413,26 +94418,33 @@ ${c}
|
|
|
94413
94418
|
}
|
|
94414
94419
|
update(e) {
|
|
94415
94420
|
let r = __privateGet(this, _n4);
|
|
94416
|
-
|
|
94417
|
-
|
|
94418
|
-
return;
|
|
94419
|
-
}
|
|
94421
|
+
__privateSet(this, _n4, e);
|
|
94422
|
+
let c = false;
|
|
94420
94423
|
if (e.width !== r.width || e.height !== r.height) {
|
|
94421
94424
|
let r2 = globalThis.devicePixelRatio ?? 1;
|
|
94422
|
-
__privateGet(this, _e8).width = e.width * r2, __privateGet(this, _e8).height = e.height * r2, __privateGet(this, _e8).style.width = `${e.width}px`, __privateGet(this, _e8).style.height = `${e.height}px
|
|
94425
|
+
__privateGet(this, _e8).width = e.width * r2, __privateGet(this, _e8).height = e.height * r2, __privateGet(this, _e8).style.width = `${e.width}px`, __privateGet(this, _e8).style.height = `${e.height}px`, c = true;
|
|
94423
94426
|
}
|
|
94424
|
-
(e.
|
|
94427
|
+
if (e.chartBase64 !== __privateGet(this, _s)) {
|
|
94428
|
+
__privateMethod(this, _MatplotlibRenderer_instances, c_fn).call(this, e.chartBase64);
|
|
94429
|
+
return;
|
|
94430
|
+
}
|
|
94431
|
+
(c || e.selectionColor !== r.selectionColor || e.selectionOpacity !== r.selectionOpacity || e.strokeWidth !== r.strokeWidth) && __privateGet(this, _l).call(this);
|
|
94425
94432
|
}
|
|
94426
94433
|
}, _e8 = new WeakMap(), _t5 = new WeakMap(), _n4 = new WeakMap(), _r2 = new WeakMap(), _i3 = new WeakMap(), _a2 = new WeakMap(), _o2 = new WeakMap(), _s = new WeakMap(), _MatplotlibRenderer_instances = new WeakSet(), c_fn = function(e) {
|
|
94427
94434
|
__privateSet(this, _s, e), __privateWrapper(this, _o2)._++;
|
|
94428
94435
|
let r = __privateGet(this, _o2);
|
|
94429
94436
|
__privateSet(this, _r2, {
|
|
94430
94437
|
type: "idle"
|
|
94431
|
-
});
|
|
94432
|
-
let c =
|
|
94433
|
-
|
|
94434
|
-
|
|
94435
|
-
|
|
94438
|
+
}), __privateSet(this, _a2, null);
|
|
94439
|
+
let c = __privateGet(this, _e8).getContext("2d");
|
|
94440
|
+
if (c) {
|
|
94441
|
+
let e2 = globalThis.devicePixelRatio ?? 1;
|
|
94442
|
+
c.setTransform(e2, 0, 0, e2, 0, 0), c.clearRect(0, 0, __privateGet(this, _n4).width, __privateGet(this, _n4).height);
|
|
94443
|
+
}
|
|
94444
|
+
let d = new Image();
|
|
94445
|
+
d.onload = () => {
|
|
94446
|
+
r === __privateGet(this, _o2) && (__privateSet(this, _a2, d), __privateGet(this, _l).call(this));
|
|
94447
|
+
}, d.src = e;
|
|
94436
94448
|
}, _l = new WeakMap(), _u = new WeakMap(), _d2 = new WeakMap(), _f2 = new WeakMap(), _p = new WeakMap(), _m = new WeakMap(), _h2 = new WeakMap(), _g2 = new WeakMap(), __ = new WeakMap(), _v = new WeakMap(), _y = new WeakMap(), _b3 = new WeakMap(), _x = new WeakMap(), _S = new WeakMap(), _k), MatplotlibPlugin = class {
|
|
94437
94449
|
constructor() {
|
|
94438
94450
|
__publicField(this, "tagName", "marimo-matplotlib");
|
package/package.json
CHANGED
|
@@ -29,14 +29,9 @@ export function formatKeymapExtension(hotkeys: HotkeyProvider) {
|
|
|
29
29
|
preventDefault: true,
|
|
30
30
|
run: (ev) => {
|
|
31
31
|
const currentLanguage = getCurrentLanguageAdapter(ev);
|
|
32
|
-
// Early return if not a supported language
|
|
33
|
-
if (currentLanguage !== "markdown" && currentLanguage !== "python") {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Toggle between markdown and python
|
|
38
32
|
const destinationLanguage =
|
|
39
|
-
currentLanguage === "
|
|
33
|
+
currentLanguage === "markdown" ? "python" : "markdown";
|
|
34
|
+
|
|
40
35
|
const response = toggleToLanguage(ev, destinationLanguage, {
|
|
41
36
|
force: true,
|
|
42
37
|
});
|
|
@@ -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 {
|
|
7
|
-
|
|
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
|
-
|
|
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",
|