@marimo-team/frontend 0.23.12-dev9 → 0.23.12
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-BGSEw-sx.js → CellStatus-xkT4Dvj4.js} +1 -1
- package/dist/assets/JsonOutput-FFLZqPUK.js +53 -0
- package/dist/assets/{MarimoErrorOutput-G8Q8ZYoi.js → MarimoErrorOutput-BQt_FXJL.js} +1 -1
- package/dist/assets/{RenderHTML-DXJCvdz4.js → RenderHTML-Cq4mwWYz.js} +1 -1
- package/dist/assets/{RunButton-B0ruC_FE.js → RunButton-DdQ4s_KP.js} +1 -1
- package/dist/assets/{add-cell-with-ai-DWNUMbns.js → add-cell-with-ai-wdY7HT-D.js} +26 -26
- package/dist/assets/{add-connection-dialog-CZ2UuO8f.js → add-connection-dialog-C41ThK2T.js} +1 -1
- package/dist/assets/{agent-panel-B-_gvxz2.js → agent-panel-q5ey8yNH.js} +1 -1
- package/dist/assets/{ai-model-dropdown-BW60s6ul.js → ai-model-dropdown-DQb_CyMN.js} +4 -4
- package/dist/assets/{app-config-button-DJaefZBz.js → app-config-button-8FXNdkBs.js} +1 -1
- package/dist/assets/{cell-editor-CvLW6KK3.js → cell-editor-CFq9iL3S.js} +1 -1
- package/dist/assets/{cell-link-BWqpbaiv.js → cell-link-DgWTiCtG.js} +1 -1
- package/dist/assets/{cells-BidbgSuB.js → cells-06TDmJ8V.js} +49 -49
- package/dist/assets/{chat-display-BRCFntOw.js → chat-display-DO7nc_uY.js} +1 -1
- package/dist/assets/{chat-panel-BGCbxSQx.js → chat-panel-DmUkj42a.js} +1 -1
- package/dist/assets/{chat-ui-CceYGzB9.js → chat-ui-Bf7t-NAW.js} +1 -1
- package/dist/assets/{column-preview-BbgM2h8n.js → column-preview-oHsVFerC.js} +1 -1
- package/dist/assets/{command-palette-Mqu8KKo1.js → command-palette-Bvl7fQ8h.js} +1 -1
- package/dist/assets/{common-B94MReIe.js → common-cKvfH0fD.js} +1 -1
- package/dist/assets/{components-DoRr7Hf1.js → components-BhmX9dcm.js} +1 -1
- package/dist/assets/{datasource-DI-YUWev.js → datasource-mVfTJz3V.js} +1 -1
- package/dist/assets/{dependency-graph-panel-B7_LMfP4.js → dependency-graph-panel-D9C_hBQw.js} +1 -1
- package/dist/assets/{documentation-panel-BGXFZYSy.js → documentation-panel-C0uXzYri.js} +1 -1
- package/dist/assets/{download-DgEarSps.js → download-VxqV5OSK.js} +1 -1
- package/dist/assets/{edit-page-DExCsBoE.js → edit-page-CInfJ1ps.js} +6 -6
- package/dist/assets/{error-panel-Bd98g_JW.js → error-panel-D2WmJDnT.js} +1 -1
- package/dist/assets/{file-explorer-panel-5GiP_o58.js → file-explorer-panel-nn5I1oLj.js} +3 -3
- package/dist/assets/{file-icons-BwFX01F6.js → file-icons-BeJWUbBH.js} +1 -1
- package/dist/assets/{file-name-input-C_iFa52z.js → file-name-input-Slq_KVFS.js} +1 -1
- package/dist/assets/{floating-outline-BDx00oB1.js → floating-outline-3UBj62S1.js} +1 -1
- package/dist/assets/{focus-CocfMydm.js → focus-DqhVePQT.js} +1 -1
- package/dist/assets/{form-DgnBiuvP.js → form-pEJO4Mq_.js} +1 -1
- package/dist/assets/{home-page-BuVWyEpt.js → home-page-CFgoMQu4.js} +1 -1
- package/dist/assets/{hooks-dPm1h9aq.js → hooks-NssnE3R8.js} +1 -1
- package/dist/assets/{html-to-image-TCtIotr9.js → html-to-image-CbQeOjEJ.js} +1 -1
- package/dist/assets/index-BjsskD4V.js +38 -0
- package/dist/assets/{index-Bj8QWDiJ.css → index-CaelsqOA.css} +1 -1
- package/dist/assets/{kiosk-mode-sfaqwl5N.js → kiosk-mode-CyYnV3_y.js} +1 -1
- package/dist/assets/{layout-CVg460UU.js → layout-ChW1-odP.js} +4 -4
- package/dist/assets/{logs-panel-Bs7u1Wfd.js → logs-panel-CiP_30S4.js} +1 -1
- package/dist/assets/{markdown-renderer-CGZTB2Dx.js → markdown-renderer-C1yypOYF.js} +1 -1
- package/dist/assets/{name-cell-input-D4k4IMJD.js → name-cell-input-CIkFEB6-.js} +1 -1
- package/dist/assets/{outline-panel-5sRz-QR2.js → outline-panel-BfysapqU.js} +1 -1
- package/dist/assets/{packages-panel-DhXpwKjz.js → packages-panel-BYm2thcs.js} +1 -1
- package/dist/assets/{panels-C3XyfWZa.js → panels-hLpsLawB.js} +1 -1
- package/dist/assets/{process-output-CRIsE74Q.js → process-output-BIlXY0iE.js} +1 -1
- package/dist/assets/{radio-group-Czn6pjhm.js → radio-group-BaOG2bSA.js} +1 -1
- package/dist/assets/{readonly-python-code-DtUWOxnZ.js → readonly-python-code-CNyK8G1T.js} +1 -1
- package/dist/assets/{reveal-component-DDZ2IxNS.js → reveal-component-D0boNLsp.js} +1 -1
- package/dist/assets/{run-page-K4C80Bqk.js → run-page-B0OR2l0l.js} +1 -1
- package/dist/assets/{scratchpad-panel-Cwl5E8lN.js → scratchpad-panel-Di7uCP6T.js} +1 -1
- package/dist/assets/{session-panel-DGjSy-dF.js → session-panel-D6GA7GoC.js} +1 -1
- package/dist/assets/{snippets-panel-94zH2JCj.js → snippets-panel-DV2ir7q8.js} +1 -1
- package/dist/assets/{state-ClDZE-YW.js → state-B3ypjIx-.js} +1 -1
- package/dist/assets/state-DD6m9X2h.js +3 -0
- package/dist/assets/{textarea-Dz09niIv.js → textarea-BM7hAwR3.js} +1 -1
- package/dist/assets/{tracing-C_GaBGFx.js → tracing-DwjgsPkU.js} +1 -1
- package/dist/assets/{tracing-panel-BkzzwM_5.js → tracing-panel-BS9eUNK_.js} +2 -2
- package/dist/assets/{tree-actions-CesD4Rcl.js → tree-actions-lVyJAYy7.js} +1 -1
- package/dist/assets/{useCellActionButton-DNYd1sgZ.js → useCellActionButton-B88iHApv.js} +1 -1
- package/dist/assets/{useDeleteCell-CCCMHD2a.js → useDeleteCell-CXc93le9.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-P57LIkal.js → useDependencyPanelTab-9Vnr8-OR.js} +1 -1
- package/dist/assets/{useNotebookActions-B8xsvWwy.js → useNotebookActions-DSfevQ7S.js} +1 -1
- package/dist/assets/{useRunCells-DFXV3Rm5.js → useRunCells-DNaOKKqW.js} +1 -1
- package/dist/assets/{useSplitCell-R-0wFhnd.js → useSplitCell-IsXuVcLF.js} +1 -1
- package/dist/index.html +23 -23
- package/package.json +1 -1
- package/src/components/data-table/TableBottomBar.tsx +4 -1
- package/src/components/data-table/data-table.tsx +26 -17
- package/src/components/data-table/utils.ts +1 -4
- package/src/components/editor/ai/__tests__/completion-utils.test.ts +48 -2
- package/src/components/editor/ai/completion-utils.ts +54 -36
- package/src/components/editor/app-container.tsx +3 -1
- package/src/components/editor/output/ImageOutput.tsx +12 -3
- package/src/components/editor/renderers/vertical-layout/vertical-layout-wrapper.tsx +2 -2
- package/src/core/codemirror/go-to-definition/__tests__/commands.test.ts +67 -0
- package/src/core/codemirror/go-to-definition/__tests__/utils.test.ts +47 -0
- package/src/core/codemirror/go-to-definition/commands.ts +47 -30
- package/src/core/codemirror/go-to-definition/utils.ts +0 -1
- package/src/core/codemirror/reactive-references/__tests__/analyzer.test.ts +54 -0
- package/src/core/codemirror/reactive-references/analyzer.ts +44 -35
- package/src/core/islands/__tests__/bridge.test.ts +25 -0
- package/src/core/islands/__tests__/parse.test.ts +585 -1
- package/src/core/islands/__tests__/test-utils.tsx +10 -1
- package/src/core/islands/bridge.ts +6 -1
- package/src/core/islands/constants.ts +2 -0
- package/src/core/islands/parse.ts +290 -13
- package/src/plugins/impl/DataTablePlugin.tsx +20 -1
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +141 -1
- package/src/plugins/impl/anywidget/AnyWidgetPlugin.tsx +54 -4
- package/src/plugins/impl/anywidget/__tests__/AnyWidgetPlugin.test.tsx +104 -1
- package/src/plugins/impl/anywidget/__tests__/model.test.ts +19 -0
- package/src/plugins/impl/anywidget/model.ts +15 -0
- package/src/utils/__tests__/records.test.ts +27 -0
- package/src/utils/records.ts +12 -0
- package/dist/assets/JsonOutput-CxKHBYIA.js +0 -53
- package/dist/assets/index-CrgYGp5w.js +0 -38
- package/dist/assets/state-CzwQl1aE.js +0 -3
package/dist/index.html
CHANGED
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
<marimo-server-token data-token="{{ server_token }}" hidden></marimo-server-token>
|
|
67
67
|
<!-- /TODO -->
|
|
68
68
|
<title>{{ title }}</title>
|
|
69
|
-
<script type="module" crossorigin src="./assets/index-
|
|
69
|
+
<script type="module" crossorigin src="./assets/index-BjsskD4V.js"></script>
|
|
70
70
|
<link rel="modulepreload" crossorigin href="./assets/preload-helper-y72bE5iF.js">
|
|
71
71
|
<link rel="modulepreload" crossorigin href="./assets/chunk-LvLJmgfZ.js">
|
|
72
72
|
<link rel="modulepreload" crossorigin href="./assets/react-Bj1aDYRI.js">
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
<link rel="modulepreload" crossorigin href="./assets/debounce-OiXznToA.js">
|
|
134
134
|
<link rel="modulepreload" crossorigin href="./assets/database-zap-DIlSqcdp.js">
|
|
135
135
|
<link rel="modulepreload" crossorigin href="./assets/main-DmhaVp6Y.js">
|
|
136
|
-
<link rel="modulepreload" crossorigin href="./assets/cells-
|
|
136
|
+
<link rel="modulepreload" crossorigin href="./assets/cells-06TDmJ8V.js">
|
|
137
137
|
<link rel="modulepreload" crossorigin href="./assets/ErrorBoundary-Bo313Z9X.js">
|
|
138
138
|
<link rel="modulepreload" crossorigin href="./assets/kbd-BCXa3Ocm.js">
|
|
139
139
|
<link rel="modulepreload" crossorigin href="./assets/useInstallPackage-DEHK-C20.js">
|
|
@@ -147,38 +147,38 @@
|
|
|
147
147
|
<link rel="modulepreload" crossorigin href="./assets/usePress-mjvipKvz.js">
|
|
148
148
|
<link rel="modulepreload" crossorigin href="./assets/input-b2KTOk0X.js">
|
|
149
149
|
<link rel="modulepreload" crossorigin href="./assets/ImperativeModal-MQnbMIO2.js">
|
|
150
|
-
<link rel="modulepreload" crossorigin href="./assets/cell-link-
|
|
150
|
+
<link rel="modulepreload" crossorigin href="./assets/cell-link-DgWTiCtG.js">
|
|
151
151
|
<link rel="modulepreload" crossorigin href="./assets/multi-map-9ogswH46.js">
|
|
152
152
|
<link rel="modulepreload" crossorigin href="./assets/alert-Bjh7v4lb.js">
|
|
153
153
|
<link rel="modulepreload" crossorigin href="./assets/chevron-right-C7RH0Nc7.js">
|
|
154
154
|
<link rel="modulepreload" crossorigin href="./assets/dropdown-menu-DfGLyCbP.js">
|
|
155
155
|
<link rel="modulepreload" crossorigin href="./assets/links-DK7te6sJ.js">
|
|
156
|
-
<link rel="modulepreload" crossorigin href="./assets/useRunCells-
|
|
156
|
+
<link rel="modulepreload" crossorigin href="./assets/useRunCells-DNaOKKqW.js">
|
|
157
157
|
<link rel="modulepreload" crossorigin href="./assets/copy-CyasABTK.js">
|
|
158
158
|
<link rel="modulepreload" crossorigin href="./assets/copy-IBNGDypD.js">
|
|
159
159
|
<link rel="modulepreload" crossorigin href="./assets/copy-icon-BCIGtBo0.js">
|
|
160
|
-
<link rel="modulepreload" crossorigin href="./assets/RenderHTML-
|
|
161
|
-
<link rel="modulepreload" crossorigin href="./assets/datasource-
|
|
162
|
-
<link rel="modulepreload" crossorigin href="./assets/state-
|
|
160
|
+
<link rel="modulepreload" crossorigin href="./assets/RenderHTML-Cq4mwWYz.js">
|
|
161
|
+
<link rel="modulepreload" crossorigin href="./assets/datasource-mVfTJz3V.js">
|
|
162
|
+
<link rel="modulepreload" crossorigin href="./assets/state-B3ypjIx-.js">
|
|
163
163
|
<link rel="modulepreload" crossorigin href="./assets/package-BoMcg6sy.js">
|
|
164
164
|
<link rel="modulepreload" crossorigin href="./assets/sparkles-DctOjjEz.js">
|
|
165
|
-
<link rel="modulepreload" crossorigin href="./assets/MarimoErrorOutput-
|
|
165
|
+
<link rel="modulepreload" crossorigin href="./assets/MarimoErrorOutput-BQt_FXJL.js">
|
|
166
166
|
<link rel="modulepreload" crossorigin href="./assets/eye-off-DI0EQXw0.js">
|
|
167
167
|
<link rel="modulepreload" crossorigin href="./assets/refresh-cw-DcEasnos.js">
|
|
168
|
-
<link rel="modulepreload" crossorigin href="./assets/tree-actions-
|
|
168
|
+
<link rel="modulepreload" crossorigin href="./assets/tree-actions-lVyJAYy7.js">
|
|
169
169
|
<link rel="modulepreload" crossorigin href="./assets/spinner-DTBVbtl-.js">
|
|
170
|
-
<link rel="modulepreload" crossorigin href="./assets/html-to-image-
|
|
171
|
-
<link rel="modulepreload" crossorigin href="./assets/focus-
|
|
170
|
+
<link rel="modulepreload" crossorigin href="./assets/html-to-image-CbQeOjEJ.js">
|
|
171
|
+
<link rel="modulepreload" crossorigin href="./assets/focus-DqhVePQT.js">
|
|
172
172
|
<link rel="modulepreload" crossorigin href="./assets/useAsyncData-CT1LpOBD.js">
|
|
173
173
|
<link rel="modulepreload" crossorigin href="./assets/LazyAnyLanguageCodeMirror-CUQODgGJ.js">
|
|
174
174
|
<link rel="modulepreload" crossorigin href="./assets/micromark-factory-space-P--XWZhg.js">
|
|
175
175
|
<link rel="modulepreload" crossorigin href="./assets/chunk-5FQGJX7Z-C6VN0dQj.js">
|
|
176
|
-
<link rel="modulepreload" crossorigin href="./assets/markdown-renderer-
|
|
176
|
+
<link rel="modulepreload" crossorigin href="./assets/markdown-renderer-C1yypOYF.js">
|
|
177
177
|
<link rel="modulepreload" crossorigin href="./assets/command-CsbsBLBw.js">
|
|
178
178
|
<link rel="modulepreload" crossorigin href="./assets/field-CA9HCE2Y.js">
|
|
179
179
|
<link rel="modulepreload" crossorigin href="./assets/popover-DMNO6Poc.js">
|
|
180
180
|
<link rel="modulepreload" crossorigin href="./assets/errors-48KFPvCp.js">
|
|
181
|
-
<link rel="modulepreload" crossorigin href="./assets/download-
|
|
181
|
+
<link rel="modulepreload" crossorigin href="./assets/download-VxqV5OSK.js">
|
|
182
182
|
<link rel="modulepreload" crossorigin href="./assets/table-Fk_msRcD.js">
|
|
183
183
|
<link rel="modulepreload" crossorigin href="./assets/useIframeCapabilities-DuGyzPVb.js">
|
|
184
184
|
<link rel="modulepreload" crossorigin href="./assets/error-banner-C4DZksWV.js">
|
|
@@ -198,21 +198,21 @@
|
|
|
198
198
|
<link rel="modulepreload" crossorigin href="./assets/plus-CExKUszm.js">
|
|
199
199
|
<link rel="modulepreload" crossorigin href="./assets/trash-2-CjPoUZCP.js">
|
|
200
200
|
<link rel="modulepreload" crossorigin href="./assets/react-resizable-panels.browser.esm-CgWOEYeG.js">
|
|
201
|
-
<link rel="modulepreload" crossorigin href="./assets/JsonOutput-
|
|
201
|
+
<link rel="modulepreload" crossorigin href="./assets/JsonOutput-FFLZqPUK.js">
|
|
202
202
|
<link rel="modulepreload" crossorigin href="./assets/chart-no-axes-column-DVEV2j1H.js">
|
|
203
203
|
<link rel="modulepreload" crossorigin href="./assets/square-function-CPbVtjKW.js">
|
|
204
204
|
<link rel="modulepreload" crossorigin href="./assets/spec-BzxoPflZ.js">
|
|
205
|
-
<link rel="modulepreload" crossorigin href="./assets/column-preview-
|
|
205
|
+
<link rel="modulepreload" crossorigin href="./assets/column-preview-oHsVFerC.js">
|
|
206
206
|
<link rel="modulepreload" crossorigin href="./assets/icons-D3YFXNmD.js">
|
|
207
|
-
<link rel="modulepreload" crossorigin href="./assets/radio-group-
|
|
208
|
-
<link rel="modulepreload" crossorigin href="./assets/floating-outline-
|
|
207
|
+
<link rel="modulepreload" crossorigin href="./assets/radio-group-BaOG2bSA.js">
|
|
208
|
+
<link rel="modulepreload" crossorigin href="./assets/floating-outline-3UBj62S1.js">
|
|
209
209
|
<link rel="modulepreload" crossorigin href="./assets/objectWithoutPropertiesLoose-Msf1n32r.js">
|
|
210
210
|
<link rel="modulepreload" crossorigin href="./assets/esm-DSv-aO_T.js">
|
|
211
|
-
<link rel="modulepreload" crossorigin href="./assets/readonly-python-code-
|
|
211
|
+
<link rel="modulepreload" crossorigin href="./assets/readonly-python-code-CNyK8G1T.js">
|
|
212
212
|
<link rel="modulepreload" crossorigin href="./assets/file-headphone-CUN2DC78.js">
|
|
213
213
|
<link rel="modulepreload" crossorigin href="./assets/file-BvoBtS_V.js">
|
|
214
214
|
<link rel="modulepreload" crossorigin href="./assets/image-jhXeQEgs.js">
|
|
215
|
-
<link rel="modulepreload" crossorigin href="./assets/file-icons-
|
|
215
|
+
<link rel="modulepreload" crossorigin href="./assets/file-icons-BeJWUbBH.js">
|
|
216
216
|
<link rel="modulepreload" crossorigin href="./assets/switch-DHhZkGEv.js">
|
|
217
217
|
<link rel="modulepreload" crossorigin href="./assets/events-BRbNg7Li.js">
|
|
218
218
|
<link rel="modulepreload" crossorigin href="./assets/globals-BDWM3c_z.js">
|
|
@@ -221,11 +221,11 @@
|
|
|
221
221
|
<link rel="modulepreload" crossorigin href="./assets/memoize-Tp7rARFe.js">
|
|
222
222
|
<link rel="modulepreload" crossorigin href="./assets/get-C-qh_et5.js">
|
|
223
223
|
<link rel="modulepreload" crossorigin href="./assets/_baseSet-CsW0tABf.js">
|
|
224
|
-
<link rel="modulepreload" crossorigin href="./assets/state-
|
|
224
|
+
<link rel="modulepreload" crossorigin href="./assets/state-DD6m9X2h.js">
|
|
225
225
|
<link rel="modulepreload" crossorigin href="./assets/label-CFvCMYuj.js">
|
|
226
|
-
<link rel="modulepreload" crossorigin href="./assets/textarea-
|
|
226
|
+
<link rel="modulepreload" crossorigin href="./assets/textarea-BM7hAwR3.js">
|
|
227
227
|
<link rel="modulepreload" crossorigin href="./assets/refresh-ccw-CUkO1Vlo.js">
|
|
228
|
-
<link rel="modulepreload" crossorigin href="./assets/form-
|
|
228
|
+
<link rel="modulepreload" crossorigin href="./assets/form-pEJO4Mq_.js">
|
|
229
229
|
<link rel="modulepreload" crossorigin href="./assets/renderShortcut-CKbqJyj4.js">
|
|
230
230
|
<link rel="modulepreload" crossorigin href="./assets/useBoolean-48bgGoSa.js">
|
|
231
231
|
<link rel="modulepreload" crossorigin href="./assets/useDeepCompareMemoize-zUHU--0D.js">
|
|
@@ -247,7 +247,7 @@
|
|
|
247
247
|
<link rel="stylesheet" crossorigin href="./assets/cells-BVzo2MHf.css">
|
|
248
248
|
<link rel="stylesheet" crossorigin href="./assets/markdown-renderer-DdDKmWlR.css">
|
|
249
249
|
<link rel="stylesheet" crossorigin href="./assets/JsonOutput-BQtz7-np.css">
|
|
250
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
250
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CaelsqOA.css">
|
|
251
251
|
</head>
|
|
252
252
|
<body>
|
|
253
253
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import type { RowSelectionState, Table } from "@tanstack/react-table";
|
|
5
5
|
import { useLocale } from "react-aria";
|
|
6
|
+
import { isStaticNotebook } from "@/core/static/static-state";
|
|
6
7
|
import type { GetRowIds } from "@/plugins/impl/DataTablePlugin";
|
|
7
8
|
import { cn } from "@/utils/cn";
|
|
8
9
|
import { Events } from "@/utils/events";
|
|
@@ -40,6 +41,8 @@ export const TableBottomBar = <TData,>({
|
|
|
40
41
|
className,
|
|
41
42
|
}: TableBottomBarProps<TData>) => {
|
|
42
43
|
const { locale } = useLocale();
|
|
44
|
+
// Pagination fetches each page via a kernel RPC, absent in static exports.
|
|
45
|
+
const isStatic = isStaticNotebook();
|
|
43
46
|
const handleSelectAllRows = (value: boolean) => {
|
|
44
47
|
if (!onRowSelectionChange) {
|
|
45
48
|
return;
|
|
@@ -171,7 +174,7 @@ export const TableBottomBar = <TData,>({
|
|
|
171
174
|
<CellSelectionStats table={table} className="lg:hidden" />
|
|
172
175
|
</div>
|
|
173
176
|
<div className="ml-auto lg:ml-0 lg:justify-self-center flex items-center shrink-0">
|
|
174
|
-
{pagination && (
|
|
177
|
+
{pagination && !isStatic && (
|
|
175
178
|
<DataTablePagination
|
|
176
179
|
table={table}
|
|
177
180
|
tableLoading={tableLoading}
|
|
@@ -25,6 +25,7 @@ import { useLocale } from "react-aria";
|
|
|
25
25
|
|
|
26
26
|
import { Button } from "@/components/ui/button";
|
|
27
27
|
import { Table } from "@/components/ui/table";
|
|
28
|
+
import { isStaticNotebook } from "@/core/static/static-state";
|
|
28
29
|
import { Banner } from "@/plugins/impl/common/error-banner";
|
|
29
30
|
import type {
|
|
30
31
|
CalculateTopKRows,
|
|
@@ -182,6 +183,11 @@ const DataTableInternal = <TData,>({
|
|
|
182
183
|
onViewedRowChange,
|
|
183
184
|
renderTableExplorerPanel,
|
|
184
185
|
}: DataTableProps<TData>) => {
|
|
186
|
+
// The top bar's controls (search, filters, column explorer, chart builder)
|
|
187
|
+
// all require a live kernel, which static exports don't have.
|
|
188
|
+
const isStatic = isStaticNotebook();
|
|
189
|
+
const showTableTopBar = !isStatic;
|
|
190
|
+
|
|
185
191
|
const [showLoadingBar, setShowLoadingBar] = React.useState<boolean>(false);
|
|
186
192
|
const { locale } = useLocale();
|
|
187
193
|
|
|
@@ -267,11 +273,12 @@ const DataTableInternal = <TData,>({
|
|
|
267
273
|
}
|
|
268
274
|
: {}),
|
|
269
275
|
manualSorting: manualSorting,
|
|
276
|
+
enableSorting: !isStatic,
|
|
270
277
|
enableMultiSort: true,
|
|
271
278
|
getSortedRowModel: getSortedRowModel(),
|
|
272
279
|
// filtering
|
|
273
280
|
manualFiltering: true,
|
|
274
|
-
enableColumnFilters: showFilters,
|
|
281
|
+
enableColumnFilters: showFilters && !isStatic,
|
|
275
282
|
getFilteredRowModel: getFilteredRowModel(),
|
|
276
283
|
onColumnFiltersChange: onFiltersChange,
|
|
277
284
|
// selection
|
|
@@ -355,22 +362,24 @@ const DataTableInternal = <TData,>({
|
|
|
355
362
|
part="table-wrapper"
|
|
356
363
|
className={cn(className || "rounded-md border overflow-hidden")}
|
|
357
364
|
>
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
365
|
+
{showTableTopBar && (
|
|
366
|
+
<TableTopBar
|
|
367
|
+
table={table}
|
|
368
|
+
showSearch={showSearch}
|
|
369
|
+
searchQuery={searchQuery}
|
|
370
|
+
onSearchQueryChange={onSearchQueryChange}
|
|
371
|
+
reloading={reloading}
|
|
372
|
+
showChartBuilder={showChartBuilder}
|
|
373
|
+
isChartBuilderOpen={isChartBuilderOpen}
|
|
374
|
+
toggleDisplayHeader={toggleDisplayHeader}
|
|
375
|
+
showTableExplorer={showTableExplorer}
|
|
376
|
+
togglePanel={togglePanel}
|
|
377
|
+
isAnyPanelOpen={isAnyPanelOpen}
|
|
378
|
+
downloadAs={downloadAs}
|
|
379
|
+
sizeBytes={sizeBytes}
|
|
380
|
+
sizeBytesIsLoading={sizeBytesIsLoading}
|
|
381
|
+
/>
|
|
382
|
+
)}
|
|
374
383
|
{allUserColumnsHidden && (
|
|
375
384
|
<Banner className="mb-1 mx-2 rounded flex items-center justify-between">
|
|
376
385
|
<span>All columns are hidden.</span>
|
|
@@ -4,6 +4,7 @@ import type { Table } from "@tanstack/react-table";
|
|
|
4
4
|
import type { TableData } from "@/plugins/impl/DataTablePlugin";
|
|
5
5
|
import { vegaLoadData } from "@/plugins/impl/vega/loader";
|
|
6
6
|
import { jsonParseWithSpecialChar } from "@/utils/json/json-parser";
|
|
7
|
+
import { isRecord } from "@/utils/records";
|
|
7
8
|
import { getMimeValues } from "./mime-cell";
|
|
8
9
|
import type { DataType } from "@/core/kernel/messages";
|
|
9
10
|
import {
|
|
@@ -232,10 +233,6 @@ function stripHtml(html: string): string {
|
|
|
232
233
|
|
|
233
234
|
const HTML_MIMETYPES = new Set(["text/html", "text/markdown"]);
|
|
234
235
|
|
|
235
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
236
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
236
|
/**
|
|
240
237
|
* Get clipboard-ready text and optional HTML for a cell.
|
|
241
238
|
*
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
afterEach,
|
|
4
|
+
beforeEach,
|
|
5
|
+
describe,
|
|
6
|
+
expect,
|
|
7
|
+
it,
|
|
8
|
+
type Mock,
|
|
9
|
+
vi,
|
|
10
|
+
} from "vitest";
|
|
3
11
|
import { variableName } from "@/__tests__/branded";
|
|
12
|
+
import * as aiContext from "@/core/ai/context/context";
|
|
4
13
|
import { getCodes } from "@/core/codemirror/copilot/getCodes";
|
|
5
14
|
import { dataSourceConnectionsAtom } from "@/core/datasets/data-source-connections";
|
|
6
15
|
import { DUCKDB_ENGINE } from "@/core/datasets/engines";
|
|
@@ -8,10 +17,11 @@ import { datasetsAtom } from "@/core/datasets/state";
|
|
|
8
17
|
import type { DatasetsState } from "@/core/datasets/types";
|
|
9
18
|
import { store } from "@/core/state/jotai";
|
|
10
19
|
import { variablesAtom } from "@/core/variables/state";
|
|
11
|
-
import type { UIMessage } from "ai";
|
|
20
|
+
import type { FileUIPart, UIMessage } from "ai";
|
|
12
21
|
import {
|
|
13
22
|
codeToCells,
|
|
14
23
|
getAICompletionBody,
|
|
24
|
+
getAICompletionBodyWithAttachments,
|
|
15
25
|
isContextAttachment,
|
|
16
26
|
MARIMO_CONTEXT_PART_TYPE,
|
|
17
27
|
resolveChatContext,
|
|
@@ -440,6 +450,42 @@ describe("isContextAttachment", () => {
|
|
|
440
450
|
});
|
|
441
451
|
});
|
|
442
452
|
|
|
453
|
+
describe("context attachment stamping", () => {
|
|
454
|
+
const rawAttachment: FileUIPart = {
|
|
455
|
+
type: "file",
|
|
456
|
+
mediaType: "image/png",
|
|
457
|
+
url: "data:image/png;base64,abc",
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
beforeEach(() => {
|
|
461
|
+
vi.spyOn(aiContext, "getAIContextRegistry").mockReturnValue({
|
|
462
|
+
parseAllContextIds: () => ["data://t1"],
|
|
463
|
+
formatContextForAI: () => '<data name="t1" />',
|
|
464
|
+
getAttachmentsForContext: async () => [rawAttachment],
|
|
465
|
+
} as unknown as ReturnType<typeof aiContext.getAIContextRegistry>);
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
afterEach(() => {
|
|
469
|
+
vi.restoreAllMocks();
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it("stamps chat attachments as context-derived", async () => {
|
|
473
|
+
const { attachments } = await resolveChatContext("see @data://t1");
|
|
474
|
+
expect(attachments).toHaveLength(1);
|
|
475
|
+
expect(isContextAttachment(attachments[0])).toBe(true);
|
|
476
|
+
// The original attachment is left untouched (we return a stamped copy).
|
|
477
|
+
expect(rawAttachment.providerMetadata).toBeUndefined();
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
it("stamps completion attachments the same way as chat", async () => {
|
|
481
|
+
const { attachments } = await getAICompletionBodyWithAttachments({
|
|
482
|
+
input: "see @data://t1",
|
|
483
|
+
});
|
|
484
|
+
expect(attachments).toHaveLength(1);
|
|
485
|
+
expect(isContextAttachment(attachments[0])).toBe(true);
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
|
|
443
489
|
describe("codeToCells", () => {
|
|
444
490
|
it("should return empty array for empty string", () => {
|
|
445
491
|
const code = "";
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
import type { ReactCodeMirrorRef } from "@uiw/react-codemirror";
|
|
10
10
|
import type { DataUIPart, FileUIPart, UIMessage } from "ai";
|
|
11
11
|
import { getAIContextRegistry } from "@/core/ai/context/context";
|
|
12
|
+
import type { ContextLocatorId } from "@/core/ai/context/registry";
|
|
12
13
|
import { getCodes } from "@/core/codemirror/copilot/getCodes";
|
|
13
14
|
import type { LanguageAdapterType } from "@/core/codemirror/language/types";
|
|
14
15
|
import type { AiCompletionRequest } from "@/core/network/types";
|
|
@@ -89,20 +90,51 @@ export function isContextAttachment(part: UIMessage["parts"][number]): boolean {
|
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
93
|
+
* Stamp a context-derived attachment with a provenance marker.
|
|
94
|
+
*
|
|
95
|
+
* Some @-mentions resolve to file attachments (e.g. a cell's image output),
|
|
96
|
+
* which get appended to the user message right alongside files the user
|
|
97
|
+
* uploaded by hand. Once they're in the message the two are indistinguishable,
|
|
98
|
+
* so we mark the context-derived ones. This matters on message edit: we
|
|
99
|
+
* re-resolve context from the edited text, and `isContextAttachment` lets us
|
|
100
|
+
* drop only the stale context attachments while preserving the user's own
|
|
101
|
+
* uploads
|
|
94
102
|
*/
|
|
95
|
-
|
|
103
|
+
function stampContextAttachment(attachment: FileUIPart): FileUIPart {
|
|
104
|
+
return {
|
|
105
|
+
...attachment,
|
|
106
|
+
providerMetadata: {
|
|
107
|
+
...attachment.providerMetadata,
|
|
108
|
+
// Merge within the `marimo` namespace so we don't clobber any other
|
|
109
|
+
// marimo metadata a provider may have already set.
|
|
110
|
+
marimo: {
|
|
111
|
+
...attachment.providerMetadata?.marimo,
|
|
112
|
+
...CONTEXT_ATTACHMENT_METADATA.marimo,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
interface ResolvedContext {
|
|
119
|
+
plainText: string;
|
|
120
|
+
contextIds: ContextLocatorId[];
|
|
121
|
+
attachments: FileUIPart[];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Parse @-context for messages
|
|
126
|
+
*/
|
|
127
|
+
async function resolveContextAttachments(
|
|
96
128
|
input: string,
|
|
97
|
-
): Promise<
|
|
129
|
+
): Promise<ResolvedContext> {
|
|
98
130
|
if (!input.includes(CONTEXT_TRIGGER)) {
|
|
99
|
-
return {
|
|
131
|
+
return { plainText: "", contextIds: [], attachments: [] };
|
|
100
132
|
}
|
|
101
133
|
|
|
102
134
|
const registry = getAIContextRegistry(store);
|
|
103
135
|
const contextIds = registry.parseAllContextIds(input);
|
|
104
136
|
if (contextIds.length === 0) {
|
|
105
|
-
return {
|
|
137
|
+
return { plainText: "", contextIds: [], attachments: [] };
|
|
106
138
|
}
|
|
107
139
|
|
|
108
140
|
const plainText = registry.formatContextForAI(contextIds);
|
|
@@ -110,20 +142,24 @@ export async function resolveChatContext(
|
|
|
110
142
|
let attachments: FileUIPart[] = [];
|
|
111
143
|
try {
|
|
112
144
|
const resolved = await registry.getAttachmentsForContext(contextIds);
|
|
113
|
-
attachments = resolved.map(
|
|
114
|
-
...attachment,
|
|
115
|
-
providerMetadata: {
|
|
116
|
-
...attachment.providerMetadata,
|
|
117
|
-
marimo: {
|
|
118
|
-
...attachment.providerMetadata?.marimo,
|
|
119
|
-
...CONTEXT_ATTACHMENT_METADATA.marimo,
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
}));
|
|
145
|
+
attachments = resolved.map(stampContextAttachment);
|
|
123
146
|
} catch (error) {
|
|
124
147
|
Logger.error("Error getting attachments:", error);
|
|
125
148
|
}
|
|
126
149
|
|
|
150
|
+
return { plainText, contextIds, attachments };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Resolve @-context for messages. They represent referenced
|
|
155
|
+
* datasets, variables, or other context from the user's prompt.
|
|
156
|
+
*/
|
|
157
|
+
export async function resolveChatContext(
|
|
158
|
+
input: string,
|
|
159
|
+
): Promise<ResolvedChatContext> {
|
|
160
|
+
const { plainText, contextIds, attachments } =
|
|
161
|
+
await resolveContextAttachments(input);
|
|
162
|
+
|
|
127
163
|
let contextPart: MarimoContextUIPart | null = null;
|
|
128
164
|
if (plainText.trim()) {
|
|
129
165
|
contextPart = {
|
|
@@ -141,31 +177,13 @@ export async function resolveChatContext(
|
|
|
141
177
|
export async function getAICompletionBodyWithAttachments({
|
|
142
178
|
input,
|
|
143
179
|
}: Opts): Promise<AICompletionBodyWithAttachments> {
|
|
144
|
-
|
|
145
|
-
let attachments: FileUIPart[] = [];
|
|
146
|
-
|
|
147
|
-
// Skip if no '@' in the input
|
|
148
|
-
if (input.includes("@")) {
|
|
149
|
-
const registry = getAIContextRegistry(store);
|
|
150
|
-
const contextIds = registry.parseAllContextIds(input);
|
|
151
|
-
|
|
152
|
-
// Get context string
|
|
153
|
-
contextString = registry.formatContextForAI(contextIds);
|
|
154
|
-
|
|
155
|
-
// Get attachments
|
|
156
|
-
try {
|
|
157
|
-
attachments = await registry.getAttachmentsForContext(contextIds);
|
|
158
|
-
Logger.debug("Included attachments", attachments.length);
|
|
159
|
-
} catch (error) {
|
|
160
|
-
Logger.error("Error getting attachments:", error);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
180
|
+
const { plainText, attachments } = await resolveContextAttachments(input);
|
|
163
181
|
|
|
164
182
|
return {
|
|
165
183
|
body: {
|
|
166
184
|
includeOtherCode: getCodes(""),
|
|
167
185
|
context: {
|
|
168
|
-
plainText
|
|
186
|
+
plainText,
|
|
169
187
|
schema: [],
|
|
170
188
|
variables: [],
|
|
171
189
|
},
|
|
@@ -48,7 +48,9 @@ export const AppContainer: React.FC<PropsWithChildren<Props>> = ({
|
|
|
48
48
|
"bg-background w-full h-full text-textColor",
|
|
49
49
|
"flex flex-col overflow-y-auto",
|
|
50
50
|
width === "full" && "config-width-full",
|
|
51
|
-
width === "columns"
|
|
51
|
+
width === "columns"
|
|
52
|
+
? "overflow-x-auto"
|
|
53
|
+
: "overflow-x-auto sm:overflow-x-hidden",
|
|
52
54
|
"print:height-fit",
|
|
53
55
|
)}
|
|
54
56
|
>
|
|
@@ -5,8 +5,8 @@ import type { JSX } from "react";
|
|
|
5
5
|
interface Props {
|
|
6
6
|
src: string;
|
|
7
7
|
alt?: string;
|
|
8
|
-
width?: number;
|
|
9
|
-
height?: number;
|
|
8
|
+
width?: number | string;
|
|
9
|
+
height?: number | string;
|
|
10
10
|
className?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -17,9 +17,18 @@ export const ImageOutput = ({
|
|
|
17
17
|
height,
|
|
18
18
|
className,
|
|
19
19
|
}: Props): JSX.Element => {
|
|
20
|
+
// Convert numeric values to pixel strings, pass string values (like "100%") as-is
|
|
21
|
+
const style: React.CSSProperties = {};
|
|
22
|
+
if (width !== undefined) {
|
|
23
|
+
style.width = typeof width === "number" ? `${width}px` : width;
|
|
24
|
+
}
|
|
25
|
+
if (height !== undefined) {
|
|
26
|
+
style.height = typeof height === "number" ? `${height}px` : height;
|
|
27
|
+
}
|
|
28
|
+
|
|
20
29
|
return (
|
|
21
30
|
<span className={className}>
|
|
22
|
-
<img src={src} alt={alt}
|
|
31
|
+
<img src={src} alt={alt} style={style} />
|
|
23
32
|
</span>
|
|
24
33
|
);
|
|
25
34
|
};
|
|
@@ -32,9 +32,9 @@ export const VerticalLayoutWrapper: React.FC<PropsWithChildren<Props>> = ({
|
|
|
32
32
|
// This padding needs to be the same from above to be correctly applied
|
|
33
33
|
"pb-24 sm:pb-12",
|
|
34
34
|
appConfig.width === "compact" &&
|
|
35
|
-
"max-w-(--content-width) min-w-[400px]",
|
|
35
|
+
"max-w-(--content-width) sm:min-w-[400px]",
|
|
36
36
|
appConfig.width === "medium" &&
|
|
37
|
-
"max-w-(--content-width-medium) min-w-[400px]",
|
|
37
|
+
"max-w-(--content-width-medium) sm:min-w-[400px]",
|
|
38
38
|
appConfig.width === "columns" && "w-fit",
|
|
39
39
|
appConfig.width === "full" && "max-w-full",
|
|
40
40
|
// Hide the cells for a fake loading effect, to avoid flickering
|
|
@@ -253,6 +253,73 @@ a = 10`;
|
|
|
253
253
|
`);
|
|
254
254
|
});
|
|
255
255
|
|
|
256
|
+
test("from-import alias is the binding, not the imported name", async () => {
|
|
257
|
+
const code = `\
|
|
258
|
+
from math import sin as my_sin
|
|
259
|
+
print(my_sin)`;
|
|
260
|
+
view = createEditor(code);
|
|
261
|
+
const usagePosition = code.lastIndexOf("my_sin");
|
|
262
|
+
const result = goToVariableDefinition(view, "my_sin", usagePosition);
|
|
263
|
+
|
|
264
|
+
expect(result).toBe(true);
|
|
265
|
+
await tick();
|
|
266
|
+
// The alias `my_sin` (after `as`) is the real binding.
|
|
267
|
+
expect(renderEditorView(view)).toMatchInlineSnapshot(`
|
|
268
|
+
"
|
|
269
|
+
from math import sin as my_sin
|
|
270
|
+
^
|
|
271
|
+
print(my_sin)
|
|
272
|
+
"
|
|
273
|
+
`);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
test("module path in from-import is not a local definition", async () => {
|
|
277
|
+
const code = `\
|
|
278
|
+
from math import sin
|
|
279
|
+
print(math)`;
|
|
280
|
+
view = createEditor(code);
|
|
281
|
+
const usagePosition = code.lastIndexOf("math");
|
|
282
|
+
// `math` is a module reference in the from-clause, not a binding in this
|
|
283
|
+
// cell, so the scoped resolver should return false and let the caller fall
|
|
284
|
+
// through to cross-cell resolution.
|
|
285
|
+
const result = goToVariableDefinition(view, "math", usagePosition);
|
|
286
|
+
|
|
287
|
+
expect(result).toBe(false);
|
|
288
|
+
expect(view.state.selection.main.head).toBe(0);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
test("imported name without `as` is a local definition", async () => {
|
|
292
|
+
const code = `\
|
|
293
|
+
from math import sin
|
|
294
|
+
print(sin)`;
|
|
295
|
+
view = createEditor(code);
|
|
296
|
+
const usagePosition = code.lastIndexOf("sin");
|
|
297
|
+
const result = goToVariableDefinition(view, "sin", usagePosition);
|
|
298
|
+
|
|
299
|
+
expect(result).toBe(true);
|
|
300
|
+
await tick();
|
|
301
|
+
expect(renderEditorView(view)).toMatchInlineSnapshot(`
|
|
302
|
+
"
|
|
303
|
+
from math import sin
|
|
304
|
+
^
|
|
305
|
+
print(sin)
|
|
306
|
+
"
|
|
307
|
+
`);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
test("imported name shadowed by `as` is not a binding", async () => {
|
|
311
|
+
const code = `\
|
|
312
|
+
from math import sin as my_sin
|
|
313
|
+
print(sin)`;
|
|
314
|
+
view = createEditor(code);
|
|
315
|
+
const usagePosition = code.lastIndexOf("sin");
|
|
316
|
+
// `sin` here refers to nothing in this cell (it was renamed to `my_sin`),
|
|
317
|
+
// so the scoped resolver should return false.
|
|
318
|
+
const result = goToVariableDefinition(view, "sin", usagePosition);
|
|
319
|
+
|
|
320
|
+
expect(result).toBe(false);
|
|
321
|
+
});
|
|
322
|
+
|
|
256
323
|
test("selects outer-scope function declaration", async () => {
|
|
257
324
|
view = createEditor(`\
|
|
258
325
|
def x():
|
|
@@ -133,4 +133,51 @@ output = _x + 10`;
|
|
|
133
133
|
await tick();
|
|
134
134
|
expect(view.state.selection.main.head).toBe(code.indexOf("_x = 10"));
|
|
135
135
|
});
|
|
136
|
+
|
|
137
|
+
test("falls through to cross-cell when in-cell occurrence is only a module path in a from-import", async () => {
|
|
138
|
+
// Regression: ImportStatement used to register every VariableName child
|
|
139
|
+
// (the module path and pre-`as` names) as in-cell declarations, so the
|
|
140
|
+
// local-first short-circuit would steal F12 from cross-cell resolution.
|
|
141
|
+
const moduleCell = cellId("module-cell");
|
|
142
|
+
const usageCell = cellId("usage-cell");
|
|
143
|
+
const moduleCode = `mymodule = 100`;
|
|
144
|
+
const usageCode = `\
|
|
145
|
+
from mymodule import something
|
|
146
|
+
print(mymodule)`;
|
|
147
|
+
|
|
148
|
+
const moduleView = createEditor(moduleCode, moduleCode.length);
|
|
149
|
+
const usageView = createEditor(
|
|
150
|
+
usageCode,
|
|
151
|
+
usageCode.lastIndexOf("mymodule"),
|
|
152
|
+
);
|
|
153
|
+
views.push(moduleView, usageView);
|
|
154
|
+
|
|
155
|
+
const notebook = initialNotebookState();
|
|
156
|
+
notebook.cellHandles[moduleCell] = {
|
|
157
|
+
current: { editorView: moduleView, editorViewOrNull: moduleView },
|
|
158
|
+
} as never;
|
|
159
|
+
notebook.cellHandles[usageCell] = {
|
|
160
|
+
current: { editorView: usageView, editorViewOrNull: usageView },
|
|
161
|
+
} as never;
|
|
162
|
+
|
|
163
|
+
store.set(notebookAtom, notebook);
|
|
164
|
+
store.set(variablesAtom, {
|
|
165
|
+
[variableName("mymodule")]: {
|
|
166
|
+
dataType: "int",
|
|
167
|
+
declaredBy: [moduleCell],
|
|
168
|
+
name: variableName("mymodule"),
|
|
169
|
+
usedBy: [usageCell],
|
|
170
|
+
value: "100",
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const result = goToDefinitionAtCursorPosition(usageView);
|
|
175
|
+
|
|
176
|
+
expect(result).toBe(true);
|
|
177
|
+
await tick();
|
|
178
|
+
// Cross-cell jump: moduleView's cursor should land on `mymodule = 100`.
|
|
179
|
+
expect(moduleView.state.selection.main.head).toBe(
|
|
180
|
+
moduleCode.indexOf("mymodule"),
|
|
181
|
+
);
|
|
182
|
+
});
|
|
136
183
|
});
|