@marimo-team/frontend 0.21.1-dev9 → 0.21.1
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-CFRv4Tvd.js → CellStatus-CDSBsjjF.js} +1 -1
- package/dist/assets/{Combination-CBJmtdux.js → Combination-Cs9nbinQ.js} +1 -1
- package/dist/assets/ConnectedDataExplorerComponent-Buaffg3u.js +1 -0
- package/dist/assets/{ErrorBoundary-H5EQrcAX.js → ErrorBoundary-Ba0LbbH4.js} +1 -1
- package/dist/assets/{ImperativeModal-CDxa8mJa.js → ImperativeModal-qEtcJ95s.js} +1 -1
- package/dist/assets/{JsonOutput-DJukuY6Z.js → JsonOutput-DKXKGKvX.js} +10 -10
- package/dist/assets/{LazyAnyLanguageCodeMirror-CrcxjfJR.js → LazyAnyLanguageCodeMirror-m8w66E4s.js} +2 -2
- package/dist/assets/{MarimoErrorOutput-zVM0B_Vj.js → MarimoErrorOutput-az74f3Mp.js} +5 -5
- package/dist/assets/{RenderHTML-BuMvdWQd.js → RenderHTML-DJ8khuob.js} +1 -1
- package/dist/assets/{add-cell-with-ai-BtzUxApq.js → add-cell-with-ai-DUn4LN4W.js} +9 -9
- package/dist/assets/{add-connection-dialog-BSsacvzU.js → add-connection-dialog-CBz0AUVX.js} +23 -23
- package/dist/assets/{agent-panel-a_m3dm9Y.js → agent-panel-u83dsDsM.js} +3 -3
- package/dist/assets/{ai-model-dropdown-CcIreMqb.js → ai-model-dropdown-DPTa_EpU.js} +4 -4
- package/dist/assets/{alert-dialog-B31Yst9T.js → alert-dialog-9WfvUF7e.js} +1 -1
- package/dist/assets/{any-language-editor-BQW3AtUK.js → any-language-editor-DwQMnAM3.js} +1 -1
- package/dist/assets/{app-config-button-D-mROEVq.js → app-config-button-rDu-lCIB.js} +1 -1
- package/dist/assets/{assertNever-CTRGz-ul.js → assertNever-DWSyoPEi.js} +1 -1
- package/dist/assets/{azure-FFoHMnHA.js → azure-BTXHztTw.js} +1 -1
- package/dist/assets/{button-BZAv3veu.js → button-Ej3vmCIF.js} +1 -1
- package/dist/assets/{cache-panel-BPbLoq59.js → cache-panel-qIxnndwr.js} +1 -1
- package/dist/assets/{capabilities-B1-dYWS8.js → capabilities-D3x_db9Y.js} +1 -1
- package/dist/assets/{capitalize-DcpkQwJe.js → capitalize-BfkXNxmI.js} +1 -1
- package/dist/assets/{cell-editor-D_RsnX0J.js → cell-editor-DX7IcqNr.js} +13 -13
- package/dist/assets/cell-link-Q_UEP94Z.js +1 -0
- package/dist/assets/{cells-CAHXVi26.js → cells-fq1RMGX_.js} +53 -53
- package/dist/assets/{chat-display-rX-JkJEO.js → chat-display-D_Fuuy6r.js} +1 -1
- package/dist/assets/{chat-panel-BudFFybg.js → chat-panel-BO-JoQSp.js} +2 -2
- package/dist/assets/{column-preview-Dk_9z2Mw.js → column-preview-WsubyItX.js} +1 -1
- package/dist/assets/command-palette-Bez4BqJF.js +1 -0
- package/dist/assets/{command-_14PjWun.js → command-rfxSsiHU.js} +1 -1
- package/dist/assets/{common-D2sp4A8j.js → common-BYwO983A.js} +1 -1
- package/dist/assets/{components-BP1LfBLA.js → components-Bpgzv_5_.js} +1 -1
- package/dist/assets/components-Ozq0825a.js +1 -0
- package/dist/assets/{config-DeEqZTX7.js → config-3Aq84phF.js} +1 -1
- package/dist/assets/context-aware-panel-CfsfBlhO.js +3 -0
- package/dist/assets/{copy-B0pTwxmU.js → copy-YwM0Pd7v.js} +1 -1
- package/dist/assets/{copy-icon-Ditn6lfU.js → copy-icon-BgmMM9Zg.js} +1 -1
- package/dist/assets/{createReducer-DgaMD0B6.js → createReducer-Drh7NmIR.js} +1 -1
- package/dist/assets/{datasource-BNXHfowL.js → datasource-F9sJtuof.js} +2 -2
- package/dist/assets/{dates-BcvJrESI.js → dates-CHaNfieI.js} +1 -1
- package/dist/assets/{dependency-graph-panel-B5Eq3e0f.js → dependency-graph-panel-AOBcX2tP.js} +4 -4
- package/dist/assets/{dialog-CyL4o0mA.js → dialog-CVN1lcMF.js} +1 -1
- package/dist/assets/{dist-D7GD2EM4.js → dist-BhNN2V5a.js} +1 -1
- package/dist/assets/{dist-D98wU_Qc.js → dist-DJBpXGro.js} +1 -1
- package/dist/assets/documentation-panel-D28MpqbI.js +1 -0
- package/dist/assets/{download-SQhwj_Eq.js → download-B9_ToVd4.js} +3 -3
- package/dist/assets/{dropdown-menu-CJ-Wwa2I.js → dropdown-menu-DdPu5Kfu.js} +1 -1
- package/dist/assets/{edit-page-qWzJGYd0.js → edit-page-otS-QvnC.js} +7 -7
- package/dist/assets/{error-banner-DQBz1e-2.js → error-banner-BRG6IPhC.js} +1 -1
- package/dist/assets/{error-panel-DmmjuXRp.js → error-panel-RRoj_iOR.js} +1 -1
- package/dist/assets/{es-997LzX0P.js → es-CzkousWe.js} +1 -1
- package/dist/assets/{field-qoWy8wEy.js → field-B1jGbQlH.js} +1 -1
- package/dist/assets/{file-explorer-panel-DW3BdMFp.js → file-explorer-panel-CB8vF5ob.js} +3 -3
- package/dist/assets/{file-icons-xucuZauP.js → file-icons-CWLHDa1J.js} +1 -1
- package/dist/assets/{floating-outline-2X-MQKSU.js → floating-outline-BvQKiC0F.js} +1 -1
- package/dist/assets/{focus-DaKeoSx6.js → focus-DYwTiH9-.js} +1 -1
- package/dist/assets/{form-C5vg9S9o.js → form-CrQYrsUC.js} +2 -2
- package/dist/assets/formats-rhOJovGE.js +1 -0
- package/dist/assets/{formatting-IErTLHRl.js → formatting-B4ZCH3ol.js} +1 -1
- package/dist/assets/{gallery-page-CzYOKRSH.js → gallery-page-eRea0yic.js} +1 -1
- package/dist/assets/{glide-data-editor-NQ4lbZ3N.js → glide-data-editor-xt5xNZeV.js} +1 -1
- package/dist/assets/{globals-DCdvUAk2.js → globals-BsV5fVR-.js} +1 -1
- package/dist/assets/{home-page-4oOWwdL4.js → home-page-itW0tRmv.js} +2 -2
- package/dist/assets/{hooks-CZT_TWa2.js → hooks-CHx5dUUq.js} +1 -1
- package/dist/assets/{html-to-image-BgHw831z.js → html-to-image-BnSc-Wa0.js} +1 -1
- package/dist/assets/{index-CPEieVCj.js → index-0n92c_W7.js} +17 -17
- package/dist/assets/{index-CVpJvEAO.css → index-GjXovVsl.css} +1 -1
- package/dist/assets/{input-BRZ8bt6P.js → input-CUwqpKjd.js} +1 -1
- package/dist/assets/{kiosk-mode-BNqp-cFU.js → kiosk-mode-DNjEnIWb.js} +1 -1
- package/dist/assets/{label-SLjr8zzy.js → label-TNNaT1M9.js} +1 -1
- package/dist/assets/{layout-52MeytEk.js → layout-CwFtCyW8.js} +4 -4
- package/dist/assets/{links-D1lqztbf.js → links-CIQwYQ48.js} +1 -1
- package/dist/assets/{logs-panel-dWMS7IIv.js → logs-panel-BU1tNEVc.js} +1 -1
- package/dist/assets/{maps-CqKCrVZ8.js → maps-OKerBHH8.js} +1 -1
- package/dist/assets/{markdown-renderer-MyhTrUey.js → markdown-renderer-MR9df58W.js} +3 -3
- package/dist/assets/{menu-items-Z4F08mfP.js → menu-items-UxKrm8hS.js} +1 -1
- package/dist/assets/{mermaid-DkQrVBDR.js → mermaid-Djr3jUAB.js} +1 -1
- package/dist/assets/{mode-D_HXqDHH.js → mode-AcL8c6qH.js} +1 -1
- package/dist/assets/{multi-map-CJMleYLX.js → multi-map-Pp1P2DOX.js} +1 -1
- package/dist/assets/{name-cell-input-CAAR5C2m.js → name-cell-input-DVFEv_aO.js} +1 -1
- package/dist/assets/{numbers-aIvy9Kr7.js → numbers-CYnquDho.js} +1 -1
- package/dist/assets/{outline-panel-Bmfna9YR.js → outline-panel-CP0oIuiU.js} +1 -1
- package/dist/assets/{packages-panel-DKH34NxN.js → packages-panel-CzRELimG.js} +1 -1
- package/dist/assets/panels-wTweRyIv.js +1 -0
- package/dist/assets/{popover-Du6bDNYH.js → popover-BPGG2gPG.js} +1 -1
- package/dist/assets/process-output-CTVsT--B.js +1 -0
- package/dist/assets/{readonly-python-code-Dz4GjF9D.js → readonly-python-code-DH-1xZGq.js} +1 -1
- package/dist/assets/{renderShortcut-Bgu3XVfT.js → renderShortcut-CnD1Dah5.js} +1 -1
- package/dist/assets/run-page-FCvGnICa.js +1 -0
- package/dist/assets/{runs-DZ_uu7bP.js → runs-Bhy0tbWr.js} +1 -1
- package/dist/assets/scratchpad-panel-k9lrm-rC.js +1 -0
- package/dist/assets/{secrets-panel-Ckqi3z-M.js → secrets-panel-B1Z-6dmz.js} +1 -1
- package/dist/assets/{select-Ch6m1k2G.js → select-CxT2Geqr.js} +1 -1
- package/dist/assets/{session-CXChHxAw.js → session-BrEm7qNv.js} +1 -1
- package/dist/assets/session-panel-WhN0qilM.js +1 -0
- package/dist/assets/{share-BYioqUE0.js → share-BdH_5I58.js} +1 -1
- package/dist/assets/{slides-component-y5hJNJFx.js → slides-component-Brm_TS4x.js} +1 -1
- package/dist/assets/snippets-panel-BCDHUuku.js +1 -0
- package/dist/assets/{spec-CYMZZDXr.js → spec-DbmSqx09.js} +1 -1
- package/dist/assets/{state-CGu0LFDk.js → state-3V5UxC3B.js} +1 -1
- package/dist/assets/{state-D59a73JQ.js → state-CBmCYWFH.js} +1 -1
- package/dist/assets/{state-Y7yVqxf_.js → state-Ce7CVShi.js} +1 -1
- package/dist/assets/{switch-krcK9lRK.js → switch-CVKxYu_0.js} +1 -1
- package/dist/assets/{terminal-vzbCncOF.js → terminal-Cr7wbEjz.js} +1 -1
- package/dist/assets/{toggle-BiIJZR6-.js → toggle-RCwU-rnE.js} +1 -1
- package/dist/assets/{tooltip-CNmaER6z.js → tooltip-D9723Brr.js} +1 -1
- package/dist/assets/{tracing-3veLCmCp.js → tracing-DUVd0jtl.js} +1 -1
- package/dist/assets/{tracing-panel-KUJifV3W.js → tracing-panel-CuTxPn_x.js} +2 -2
- package/dist/assets/{tree-4weMpXk4.js → tree-Ch2-GuhG.js} +1 -1
- package/dist/assets/useAddCell-YC7rpcmD.js +1 -0
- package/dist/assets/{useBoolean-D8-4no-l.js → useBoolean-m1e6E3Ao.js} +1 -1
- package/dist/assets/useCellActionButton-GUb2fXU8.js +1 -0
- package/dist/assets/{useDeleteCell-BAuuakkK.js → useDeleteCell-DRUDRiy0.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-ClmZIdnO.js → useDependencyPanelTab-nFVMlEx0.js} +1 -1
- package/dist/assets/useEventListener-Dy81QR4n.js +1 -0
- package/dist/assets/{useIframeCapabilities-DDlGrM1g.js → useIframeCapabilities-DTN9kFDq.js} +1 -1
- package/dist/assets/{useInstallPackage-CIJ1-EHx.js → useInstallPackage-C9V-on2J.js} +1 -1
- package/dist/assets/{useInterval-D7ibzbpc.js → useInterval-BJucVdV-.js} +1 -1
- package/dist/assets/{useLifecycle-CWjBWFMI.js → useLifecycle-DA9DjSPo.js} +1 -1
- package/dist/assets/{useNotebookActions-DhmD75et.js → useNotebookActions-ChLHy-0O.js} +1 -1
- package/dist/assets/useRunCells-5m6jCnyo.js +1 -0
- package/dist/assets/useSplitCell-DGD9smMq.js +1 -0
- package/dist/assets/{useTheme-CM9j8dgy.js → useTheme-BYXBU1of.js} +1 -1
- package/dist/assets/{tooltip-DLsts-7g.js → utils-CdjCA1J8.js} +3 -3
- package/dist/assets/{utils-BvPM6Bro.js → utils-tNbLd14P.js} +1 -1
- package/dist/assets/vega-component-CRbeDmeM.js +1 -0
- package/dist/assets/{write-secret-modal-VGPgwkTg.js → write-secret-modal-BCvuRAFb.js} +1 -1
- package/dist/index.html +76 -76
- package/package.json +1 -1
- package/src/components/data-table/charts/lazy-chart.tsx +2 -0
- package/src/components/data-table/column-summary/column-summary.tsx +1 -0
- package/src/components/datasources/column-preview.tsx +1 -0
- package/src/components/editor/Output.tsx +2 -0
- package/src/components/editor/actions/useCellActionButton.tsx +38 -29
- package/src/components/editor/cell/code/cell-editor.tsx +9 -0
- package/src/components/editor/chrome/panels/context-aware-panel/context-aware-panel.tsx +6 -0
- package/src/components/editor/chrome/wrapper/__tests__/utils.test.ts +35 -0
- package/src/components/editor/chrome/wrapper/app-chrome.tsx +12 -14
- package/src/components/editor/chrome/wrapper/utils.ts +5 -1
- package/src/components/editor/header/status.tsx +19 -11
- package/src/components/editor/renderers/grid-layout/grid-layout.tsx +10 -3
- package/src/core/cells/cells.ts +6 -0
- package/src/core/cells/utils.ts +1 -0
- package/src/core/codemirror/__tests__/setup.test.ts +1 -0
- package/src/core/codemirror/cells/state.ts +1 -0
- package/src/core/codemirror/extensions.ts +20 -0
- package/src/core/codemirror/language/utils.ts +16 -1
- package/src/core/codemirror/reactive-references/__tests__/analyzer.test.ts +54 -0
- package/src/core/codemirror/reactive-references/analyzer.ts +14 -0
- package/src/core/hotkeys/hotkeys.ts +8 -0
- package/src/css/md.css +4 -0
- package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +6 -3
- package/src/plugins/impl/vega/__tests__/utils.test.ts +36 -0
- package/src/plugins/impl/vega/utils.ts +14 -0
- package/src/plugins/impl/vega/vega-component.tsx +6 -7
- package/src/plugins/impl/vega/vega.css +1 -1
- package/dist/assets/ConnectedDataExplorerComponent-BrZvYzEX.js +0 -1
- package/dist/assets/cell-link-BjgRgErj.js +0 -1
- package/dist/assets/command-palette-NBOgLsWz.js +0 -1
- package/dist/assets/components-Wzn4JDkV.js +0 -1
- package/dist/assets/context-aware-panel--8JnQtYo.js +0 -3
- package/dist/assets/documentation-panel-DLE-AkPt.js +0 -1
- package/dist/assets/formats-CmvHepzl.js +0 -1
- package/dist/assets/panels-jo8u0sPM.js +0 -1
- package/dist/assets/process-output-B2kGZ_VU.js +0 -1
- package/dist/assets/run-page-DQIGlYAL.js +0 -1
- package/dist/assets/scratchpad-panel-ClYOgTQp.js +0 -1
- package/dist/assets/session-panel-BYjloSxn.js +0 -1
- package/dist/assets/snippets-panel-C0yfvEEg.js +0 -1
- package/dist/assets/useAddCell-_oR2xY1x.js +0 -1
- package/dist/assets/useCellActionButton-DNIW0rqj.js +0 -1
- package/dist/assets/useEventListener-BGihH8bs.js +0 -1
- package/dist/assets/useRunCells-BOsp_Hau.js +0 -1
- package/dist/assets/useSplitCell-DfYEUeyE.js +0 -1
- package/dist/assets/vega-component-D3vsTtly.js +0 -1
|
@@ -158,12 +158,19 @@ export const GridLayoutRenderer: React.FC<Props> = ({
|
|
|
158
158
|
compactType={null}
|
|
159
159
|
preventCollision={true}
|
|
160
160
|
rowHeight={layout.rowHeight}
|
|
161
|
-
onLayoutChange={(cellLayouts) =>
|
|
161
|
+
onLayoutChange={(cellLayouts) => {
|
|
162
|
+
// Don't update state in read mode — the layout is static and
|
|
163
|
+
// updating triggers a re-render cycle that causes an infinite loop
|
|
164
|
+
// (React error https://react.dev/errors/185 Maximum update depth exceeded).
|
|
165
|
+
// https://github.com/marimo-team/marimo/issues/8644
|
|
166
|
+
if (isReading) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
162
169
|
setLayout({
|
|
163
170
|
...layout,
|
|
164
171
|
cells: cellLayouts,
|
|
165
|
-
})
|
|
166
|
-
}
|
|
172
|
+
});
|
|
173
|
+
}}
|
|
167
174
|
droppingItem={
|
|
168
175
|
droppingItem
|
|
169
176
|
? {
|
package/src/core/cells/cells.ts
CHANGED
|
@@ -1640,6 +1640,12 @@ export const cellsRuntimeAtom = atom((get) => get(notebookAtom).cellRuntime);
|
|
|
1640
1640
|
export const notebookIsRunningAtom = atom((get) =>
|
|
1641
1641
|
notebookIsRunning(get(notebookAtom)),
|
|
1642
1642
|
);
|
|
1643
|
+
export const onlyScratchpadIsRunningAtom = atom((get) => {
|
|
1644
|
+
const { cellRuntime } = get(notebookAtom);
|
|
1645
|
+
return Object.entries(cellRuntime).every(
|
|
1646
|
+
([id, rt]) => rt.status !== "running" || id === SCRATCH_CELL_ID,
|
|
1647
|
+
);
|
|
1648
|
+
});
|
|
1643
1649
|
export const notebookQueuedOrRunningCountAtom = atom((get) =>
|
|
1644
1650
|
notebookQueueOrRunningCount(get(notebookAtom)),
|
|
1645
1651
|
);
|
package/src/core/cells/utils.ts
CHANGED
|
@@ -11,6 +11,7 @@ export function notebookIsRunning(state: NotebookState) {
|
|
|
11
11
|
(cell) => cell.status === "running",
|
|
12
12
|
);
|
|
13
13
|
}
|
|
14
|
+
|
|
14
15
|
export function notebookQueueOrRunningCount(state: NotebookState) {
|
|
15
16
|
return Object.values(state.cellRuntime).filter(
|
|
16
17
|
(cell) => cell.status === "running" || cell.status === "queued",
|
|
@@ -45,6 +45,7 @@ function getOpts() {
|
|
|
45
45
|
onRun: namedFunction("onRun"),
|
|
46
46
|
deleteCell: namedFunction("deleteCell"),
|
|
47
47
|
afterToggleMarkdown: namedFunction("afterToggleMarkdown"),
|
|
48
|
+
afterToggleSQL: namedFunction("afterToggleSQL"),
|
|
48
49
|
} as unknown as CodemirrorCellActions,
|
|
49
50
|
completionConfig: {
|
|
50
51
|
activate_on_typing: false,
|
|
@@ -42,6 +42,26 @@ export function formatKeymapExtension(hotkeys: HotkeyProvider) {
|
|
|
42
42
|
actions.afterToggleMarkdown();
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
return response !== false;
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
key: hotkeys.getHotkey("cell.viewAsSQL").key,
|
|
50
|
+
preventDefault: true,
|
|
51
|
+
run: (ev) => {
|
|
52
|
+
const currentLanguage = getCurrentLanguageAdapter(ev);
|
|
53
|
+
const destinationLanguage =
|
|
54
|
+
currentLanguage === "sql" ? "python" : "sql";
|
|
55
|
+
|
|
56
|
+
const response = toggleToLanguage(ev, destinationLanguage, {
|
|
57
|
+
force: true,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (response === "sql") {
|
|
61
|
+
const actions = ev.state.facet(cellActionsState);
|
|
62
|
+
actions.afterToggleSQL();
|
|
63
|
+
}
|
|
64
|
+
|
|
45
65
|
return response !== false;
|
|
46
66
|
},
|
|
47
67
|
},
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
import type { EditorState } from "@codemirror/state";
|
|
4
4
|
import type { EditorView } from "@codemirror/view";
|
|
5
5
|
import { replaceEditorContent } from "../replace-editor-content";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
languageAdapterFromCode,
|
|
8
|
+
languageAdapterState,
|
|
9
|
+
switchLanguage,
|
|
10
|
+
} from "./extension";
|
|
7
11
|
import { languageMetadataField } from "./metadata";
|
|
8
12
|
|
|
9
13
|
/**
|
|
@@ -35,6 +39,17 @@ export function updateEditorCodeFromPython(
|
|
|
35
39
|
editor: EditorView,
|
|
36
40
|
pythonCode: string,
|
|
37
41
|
): string {
|
|
42
|
+
const currentAdapter = editor.state.field(languageAdapterState);
|
|
43
|
+
const correctAdapter = languageAdapterFromCode(pythonCode);
|
|
44
|
+
|
|
45
|
+
// If the language type changed (e.g., markdown → python), switch adapters
|
|
46
|
+
if (correctAdapter.type !== currentAdapter.type) {
|
|
47
|
+
switchLanguage(editor, {
|
|
48
|
+
language: correctAdapter.type,
|
|
49
|
+
keepCodeAsIs: true,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
38
53
|
const languageAdapter = editor.state.field(languageAdapterState);
|
|
39
54
|
const [code] = languageAdapter.transformIn(pythonCode);
|
|
40
55
|
// Use replaceEditorContent which preserves cursor position when focused
|
|
@@ -1115,6 +1115,60 @@ class Foo:
|
|
|
1115
1115
|
`);
|
|
1116
1116
|
});
|
|
1117
1117
|
|
|
1118
|
+
test("should not highlight attribute access matching a for-loop variable", () => {
|
|
1119
|
+
// When `tool` is used as a for-loop variable, `mcp.tool` (attribute access)
|
|
1120
|
+
// should NOT have `tool` highlighted — it's a property, not a variable reference.
|
|
1121
|
+
expect(
|
|
1122
|
+
runHighlight(
|
|
1123
|
+
["mcp", "client"],
|
|
1124
|
+
`
|
|
1125
|
+
@mcp.tool
|
|
1126
|
+
def roll_dice():
|
|
1127
|
+
pass
|
|
1128
|
+
|
|
1129
|
+
async with client:
|
|
1130
|
+
for tool in await client.list_tools():
|
|
1131
|
+
print(tool)
|
|
1132
|
+
`,
|
|
1133
|
+
),
|
|
1134
|
+
).toMatchInlineSnapshot(`
|
|
1135
|
+
"
|
|
1136
|
+
@mcp.tool
|
|
1137
|
+
^^^
|
|
1138
|
+
def roll_dice():
|
|
1139
|
+
pass
|
|
1140
|
+
|
|
1141
|
+
async with client:
|
|
1142
|
+
^^^^^^
|
|
1143
|
+
for tool in await client.list_tools():
|
|
1144
|
+
^^^^^^
|
|
1145
|
+
print(tool)
|
|
1146
|
+
"
|
|
1147
|
+
`);
|
|
1148
|
+
});
|
|
1149
|
+
|
|
1150
|
+
test("should not highlight property name matching a global variable", () => {
|
|
1151
|
+
// `tool` is a global variable, but `mcp.tool` should not highlight `tool`
|
|
1152
|
+
// because it's a property access, not a variable reference.
|
|
1153
|
+
expect(
|
|
1154
|
+
runHighlight(
|
|
1155
|
+
["mcp", "tool"],
|
|
1156
|
+
`
|
|
1157
|
+
@mcp.tool
|
|
1158
|
+
def roll_dice():
|
|
1159
|
+
pass
|
|
1160
|
+
`,
|
|
1161
|
+
),
|
|
1162
|
+
).toMatchInlineSnapshot(`
|
|
1163
|
+
"
|
|
1164
|
+
@mcp.tool
|
|
1165
|
+
^^^
|
|
1166
|
+
def roll_dice():
|
|
1167
|
+
pass
|
|
1168
|
+
"
|
|
1169
|
+
`);
|
|
1170
|
+
});
|
|
1171
|
+
|
|
1118
1172
|
test("class property self-reference", () => {
|
|
1119
1173
|
expect(
|
|
1120
1174
|
runHighlight(
|
|
@@ -462,6 +462,7 @@ export function findReactiveVariables(options: {
|
|
|
462
462
|
): boolean {
|
|
463
463
|
return (
|
|
464
464
|
allVariableNames.has(varName) &&
|
|
465
|
+
!isPropertyAccess(cursor) &&
|
|
465
466
|
!isKeywordArgumentName(cursor) &&
|
|
466
467
|
!isAssignmentTarget(cursor)
|
|
467
468
|
);
|
|
@@ -529,6 +530,19 @@ function isAssignmentTarget(cursor: TreeCursor): boolean {
|
|
|
529
530
|
return false;
|
|
530
531
|
}
|
|
531
532
|
|
|
533
|
+
/** Checks whether a `VariableName` is a property access (e.g. `tool` in `mcp.tool`). */
|
|
534
|
+
function isPropertyAccess(cursor: TreeCursor): boolean {
|
|
535
|
+
// Check if the previous sibling is a "." node, which means this
|
|
536
|
+
// VariableName is a property access rather than a standalone variable.
|
|
537
|
+
// This handles both MemberExpression (e.g. `obj.attr`) and Decorator
|
|
538
|
+
// (e.g. `@mcp.tool`) where the parser emits flat sibling nodes.
|
|
539
|
+
const temp = cursor.node.cursor();
|
|
540
|
+
if (temp.prevSibling() && temp.name === ".") {
|
|
541
|
+
return true;
|
|
542
|
+
}
|
|
543
|
+
return false;
|
|
544
|
+
}
|
|
545
|
+
|
|
532
546
|
/**
|
|
533
547
|
* Checks if the syntax tree contains any syntax errors.
|
|
534
548
|
* If there are errors, we shouldn't show reactive variable highlighting.
|
|
@@ -142,6 +142,14 @@ const DEFAULT_HOT_KEY = {
|
|
|
142
142
|
group: "Editing",
|
|
143
143
|
key: "Mod-Shift-m",
|
|
144
144
|
},
|
|
145
|
+
"cell.viewAsSQL": {
|
|
146
|
+
name: "Toggle SQL",
|
|
147
|
+
group: "Editing",
|
|
148
|
+
key: {
|
|
149
|
+
windows: "Alt-Shift-l",
|
|
150
|
+
main: "Mod-Shift-l",
|
|
151
|
+
},
|
|
152
|
+
},
|
|
145
153
|
"cell.complete": {
|
|
146
154
|
name: "Code completion",
|
|
147
155
|
group: "Editing",
|
package/src/css/md.css
CHANGED
|
@@ -17,6 +17,7 @@ import { cn } from "@/utils/cn";
|
|
|
17
17
|
import { Objects } from "@/utils/objects";
|
|
18
18
|
import { ErrorBanner } from "../common/error-banner";
|
|
19
19
|
import { vegaLoadData } from "../vega/loader";
|
|
20
|
+
import { getContainerWidth } from "../vega/utils";
|
|
20
21
|
import { ColumnSummary } from "./components/column-summary";
|
|
21
22
|
import { QueryForm } from "./components/query-form";
|
|
22
23
|
import type { SpecificEncoding } from "./encoding";
|
|
@@ -140,16 +141,18 @@ export const DataExplorerComponent = ({
|
|
|
140
141
|
const responsiveSpec = makeResponsive(spec);
|
|
141
142
|
// TODO: We can optimize by updating the data dynamically. https://github.com/vega/react-vega?tab=readme-ov-file#recipes
|
|
142
143
|
const augmentedSpec = augmentSpecWithData(responsiveSpec, chartData);
|
|
143
|
-
const isContainerWidth = responsiveSpec.width === "container";
|
|
144
144
|
|
|
145
145
|
return (
|
|
146
146
|
<div
|
|
147
147
|
className={cn(
|
|
148
148
|
"flex overflow-y-auto justify-center items-center flex-1 w-[90%]",
|
|
149
|
-
isContainerWidth && "vega-container-width",
|
|
150
149
|
)}
|
|
151
150
|
>
|
|
152
|
-
<VegaEmbed
|
|
151
|
+
<VegaEmbed
|
|
152
|
+
data-container-width={getContainerWidth(augmentedSpec)}
|
|
153
|
+
spec={augmentedSpec}
|
|
154
|
+
options={chartOptions(theme)}
|
|
155
|
+
/>
|
|
153
156
|
</div>
|
|
154
157
|
);
|
|
155
158
|
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
import { getContainerWidth } from "../utils";
|
|
5
|
+
|
|
6
|
+
describe("getContainerWidth", () => {
|
|
7
|
+
it('should return "container" when spec width is "container"', () => {
|
|
8
|
+
expect(getContainerWidth({ width: "container" })).toBe("container");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("should return a numeric width", () => {
|
|
12
|
+
expect(getContainerWidth({ width: 500 })).toBe(500);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("should return undefined when spec has no width", () => {
|
|
16
|
+
expect(getContainerWidth({ height: 300 })).toBeUndefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should return undefined for null", () => {
|
|
20
|
+
expect(getContainerWidth(null)).toBeUndefined();
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should return undefined for undefined", () => {
|
|
24
|
+
expect(getContainerWidth(undefined)).toBeUndefined();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should return undefined for non-object values", () => {
|
|
28
|
+
expect(getContainerWidth("string")).toBeUndefined();
|
|
29
|
+
expect(getContainerWidth(42)).toBeUndefined();
|
|
30
|
+
expect(getContainerWidth(true)).toBeUndefined();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("should return undefined when width is explicitly undefined", () => {
|
|
34
|
+
expect(getContainerWidth({ width: undefined })).toBeUndefined();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
import { Objects } from "@/utils/objects";
|
|
4
4
|
import type { DataType, FieldTypes, VegaDataType } from "./vega-loader";
|
|
5
5
|
|
|
6
|
+
export type ContainerWidth = number | "container";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get the container width from a VegaLite spec.
|
|
10
|
+
* @param spec - The VegaLite spec.
|
|
11
|
+
* @returns The container width.
|
|
12
|
+
*/
|
|
13
|
+
export function getContainerWidth(spec: unknown): ContainerWidth | undefined {
|
|
14
|
+
if (typeof spec === "object" && spec !== null && "width" in spec) {
|
|
15
|
+
return spec.width as ContainerWidth | undefined;
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
6
20
|
export function mergeAsArrays<T>(
|
|
7
21
|
left: T | T[] | undefined,
|
|
8
22
|
right: T | T[] | undefined,
|
|
@@ -27,6 +27,7 @@ import { makeSelectable } from "./make-selectable";
|
|
|
27
27
|
import { getSelectionParamNames, ParamNames } from "./params";
|
|
28
28
|
import { resolveVegaSpecData } from "./resolve-data";
|
|
29
29
|
import type { VegaLiteSpec } from "./types";
|
|
30
|
+
import { getContainerWidth } from "./utils";
|
|
30
31
|
|
|
31
32
|
// register arrow reader under type 'arrow'
|
|
32
33
|
formats("arrow", arrow);
|
|
@@ -305,16 +306,14 @@ const LoadedVegaComponent = ({
|
|
|
305
306
|
</Alert>
|
|
306
307
|
)}
|
|
307
308
|
<div
|
|
308
|
-
className={cn(
|
|
309
|
-
"relative",
|
|
310
|
-
"width" in selectableSpec &&
|
|
311
|
-
selectableSpec.width === "container" &&
|
|
312
|
-
"vega-container-width",
|
|
313
|
-
)}
|
|
309
|
+
className={cn("relative")}
|
|
314
310
|
// Capture the pointer down event to prevent the parent from handling it
|
|
315
311
|
onPointerDown={Events.stopPropagation()}
|
|
316
312
|
>
|
|
317
|
-
<div
|
|
313
|
+
<div
|
|
314
|
+
ref={vegaRef}
|
|
315
|
+
data-container-width={getContainerWidth(selectableSpec)}
|
|
316
|
+
/>
|
|
318
317
|
{renderHelpContent()}
|
|
319
318
|
</div>
|
|
320
319
|
</>
|