@marimo-team/frontend 0.22.1-dev34 → 0.22.1-dev39
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/assets/{CellStatus-DKyVv7Zj.js → CellStatus-Cf0Jlrcs.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-BUc9LHJJ.js → ConnectedDataExplorerComponent-DUxaLoL7.js} +1 -1
- package/dist/assets/{JsonOutput-D1i8P1dG.js → JsonOutput-IpD2GLtO.js} +2 -2
- package/dist/assets/{MarimoErrorOutput-RmM7djc-.js → MarimoErrorOutput-dTNCLY-Q.js} +1 -1
- package/dist/assets/{Plot-C7NE7pEx.js → Plot-BAM1jEAz.js} +72 -72
- package/dist/assets/{RenderHTML-Bmn77an6.js → RenderHTML-C5GEp4ca.js} +1 -1
- package/dist/assets/{add-cell-with-ai-RyZ9Xe2b.js → add-cell-with-ai-C0J3LyiV.js} +1 -1
- package/dist/assets/{add-connection-dialog-ogwy8tvS.js → add-connection-dialog-C42PDYI7.js} +1 -1
- package/dist/assets/{agent-panel-BHLkHj7k.js → agent-panel-CH-jHjEl.js} +1 -1
- package/dist/assets/{ai-model-dropdown-Dnf-CxbP.js → ai-model-dropdown-D14GiszF.js} +1 -1
- package/dist/assets/{app-config-button-D1Z_xsvC.js → app-config-button-v-557oRb.js} +1 -1
- package/dist/assets/{cell-editor-_GDTh-4a.js → cell-editor-Dd6UaL1A.js} +2 -2
- package/dist/assets/{cell-link-D4UrIH9w.js → cell-link-Cimoe3Fv.js} +1 -1
- package/dist/assets/{cells-ArUhhHls.js → cells-CcsG9Aum.js} +1 -1
- package/dist/assets/{chat-display-YmFjOXkV.js → chat-display-hfpeXiYe.js} +1 -1
- package/dist/assets/{chat-panel-B76rxYTh.js → chat-panel-DxT370nA.js} +1 -1
- package/dist/assets/{chat-ui-BitNq1z6.js → chat-ui-Dv4y0-td.js} +1 -1
- package/dist/assets/{column-preview-NDhbeu0E.js → column-preview-ZSErTRFA.js} +1 -1
- package/dist/assets/{command-palette-uJxkhle4.js → command-palette-CjF_cblG.js} +1 -1
- package/dist/assets/{common-CRBlPqv5.js → common-BZK7spst.js} +1 -1
- package/dist/assets/{components-DwGcJvMB.js → components-D2OlyENc.js} +1 -1
- package/dist/assets/{components-BfHGr__b.js → components-DpxyscxU.js} +1 -1
- package/dist/assets/{datasource-D9e37ifa.js → datasource-D9nfSxKS.js} +1 -1
- package/dist/assets/{dependency-graph-panel-BBmN-Vc7.js → dependency-graph-panel-5MbMtFss.js} +1 -1
- package/dist/assets/{documentation-panel-Dm2xtsTq.js → documentation-panel-DPdXS3YO.js} +1 -1
- package/dist/assets/{download-7EtMZf2Y.js → download-BFQaUFKI.js} +1 -1
- package/dist/assets/{edit-page-Cr_DnrkM.js → edit-page-CMd8_Psc.js} +4 -4
- package/dist/assets/{error-panel-C3-vTzaH.js → error-panel-DV8jpRsf.js} +1 -1
- package/dist/assets/{file-explorer-panel-g9KppC7Y.js → file-explorer-panel-Dr_ZNDk3.js} +1 -1
- package/dist/assets/{file-icons-JXAG6vK-.js → file-icons-DSJsG_mI.js} +1 -1
- package/dist/assets/{floating-outline-B6Qyid7Q.js → floating-outline-Cfa1ESSb.js} +1 -1
- package/dist/assets/{focus-DCN0oEe0.js → focus-C5u0JQUq.js} +1 -1
- package/dist/assets/{form-BVnQnVQ2.js → form-3ZUGKch9.js} +1 -1
- package/dist/assets/glide-data-editor-a3qLDl-r.js +132 -0
- package/dist/assets/{home-page-Bg02jazh.js → home-page-BrqppCUS.js} +1 -1
- package/dist/assets/{hooks-zQJ9iU_R.js → hooks-CHE17GG1.js} +1 -1
- package/dist/assets/{html-to-image-C5XSE7QT.js → html-to-image-BRbQwG7G.js} +1 -1
- package/dist/assets/{index-BaQAJwyb.css → index-BkdonYlq.css} +1 -1
- package/dist/assets/index-Bt8G6SSE.js +42 -0
- package/dist/assets/{kiosk-mode-CriCUOI1.js → kiosk-mode-Cu86-jaD.js} +1 -1
- package/dist/assets/{layout-Cudicm29.js → layout-B-lTkLKA.js} +1 -1
- package/dist/assets/{logs-panel-CoWO9c8s.js → logs-panel-CNVgwoHO.js} +1 -1
- package/dist/assets/{markdown-renderer-CyUc0f8D.js → markdown-renderer-B91NzmVT.js} +1 -1
- package/dist/assets/{name-cell-input-DeM6upjB.js → name-cell-input-hsV_b1Op.js} +1 -1
- package/dist/assets/{outline-panel-C4P3wA7Z.js → outline-panel-C3jvSnZF.js} +1 -1
- package/dist/assets/{packages-panel-DnrjjQDF.js → packages-panel-0_Z5vM7i.js} +1 -1
- package/dist/assets/{panels-BCRqI88j.js → panels-uc8QhzpO.js} +1 -1
- package/dist/assets/{process-output-e_aMblRk.js → process-output-CsvKn_Mr.js} +1 -1
- package/dist/assets/{readonly-python-code-CVgh88Tn.js → readonly-python-code-oFCRG7Wt.js} +1 -1
- package/dist/assets/{run-page-C-ySBXLo.js → run-page-DKCqiq_f.js} +1 -1
- package/dist/assets/{scratchpad-panel-C5Pogi1P.js → scratchpad-panel-ChHLgDv_.js} +1 -1
- package/dist/assets/{session-panel-DEsnZWks.js → session-panel-CPKKt31q.js} +1 -1
- package/dist/assets/{snippets-panel-DQgE3W8I.js → snippets-panel-CDqEDwpY.js} +1 -1
- package/dist/assets/{spec-CBbUxOvL.js → spec-CFx2bitO.js} +1 -1
- package/dist/assets/{state-pGNeffyB.js → state-BBVlYaRC.js} +1 -1
- package/dist/assets/{state-CV8Wy3e4.js → state-C93JW11U.js} +1 -1
- package/dist/assets/{textarea-DqzNK0s9.js → textarea-DJEKmYtw.js} +1 -1
- package/dist/assets/{tracing-BUFVOmZw.js → tracing-CLWi5jD3.js} +1 -1
- package/dist/assets/{tracing-panel-BsLloPWd.js → tracing-panel-ksnvVrMH.js} +2 -2
- package/dist/assets/{useAddCell-cC7JUC0q.js → useAddCell-mJ1PkF-E.js} +1 -1
- package/dist/assets/{useCellActionButton-BiYBXHfb.js → useCellActionButton-4HWj1rt3.js} +1 -1
- package/dist/assets/{useDeleteCell-D2p4Dz0U.js → useDeleteCell-B0OAS0ly.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-c5-eXlcr.js → useDependencyPanelTab-BuZ0fgAR.js} +1 -1
- package/dist/assets/useLifecycle-N3bfh_O1.js +1 -0
- package/dist/assets/useNotebookActions-DuHUqtII.js +1 -0
- package/dist/assets/{useRunCells-DgBY-vh9.js → useRunCells-Du76UV1R.js} +1 -1
- package/dist/assets/{useSplitCell-SS0kKwVk.js → useSplitCell-CeL7eJq1.js} +1 -1
- package/dist/index.html +25 -25
- package/package.json +1 -1
- package/src/__mocks__/common.ts +4 -4
- package/src/components/chat/acp/agent-panel.tsx +2 -2
- package/src/components/data-table/__tests__/columns.test.tsx +7 -7
- package/src/components/data-table/cell-hover-template/types.ts +1 -1
- package/src/components/data-table/cell-hover-text/types.ts +1 -1
- package/src/components/data-table/cell-selection/__tests__/feature.test.ts +1 -1
- package/src/components/data-table/cell-selection/types.ts +1 -1
- package/src/components/data-table/cell-styling/types.ts +1 -1
- package/src/components/data-table/charts/chart-spec/altair-generator.ts +2 -2
- package/src/components/data-table/column-formatting/types.ts +2 -2
- package/src/components/data-table/column-summary/legacy-chart-spec.ts +1 -1
- package/src/components/data-table/column-wrapping/types.ts +1 -1
- package/src/components/data-table/copy-column/types.ts +1 -1
- package/src/components/data-table/data-table.tsx +12 -12
- package/src/components/data-table/focus-row/types.ts +1 -1
- package/src/components/data-table/loading-table.tsx +1 -1
- package/src/components/data-table/range-focus/__tests__/atoms.test.ts +2 -2
- package/src/components/data-table/range-focus/atoms.ts +2 -2
- package/src/components/dependency-graph/dependency-graph-tree.tsx +1 -1
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +1 -1
- package/src/components/editor/actions/pair-with-agent-modal.tsx +142 -0
- package/src/components/editor/actions/useNotebookActions.tsx +10 -0
- package/src/components/editor/ai/ai-completion-editor.tsx +1 -1
- package/src/components/editor/app-container.tsx +1 -1
- package/src/components/editor/chrome/panels/empty-state.tsx +1 -0
- package/src/components/editor/controls/keyboard-shortcuts.tsx +1 -1
- package/src/components/editor/navigation/__tests__/navigation.test.ts +1 -1
- package/src/components/editor/navigation/navigation.ts +1 -1
- package/src/components/editor/notebook-cell.tsx +1 -1
- package/src/components/editor/output/JsonOutput.tsx +4 -4
- package/src/components/editor/output/ansi-reduce.ts +2 -2
- package/src/components/editor/output/console/ConsoleOutput.tsx +1 -1
- package/src/components/editor/renderers/cells-renderer.tsx +1 -1
- package/src/components/editor/renderers/grid-layout/grid-layout.tsx +1 -1
- package/src/components/editor/renderers/plugins.ts +1 -1
- package/src/components/editor/renderers/slides-layout/types.ts +2 -2
- package/src/components/editor/renderers/vertical-layout/__tests__/useFocusFirstEditor.test.ts +2 -2
- package/src/components/editor/renderers/vertical-layout/__tests__/vertical-layout.test.ts +1 -1
- package/src/components/find-replace/find-replace.tsx +3 -1
- package/src/components/forms/form.tsx +1 -1
- package/src/components/forms/options.ts +1 -1
- package/src/components/static-html/static-banner.tsx +2 -2
- package/src/components/terminal/terminal.tsx +4 -4
- package/src/components/ui/button.tsx +1 -1
- package/src/components/ui/command.tsx +1 -1
- package/src/core/ai/context/providers/__tests__/datasource.test.ts +1 -1
- package/src/core/ai/context/providers/__tests__/error.test.ts +1 -1
- package/src/core/ai/context/providers/__tests__/variable.test.ts +1 -1
- package/src/core/ai/context/registry.ts +2 -2
- package/src/core/ai/tools/registry.ts +1 -1
- package/src/core/cells/__tests__/cells.test.ts +2 -2
- package/src/core/cells/__tests__/scrollCellIntoView.test.ts +1 -1
- package/src/core/cells/__tests__/session.test.ts +1 -1
- package/src/core/cells/__tests__/utils.test.ts +1 -1
- package/src/core/cells/cells.ts +1 -1
- package/src/core/cells/ids.ts +1 -1
- package/src/core/codemirror/ai/request.ts +1 -1
- package/src/core/codemirror/copilot/__tests__/language-server.test.ts +1 -1
- package/src/core/codemirror/copilot/__tests__/transport.test.ts +1 -1
- package/src/core/codemirror/copilot/language-server.ts +1 -1
- package/src/core/codemirror/copilot/types.ts +1 -1
- package/src/core/codemirror/facet.ts +1 -1
- package/src/core/codemirror/language/__tests__/sql.test.ts +4 -4
- package/src/core/codemirror/language/languages/sql/completion-builder.ts +1 -1
- package/src/core/codemirror/language/metadata.ts +1 -1
- package/src/core/codemirror/language/types.ts +1 -1
- package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +1 -1
- package/src/core/codemirror/lsp/notebook-lsp.ts +1 -1
- package/src/core/codemirror/misc/__tests__/dnd.test.ts +1 -1
- package/src/core/codemirror/rtc/loro/awareness.ts +1 -1
- package/src/core/config/feature-flag.tsx +1 -1
- package/src/core/dom/outline.ts +1 -1
- package/src/core/export/__tests__/hooks.test.ts +1 -1
- package/src/core/hotkeys/__tests__/hotkeys.test.ts +1 -1
- package/src/core/hotkeys/shortcuts.ts +1 -1
- package/src/core/islands/__tests__/bridge.test.ts +2 -2
- package/src/core/islands/bridge.ts +2 -2
- package/src/core/islands/components/output-wrapper.tsx +1 -1
- package/src/core/islands/parse.ts +1 -1
- package/src/core/lsp/__tests__/transport.test.ts +1 -1
- package/src/core/network/DeferredRequestRegistry.ts +1 -1
- package/src/core/network/__tests__/requests-network.test.ts +1 -1
- package/src/core/network/api.ts +2 -2
- package/src/core/network/requests-lazy.ts +1 -1
- package/src/core/network/requests-toasting.tsx +1 -1
- package/src/core/static/files.ts +1 -1
- package/src/core/vscode/vscode-bindings.ts +1 -1
- package/src/core/wasm/bridge.ts +3 -3
- package/src/core/wasm/worker/tracer.ts +1 -1
- package/src/core/websocket/useWebSocket.tsx +2 -2
- package/src/css/globals.css +37 -61
- package/src/custom.d.ts +1 -1
- package/src/hooks/__tests__/useDuplicateShortcuts.test.ts +2 -2
- package/src/hooks/debug.ts +3 -3
- package/src/hooks/useDebounce.ts +1 -1
- package/src/hooks/useEventListener.ts +1 -1
- package/src/hooks/useHotkey.ts +1 -1
- package/src/hooks/useLifecycle.ts +2 -2
- package/src/hooks/useNonce.ts +1 -1
- package/src/hooks/useResizeObserver.ts +2 -2
- package/src/main.tsx +1 -1
- package/src/plugins/core/RenderHTML.tsx +3 -3
- package/src/plugins/core/__test__/registerReactComponent.test.ts +1 -1
- package/src/plugins/core/registerReactComponent.tsx +4 -4
- package/src/plugins/core/rpc.ts +1 -1
- package/src/plugins/impl/DataTablePlugin.tsx +1 -1
- package/src/plugins/impl/FileBrowserPlugin.tsx +1 -1
- package/src/plugins/impl/FormPlugin.tsx +1 -1
- package/src/plugins/impl/__tests__/MatrixPlugin.test.tsx +1 -1
- package/src/plugins/impl/anywidget/AnyWidgetPlugin.tsx +1 -1
- package/src/plugins/impl/anywidget/model.ts +1 -1
- package/src/plugins/impl/anywidget/types.ts +2 -2
- package/src/plugins/impl/anywidget/widget-binding.ts +1 -1
- package/src/plugins/impl/chat/ChatPlugin.tsx +1 -1
- package/src/plugins/impl/chat/chat-ui.tsx +1 -1
- package/src/plugins/impl/data-editor/glide-data-editor.tsx +1 -1
- package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +2 -2
- package/src/plugins/impl/data-explorer/components/query-form.tsx +1 -1
- package/src/plugins/impl/data-explorer/functions/function.ts +1 -1
- package/src/plugins/impl/data-explorer/queries/types.ts +1 -1
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -1
- package/src/plugins/impl/data-frames/forms/renderers.tsx +1 -1
- package/src/plugins/impl/data-frames/utils/operators.ts +1 -1
- package/src/plugins/impl/matplotlib/MatplotlibPlugin.tsx +1 -1
- package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +1 -1
- package/src/plugins/impl/panel/PanelPlugin.tsx +2 -2
- package/src/plugins/impl/plotly/Plot.tsx +3 -3
- package/src/plugins/impl/plotly/PlotlyPlugin.tsx +62 -44
- package/src/plugins/impl/plotly/__tests__/PlotlyPlugin.test.tsx +114 -0
- package/src/plugins/impl/plotly/__tests__/selection.test.ts +158 -196
- package/src/plugins/impl/plotly/selection.ts +274 -56
- package/src/plugins/impl/vega/batched.ts +1 -1
- package/src/plugins/impl/vega/make-selectable.ts +1 -1
- package/src/plugins/impl/vega/types.ts +1 -1
- package/src/plugins/layout/DownloadPlugin.tsx +1 -1
- package/src/plugins/layout/LazyPlugin.tsx +1 -1
- package/src/plugins/layout/RoutesPlugin.tsx +1 -1
- package/src/plugins/layout/mermaid/mermaid.tsx +1 -1
- package/src/plugins/plugins.ts +1 -1
- package/src/stories/data-explorer.stories.tsx +1 -1
- package/src/stories/dataframe.stories.tsx +1 -1
- package/src/stories/editor.stories.tsx +1 -1
- package/src/stories/select.stories.tsx +1 -1
- package/src/stories/switchable-multi-select.stories.tsx +1 -1
- package/src/utils/Logger.ts +1 -1
- package/src/utils/__tests__/arrays.test.ts +1 -1
- package/src/utils/__tests__/blob.test.ts +1 -1
- package/src/utils/__tests__/dates.test.ts +1 -1
- package/src/utils/__tests__/errors.test.ts +1 -1
- package/src/utils/__tests__/objects.test.ts +3 -3
- package/src/utils/__tests__/waitForWs.test.ts +1 -1
- package/src/utils/arrays.ts +1 -1
- package/src/utils/assertNever.ts +1 -1
- package/src/utils/batch-requests.ts +2 -2
- package/src/utils/createReducer.ts +2 -2
- package/src/utils/id-tree.tsx +2 -2
- package/src/utils/idle.ts +1 -1
- package/src/utils/invariant.ts +1 -2
- package/src/utils/maps.ts +1 -1
- package/src/utils/math.ts +0 -1
- package/src/utils/multi-map.ts +1 -1
- package/src/utils/objects.ts +1 -1
- package/src/utils/once.ts +2 -2
- package/src/utils/staticImplements.ts +1 -1
- package/src/utils/storage/jotai.ts +1 -1
- package/src/utils/tracer.ts +2 -2
- package/dist/assets/glide-data-editor-CDqunAkw.js +0 -132
- package/dist/assets/index-KI45dku7.js +0 -35
- package/dist/assets/useLifecycle-D202VvPd.js +0 -1
- package/dist/assets/useNotebookActions-Bb4xxjuJ.js +0 -1
|
@@ -1,237 +1,199 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import type * as Plotly from "plotly.js";
|
|
4
|
-
import { describe, expect, it } from "vitest";
|
|
4
|
+
import { describe, expect, it, vi } from "vitest";
|
|
5
5
|
import {
|
|
6
|
-
extractClickSelection,
|
|
7
6
|
extractIndices,
|
|
8
7
|
extractPoints,
|
|
8
|
+
hasPureLineTrace,
|
|
9
|
+
lineSelectionButtons,
|
|
10
|
+
type ModeBarButton,
|
|
11
|
+
mergeModeBarButtonsToAdd,
|
|
12
|
+
shouldHandleClickSelection,
|
|
9
13
|
} from "../selection";
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
type: string;
|
|
14
|
-
hovertemplate?: string | string[];
|
|
15
|
-
};
|
|
16
|
-
[key: string]: unknown;
|
|
15
|
+
function createTrace(trace: Partial<Plotly.PlotData>): Plotly.Data {
|
|
16
|
+
return trace as unknown as Plotly.Data;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
function
|
|
20
|
-
return
|
|
19
|
+
function createPlotDatum<T extends object>(overrides: T): Plotly.PlotDatum & T {
|
|
20
|
+
return overrides as unknown as Plotly.PlotDatum & T;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
];
|
|
23
|
+
describe("hasPureLineTrace", () => {
|
|
24
|
+
it("detects scatter and scattergl traces that are pure lines", () => {
|
|
25
|
+
expect(
|
|
26
|
+
hasPureLineTrace([
|
|
27
|
+
createTrace({ type: "scatter", mode: "lines" }),
|
|
28
|
+
createTrace({ type: "scattergl", mode: "text+lines" }),
|
|
29
|
+
]),
|
|
30
|
+
).toBe(true);
|
|
31
|
+
});
|
|
45
32
|
|
|
46
|
-
|
|
33
|
+
it("ignores non-line and marker traces", () => {
|
|
34
|
+
expect(
|
|
35
|
+
hasPureLineTrace([
|
|
36
|
+
createTrace({ type: "scatter", mode: "markers" }),
|
|
37
|
+
createTrace({ type: "scatter", mode: "lines+markers" }),
|
|
38
|
+
createTrace({ type: "bar" }),
|
|
39
|
+
]),
|
|
40
|
+
).toBe(false);
|
|
47
41
|
});
|
|
48
42
|
});
|
|
49
43
|
|
|
50
|
-
describe("
|
|
51
|
-
it("
|
|
52
|
-
const
|
|
53
|
-
|
|
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
|
-
];
|
|
44
|
+
describe("lineSelectionButtons", () => {
|
|
45
|
+
it("creates dragmode buttons that update dragmode", () => {
|
|
46
|
+
const setDragmode = vi.fn();
|
|
47
|
+
const buttons = lineSelectionButtons(setDragmode);
|
|
66
48
|
|
|
67
|
-
expect(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
label: "B",
|
|
74
|
-
},
|
|
75
|
-
]);
|
|
76
|
-
});
|
|
49
|
+
expect(buttons).toHaveLength(2);
|
|
50
|
+
expect(
|
|
51
|
+
buttons.map((button) =>
|
|
52
|
+
typeof button === "string" ? button : button.name,
|
|
53
|
+
),
|
|
54
|
+
).toEqual(["line-box-select", "line-lasso-select"]);
|
|
77
55
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
y: "Row 2",
|
|
83
|
-
z: 6,
|
|
84
|
-
curveNumber: 0,
|
|
85
|
-
pointIndex: 5,
|
|
86
|
-
data: { type: "heatmap", hovertemplate: "ignored=%{z}" },
|
|
87
|
-
}),
|
|
88
|
-
];
|
|
56
|
+
const graphDiv = document.createElement(
|
|
57
|
+
"div",
|
|
58
|
+
) as unknown as Plotly.PlotlyHTMLElement;
|
|
59
|
+
const clickEvent = new MouseEvent("click");
|
|
89
60
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
curveNumber: 0,
|
|
96
|
-
pointIndex: 5,
|
|
97
|
-
},
|
|
98
|
-
]);
|
|
61
|
+
(buttons[0] as Exclude<ModeBarButton, string>).click(graphDiv, clickEvent);
|
|
62
|
+
(buttons[1] as Exclude<ModeBarButton, string>).click(graphDiv, clickEvent);
|
|
63
|
+
|
|
64
|
+
expect(setDragmode).toHaveBeenNthCalledWith(1, "select");
|
|
65
|
+
expect(setDragmode).toHaveBeenNthCalledWith(2, "lasso");
|
|
99
66
|
});
|
|
100
67
|
});
|
|
101
68
|
|
|
102
|
-
describe("
|
|
103
|
-
it("
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
69
|
+
describe("mergeModeBarButtonsToAdd", () => {
|
|
70
|
+
it("deduplicates string buttons while preserving custom buttons", () => {
|
|
71
|
+
const customButton = {
|
|
72
|
+
name: "custom",
|
|
73
|
+
title: "Custom",
|
|
74
|
+
icon: { svg: "<svg />" },
|
|
75
|
+
click: vi.fn(),
|
|
76
|
+
} satisfies Exclude<ModeBarButton, string>;
|
|
77
|
+
|
|
78
|
+
expect(
|
|
79
|
+
mergeModeBarButtonsToAdd(
|
|
80
|
+
["zoom2d", "lasso2d"],
|
|
81
|
+
["lasso2d", customButton, "zoom2d"],
|
|
82
|
+
),
|
|
83
|
+
).toEqual(["zoom2d", "lasso2d", customButton]);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
112
86
|
|
|
113
|
-
|
|
87
|
+
describe("shouldHandleClickSelection", () => {
|
|
88
|
+
it("accepts bar clicks", () => {
|
|
89
|
+
const barPoint = createPlotDatum({
|
|
90
|
+
data: { type: "bar" },
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
expect(shouldHandleClickSelection([barPoint])).toBe(true);
|
|
114
94
|
});
|
|
115
95
|
|
|
116
|
-
it("
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
]);
|
|
96
|
+
it("accepts heatmap clicks", () => {
|
|
97
|
+
const heatmapPoint = createPlotDatum({
|
|
98
|
+
data: { type: "heatmap" },
|
|
99
|
+
});
|
|
142
100
|
|
|
143
|
-
expect(
|
|
101
|
+
expect(shouldHandleClickSelection([heatmapPoint])).toBe(true);
|
|
144
102
|
});
|
|
145
103
|
|
|
146
|
-
it("
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
]);
|
|
104
|
+
it("accepts histogram clicks", () => {
|
|
105
|
+
const histogramPoint = createPlotDatum({
|
|
106
|
+
data: { type: "histogram" },
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
expect(shouldHandleClickSelection([histogramPoint])).toBe(true);
|
|
110
|
+
});
|
|
165
111
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
],
|
|
112
|
+
it("accepts scatter clicks when Plotly omits mode", () => {
|
|
113
|
+
const linePoint = createPlotDatum({
|
|
114
|
+
data: { type: "scatter" },
|
|
179
115
|
});
|
|
116
|
+
|
|
117
|
+
expect(shouldHandleClickSelection([linePoint])).toBe(true);
|
|
180
118
|
});
|
|
181
119
|
|
|
182
|
-
it("
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
y: 2,
|
|
187
|
-
curveNumber: 0,
|
|
188
|
-
pointNumber: 3,
|
|
189
|
-
pointNumbers: [6, 7],
|
|
190
|
-
data: { type: "histogram" },
|
|
191
|
-
}),
|
|
192
|
-
]);
|
|
120
|
+
it("rejects non-line scatter marker clicks", () => {
|
|
121
|
+
const markerPoint = createPlotDatum({
|
|
122
|
+
data: { type: "scatter", mode: "markers" },
|
|
123
|
+
});
|
|
193
124
|
|
|
194
|
-
expect(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
125
|
+
expect(shouldHandleClickSelection([markerPoint])).toBe(false);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe("extractIndices", () => {
|
|
130
|
+
it("prefers pointIndex and falls back to pointNumber and pointNumbers", () => {
|
|
131
|
+
const points = [
|
|
132
|
+
createPlotDatum({ pointIndex: 2 }),
|
|
133
|
+
createPlotDatum({ pointNumber: 5 }),
|
|
134
|
+
createPlotDatum({ pointNumbers: [Number.NaN, 8] }),
|
|
135
|
+
createPlotDatum({ pointNumbers: [Infinity] }),
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
expect(extractIndices(points)).toEqual([2, 5, 8]);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe("extractPoints", () => {
|
|
143
|
+
it("infers missing x/y from trace data for line clicks", () => {
|
|
144
|
+
const point = createPlotDatum({
|
|
145
|
+
pointNumber: 1,
|
|
146
|
+
data: { type: "scatter" },
|
|
147
|
+
fullData: {
|
|
148
|
+
type: "scatter",
|
|
149
|
+
mode: "lines",
|
|
150
|
+
x: new Float64Array([10, 20, 30]),
|
|
151
|
+
y: [100, 200, 300],
|
|
152
|
+
},
|
|
207
153
|
});
|
|
154
|
+
|
|
155
|
+
expect(extractPoints([point])).toEqual([
|
|
156
|
+
{ pointNumber: 1, pointIndex: 1, x: 20, y: 200 },
|
|
157
|
+
]);
|
|
208
158
|
});
|
|
209
159
|
|
|
210
|
-
it("
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
160
|
+
it("parses hovertemplate values while keeping inferred point fields", () => {
|
|
161
|
+
const point = createPlotDatum({
|
|
162
|
+
pointIndex: 0,
|
|
163
|
+
customdata: ["Mustang", "USA"],
|
|
164
|
+
fullData: {
|
|
165
|
+
type: "scatter",
|
|
166
|
+
mode: "lines",
|
|
167
|
+
x: ["300"],
|
|
168
|
+
y: ["30"],
|
|
169
|
+
hovertemplate:
|
|
170
|
+
"Name=%{customdata[0]}<br>Origin=%{customdata[1]}<extra></extra>",
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
expect(extractPoints([point])).toEqual([
|
|
175
|
+
{
|
|
176
|
+
pointIndex: 0,
|
|
177
|
+
x: "300",
|
|
178
|
+
y: "30",
|
|
179
|
+
Name: "Mustang",
|
|
180
|
+
Origin: "USA",
|
|
181
|
+
},
|
|
220
182
|
]);
|
|
183
|
+
});
|
|
221
184
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
pointIndex: 10,
|
|
233
|
-
},
|
|
234
|
-
],
|
|
185
|
+
it("returns only standard fields for heatmaps", () => {
|
|
186
|
+
const point = createPlotDatum({
|
|
187
|
+
x: 1,
|
|
188
|
+
y: 2,
|
|
189
|
+
z: 3,
|
|
190
|
+
text: "ignored",
|
|
191
|
+
data: {
|
|
192
|
+
type: "heatmap",
|
|
193
|
+
hovertemplate: "Label=%{text}<extra></extra>",
|
|
194
|
+
},
|
|
235
195
|
});
|
|
196
|
+
|
|
197
|
+
expect(extractPoints([point])).toEqual([{ x: 1, y: 2, z: 3 }]);
|
|
236
198
|
});
|
|
237
199
|
});
|