@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
|
@@ -58,7 +58,7 @@ describe("isCustomMarimoElement", () => {
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
describe("connectedCallback - light DOM nesting detection", () => {
|
|
61
|
-
//
|
|
61
|
+
// oxlint-disable-next-line typescript/no-explicit-any
|
|
62
62
|
let createRootSpy: any;
|
|
63
63
|
const mockRoot = {
|
|
64
64
|
render: vi.fn(),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
/*
|
|
3
|
+
/* oxlint-disable unicorn/prefer-spread */
|
|
4
4
|
/**
|
|
5
5
|
* WebComponent Factory for React Components
|
|
6
6
|
*
|
|
@@ -88,7 +88,7 @@ interface PluginSlotProps<T> {
|
|
|
88
88
|
|
|
89
89
|
/* Handles synchronization of value on behalf of the component */
|
|
90
90
|
|
|
91
|
-
//
|
|
91
|
+
// oxlint-disable-next-line react/function-component-definition
|
|
92
92
|
function PluginSlotInternal<T>(
|
|
93
93
|
{ hostElement, plugin, children, getInitialValue }: PluginSlotProps<T>,
|
|
94
94
|
ref: React.Ref<PluginSlotHandle>,
|
|
@@ -231,7 +231,7 @@ function PluginSlotInternal<T>(
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
return methods;
|
|
234
|
-
//
|
|
234
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
|
235
235
|
}, [plugin.functions, hostElement, resetNonce]);
|
|
236
236
|
|
|
237
237
|
// If we failed to parse the initial value, render an error
|
|
@@ -265,7 +265,7 @@ function PluginSlotInternal<T>(
|
|
|
265
265
|
}
|
|
266
266
|
|
|
267
267
|
const PluginSlot: React.ForwardRefExoticComponent<
|
|
268
|
-
//
|
|
268
|
+
// oxlint-disable-next-line typescript/no-explicit-any
|
|
269
269
|
PluginSlotProps<any> & React.RefAttributes<PluginSlotHandle>
|
|
270
270
|
> = React.forwardRef(PluginSlotInternal);
|
|
271
271
|
|
package/src/plugins/core/rpc.ts
CHANGED
|
@@ -205,7 +205,7 @@ interface Data<T> {
|
|
|
205
205
|
cellHoverTexts?: Record<string, Record<string, string | null>> | null;
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
//
|
|
208
|
+
// oxlint-disable-next-line typescript/consistent-type-definitions
|
|
209
209
|
type DataTableFunctions = {
|
|
210
210
|
download_as: DownloadAsArgs;
|
|
211
211
|
get_column_summaries: <T>(opts: {}) => Promise<ColumnSummaries<T>>;
|
|
@@ -62,7 +62,7 @@ interface FileInfo {
|
|
|
62
62
|
is_directory: boolean;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
//
|
|
65
|
+
// oxlint-disable-next-line typescript/consistent-type-definitions
|
|
66
66
|
type PluginFunctions = {
|
|
67
67
|
list_directory: (req: { path: string }) => Promise<{
|
|
68
68
|
files: FileInfo[];
|
|
@@ -44,7 +44,7 @@ interface Data {
|
|
|
44
44
|
* is clicked, this plugin assumes the value of the associated plugin.
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
|
-
//
|
|
47
|
+
// oxlint-disable-next-line typescript/consistent-type-definitions
|
|
48
48
|
type Functions = {
|
|
49
49
|
validate: (req: { value?: unknown }) => Promise<string | undefined | null>;
|
|
50
50
|
};
|
|
@@ -52,7 +52,7 @@ beforeEach(() => {
|
|
|
52
52
|
|
|
53
53
|
// jsdom's PointerEvent doesn't properly inherit MouseEvent properties
|
|
54
54
|
// like clientX. Polyfill it so fireEvent.pointerDown/Move/Up work.
|
|
55
|
-
//
|
|
55
|
+
// oxlint-disable-next-line typescript/no-explicit-any
|
|
56
56
|
(globalThis as any).PointerEvent = class PointerEvent extends MouseEvent {
|
|
57
57
|
readonly pointerId: number;
|
|
58
58
|
constructor(type: string, init: PointerEventInit = {}) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { Base64String } from "@/utils/json/base64";
|
|
3
3
|
import type { TypedString } from "@/utils/typed";
|
|
4
4
|
|
|
5
|
-
//
|
|
5
|
+
// oxlint-disable-next-line typescript/no-explicit-any
|
|
6
6
|
export type EventHandler = (...args: any[]) => void;
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -13,7 +13,7 @@ export type WidgetModelId = TypedString<"WidgetModelId">;
|
|
|
13
13
|
/**
|
|
14
14
|
* AnyWidget model state with buffers.
|
|
15
15
|
*/
|
|
16
|
-
//
|
|
16
|
+
// oxlint-disable-next-line typescript/no-explicit-any
|
|
17
17
|
export type ModelState = Record<string | number, any>;
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
/*
|
|
2
|
+
/* oxlint-disable typescript/no-explicit-any */
|
|
3
3
|
|
|
4
4
|
import type { AnyWidget, Experimental } from "@anywidget/types";
|
|
5
5
|
import { asRemoteURL } from "@/core/runtime/config";
|
|
@@ -13,7 +13,7 @@ const LazyChatbot = React.lazy(() =>
|
|
|
13
13
|
import("./chat-ui").then((m) => ({ default: m.Chatbot })),
|
|
14
14
|
);
|
|
15
15
|
|
|
16
|
-
//
|
|
16
|
+
// oxlint-disable-next-line typescript/consistent-type-definitions
|
|
17
17
|
export type PluginFunctions = {
|
|
18
18
|
get_chat_history: (req: {}) => Promise<{ messages: UIMessage[] }>;
|
|
19
19
|
delete_chat_history: (req: {}) => Promise<null>;
|
|
@@ -469,7 +469,7 @@ export const Chatbot: React.FC<Props> = (props) => {
|
|
|
469
469
|
resetInput();
|
|
470
470
|
}}
|
|
471
471
|
ref={formRef}
|
|
472
|
-
//
|
|
472
|
+
// oxlint-ignore-next-line -- inert is used to disable the entire form
|
|
473
473
|
inert={props.disabled || undefined}
|
|
474
474
|
className={cn(
|
|
475
475
|
"flex w-full border-t border-(--slate-6) px-2 py-1 items-center",
|
|
@@ -227,7 +227,7 @@ export const GlideDataEditor = <T,>({
|
|
|
227
227
|
|
|
228
228
|
// Force re-render to update the total rows
|
|
229
229
|
rerender();
|
|
230
|
-
//
|
|
230
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
|
231
231
|
}, [data.length]);
|
|
232
232
|
|
|
233
233
|
const getCellContent = useCallback(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
/*
|
|
2
|
+
/* oxlint-disable typescript/no-base-to-string */
|
|
3
3
|
import * as cql from "compassql/build/src";
|
|
4
4
|
import { createStore, Provider, useAtomValue } from "jotai";
|
|
5
5
|
import { ListFilterIcon } from "lucide-react";
|
|
@@ -268,7 +268,7 @@ const HorizontalCarouselItem = ({
|
|
|
268
268
|
);
|
|
269
269
|
};
|
|
270
270
|
// Make the plot responsive
|
|
271
|
-
//
|
|
271
|
+
// oxlint-disable-next-line typescript/no-explicit-any
|
|
272
272
|
function makeResponsive(spec: any) {
|
|
273
273
|
// NOTE: for row/column, this applies to the inner plot
|
|
274
274
|
// so we tend to overflow due to the legends,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
/*
|
|
2
|
+
/* oxlint-disable typescript/no-base-to-string */
|
|
3
3
|
|
|
4
4
|
import { ExpandedType } from "compassql/build/src/query/expandedtype";
|
|
5
5
|
import { PrimitiveType, type Schema } from "compassql/build/src/schema";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
/*
|
|
2
|
+
/* oxlint-disable typescript/no-base-to-string */
|
|
3
3
|
import type { FieldQuery } from "compassql/build/src/query/encoding";
|
|
4
4
|
import { type FieldFunction, isAggregateOp, type TimeUnitOp } from "./types";
|
|
5
5
|
|
|
@@ -28,7 +28,7 @@ export interface Result {
|
|
|
28
28
|
limit: number;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// oxlint-disable-next-line typescript/no-explicit-any, typescript/no-redundant-type-constituents
|
|
32
32
|
export type TopLevelFacetedUnitSpec = TopLevel<FacetedUnitSpec<any, any>> & {
|
|
33
33
|
data: NamedData;
|
|
34
34
|
};
|
|
@@ -54,7 +54,7 @@ interface Data {
|
|
|
54
54
|
lazy: boolean;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
//
|
|
57
|
+
// oxlint-disable-next-line typescript/consistent-type-definitions
|
|
58
58
|
type PluginFunctions = {
|
|
59
59
|
get_dataframe: (req: {}) => Promise<{
|
|
60
60
|
url: string;
|
|
@@ -194,7 +194,7 @@ export function isConditionValueValid(operator: string, value: unknown) {
|
|
|
194
194
|
return possibleSchemas.some((schema) => schema.safeParse(value).success);
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
//
|
|
197
|
+
// oxlint-disable-next-line typescript/no-explicit-any
|
|
198
198
|
const safeGet = (obj: any, key: string): [z.ZodType] | [] => {
|
|
199
199
|
if (obj[key]) {
|
|
200
200
|
return obj[key];
|
|
@@ -57,7 +57,7 @@ const MatplotlibComponent = (props: MatplotlibState) => {
|
|
|
57
57
|
controller.abort();
|
|
58
58
|
instance.current = null;
|
|
59
59
|
};
|
|
60
|
-
//
|
|
60
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
|
61
61
|
}, []);
|
|
62
62
|
|
|
63
63
|
// No dependency array: intentionally syncs all props into the imperative
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
/*
|
|
2
|
+
/* oxlint-disable typescript/no-explicit-any */
|
|
3
3
|
|
|
4
4
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
5
5
|
import { z } from "zod";
|
|
@@ -74,7 +74,7 @@ interface PanelData {
|
|
|
74
74
|
|
|
75
75
|
type T = Record<string, unknown>;
|
|
76
76
|
|
|
77
|
-
//
|
|
77
|
+
// oxlint-disable-next-line typescript/consistent-type-definitions
|
|
78
78
|
type PluginFunctions = {
|
|
79
79
|
send_to_widget: <T>(req: {
|
|
80
80
|
message?: unknown;
|
|
@@ -4,7 +4,7 @@ import type * as PlotlyTypes from "plotly.js";
|
|
|
4
4
|
// Import the pre-built dist bundle, not the source entry point.
|
|
5
5
|
// The source entry point requires Node.js polyfills (e.g. `buffer/`)
|
|
6
6
|
// that are unavailable in the browser/bundler environment.
|
|
7
|
-
//
|
|
7
|
+
// oxlint-disable-next-line typescript/ban-ts-comment
|
|
8
8
|
// @ts-expect-error — no type declarations for dist path, we use PlotlyTypes above
|
|
9
9
|
import Plotly from "plotly.js/dist/plotly";
|
|
10
10
|
import { useEffect, useRef } from "react";
|
|
@@ -107,7 +107,7 @@ export const Plot = (props: PlotProps) => {
|
|
|
107
107
|
|
|
108
108
|
const plotlyEl = el as unknown as PlotlyElement;
|
|
109
109
|
|
|
110
|
-
//
|
|
110
|
+
// oxlint-disable-next-line typescript/ban-types -- Plotly's event API uses generic function references
|
|
111
111
|
const attached: {
|
|
112
112
|
plotlyName: string;
|
|
113
113
|
handler: (...args: never[]) => void;
|
|
@@ -131,7 +131,7 @@ export const Plot = (props: PlotProps) => {
|
|
|
131
131
|
}
|
|
132
132
|
};
|
|
133
133
|
// Re-sync whenever any event handler prop changes
|
|
134
|
-
//
|
|
134
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps
|
|
135
135
|
},
|
|
136
136
|
EVENT_NAMES.map((name) => props[propName(name)]),
|
|
137
137
|
);
|
|
@@ -14,11 +14,16 @@ import useEvent from "react-use-event-hook";
|
|
|
14
14
|
import { useDeepCompareMemoize } from "@/hooks/useDeepCompareMemoize";
|
|
15
15
|
import { useScript } from "@/hooks/useScript";
|
|
16
16
|
import { Arrays } from "@/utils/arrays";
|
|
17
|
-
import { Objects } from "@/utils/objects";
|
|
18
17
|
import {
|
|
19
|
-
extractClickSelection,
|
|
20
18
|
extractIndices,
|
|
21
19
|
extractPoints,
|
|
20
|
+
extractSunburstPoints,
|
|
21
|
+
extractTreemapPoints,
|
|
22
|
+
hasPureLineTrace,
|
|
23
|
+
lineSelectionButtons,
|
|
24
|
+
type ModeBarButton,
|
|
25
|
+
mergeModeBarButtonsToAdd,
|
|
26
|
+
shouldHandleClickSelection,
|
|
22
27
|
} from "./selection";
|
|
23
28
|
import { usePlotlyLayout } from "./usePlotlyLayout";
|
|
24
29
|
|
|
@@ -35,6 +40,10 @@ type T =
|
|
|
35
40
|
x?: number[];
|
|
36
41
|
y?: number[];
|
|
37
42
|
};
|
|
43
|
+
lasso?: {
|
|
44
|
+
x?: unknown[];
|
|
45
|
+
y?: unknown[];
|
|
46
|
+
};
|
|
38
47
|
// These are kept in the state to persist selections across re-renders
|
|
39
48
|
// on the frontend, but likely not used in the backend.
|
|
40
49
|
selections?: unknown[];
|
|
@@ -77,23 +86,6 @@ const LazyPlot = lazy(() =>
|
|
|
77
86
|
import("./Plot").then((mod) => ({ default: mod.Plot })),
|
|
78
87
|
);
|
|
79
88
|
|
|
80
|
-
const SUNBURST_DATA_KEYS: (keyof Plotly.SunburstPlotDatum)[] = [
|
|
81
|
-
"color",
|
|
82
|
-
"curveNumber",
|
|
83
|
-
"entry",
|
|
84
|
-
"hovertext",
|
|
85
|
-
"id",
|
|
86
|
-
"label",
|
|
87
|
-
"parent",
|
|
88
|
-
"percentEntry",
|
|
89
|
-
"percentParent",
|
|
90
|
-
"percentRoot",
|
|
91
|
-
"pointNumber",
|
|
92
|
-
"root",
|
|
93
|
-
"value",
|
|
94
|
-
] as const;
|
|
95
|
-
const TREE_MAP_DATA_KEYS = SUNBURST_DATA_KEYS;
|
|
96
|
-
|
|
97
89
|
export const PlotlyComponent = memo(
|
|
98
90
|
({ figure: originalFigure, value, setValue, config }: PlotlyPluginProps) => {
|
|
99
91
|
// Used for rendering LaTeX. TODO: Serve this library from Marimo
|
|
@@ -102,7 +94,7 @@ export const PlotlyComponent = memo(
|
|
|
102
94
|
);
|
|
103
95
|
const isScriptLoaded = scriptStatus === "ready";
|
|
104
96
|
|
|
105
|
-
const { figure, layout, handleReset } = usePlotlyLayout({
|
|
97
|
+
const { figure, layout, setLayout, handleReset } = usePlotlyLayout({
|
|
106
98
|
originalFigure,
|
|
107
99
|
initialValue: value,
|
|
108
100
|
isScriptLoaded,
|
|
@@ -112,31 +104,48 @@ export const PlotlyComponent = memo(
|
|
|
112
104
|
handleReset();
|
|
113
105
|
setValue({});
|
|
114
106
|
});
|
|
107
|
+
const handleSetDragmode = useEvent(
|
|
108
|
+
(dragmode: Plotly.Layout["dragmode"]) => {
|
|
109
|
+
setLayout((prev) => ({ ...prev, dragmode }));
|
|
110
|
+
setValue((prev) => ({ ...prev, dragmode }));
|
|
111
|
+
},
|
|
112
|
+
);
|
|
115
113
|
|
|
116
114
|
const configMemo = useDeepCompareMemoize(config);
|
|
117
115
|
const plotlyConfig = useMemo((): Partial<Plotly.Config> => {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
svg: `
|
|
116
|
+
const hasPureLine = hasPureLineTrace(figure.data);
|
|
117
|
+
const defaultButtons: ModeBarButton[] = [
|
|
118
|
+
// Custom button to reset the state
|
|
119
|
+
{
|
|
120
|
+
name: "reset",
|
|
121
|
+
title: "Reset state",
|
|
122
|
+
icon: {
|
|
123
|
+
svg: `
|
|
127
124
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
128
125
|
stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rotate-ccw">
|
|
129
126
|
<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" />
|
|
130
127
|
<path d="M3 3v5h5" />
|
|
131
128
|
</svg>`,
|
|
132
|
-
},
|
|
133
|
-
click: handleResetWithClear,
|
|
134
129
|
},
|
|
135
|
-
|
|
130
|
+
click: handleResetWithClear,
|
|
131
|
+
},
|
|
132
|
+
];
|
|
133
|
+
if (hasPureLine) {
|
|
134
|
+
defaultButtons.push(...lineSelectionButtons(handleSetDragmode));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
displaylogo: false,
|
|
136
139
|
// Prioritize user's config
|
|
137
140
|
...configMemo,
|
|
141
|
+
modeBarButtonsToAdd: mergeModeBarButtonsToAdd(
|
|
142
|
+
defaultButtons,
|
|
143
|
+
configMemo.modeBarButtonsToAdd as
|
|
144
|
+
| readonly ModeBarButton[]
|
|
145
|
+
| undefined,
|
|
146
|
+
),
|
|
138
147
|
};
|
|
139
|
-
}, [handleResetWithClear, configMemo]);
|
|
148
|
+
}, [handleResetWithClear, handleSetDragmode, configMemo, figure.data]);
|
|
140
149
|
|
|
141
150
|
return (
|
|
142
151
|
<LazyPlot
|
|
@@ -171,6 +180,7 @@ export const PlotlyComponent = memo(
|
|
|
171
180
|
points: Arrays.EMPTY,
|
|
172
181
|
indices: Arrays.EMPTY,
|
|
173
182
|
range: undefined,
|
|
183
|
+
lasso: undefined,
|
|
174
184
|
};
|
|
175
185
|
});
|
|
176
186
|
})}
|
|
@@ -181,9 +191,7 @@ export const PlotlyComponent = memo(
|
|
|
181
191
|
|
|
182
192
|
setValue((prev) => ({
|
|
183
193
|
...prev,
|
|
184
|
-
points: evt.points
|
|
185
|
-
Objects.pick(point, TREE_MAP_DATA_KEYS),
|
|
186
|
-
),
|
|
194
|
+
points: extractTreemapPoints(evt.points),
|
|
187
195
|
}));
|
|
188
196
|
})}
|
|
189
197
|
onSunburstClick={useEvent((evt: Readonly<Plotly.PlotMouseEvent>) => {
|
|
@@ -193,9 +201,7 @@ export const PlotlyComponent = memo(
|
|
|
193
201
|
|
|
194
202
|
setValue((prev) => ({
|
|
195
203
|
...prev,
|
|
196
|
-
points: evt.points
|
|
197
|
-
Objects.pick(point, SUNBURST_DATA_KEYS),
|
|
198
|
-
),
|
|
204
|
+
points: extractSunburstPoints(evt.points),
|
|
199
205
|
}));
|
|
200
206
|
})}
|
|
201
207
|
config={plotlyConfig}
|
|
@@ -203,13 +209,21 @@ export const PlotlyComponent = memo(
|
|
|
203
209
|
if (!evt) {
|
|
204
210
|
return;
|
|
205
211
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (!
|
|
212
|
+
// Handle clicks for chart types where box/lasso selection
|
|
213
|
+
// is limited or unavailable (e.g. bar, heatmaps, histograms, pure line traces).
|
|
214
|
+
if (!shouldHandleClickSelection(evt.points)) {
|
|
209
215
|
return;
|
|
210
216
|
}
|
|
211
|
-
|
|
212
|
-
|
|
217
|
+
const extractedPoints = extractPoints(evt.points);
|
|
218
|
+
const extractedIndices = extractIndices(evt.points);
|
|
219
|
+
setValue((prev) => ({
|
|
220
|
+
...prev,
|
|
221
|
+
selections: Arrays.EMPTY,
|
|
222
|
+
range: undefined,
|
|
223
|
+
lasso: undefined,
|
|
224
|
+
points: extractedPoints,
|
|
225
|
+
indices: extractedIndices,
|
|
226
|
+
}));
|
|
213
227
|
})}
|
|
214
228
|
onSelected={useEvent((evt: Readonly<Plotly.PlotSelectionEvent>) => {
|
|
215
229
|
if (!evt) {
|
|
@@ -223,6 +237,10 @@ export const PlotlyComponent = memo(
|
|
|
223
237
|
points: extractPoints(evt.points),
|
|
224
238
|
indices: extractIndices(evt.points),
|
|
225
239
|
range: evt.range,
|
|
240
|
+
lasso:
|
|
241
|
+
"lassoPoints" in evt
|
|
242
|
+
? (evt.lassoPoints as { x?: unknown[]; y?: unknown[] })
|
|
243
|
+
: undefined,
|
|
226
244
|
}));
|
|
227
245
|
})}
|
|
228
246
|
className="w-full"
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { act, render, waitFor } from "@testing-library/react";
|
|
4
|
+
import { Suspense } from "react";
|
|
5
|
+
import { describe, expect, it, vi } from "vitest";
|
|
6
|
+
import { SetupMocks } from "@/__mocks__/common";
|
|
7
|
+
import type { Setter } from "@/plugins/types";
|
|
8
|
+
import { PlotlyComponent } from "../PlotlyPlugin";
|
|
9
|
+
|
|
10
|
+
SetupMocks.resizeObserver();
|
|
11
|
+
|
|
12
|
+
type CapturedPlotProps = {
|
|
13
|
+
onClick?: (event: {
|
|
14
|
+
points: {
|
|
15
|
+
data?: { type?: string };
|
|
16
|
+
x?: string | number;
|
|
17
|
+
y?: string | number;
|
|
18
|
+
pointIndex?: number;
|
|
19
|
+
pointNumber?: number;
|
|
20
|
+
curveNumber?: number;
|
|
21
|
+
}[];
|
|
22
|
+
}) => void;
|
|
23
|
+
} | null;
|
|
24
|
+
|
|
25
|
+
let capturedPlotProps: CapturedPlotProps = null;
|
|
26
|
+
|
|
27
|
+
vi.mock("../Plot", () => ({
|
|
28
|
+
Plot: (props: CapturedPlotProps) => {
|
|
29
|
+
capturedPlotProps = props;
|
|
30
|
+
return <div data-testid="plotly-mock" />;
|
|
31
|
+
},
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
vi.mock("../usePlotlyLayout", () => ({
|
|
35
|
+
usePlotlyLayout: ({
|
|
36
|
+
originalFigure,
|
|
37
|
+
}: {
|
|
38
|
+
originalFigure: {
|
|
39
|
+
data: unknown[];
|
|
40
|
+
layout: Record<string, unknown>;
|
|
41
|
+
frames: unknown[] | null;
|
|
42
|
+
};
|
|
43
|
+
}) => ({
|
|
44
|
+
figure: originalFigure,
|
|
45
|
+
layout: originalFigure.layout,
|
|
46
|
+
handleReset: vi.fn(),
|
|
47
|
+
}),
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
vi.mock("@/hooks/useScript", () => ({
|
|
51
|
+
useScript: () => "ready",
|
|
52
|
+
}));
|
|
53
|
+
|
|
54
|
+
vi.mock("react-use-event-hook", () => ({
|
|
55
|
+
default: <T,>(callback: T) => callback,
|
|
56
|
+
}));
|
|
57
|
+
|
|
58
|
+
describe("PlotlyPlugin", () => {
|
|
59
|
+
it("clicking a bar selects that bar", async () => {
|
|
60
|
+
const setValue = vi.fn<Setter<unknown>>();
|
|
61
|
+
|
|
62
|
+
render(
|
|
63
|
+
<Suspense fallback={null}>
|
|
64
|
+
<PlotlyComponent
|
|
65
|
+
figure={{
|
|
66
|
+
data: [{ type: "bar" }],
|
|
67
|
+
layout: {},
|
|
68
|
+
frames: null,
|
|
69
|
+
}}
|
|
70
|
+
value={undefined}
|
|
71
|
+
setValue={setValue}
|
|
72
|
+
host={document.createElement("div")}
|
|
73
|
+
config={{}}
|
|
74
|
+
/>
|
|
75
|
+
</Suspense>,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
await waitFor(() => {
|
|
79
|
+
expect(capturedPlotProps).not.toBeNull();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
act(() => {
|
|
83
|
+
capturedPlotProps?.onClick?.({
|
|
84
|
+
points: [
|
|
85
|
+
{
|
|
86
|
+
data: { type: "bar" },
|
|
87
|
+
x: "Feb",
|
|
88
|
+
y: 18,
|
|
89
|
+
pointIndex: 1,
|
|
90
|
+
pointNumber: 1,
|
|
91
|
+
curveNumber: 0,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(setValue).toHaveBeenCalledTimes(1);
|
|
98
|
+
const updater = setValue.mock.calls[0][0] as (value: unknown) => unknown;
|
|
99
|
+
expect(updater({})).toEqual({
|
|
100
|
+
selections: [],
|
|
101
|
+
points: [
|
|
102
|
+
{
|
|
103
|
+
x: "Feb",
|
|
104
|
+
y: 18,
|
|
105
|
+
curveNumber: 0,
|
|
106
|
+
pointNumber: 1,
|
|
107
|
+
pointIndex: 1,
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
indices: [1],
|
|
111
|
+
range: undefined,
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|