@marimo-team/islands 0.22.1-dev27 → 0.22.1-dev28

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 (65) hide show
  1. package/dist/_basePickBy-Sow3pJjS.js +41 -0
  2. package/dist/{_baseUniq--7il0Js0.js → _baseUniq-C87CckHL.js} +14 -53
  3. package/dist/{architecture-7HQA4BMR-CSK94-xM.js → architecture-7HQA4BMR-BHdkAMvZ.js} +2 -2
  4. package/dist/{architectureDiagram-VXUJARFQ-Cw5_EP5P.js → architectureDiagram-VXUJARFQ-B3YQo9At.js} +9 -9
  5. package/dist/{blockDiagram-VD42YOAC-BiuOHEQv.js → blockDiagram-VD42YOAC-CpQ3TKEN.js} +2 -2
  6. package/dist/{chat-ui-MFxd7AGf.js → chat-ui-Wi1Lm6y4.js} +3 -3
  7. package/dist/{chunk-4F5CHEZ2-B0Jbisw2.js → chunk-4F5CHEZ2-D5mClyDv.js} +1 -1
  8. package/dist/{chunk-B2363JML-mJ3Q9WfR.js → chunk-B2363JML-Br0eA2T3.js} +1 -1
  9. package/dist/{chunk-B4BG7PRW-C4MiRcFI.js → chunk-B4BG7PRW-4BjV11Br.js} +1 -1
  10. package/dist/{chunk-DI55MBZ5-CMx27S12.js → chunk-DI55MBZ5-DITY3EyP.js} +1 -1
  11. package/dist/{chunk-FRFDVMJY-IPSTV3Ua.js → chunk-FRFDVMJY-DnEvEFRR.js} +1 -1
  12. package/dist/{chunk-N4CR4FBY-DYub3dan.js → chunk-N4CR4FBY-CpZSuGSU.js} +1 -1
  13. package/dist/{chunk-PL6DKKU2-DZiAP4HM.js → chunk-PL6DKKU2-DnId6G-x.js} +1 -1
  14. package/dist/{chunk-SJTYNZTY-s-hMTFeC.js → chunk-SJTYNZTY-BsBZnJUj.js} +1 -1
  15. package/dist/{chunk-TCCFYFTB-D7iQP6Bp.js → chunk-TCCFYFTB-Clbl-fTg.js} +5 -4
  16. package/dist/{chunk-TQ3KTPDO-BmFTqg51.js → chunk-TQ3KTPDO-CFkSQ30e.js} +1 -1
  17. package/dist/{chunk-UMXZTB3W-AUirFhbD.js → chunk-UMXZTB3W-D-A834Bq.js} +1 -1
  18. package/dist/{classDiagram-2ON5EDUG-BJCfK6hn.js → classDiagram-2ON5EDUG-C8-zE3Zv.js} +2 -2
  19. package/dist/{classDiagram-v2-WZHVMYZB-aaIrLBHp.js → classDiagram-v2-WZHVMYZB-DrmbGANl.js} +2 -2
  20. package/dist/{clone-BsAy1q8B.js → clone-DZFQCtFJ.js} +1 -1
  21. package/dist/{constants-CMDkKrpC.js → constants-CvyfaCvs.js} +1 -1
  22. package/dist/{dagre-6UL2VRFP-CLYtUWgC.js → dagre-6UL2VRFP-OMItEBnY.js} +5 -5
  23. package/dist/{dagre-oeMGMQA0.js → dagre-QVd-lCXU.js} +10 -20
  24. package/dist/{diagram-PSM6KHXK-D_6t-W86.js → diagram-PSM6KHXK-CkKbohWI.js} +9 -9
  25. package/dist/{diagram-QEK2KX5R-DyPwbpot.js → diagram-QEK2KX5R-DjUMpVcx.js} +9 -9
  26. package/dist/{diagram-S2PKOQOG-nwsLe-2u.js → diagram-S2PKOQOG-b-c0d-wZ.js} +9 -9
  27. package/dist/{erDiagram-Q2GNP2WA-C3PXcCCI.js → erDiagram-Q2GNP2WA-CDhLaOZ1.js} +1 -1
  28. package/dist/{flowDiagram-NV44I4VS-DFDCBPb3.js → flowDiagram-NV44I4VS-BDi4O4CL.js} +1 -1
  29. package/dist/{gitGraph-G5XIXVHT-CuhmzmB1.js → gitGraph-G5XIXVHT-B_c6xFJv.js} +2 -2
  30. package/dist/{gitGraphDiagram-V2S2FVAM-B3inBgCa.js → gitGraphDiagram-V2S2FVAM-iQnXzbPM.js} +9 -9
  31. package/dist/{glide-data-editor-kjT1twjd.js → glide-data-editor-D8O9AS1C.js} +2 -2
  32. package/dist/{graphlib-B05vp8B3.js → graphlib-BV1_gi0C.js} +2 -1
  33. package/dist/hasIn-DnfJcYpY.js +108 -0
  34. package/dist/{info-VBDWY6EO-CHQo46SB.js → info-VBDWY6EO-BTyzxmhr.js} +2 -2
  35. package/dist/{infoDiagram-HS3SLOUP-WHNM1sDJ.js → infoDiagram-HS3SLOUP-OYrX6uO3.js} +9 -9
  36. package/dist/{input-DONWC1s4.js → input-BeQSGpld.js} +1 -1
  37. package/dist/main.js +95 -73
  38. package/dist/{mermaid-BdEvqBXn.js → mermaid-808LPVim.js} +19 -19
  39. package/dist/{mermaid-parser.core-C2Dti_2f.js → mermaid-parser.core-ntCgyx0x.js} +8 -8
  40. package/dist/min-Ds3gG0Ff.js +96 -0
  41. package/dist/{mindmap-definition-VGOIOE7T-B02Y_l4r.js → mindmap-definition-VGOIOE7T-CxEUZZvY.js} +1 -1
  42. package/dist/{packet-DYOGHKS2-DjPkocnd.js → packet-DYOGHKS2-BhvnpoGi.js} +2 -2
  43. package/dist/{pie-VRWISCQL-B9pA8cOD.js → pie-VRWISCQL-dILuA3iG.js} +2 -2
  44. package/dist/{pieDiagram-ADFJNKIX-Bzhvjry9.js → pieDiagram-ADFJNKIX-U3LrUqAS.js} +9 -9
  45. package/dist/{process-output-LVENbROu.js → process-output-BvZAAk1w.js} +3 -3
  46. package/dist/{radar-ZZBFDIW7-C2obWVPx.js → radar-ZZBFDIW7-DwFrOJDj.js} +2 -2
  47. package/dist/range-fJeId9Ri.js +30 -0
  48. package/dist/{requirementDiagram-UZGBJVZJ-B7RuV-90.js → requirementDiagram-UZGBJVZJ-D0zpQnKC.js} +1 -1
  49. package/dist/{stateDiagram-FKZM4ZOC-QeUJrF7u.js → stateDiagram-FKZM4ZOC-B1S8jGMn.js} +4 -4
  50. package/dist/{stateDiagram-v2-4FDKWEC3-eOW_mDCq.js → stateDiagram-v2-4FDKWEC3-BH5ozUbc.js} +2 -2
  51. package/dist/{toDate-CamIA0ND.js → toDate-O4H9dZVC.js} +1 -1
  52. package/dist/{treemap-GDKQZRPO-DWMsd3D8.js → treemap-GDKQZRPO-bx2ngsgN.js} +2 -2
  53. package/dist/{types-IIG7e4M2.js → types-D_ntCXg0.js} +1 -1
  54. package/dist/{useDeepCompareMemoize-DAfQftmI.js → useDeepCompareMemoize-B8DwRVrX.js} +1 -1
  55. package/dist/{vega-component-CuWVhTG9.js → vega-component-C-fsM9rL.js} +3 -3
  56. package/package.json +1 -1
  57. package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +43 -15
  58. package/src/plugins/impl/plotly/PlotlyPlugin.tsx +12 -68
  59. package/src/plugins/impl/plotly/__tests__/selection.test.ts +237 -0
  60. package/src/plugins/impl/plotly/selection.ts +118 -0
  61. package/dist/_basePickBy-CsPbmRlg.js +0 -110
  62. package/dist/_baseSet-Cs7YTRXk.js +0 -27
  63. package/dist/get-Wu1vTRhN.js +0 -68
  64. package/dist/range-CNXr10o1.js +0 -17
  65. /package/dist/{now-Dh_IQA36.js → now-nrrrOr01.js} +0 -0
@@ -9,6 +9,35 @@ import { store } from "@/core/state/jotai";
9
9
  import type { IPluginProps } from "../../types";
10
10
  import { SliderPlugin } from "../SliderPlugin";
11
11
 
12
+ vi.mock("@/components/ui/slider", () => ({
13
+ Slider: ({
14
+ disabled,
15
+ onValueChange,
16
+ onValueCommit,
17
+ value,
18
+ }: {
19
+ disabled?: boolean;
20
+ onValueChange?: (value: number[]) => void;
21
+ onValueCommit?: (value: number[]) => void;
22
+ value: number[];
23
+ }) => (
24
+ <div>
25
+ <button
26
+ aria-label="Slider change"
27
+ disabled={disabled}
28
+ onClick={() => onValueChange?.([value[0] + 1])}
29
+ type="button"
30
+ />
31
+ <button
32
+ aria-label="Slider commit"
33
+ disabled={disabled}
34
+ onClick={() => onValueCommit?.(value)}
35
+ type="button"
36
+ />
37
+ </div>
38
+ ),
39
+ }));
40
+
12
41
  SetupMocks.resizeObserver();
13
42
 
14
43
  describe("SliderPlugin", () => {
@@ -51,46 +80,45 @@ describe("SliderPlugin", () => {
51
80
  const plugin = new SliderPlugin();
52
81
  const setValue = vi.fn();
53
82
  const props = createProps(false, false, setValue);
54
- const { container } = render(plugin.render(props));
83
+ const { getByRole } = render(plugin.render(props));
55
84
 
56
85
  act(() => {
57
86
  vi.advanceTimersByTime(0);
58
87
  });
59
88
 
60
- const thumb = container.querySelector('[role="slider"]');
61
- expect(thumb).toBeTruthy();
89
+ const changeButton = getByRole("button", { name: "Slider change" });
62
90
 
63
- // Radix UI Slider updates on keyboard ArrowRight/ArrowLeft
64
91
  act(() => {
65
- (thumb as HTMLElement)?.focus();
66
- fireEvent.keyDown(thumb!, { key: "ArrowRight" });
92
+ fireEvent.click(changeButton);
67
93
  });
68
94
 
69
95
  expect(setValue).toHaveBeenCalledWith(6);
70
96
  });
71
97
 
72
- it("slider does not trigger setValue immediately when debounce is true", () => {
98
+ it("slider waits until commit before calling setValue when debounce is true", () => {
73
99
  const plugin = new SliderPlugin();
74
100
  const setValue = vi.fn();
75
101
  const props = createProps(true, false, setValue);
76
- const { container } = render(plugin.render(props));
102
+ const { getByRole } = render(plugin.render(props));
77
103
 
78
104
  act(() => {
79
105
  vi.advanceTimersByTime(0);
80
106
  });
81
107
 
82
- const thumb = container.querySelector('[role="slider"]');
108
+ const changeButton = getByRole("button", { name: "Slider change" });
109
+ const commitButton = getByRole("button", { name: "Slider commit" });
83
110
 
84
111
  act(() => {
85
- (thumb as HTMLElement)?.focus();
86
- // Simulate just a programmatic change that Radix would trigger via pointer move
87
- // which fires onValueChange but not onValueCommit yet
88
- // Because we can't easily separated Radix's internal pointer events in jsdom, we
89
- // test the main issue: editable input. We can trust Radix's onValueChange vs onValueCommit.
112
+ fireEvent.click(changeButton);
90
113
  });
91
114
 
92
- // We verified above that NumberField works when debounce=true
93
115
  expect(setValue).not.toHaveBeenCalled();
116
+
117
+ act(() => {
118
+ fireEvent.click(commitButton);
119
+ });
120
+
121
+ expect(setValue).toHaveBeenCalledWith(6);
94
122
  });
95
123
 
96
124
  it("editable input triggers setValue immediately even when slider debounce is true", () => {
@@ -15,7 +15,11 @@ import { useDeepCompareMemoize } from "@/hooks/useDeepCompareMemoize";
15
15
  import { useScript } from "@/hooks/useScript";
16
16
  import { Arrays } from "@/utils/arrays";
17
17
  import { Objects } from "@/utils/objects";
18
- import { createParser, type PlotlyTemplateParser } from "./parse-from-template";
18
+ import {
19
+ extractClickSelection,
20
+ extractIndices,
21
+ extractPoints,
22
+ } from "./selection";
19
23
  import { usePlotlyLayout } from "./usePlotlyLayout";
20
24
 
21
25
  interface Data {
@@ -23,12 +27,9 @@ interface Data {
23
27
  config: Partial<Plotly.Config>;
24
28
  }
25
29
 
26
- type AxisName = string;
27
- type AxisDatum = unknown;
28
-
29
30
  type T =
30
31
  | {
31
- points?: Record<AxisName, AxisDatum>[] | Plotly.PlotDatum[];
32
+ points?: Record<string, unknown>[] | Plotly.PlotDatum[];
32
33
  indices?: number[];
33
34
  range?: {
34
35
  x?: number[];
@@ -202,19 +203,13 @@ export const PlotlyComponent = memo(
202
203
  if (!evt) {
203
204
  return;
204
205
  }
205
- // Only handle clicks for chart types where box/lasso selection
206
- // (onSelected) doesn't work, such as heatmaps.
207
- const isHeatmap = evt.points.some(
208
- (point) => point.data?.type === "heatmap",
209
- );
210
- if (!isHeatmap) {
206
+
207
+ const clickSelection = extractClickSelection(evt);
208
+ if (!clickSelection) {
211
209
  return;
212
210
  }
213
- setValue((prev) => ({
214
- ...prev,
215
- points: extractPoints(evt.points),
216
- indices: evt.points.map((point) => point.pointIndex),
217
- }));
211
+
212
+ setValue((prev) => ({ ...prev, ...clickSelection }));
218
213
  })}
219
214
  onSelected={useEvent((evt: Readonly<Plotly.PlotSelectionEvent>) => {
220
215
  if (!evt) {
@@ -226,7 +221,7 @@ export const PlotlyComponent = memo(
226
221
  selections:
227
222
  "selections" in evt ? (evt.selections as unknown[]) : [],
228
223
  points: extractPoints(evt.points),
229
- indices: evt.points.map((point) => point.pointIndex),
224
+ indices: extractIndices(evt.points),
230
225
  range: evt.range,
231
226
  }));
232
227
  })}
@@ -241,54 +236,3 @@ export const PlotlyComponent = memo(
241
236
  },
242
237
  );
243
238
  PlotlyComponent.displayName = "PlotlyComponent";
244
-
245
- /**
246
- * This is a hack to extract the points with their original keys,
247
- * instead of the ones that Plotly uses internally,
248
- * by using the hovertemplate.
249
- */
250
- const STANDARD_POINT_KEYS: string[] = [
251
- "x",
252
- "y",
253
- "z",
254
- "lat",
255
- "lon",
256
- "curveNumber",
257
- "pointNumber",
258
- "pointNumbers",
259
- "pointIndex",
260
- ];
261
-
262
- function extractPoints(
263
- points: Plotly.PlotDatum[],
264
- ): Record<AxisName, AxisDatum>[] {
265
- if (!points) {
266
- return [];
267
- }
268
-
269
- let parser: PlotlyTemplateParser | undefined;
270
-
271
- return points.map((point) => {
272
- const standardPointFields = Objects.pick(point, STANDARD_POINT_KEYS);
273
-
274
- // Get the first hovertemplate
275
- const hovertemplate = Array.isArray(point.data.hovertemplate)
276
- ? point.data.hovertemplate[0]
277
- : point.data.hovertemplate;
278
-
279
- // For chart types with standard point keys (e.g. heatmaps),
280
- // or when there's no hovertemplate, pick keys directly from the point.
281
- if (!hovertemplate || point.data?.type === "heatmap") {
282
- return standardPointFields;
283
- }
284
-
285
- // Update or create a parser
286
- parser = parser
287
- ? parser.update(hovertemplate)
288
- : createParser(hovertemplate);
289
- return {
290
- ...standardPointFields,
291
- ...parser.parse(point),
292
- };
293
- });
294
- }
@@ -0,0 +1,237 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import type * as Plotly from "plotly.js";
4
+ import { describe, expect, it } from "vitest";
5
+ import {
6
+ extractClickSelection,
7
+ extractIndices,
8
+ extractPoints,
9
+ } from "../selection";
10
+
11
+ interface PlotlyPointInput {
12
+ data: {
13
+ type: string;
14
+ hovertemplate?: string | string[];
15
+ };
16
+ [key: string]: unknown;
17
+ }
18
+
19
+ function makePoint(point: PlotlyPointInput): Plotly.PlotDatum {
20
+ return point as unknown as Plotly.PlotDatum;
21
+ }
22
+
23
+ function makeClickEvent(
24
+ points: Plotly.PlotDatum[],
25
+ ): Readonly<Plotly.PlotMouseEvent> {
26
+ return { points } as unknown as Readonly<Plotly.PlotMouseEvent>;
27
+ }
28
+
29
+ describe("extractIndices", () => {
30
+ it("prefers pointIndex and falls back to pointNumber", () => {
31
+ const points = [
32
+ makePoint({
33
+ pointIndex: 2,
34
+ pointNumber: 99,
35
+ data: { type: "scatter" },
36
+ }),
37
+ makePoint({
38
+ pointNumber: 4,
39
+ data: { type: "scattergl" },
40
+ }),
41
+ makePoint({
42
+ data: { type: "heatmap" },
43
+ }),
44
+ ];
45
+
46
+ expect(extractIndices(points)).toEqual([2, 4]);
47
+ });
48
+ });
49
+
50
+ describe("extractPoints", () => {
51
+ it("extracts parsed scatter payload fields from the hovertemplate", () => {
52
+ const points = [
53
+ makePoint({
54
+ x: 3,
55
+ y: 7,
56
+ curveNumber: 0,
57
+ pointIndex: 1,
58
+ customdata: ["B"],
59
+ data: {
60
+ type: "scatter",
61
+ hovertemplate:
62
+ "label=%{customdata[0]}<br>x=%{x}<br>y=%{y}<extra></extra>",
63
+ },
64
+ }),
65
+ ];
66
+
67
+ expect(extractPoints(points)).toEqual([
68
+ {
69
+ x: 3,
70
+ y: 7,
71
+ curveNumber: 0,
72
+ pointIndex: 1,
73
+ label: "B",
74
+ },
75
+ ]);
76
+ });
77
+
78
+ it("keeps standard heatmap keys without hovertemplate parsing", () => {
79
+ const points = [
80
+ makePoint({
81
+ x: "B",
82
+ y: "Row 2",
83
+ z: 6,
84
+ curveNumber: 0,
85
+ pointIndex: 5,
86
+ data: { type: "heatmap", hovertemplate: "ignored=%{z}" },
87
+ }),
88
+ ];
89
+
90
+ expect(extractPoints(points)).toEqual([
91
+ {
92
+ x: "B",
93
+ y: "Row 2",
94
+ z: 6,
95
+ curveNumber: 0,
96
+ pointIndex: 5,
97
+ },
98
+ ]);
99
+ });
100
+ });
101
+
102
+ describe("extractClickSelection", () => {
103
+ it("returns undefined for unsupported trace types", () => {
104
+ const event = makeClickEvent([
105
+ makePoint({
106
+ x: "A",
107
+ y: 10,
108
+ pointIndex: 0,
109
+ data: { type: "bar" },
110
+ }),
111
+ ]);
112
+
113
+ expect(extractClickSelection(event)).toBeUndefined();
114
+ });
115
+
116
+ it("returns undefined when all points are non-click-selectable trace types", () => {
117
+ // scatter and scattergl use onSelected (box/lasso) for selection, not onClick.
118
+ // Clicks on these traces fire both plotly_click and plotly_selected; the
119
+ // latter provides a range and must be the authoritative source.
120
+ const event = makeClickEvent([
121
+ makePoint({
122
+ x: "ignore",
123
+ y: 1,
124
+ pointIndex: 0,
125
+ data: { type: "bar" },
126
+ }),
127
+ makePoint({
128
+ x: 2,
129
+ y: 5,
130
+ curveNumber: 1,
131
+ pointIndex: 3,
132
+ data: { type: "scatter" },
133
+ }),
134
+ makePoint({
135
+ x: 4,
136
+ y: 12,
137
+ curveNumber: 2,
138
+ pointNumber: 5,
139
+ data: { type: "scattergl" },
140
+ }),
141
+ ]);
142
+
143
+ expect(extractClickSelection(event)).toBeUndefined();
144
+ });
145
+
146
+ it("filters unsupported points and preserves supported click payloads", () => {
147
+ // bar is unsupported; histogram is supported and its pointNumbers must be
148
+ // forwarded so the backend can recover the exact sample rows.
149
+ const event = makeClickEvent([
150
+ makePoint({
151
+ x: "ignore",
152
+ y: 1,
153
+ pointIndex: 0,
154
+ data: { type: "bar" },
155
+ }),
156
+ makePoint({
157
+ x: 8,
158
+ y: 3,
159
+ curveNumber: 1,
160
+ pointNumber: 2,
161
+ pointNumbers: [4, 5, 6],
162
+ data: { type: "histogram" },
163
+ }),
164
+ ]);
165
+
166
+ expect(extractClickSelection(event)).toEqual({
167
+ selections: [],
168
+ range: undefined,
169
+ indices: [2],
170
+ points: [
171
+ {
172
+ x: 8,
173
+ y: 3,
174
+ curveNumber: 1,
175
+ pointNumber: 2,
176
+ pointNumbers: [4, 5, 6],
177
+ },
178
+ ],
179
+ });
180
+ });
181
+
182
+ it("preserves histogram pointNumbers for backend row extraction", () => {
183
+ const event = makeClickEvent([
184
+ makePoint({
185
+ x: 8,
186
+ y: 2,
187
+ curveNumber: 0,
188
+ pointNumber: 3,
189
+ pointNumbers: [6, 7],
190
+ data: { type: "histogram" },
191
+ }),
192
+ ]);
193
+
194
+ expect(extractClickSelection(event)).toEqual({
195
+ selections: [],
196
+ range: undefined,
197
+ indices: [3],
198
+ points: [
199
+ {
200
+ x: 8,
201
+ y: 2,
202
+ curveNumber: 0,
203
+ pointNumber: 3,
204
+ pointNumbers: [6, 7],
205
+ },
206
+ ],
207
+ });
208
+ });
209
+
210
+ it("preserves standard heatmap click payloads", () => {
211
+ const event = makeClickEvent([
212
+ makePoint({
213
+ x: "C",
214
+ y: "Row 3",
215
+ z: 11,
216
+ curveNumber: 0,
217
+ pointIndex: 10,
218
+ data: { type: "heatmap" },
219
+ }),
220
+ ]);
221
+
222
+ expect(extractClickSelection(event)).toEqual({
223
+ selections: [],
224
+ range: undefined,
225
+ indices: [10],
226
+ points: [
227
+ {
228
+ x: "C",
229
+ y: "Row 3",
230
+ z: 11,
231
+ curveNumber: 0,
232
+ pointIndex: 10,
233
+ },
234
+ ],
235
+ });
236
+ });
237
+ });
@@ -0,0 +1,118 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { pick } from "lodash-es";
4
+ import type * as Plotly from "plotly.js";
5
+ import { Arrays } from "@/utils/arrays";
6
+ import { createParser, type PlotlyTemplateParser } from "./parse-from-template";
7
+
8
+ type AxisName = string;
9
+ type AxisDatum = unknown;
10
+
11
+ export interface PlotlyClickSelection {
12
+ points: Record<AxisName, AxisDatum>[] | Plotly.PlotDatum[];
13
+ indices: number[];
14
+ range: undefined;
15
+ selections: unknown[];
16
+ }
17
+
18
+ const CLICK_SELECTABLE_TRACE_TYPES = new Set([
19
+ "heatmap",
20
+ "histogram",
21
+ ]);
22
+
23
+ const STANDARD_POINT_KEYS: string[] = [
24
+ "x",
25
+ "y",
26
+ "z",
27
+ "lat",
28
+ "lon",
29
+ "curveNumber",
30
+ "pointNumber",
31
+ "pointNumbers",
32
+ "pointIndex",
33
+ ] as const;
34
+
35
+ function getPointIndex(point: Plotly.PlotDatum): number | undefined {
36
+ if (typeof point.pointIndex === "number") {
37
+ return point.pointIndex;
38
+ }
39
+
40
+ if (typeof point.pointNumber === "number") {
41
+ return point.pointNumber;
42
+ }
43
+
44
+ return undefined;
45
+ }
46
+
47
+ function isClickSelectablePoint(point: Plotly.PlotDatum): boolean {
48
+ const traceType = point.data?.type;
49
+ return typeof traceType === "string"
50
+ ? CLICK_SELECTABLE_TRACE_TYPES.has(traceType)
51
+ : false;
52
+ }
53
+
54
+ export function extractIndices(points: Plotly.PlotDatum[]): number[] {
55
+ return points.flatMap((point) => {
56
+ const index = getPointIndex(point);
57
+ return typeof index === "number" ? [index] : [];
58
+ });
59
+ }
60
+
61
+ /**
62
+ * This is a hack to extract the points with their original keys,
63
+ * instead of the ones that Plotly uses internally,
64
+ * by using the hovertemplate.
65
+ */
66
+ export function extractPoints(
67
+ points: Plotly.PlotDatum[],
68
+ ): Record<AxisName, AxisDatum>[] {
69
+ if (!points) {
70
+ return [];
71
+ }
72
+
73
+ let parser: PlotlyTemplateParser | undefined;
74
+
75
+ return points.map((point) => {
76
+ const standardPointFields = pick(point, STANDARD_POINT_KEYS);
77
+
78
+ // Get the first hovertemplate
79
+ const hovertemplate = Array.isArray(point.data.hovertemplate)
80
+ ? point.data.hovertemplate[0]
81
+ : point.data.hovertemplate;
82
+
83
+ // For chart types with standard point keys (e.g. heatmaps),
84
+ // or when there's no hovertemplate, pick keys directly from the point.
85
+ if (!hovertemplate || point.data?.type === "heatmap") {
86
+ return standardPointFields;
87
+ }
88
+
89
+ // Update or create a parser
90
+ parser = parser
91
+ ? parser.update(hovertemplate)
92
+ : createParser(hovertemplate);
93
+ return {
94
+ ...standardPointFields,
95
+ ...parser.parse(point),
96
+ };
97
+ });
98
+ }
99
+
100
+ export function extractClickSelection(
101
+ evt: Readonly<Plotly.PlotMouseEvent>,
102
+ ): PlotlyClickSelection | undefined {
103
+ if (!evt.points?.length) {
104
+ return undefined;
105
+ }
106
+
107
+ const points = evt.points.filter(isClickSelectablePoint);
108
+ if (points.length === 0) {
109
+ return undefined;
110
+ }
111
+
112
+ return {
113
+ selections: Arrays.EMPTY,
114
+ points: extractPoints(points),
115
+ indices: extractIndices(points),
116
+ range: undefined,
117
+ };
118
+ }
@@ -1,110 +0,0 @@
1
- import { B as isArray_default, C as isArrayLike_default, H as _baseGetTag_default, R as identity_default, S as _isIterateeCall_default, T as _baseRest_default, V as isObjectLike_default, f as keysIn_default, k as eq_default } from "./isArrayLikeObject-LXbTYiBa.js";
2
- import { t as isSymbol_default } from "./isSymbol-DCbjQG_U.js";
3
- import { i as _castPath_default, n as _baseGet_default, s as _arrayMap_default } from "./get-Wu1vTRhN.js";
4
- import { n as toFinite_default, t as _baseSet_default } from "./_baseSet-Cs7YTRXk.js";
5
- import { C as keys_default, E as _baseFindIndex_default, S as _baseFlatten_default, f as _baseIteratee_default, h as _hasPath_default, u as _baseEach_default } from "./_baseUniq--7il0Js0.js";
6
- function toInteger(f) {
7
- var V = toFinite_default(f), H = V % 1;
8
- return V === V ? H ? V - H : V : 0;
9
- }
10
- var toInteger_default = toInteger;
11
- function flatten(f) {
12
- return f != null && f.length ? _baseFlatten_default(f, 1) : [];
13
- }
14
- var flatten_default = flatten, objectProto = Object.prototype, hasOwnProperty$1 = objectProto.hasOwnProperty, defaults_default = _baseRest_default(function(f, V) {
15
- f = Object(f);
16
- var H = -1, U = V.length, G = U > 2 ? V[2] : void 0;
17
- for (G && _isIterateeCall_default(V[0], V[1], G) && (U = 1); ++H < U; ) for (var K = V[H], Y = keysIn_default(K), X = -1, Z = Y.length; ++X < Z; ) {
18
- var Q = Y[X], $ = f[Q];
19
- ($ === void 0 || eq_default($, objectProto[Q]) && !hasOwnProperty$1.call(f, Q)) && (f[Q] = K[Q]);
20
- }
21
- return f;
22
- });
23
- function last(f) {
24
- var V = f == null ? 0 : f.length;
25
- return V ? f[V - 1] : void 0;
26
- }
27
- var last_default = last;
28
- function createFind(f) {
29
- return function(H, U, W) {
30
- var G = Object(H);
31
- if (!isArrayLike_default(H)) {
32
- var K = _baseIteratee_default(U, 3);
33
- H = keys_default(H), U = function(f2) {
34
- return K(G[f2], f2, G);
35
- };
36
- }
37
- var q = f(H, U, W);
38
- return q > -1 ? G[K ? H[q] : q] : void 0;
39
- };
40
- }
41
- var _createFind_default = createFind, nativeMax = Math.max;
42
- function findIndex(f, V, H) {
43
- var U = f == null ? 0 : f.length;
44
- if (!U) return -1;
45
- var W = H == null ? 0 : toInteger_default(H);
46
- return W < 0 && (W = nativeMax(U + W, 0)), _baseFindIndex_default(f, _baseIteratee_default(V, 3), W);
47
- }
48
- var find_default = _createFind_default(findIndex);
49
- function baseMap(f, H) {
50
- var U = -1, W = isArrayLike_default(f) ? Array(f.length) : [];
51
- return _baseEach_default(f, function(f2, V, G) {
52
- W[++U] = H(f2, V, G);
53
- }), W;
54
- }
55
- var _baseMap_default = baseMap;
56
- function map(V, H) {
57
- return (isArray_default(V) ? _arrayMap_default : _baseMap_default)(V, _baseIteratee_default(H, 3));
58
- }
59
- var map_default = map, hasOwnProperty = Object.prototype.hasOwnProperty;
60
- function baseHas(f, V) {
61
- return f != null && hasOwnProperty.call(f, V);
62
- }
63
- var _baseHas_default = baseHas;
64
- function has(f, V) {
65
- return f != null && _hasPath_default(f, V, _baseHas_default);
66
- }
67
- var has_default = has, stringTag = "[object String]";
68
- function isString(V) {
69
- return typeof V == "string" || !isArray_default(V) && isObjectLike_default(V) && _baseGetTag_default(V) == stringTag;
70
- }
71
- var isString_default = isString;
72
- function baseLt(f, V) {
73
- return f < V;
74
- }
75
- var _baseLt_default = baseLt;
76
- function baseExtremum(f, V, H) {
77
- for (var U = -1, W = f.length; ++U < W; ) {
78
- var G = f[U], K = V(G);
79
- if (K != null && (q === void 0 ? K === K && !isSymbol_default(K) : H(K, q))) var q = K, J = G;
80
- }
81
- return J;
82
- }
83
- var _baseExtremum_default = baseExtremum;
84
- function min(f) {
85
- return f && f.length ? _baseExtremum_default(f, identity_default, _baseLt_default) : void 0;
86
- }
87
- var min_default = min;
88
- function basePickBy(f, V, H) {
89
- for (var U = -1, W = V.length, G = {}; ++U < W; ) {
90
- var K = V[U], q = _baseGet_default(f, K);
91
- H(q, K) && _baseSet_default(G, _castPath_default(K, f), q);
92
- }
93
- return G;
94
- }
95
- var _basePickBy_default = basePickBy;
96
- export {
97
- isString_default as a,
98
- _baseMap_default as c,
99
- defaults_default as d,
100
- flatten_default as f,
101
- _baseLt_default as i,
102
- find_default as l,
103
- min_default as n,
104
- has_default as o,
105
- toInteger_default as p,
106
- _baseExtremum_default as r,
107
- map_default as s,
108
- _basePickBy_default as t,
109
- last_default as u
110
- };
@@ -1,27 +0,0 @@
1
- import { O as _assignValue_default, j as _isIndex_default, z as isObject_default } from "./isArrayLikeObject-LXbTYiBa.js";
2
- import { i as _castPath_default, r as _toKey_default } from "./get-Wu1vTRhN.js";
3
- import { t as toNumber_default } from "./toNumber-55tjPCWr.js";
4
- var INFINITY = Infinity, MAX_INTEGER = 17976931348623157e292;
5
- function toFinite(e) {
6
- return e ? (e = toNumber_default(e), e === INFINITY || e === -INFINITY ? (e < 0 ? -1 : 1) * MAX_INTEGER : e === e ? e : 0) : e === 0 ? e : 0;
7
- }
8
- var toFinite_default = toFinite;
9
- function baseSet(a, o, s, c) {
10
- if (!isObject_default(a)) return a;
11
- o = _castPath_default(o, a);
12
- for (var l = -1, u = o.length, d = u - 1, f = a; f != null && ++l < u; ) {
13
- var p = _toKey_default(o[l]), m = s;
14
- if (p === "__proto__" || p === "constructor" || p === "prototype") return a;
15
- if (l != d) {
16
- var h = f[p];
17
- m = c ? c(h, p, f) : void 0, m === void 0 && (m = isObject_default(h) ? h : _isIndex_default(o[l + 1]) ? [] : {});
18
- }
19
- _assignValue_default(f, p, m), f = f[p];
20
- }
21
- return a;
22
- }
23
- var _baseSet_default = baseSet;
24
- export {
25
- toFinite_default as n,
26
- _baseSet_default as t
27
- };