@marimo-team/frontend 0.20.5-dev83 → 0.20.5-dev88

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 (55) hide show
  1. package/dist/assets/{ConnectedDataExplorerComponent-DrjF-Wem.js → ConnectedDataExplorerComponent-CtWDfp3l.js} +1 -1
  2. package/dist/assets/{JsonOutput-BRjuq1Jw.js → JsonOutput-DjokO226.js} +1 -1
  3. package/dist/assets/{LazyAnyLanguageCodeMirror-CwbmGJrl.js → LazyAnyLanguageCodeMirror-Cqo8_z2X.js} +2 -2
  4. package/dist/assets/{RenderHTML-B0MiHkXS.js → RenderHTML-ncKzTdNN.js} +1 -1
  5. package/dist/assets/{add-cell-with-ai-BC41mi_U.js → add-cell-with-ai-Bl1TJ3Bp.js} +1 -1
  6. package/dist/assets/{agent-panel-CXdo6rmq.js → agent-panel-DFVcMxMV.js} +1 -1
  7. package/dist/assets/{ai-model-dropdown-V-_6L1Ri.js → ai-model-dropdown-DxpOlTBW.js} +1 -1
  8. package/dist/assets/{any-language-editor-BsZ7S7c3.js → any-language-editor-TJ9GwX4u.js} +1 -1
  9. package/dist/assets/{app-config-button-bSfCHsrZ.js → app-config-button-zy3OAtTs.js} +1 -1
  10. package/dist/assets/{cell-editor-BphfP1AG.js → cell-editor-CSaoLcvI.js} +1 -1
  11. package/dist/assets/{chat-display-Dv9VfU7V.js → chat-display-CWCYGDhk.js} +1 -1
  12. package/dist/assets/{chat-panel-BMoo_OFn.js → chat-panel-CYOmGmIc.js} +1 -1
  13. package/dist/assets/{column-preview-DBQzaLrY.js → column-preview-UqRUB1pJ.js} +1 -1
  14. package/dist/assets/{command-palette-D-iipine.js → command-palette-CQFQWyFs.js} +1 -1
  15. package/dist/assets/{common-Msb-h79F.js → common-D7Sae5Jl.js} +1 -1
  16. package/dist/assets/{context-aware-panel-CaZEaV8C.js → context-aware-panel-DScGcWey.js} +1 -1
  17. package/dist/assets/copy-BvFGCBvy.js +1 -0
  18. package/dist/assets/{copy-icon-Cu7az85f.js → copy-icon-HTFh4odu.js} +1 -1
  19. package/dist/assets/{dependency-graph-panel-RAEDBSLL.js → dependency-graph-panel-Cg4IqU-y.js} +1 -1
  20. package/dist/assets/{documentation-panel-B5ZS7rdM.js → documentation-panel-D5CHwsu6.js} +1 -1
  21. package/dist/assets/{edit-page-CfrFWBII.js → edit-page-BQEJKlvv.js} +7 -7
  22. package/dist/assets/{file-explorer-panel-DiJOGwKe.js → file-explorer-panel-DclnBp04.js} +1 -1
  23. package/dist/assets/{glide-data-editor-UlfiEtnp.js → glide-data-editor-caCB-p9t.js} +1 -1
  24. package/dist/assets/{home-page-2mWoP4xq.js → home-page-Cz5JcEtF.js} +1 -1
  25. package/dist/assets/{hooks-ChoVWWrC.js → hooks-BOa-vQTI.js} +1 -1
  26. package/dist/assets/{index-CDgqxTU8.css → index-CVpJvEAO.css} +1 -1
  27. package/dist/assets/{index-D3l50M_C.js → index-CfAeGR1K.js} +6 -6
  28. package/dist/assets/{layout-OuSaBBrA.js → layout-BOEBdVW9.js} +3 -3
  29. package/dist/assets/{markdown-renderer-D2_DEfz5.js → markdown-renderer-DwRjZSV8.js} +1 -1
  30. package/dist/assets/{packages-panel-BGH4NaYQ.js → packages-panel-CPHdKpTu.js} +1 -1
  31. package/dist/assets/{panels-Z0QtbAii.js → panels-BfLG6GHU.js} +1 -1
  32. package/dist/assets/{readonly-python-code-YmScI7wz.js → readonly-python-code-Cyn1aSna.js} +1 -1
  33. package/dist/assets/{run-page-D5R165Vz.js → run-page-lC8nyJai.js} +1 -1
  34. package/dist/assets/{scratchpad-panel-Dx0D4qLp.js → scratchpad-panel-B1HOh6tu.js} +1 -1
  35. package/dist/assets/{secrets-panel-DbkurO8B.js → secrets-panel-Bd4T4aNP.js} +1 -1
  36. package/dist/assets/{session-panel-D2vq8N6n.js → session-panel-3pPZOei4.js} +1 -1
  37. package/dist/assets/{snippets-panel-BReCSuHT.js → snippets-panel-DVBJJk2i.js} +1 -1
  38. package/dist/assets/{terminal-D3Lu-b1F.js → terminal-D7RRO5NO.js} +1 -1
  39. package/dist/assets/{useBoolean-DbIYzMhl.js → useBoolean-COWWzCBr.js} +1 -1
  40. package/dist/assets/{useCellActionButton-5K5fLTMd.js → useCellActionButton-DFS0hpsU.js} +1 -1
  41. package/dist/assets/{useDependencyPanelTab-CVeDMlz5.js → useDependencyPanelTab-Dakjo7fJ.js} +1 -1
  42. package/dist/assets/{useNotebookActions-CFogiTi9.js → useNotebookActions-CtiT4Mzf.js} +1 -1
  43. package/dist/assets/vega-component-tdJ9PJ9x.js +1 -0
  44. package/dist/index.html +15 -15
  45. package/package.json +1 -1
  46. package/src/components/editor/cell/cell-context-menu.tsx +2 -6
  47. package/src/components/editor/output/console/ConsoleOutput.tsx +51 -2
  48. package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +94 -3
  49. package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +8 -1
  50. package/src/plugins/impl/vega/vega-component.tsx +7 -1
  51. package/src/plugins/impl/vega/vega.css +4 -11
  52. package/src/utils/__tests__/copy.test.ts +129 -0
  53. package/src/utils/copy.ts +43 -0
  54. package/dist/assets/copy-f2iEg0yL.js +0 -1
  55. package/dist/assets/vega-component-DzBZ6SmR.js +0 -1
@@ -16,6 +16,7 @@ import { Tooltip } from "@/components/ui/tooltip";
16
16
  import { useAsyncData } from "@/hooks/useAsyncData";
17
17
  import { useDeepCompareMemoize } from "@/hooks/useDeepCompareMemoize";
18
18
  import { useTheme } from "@/theme/useTheme";
19
+ import { cn } from "@/utils/cn";
19
20
  import { Events } from "@/utils/events";
20
21
  import { Logger } from "@/utils/Logger";
21
22
  import { Objects } from "@/utils/objects";
@@ -304,7 +305,12 @@ const LoadedVegaComponent = ({
304
305
  </Alert>
305
306
  )}
306
307
  <div
307
- className="relative"
308
+ className={cn(
309
+ "relative",
310
+ "width" in selectableSpec &&
311
+ selectableSpec.width === "container" &&
312
+ "vega-container-width",
313
+ )}
308
314
  // Capture the pointer down event to prevent the parent from handling it
309
315
  onPointerDown={Events.stopPropagation()}
310
316
  >
@@ -1,18 +1,11 @@
1
1
  @reference "../../../css/globals.css";
2
2
 
3
3
  .vega-embed {
4
- width: 100%;
5
- flex: 1;
6
- display: inline-block;
7
-
8
- @media (min-width: 500px) {
9
- min-width: 300px;
10
- }
4
+ max-width: 100%;
5
+ }
11
6
 
12
- /* For vega embeds in slots, reset the styles to let the user set the width */
13
- @container style(--slot: true) {
14
- min-width: unset;
15
- }
7
+ .vega-container-width .vega-embed {
8
+ width: 100%;
16
9
  }
17
10
 
18
11
  .vega-embed > .chart-wrapper {
@@ -0,0 +1,129 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { copyImageToClipboard, isSafari } from "../copy";
4
+
5
+ describe("isSafari", () => {
6
+ afterEach(() => {
7
+ vi.restoreAllMocks();
8
+ });
9
+
10
+ it("returns true for Safari on macOS", () => {
11
+ vi.spyOn(navigator, "userAgent", "get").mockReturnValue(
12
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
13
+ );
14
+ expect(isSafari()).toBe(true);
15
+ });
16
+
17
+ it("returns true for Safari on iOS", () => {
18
+ vi.spyOn(navigator, "userAgent", "get").mockReturnValue(
19
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1",
20
+ );
21
+ expect(isSafari()).toBe(true);
22
+ });
23
+
24
+ it("returns false for Chrome", () => {
25
+ vi.spyOn(navigator, "userAgent", "get").mockReturnValue(
26
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
27
+ );
28
+ expect(isSafari()).toBe(false);
29
+ });
30
+
31
+ it("returns false for Chrome on iOS (CriOS)", () => {
32
+ vi.spyOn(navigator, "userAgent", "get").mockReturnValue(
33
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/120.0.0.0 Mobile/15E148 Safari/604.1",
34
+ );
35
+ expect(isSafari()).toBe(false);
36
+ });
37
+
38
+ it("returns false for Firefox on iOS (FxiOS)", () => {
39
+ vi.spyOn(navigator, "userAgent", "get").mockReturnValue(
40
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/120.0 Mobile/15E148 Safari/604.1",
41
+ );
42
+ expect(isSafari()).toBe(false);
43
+ });
44
+
45
+ it("returns false for Edge on iOS (EdgiOS)", () => {
46
+ vi.spyOn(navigator, "userAgent", "get").mockReturnValue(
47
+ "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) EdgiOS/120.0.0.0 Mobile/15E148 Safari/604.1",
48
+ );
49
+ expect(isSafari()).toBe(false);
50
+ });
51
+
52
+ it("returns false for Firefox on desktop", () => {
53
+ vi.spyOn(navigator, "userAgent", "get").mockReturnValue(
54
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:120.0) Gecko/20100101 Firefox/120.0",
55
+ );
56
+ expect(isSafari()).toBe(false);
57
+ });
58
+ });
59
+
60
+ describe("copyImageToClipboard", () => {
61
+ let writeMock: ReturnType<typeof vi.fn>;
62
+ let clipboardItemSpy: ReturnType<typeof vi.fn>;
63
+
64
+ beforeEach(() => {
65
+ writeMock = vi.fn().mockResolvedValue(undefined);
66
+ Object.assign(navigator, {
67
+ clipboard: { write: writeMock },
68
+ });
69
+
70
+ // ClipboardItem is not available in jsdom, so we mock it
71
+ clipboardItemSpy = vi.fn().mockImplementation((data) => ({ data }));
72
+ vi.stubGlobal("ClipboardItem", clipboardItemSpy);
73
+ });
74
+
75
+ afterEach(() => {
76
+ vi.restoreAllMocks();
77
+ vi.unstubAllGlobals();
78
+ });
79
+
80
+ it("uses blob type from response on non-Safari browsers", async () => {
81
+ vi.spyOn(navigator, "userAgent", "get").mockReturnValue(
82
+ "Mozilla/5.0 Chrome/120.0.0.0 Safari/537.36",
83
+ );
84
+
85
+ const fakeBlob = new Blob(["fake"], { type: "image/jpeg" });
86
+ vi.spyOn(globalThis, "fetch").mockResolvedValue(
87
+ new Response(fakeBlob, {
88
+ headers: { "Content-Type": "image/jpeg" },
89
+ }),
90
+ );
91
+
92
+ await copyImageToClipboard("https://example.com/image.jpg");
93
+
94
+ expect(writeMock).toHaveBeenCalledOnce();
95
+ // Non-Safari path: awaits blob, uses blob.type as key
96
+ const arg = clipboardItemSpy.mock.calls[0][0];
97
+ expect(arg).toHaveProperty("image/jpeg");
98
+ expect(arg["image/jpeg"].type).toBe("image/jpeg");
99
+ });
100
+
101
+ it("uses image/png on Safari", async () => {
102
+ vi.spyOn(navigator, "userAgent", "get").mockReturnValue(
103
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
104
+ );
105
+
106
+ const fakeBlob = new Blob(["fake"], { type: "image/png" });
107
+ vi.spyOn(globalThis, "fetch").mockResolvedValue(new Response(fakeBlob));
108
+
109
+ await copyImageToClipboard("https://example.com/image.png");
110
+
111
+ expect(writeMock).toHaveBeenCalledOnce();
112
+ // Safari path: uses "image/png" key with a Promise<Blob>
113
+ expect(clipboardItemSpy).toHaveBeenCalledWith({
114
+ "image/png": expect.any(Promise),
115
+ });
116
+ });
117
+
118
+ it("propagates fetch errors", async () => {
119
+ vi.spyOn(navigator, "userAgent", "get").mockReturnValue(
120
+ "Mozilla/5.0 Chrome/120.0.0.0 Safari/537.36",
121
+ );
122
+
123
+ vi.spyOn(globalThis, "fetch").mockRejectedValue(new Error("Network error"));
124
+
125
+ await expect(
126
+ copyImageToClipboard("https://example.com/image.png"),
127
+ ).rejects.toThrow("Network error");
128
+ });
129
+ });
package/src/utils/copy.ts CHANGED
@@ -21,3 +21,46 @@ export async function copyToClipboard(text: string) {
21
21
  window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
22
22
  });
23
23
  }
24
+
25
+ /**
26
+ * Returns true if the current browser is Safari.
27
+ *
28
+ * Safari requires special handling for clipboard operations because it
29
+ * drops the user-activation context during async operations like fetch.
30
+ */
31
+ export function isSafari(): boolean {
32
+ const ua = navigator.userAgent;
33
+ // Safari includes "Safari" but not "Chrome"/"Chromium" in its UA string.
34
+ // iOS in-app browsers (CriOS, FxiOS, EdgiOS) also include "Safari"
35
+ // but are excluded by checking for their specific tokens.
36
+ return (
37
+ /safari/i.test(ua) && !/chrome|chromium|crios|fxios|edgios|opios/i.test(ua)
38
+ );
39
+ }
40
+
41
+ /**
42
+ * Copies an image to the clipboard from a URL.
43
+ *
44
+ * On Safari, the ClipboardItem is constructed synchronously with a
45
+ * Promise<Blob> to preserve the user-activation context, which Safari
46
+ * drops during async operations like fetch. This means we must assume
47
+ * the MIME type (image/png) since we can't inspect the response first.
48
+ *
49
+ * On other browsers, we await the fetch and use the actual MIME type.
50
+ */
51
+ export async function copyImageToClipboard(imageSrc: string): Promise<void> {
52
+ let item: ClipboardItem;
53
+ if (isSafari()) {
54
+ // Safari drops user-activation context during await, so we must
55
+ // construct the ClipboardItem synchronously with a Promise<Blob>.
56
+ item = new ClipboardItem({
57
+ "image/png": fetch(imageSrc).then((response) => response.blob()),
58
+ });
59
+ } else {
60
+ const response = await fetch(imageSrc);
61
+ const blob = await response.blob();
62
+ item = new ClipboardItem({ [blob.type]: blob });
63
+ }
64
+
65
+ await navigator.clipboard.write([item]);
66
+ }
@@ -1 +0,0 @@
1
- import{m as r}from"./useEventListener-BGihH8bs.js";async function a(o){if(navigator.clipboard===void 0){r.warn("navigator.clipboard is not supported"),window.prompt("Copy to clipboard: Ctrl+C, Enter",o);return}await navigator.clipboard.writeText(o).catch(async()=>{r.warn("Failed to copy to clipboard using navigator.clipboard"),window.prompt("Copy to clipboard: Ctrl+C, Enter",o)})}export{a as t};
@@ -1 +0,0 @@
1
- import{s as Z}from"./chunk-LvLJmgfZ.js";import{n as C}from"./useEvent-O0nX5vok.js";import{t as Y}from"./react-Bj1aDYRI.js";import"./react-dom-CSu739Rf.js";import{t as tt}from"./compiler-runtime-B3qBwwSJ.js";import{t as et}from"./debounce-DS_VtWMt.js";import{r as nt,t as rt}from"./tooltip-WkrsrB6k.js";import{t as N}from"./uniq-fnEfqrGj.js";import{c as V,m as O}from"./useEventListener-BGihH8bs.js";import{n as F}from"./config-DeEqZTX7.js";import{t as at}from"./jsx-runtime-icT_Ltz2.js";import{r as it}from"./button-BZAv3veu.js";import{u as ot}from"./toDate-BqKH-Jd9.js";import"./session-CXChHxAw.js";import{r as lt}from"./useTheme-CM9j8dgy.js";import"./Combination-CBJmtdux.js";import{t as ct}from"./tooltip-CNmaER6z.js";import{t as st}from"./isValid-BGe7pJXT.js";import{n as mt}from"./vega-loader.browser-BJ9oKrvH.js";import{t as pt}from"./react-vega-BFWsPELq.js";import"./defaultLocale-CuYNS33t.js";import"./defaultLocale-CGfP-Ye3.js";import{r as ut,t as ft}from"./alert-DkRmN0_B.js";import{n as dt}from"./error-banner-CAuK5DPN.js";import{n as ht}from"./useAsyncData-a8f2Q_nk.js";import{t as gt}from"./formats-DEgTLsde.js";import{t as H}from"./useDeepCompareMemoize-BEmJ3M7I.js";var yt=tt(),x=Z(Y(),1);function vt(t){return t.data&&"url"in t.data&&(t.data.url=F(t.data.url).href),t}const u={arc:"arc",area:"area",bar:"bar",image:"image",line:"line",point:"point",rect:"rect",rule:"rule",text:"text",tick:"tick",trail:"trail",circle:"circle",square:"square",geoshape:"geoshape"};var W=new Set(["boxplot","errorband","errorbar"]);const S={getMarkType(t){let e=typeof t=="string"?t:t.type;if(W.has(e))throw Error("Not supported");return e},isInteractive(t){let e=typeof t=="string"?t:t.type;return!W.has(e)},makeClickable(t){let e=typeof t=="string"?t:t.type;return e in u?typeof t=="string"?{type:t,cursor:"pointer",tooltip:!0}:{...t,type:e,cursor:"pointer",tooltip:!0}:t},getOpacity(t){return typeof t=="string"?null:"opacity"in t&&typeof t.opacity=="number"?t.opacity:null}},y={point(t){return t==null?"select_point":`select_point_${t}`},interval(t){return t==null?"select_interval":`select_interval_${t}`},legendSelection(t){return`legend_selection_${t}`},binColoring(t){return t==null?"bin_coloring":`bin_coloring_${t}`},HIGHLIGHT:"highlight",PAN_ZOOM:"pan_zoom",hasPoint(t){return t.some(e=>e.startsWith("select_point"))},hasInterval(t){return t.some(e=>e.startsWith("select_interval"))},hasLegend(t){return t.some(e=>e.startsWith("legend_selection"))},hasPanZoom(t){return t.some(e=>e.startsWith("pan_zoom"))},isBinColoring(t){return t.startsWith("bin_coloring")}},_={highlight(){return{name:y.HIGHLIGHT,select:{type:"point",on:"mouseover"}}},interval(t,e){return{name:y.interval(e),select:{type:"interval",encodings:D(t),mark:{fill:"#669EFF",fillOpacity:.07,stroke:"#669EFF",strokeOpacity:.4},on:"[mousedown[!event.metaKey], mouseup] > mousemove[!event.metaKey]",translate:"[mousedown[!event.metaKey], mouseup] > mousemove[!event.metaKey]"}}},point(t,e){return{name:y.point(e),select:{type:"point",encodings:D(t),on:"click[!event.metaKey]"}}},binColoring(t){return{name:y.binColoring(t),select:{type:"point",on:"click[!event.metaKey]"}}},legend(t){return{name:y.legendSelection(t),select:{type:"point",fields:[t]},bind:"legend"}},panZoom(){return{name:y.PAN_ZOOM,bind:"scales",select:{type:"interval",on:"[mousedown[event.metaKey], window:mouseup] > window:mousemove!",translate:"[mousedown[event.metaKey], window:mouseup] > window:mousemove!",zoom:"wheel![event.metaKey]"}}}};function D(t){switch(S.getMarkType(t.mark)){case u.image:case u.trail:return;case u.area:case u.arc:return["color"];case u.bar:{let e=kt(t);return e==="horizontal"?["y"]:e==="vertical"?["x"]:void 0}case u.circle:case u.geoshape:case u.line:case u.point:case u.rect:case u.rule:case u.square:case u.text:case u.tick:return["x","y"]}}function P(t){return"params"in t&&t.params&&t.params.length>0?N(t.params.filter(e=>e==null?!1:"select"in e&&e.select!==void 0).map(e=>e.name)):"layer"in t?N(t.layer.flatMap(P)):"vconcat"in t?N(t.vconcat.flatMap(P)):"hconcat"in t?N(t.hconcat.flatMap(P)):[]}function kt(t){var a,r;if(!t||!("mark"in t))return;let e=(a=t.encoding)==null?void 0:a.x,n=(r=t.encoding)==null?void 0:r.y;if(e&&"type"in e&&e.type==="nominal")return"vertical";if(n&&"type"in n&&n.type==="nominal"||e&&"aggregate"in e)return"horizontal";if(n&&"aggregate"in n)return"vertical"}function bt(t){if(!t.encoding)return[];let e=[];for(let n of Object.values(t.encoding))n&&typeof n=="object"&&"bin"in n&&n.bin&&"field"in n&&typeof n.field=="string"&&e.push(n.field);return e}function G(t){if(!t||!("encoding"in t))return[];let{encoding:e}=t;return e?Object.entries(e).flatMap(n=>{let[a,r]=n;return!r||!wt.has(a)?[]:"field"in r&&typeof r.field=="string"?[r.field]:"condition"in r&&r.condition&&typeof r.condition=="object"&&"field"in r.condition&&r.condition.field&&typeof r.condition.field=="string"?[r.condition.field]:[]}):[]}var wt=new Set(["color","fill","fillOpacity","opacity","shape","size"]);function $(t,e,n,a){let r=n.filter(o=>y.isBinColoring(o)),i={and:(r.length>0?r:n).map(o=>({param:o}))};if(t==="opacity"){let o=S.getOpacity(a)||1;return{...e,opacity:{condition:{test:i,value:o},value:o/5}}}else return e}function xt(t){if(!("select"in t)||!t.select)return JSON.stringify(t);let e=t.select;if(typeof e=="string")return JSON.stringify({type:e,bind:t.bind});let n={type:e.type,encodings:"encodings"in e&&e.encodings?[...e.encodings].sort():void 0,fields:"fields"in e&&e.fields?[...e.fields].sort():void 0,bind:t.bind};return JSON.stringify(n)}function q(t){let e=K(t);if(e.length===0)return t;let n=St(e);return n.length===0?t:{...L(E(t,new Set(n.map(a=>a.name))),n.map(a=>a.name)),params:[...t.params||[],...n]}}function K(t){let e=[];if("vconcat"in t&&Array.isArray(t.vconcat))for(let n of t.vconcat)e.push(...K(n));else if("hconcat"in t&&Array.isArray(t.hconcat))for(let n of t.hconcat)e.push(...K(n));else{if("layer"in t)return[];"mark"in t&&"params"in t&&t.params&&t.params.length>0&&e.push({params:t.params})}return e}function St(t){if(t.length===0)return[];let e=new Map,n=t.length;for(let{params:r}of t){let i=new Set;for(let o of r){let l=xt(o);i.has(l)||(i.add(l),e.has(l)||e.set(l,{count:0,param:o}),e.get(l).count++)}}let a=[];for(let[,{count:r,param:i}]of e)r===n&&a.push(i);return a}function E(t,e){if("vconcat"in t&&Array.isArray(t.vconcat))return{...t,vconcat:t.vconcat.map(n=>E(n,e))};if("hconcat"in t&&Array.isArray(t.hconcat))return{...t,hconcat:t.hconcat.map(n=>E(n,e))};if("mark"in t&&"params"in t&&t.params){let n=t.params,a=[];for(let r of n){if(!r||typeof r!="object"||!("name"in r)){a.push(r);continue}e.has(r.name)||a.push(r)}if(a.length===0){let{params:r,...i}=t;return i}return{...t,params:a}}return t}function L(t,e){return"vconcat"in t&&Array.isArray(t.vconcat)?{...t,vconcat:t.vconcat.map(n=>L(n,e))}:"hconcat"in t&&Array.isArray(t.hconcat)?{...t,hconcat:t.hconcat.map(n=>L(n,e))}:"layer"in t?t:"mark"in t&&S.isInteractive(t.mark)?{...t,mark:S.makeClickable(t.mark),encoding:$("opacity",t.encoding||{},e,t.mark)}:t}function T(t,e){var l,k;let{chartSelection:n=!0,fieldSelection:a=!0}=e;if(!n&&!a)return t;(l=t.params)!=null&&l.some(s=>s.bind==="legend")&&(a=!1);let r=(k=t.params)==null?void 0:k.some(s=>!s.bind);r&&(n=!1);let i="vconcat"in t||"hconcat"in t;if(r&&i)return t;if("vconcat"in t){let s=t.vconcat.map(m=>"mark"in m?T(m,{chartSelection:n,fieldSelection:a}):m);return q({...t,vconcat:s})}if("hconcat"in t){let s=t.hconcat.map(m=>"mark"in m?T(m,{chartSelection:n,fieldSelection:a}):m);return q({...t,hconcat:s})}if("layer"in t){let s=t.params&&t.params.length>0,m=a!==!1&&!s,v=[];if(m){let p=t.layer.flatMap(f=>"mark"in f?G(f):[]);v=[...new Set(p)],Array.isArray(a)&&(v=v.filter(f=>a.includes(f)))}let w=t.layer.map((p,f)=>{if(!("mark"in p))return p;let h=p;if(f===0&&v.length>0){let j=v.map(M=>_.legend(M));h={...h,params:[...h.params||[],...j]}}return h=z(h,n,f),h=J(h),f===0&&(h=B(h)),h});return{...t,layer:w}}if(!("mark"in t)||!S.isInteractive(t.mark))return t;let o=t;return o=At(o,a),o=z(o,n,void 0),o=J(o),o=B(o),o}function At(t,e){if(e===!1)return t;let n=G(t);Array.isArray(e)&&(n=n.filter(i=>e.includes(i)));let a=n.map(i=>_.legend(i)),r=[...t.params||[],...a];return{...t,params:r}}function z(t,e,n){if(e===!1)return t;let a;try{a=S.getMarkType(t.mark)}catch{return t}if(a==="geoshape")return t;let r=bt(t),i=e===!0?r.length>0?["point"]:Ot(a):[e];if(!i||i.length===0)return t;let o=i.map(k=>k==="interval"?_.interval(t,n):_.point(t,n)),l=[...t.params||[],...o];return r.length>0&&i.includes("point")&&l.push(_.binColoring(n)),{...t,params:l}}function B(t){let e;try{e=S.getMarkType(t.mark)}catch{}if(e==="geoshape")return t;let n=t.params||[];return n.some(a=>a.bind==="scales")?t:{...t,params:[...n,_.panZoom()]}}function J(t){let e="encoding"in t?t.encoding:void 0,n=t.params||[],a=n.map(r=>r.name);return n.length===0||!S.isInteractive(t.mark)?t:{...t,mark:S.makeClickable(t.mark),encoding:$("opacity",e||{},a,t.mark)}}function Ot(t){switch(t){case"arc":case"area":return["point"];case"text":case"bar":return["point","interval"];case"line":return;default:return["point","interval"]}}async function _t(t){if(!t)return t;let e="datasets"in t?{...t.datasets}:{},n=async r=>{if(!r)return r;if("layer"in r){let l=await Promise.all(r.layer.map(n));r={...r,layer:l}}if("hconcat"in r){let l=await Promise.all(r.hconcat.map(n));r={...r,hconcat:l}}if("vconcat"in r){let l=await Promise.all(r.vconcat.map(n));r={...r,vconcat:l}}if("spec"in r&&(r={...r,spec:await n(r.spec)}),!r.data||!("url"in r.data))return r;let i;try{i=F(r.data.url)}catch{return r}let o=await nt(i.href,r.data.format);return e[i.pathname]=o,{...r,data:{name:i.pathname}}},a=await n(t);return Object.keys(e).length===0?a:{...a,datasets:e}}var d=Z(at(),1);mt("arrow",gt);var jt=t=>{let e=(0,yt.c)(12),{value:n,setValue:a,chartSelection:r,fieldSelection:i,spec:o,embedOptions:l}=t,k,s;e[0]===o?(k=e[1],s=e[2]):(k=async()=>_t(o),s=[o],e[0]=o,e[1]=k,e[2]=s);let{data:m,error:v}=ht(k,s);if(v){let p;return e[3]===v?p=e[4]:(p=(0,d.jsx)(dt,{error:v}),e[3]=v,e[4]=p),p}if(!m)return null;let w;return e[5]!==r||e[6]!==l||e[7]!==i||e[8]!==m||e[9]!==a||e[10]!==n?(w=(0,d.jsx)(Mt,{value:n,setValue:a,chartSelection:r,fieldSelection:i,spec:m,embedOptions:l}),e[5]=r,e[6]=l,e[7]=i,e[8]=m,e[9]=a,e[10]=n,e[11]=w):w=e[11],w},Mt=({value:t,setValue:e,chartSelection:n,fieldSelection:a,spec:r,embedOptions:i})=>{let{theme:o}=lt(),l=(0,x.useRef)(null),k=(0,x.useRef)(void 0),[s,m]=(0,x.useState)(),v=(0,x.useMemo)(()=>i&&"actions"in i?i.actions:{source:!1,compiled:!1},[i]),w=H(r),p=(0,x.useMemo)(()=>T(vt(w),{chartSelection:n,fieldSelection:a}),[w,n,a]),f=(0,x.useMemo)(()=>P(p),[p]),h=C(c=>{e({...t,...c})}),j=(0,x.useMemo)(()=>et((c,g)=>{O.debug("[Vega signal]",c,g);let b=V.mapValues(g,Pt);b=V.mapValues(b,Nt),h({[c]:b})},100),[h]),M=H(f),I=(0,x.useMemo)(()=>M.reduce((c,g)=>(y.PAN_ZOOM===g||y.isBinColoring(g)||c.push({signalName:g,handler:(b,X)=>j(b,X)}),c),[]),[M,j]),R=C(c=>{O.error(c),O.debug(p),m(c)}),Q=C(c=>{O.debug("[Vega view] created",c),k.current=c,m(void 0)}),U=()=>{let c=[];return y.hasPoint(f)&&c.push(["Point selection","click to select a point; hold shift for multi-select"]),y.hasInterval(f)&&c.push(["Interval selection","click and drag to select an interval"]),y.hasLegend(f)&&c.push(["Legend selection","click to select a legend item; hold shift for multi-select"]),y.hasPanZoom(f)&&c.push(["Pan","hold the meta key and drag"],["Zoom","hold the meta key and scroll"]),c.length===0?null:(0,d.jsx)(ct,{delayDuration:300,side:"left",content:(0,d.jsx)("div",{className:"text-xs flex flex-col",children:c.map((g,b)=>(0,d.jsxs)("div",{children:[(0,d.jsxs)("span",{className:"font-bold tracking-wide",children:[g[0],":"]})," ",g[1]]},b))}),children:(0,d.jsx)(ot,{className:"absolute bottom-1 right-0 m-2 h-4 w-4 cursor-help text-muted-foreground hover:text-foreground"})})},A=pt({ref:l,spec:p,options:{theme:o==="dark"?"dark":void 0,actions:v,mode:"vega-lite",tooltip:rt.call,renderer:"canvas"},onError:R,onEmbed:Q});return(0,x.useEffect)(()=>(I.forEach(({signalName:c,handler:g})=>{try{A==null||A.view.addSignalListener(c,g)}catch(b){O.error(b)}}),()=>{I.forEach(({signalName:c,handler:g})=>{try{A==null||A.view.removeSignalListener(c,g)}catch(b){O.error(b)}})}),[A,I]),(0,d.jsxs)(d.Fragment,{children:[s&&(0,d.jsxs)(ft,{variant:"destructive",children:[(0,d.jsx)(ut,{children:s.message}),(0,d.jsx)("div",{className:"text-md",children:s.stack})]}),(0,d.jsxs)("div",{className:"relative",onPointerDown:it.stopPropagation(),children:[(0,d.jsx)("div",{ref:l}),U()]})]})};function Nt(t){return t instanceof Set?[...t]:t}function Pt(t){return Array.isArray(t)?t.map(e=>e instanceof Date&&st(e)?new Date(e).getTime():e):t}var It=jt;export{It as default};