@marimo-team/frontend 0.22.5-dev2 → 0.22.5-dev21
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-HZQ0Twqj.js → CellStatus-CP1jrQ3A.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-C9jSHm_Y.js → ConnectedDataExplorerComponent-CfU-ThkK.js} +1 -1
- package/dist/assets/{ImperativeModal-Ka_MU6gk.js → ImperativeModal-DoGv2BXV.js} +1 -1
- package/dist/assets/JsonOutput-Bk2by9qo.js +49 -0
- package/dist/assets/{LazyAnyLanguageCodeMirror-Bb2dITRz.js → LazyAnyLanguageCodeMirror-CoYqQxHb.js} +2 -2
- package/dist/assets/MarimoErrorOutput-Cyd8ikG3.js +7 -0
- package/dist/assets/RSPContexts-LWFBF00h.js +1 -0
- package/dist/assets/{RenderHTML-Cyj8OBbz.js → RenderHTML-BOW_1WUn.js} +1 -1
- package/dist/assets/{add-cell-with-ai-BccDsMLb.js → add-cell-with-ai-DUq7Y523.js} +9 -9
- package/dist/assets/{add-connection-dialog-BO_nxLQi.js → add-connection-dialog-20N0EHLl.js} +1 -1
- package/dist/assets/{agent-panel-BMTl3Cgd.js → agent-panel-DEza5aFa.js} +3 -3
- package/dist/assets/{ai-model-dropdown-CS5ryevV.js → ai-model-dropdown-B-sbS07W.js} +4 -4
- package/dist/assets/{any-language-editor-BKxF_o5k.js → any-language-editor-DYgTL8eG.js} +1 -1
- package/dist/assets/app-config-button-CJFpYJ_2.js +1 -0
- package/dist/assets/{cache-panel-PA0cVzei.js → cache-panel-8E_Y5OSb.js} +1 -1
- package/dist/assets/{cell-editor-qLPKK49y.js → cell-editor-DLL6kX__.js} +11 -11
- package/dist/assets/{cell-link-CY7i_e4O.js → cell-link-Dtonmtv_.js} +1 -1
- package/dist/assets/{cells-CuaAKcwV.js → cells-BVG4a-Qn.js} +42 -42
- package/dist/assets/{chat-display-BLYrUQhO.js → chat-display-DsIGz-Wy.js} +1 -1
- package/dist/assets/{chat-panel-w9jaKRAD.js → chat-panel-aXOgktdv.js} +2 -2
- package/dist/assets/{chat-ui-BqpUGrwS.js → chat-ui-C--RApyx.js} +4 -4
- package/dist/assets/{column-preview-Dk6-wUK-.js → column-preview-CB_HZPdz.js} +1 -1
- package/dist/assets/{command-DkwDd6Ey.js → command-DvF_4mQa.js} +1 -1
- package/dist/assets/{command-palette-C0hZrhup.js → command-palette-DLKNdcX_.js} +1 -1
- package/dist/assets/{common-CL1iSwod.js → common-CLVI2BhO.js} +1 -1
- package/dist/assets/{components-CBihADZo.js → components-CGwwQ0Y4.js} +1 -1
- package/dist/assets/{components-CtOW1DR4.js → components-DiALLQRt.js} +1 -1
- package/dist/assets/{copy-icon-n6r2uyq3.js → copy-icon-BGs1Pbai.js} +1 -1
- package/dist/assets/{datasource-DwmhT5-D.js → datasource-BzTPyEw3.js} +1 -1
- package/dist/assets/{dependency-graph-panel-3AdEtWPZ.js → dependency-graph-panel-Pxmnzmd4.js} +1 -1
- package/dist/assets/{diagram-PSM6KHXK-D6nw8Fvd.js → diagram-PSM6KHXK-UdiW7QQb.js} +1 -1
- package/dist/assets/{documentation-panel-CVIUk8ga.js → documentation-panel-bgaPBvan.js} +1 -1
- package/dist/assets/{download-pkTDt-sj.js → download-QIfZjflb.js} +3 -3
- package/dist/assets/{edit-page-6Fpl3Fez.js → edit-page-DB_go-vo.js} +7 -7
- package/dist/assets/{error-banner-Bfe6BopK.js → error-banner-bXc_9BBZ.js} +1 -1
- package/dist/assets/{error-panel-Cy3_isDL.js → error-panel-DfHzC7q-.js} +1 -1
- package/dist/assets/{field-CXDGiU3T.js → field-DTzXkFLZ.js} +1 -1
- package/dist/assets/{file-explorer-panel-qM-Iflzm.js → file-explorer-panel-CEd-m832.js} +3 -3
- package/dist/assets/{file-icons-DaGma7HH.js → file-icons-ma7AC7Pi.js} +1 -1
- package/dist/assets/{floating-outline-oPCmn9_F.js → floating-outline-BluCz3vD.js} +1 -1
- package/dist/assets/{focus-B524Cy57.js → focus-BHXzPxK_.js} +1 -1
- package/dist/assets/{form-IHIhviLb.js → form-C0W8wa3f.js} +1 -1
- package/dist/assets/{formats-DC_7w22O.js → formats-BQHP_yQk.js} +1 -1
- package/dist/assets/{formatting-Dw_0ktP1.js → formatting-BCAZDWQ0.js} +1 -1
- package/dist/assets/{gallery-page-DCkpFwYi.js → gallery-page-XSrY7bw_.js} +1 -1
- package/dist/assets/{ganttDiagram-JELNMOA3-BC4H0xrj.js → ganttDiagram-JELNMOA3-KWj06bYC.js} +1 -1
- package/dist/assets/{glide-data-editor-BkvzN8Tk.js → glide-data-editor-Bd4FOxvW.js} +1 -1
- package/dist/assets/{home-page-bB7oHRxE.js → home-page-nNrKA7jH.js} +2 -2
- package/dist/assets/{hooks-DmeHnl8J.js → hooks-C7qnb_ft.js} +1 -1
- package/dist/assets/{html-to-image-C-c-Hfuw.js → html-to-image-B3VySJ1_.js} +1 -1
- package/dist/assets/index-CLnKZIHZ.js +42 -0
- package/dist/assets/index-DBs2il8a.css +2 -0
- package/dist/assets/input-Bg12i6qY.js +1 -0
- package/dist/assets/{kiosk-mode-CnJjuo6B.js → kiosk-mode-BSY8y4kL.js} +1 -1
- package/dist/assets/{layout-Ce-vzLs_.js → layout-V4eTNc4M.js} +3 -3
- package/dist/assets/{linear-bY7qDnP9.js → linear-BICTUQLW.js} +1 -1
- package/dist/assets/{logs-panel-CzlMq5La.js → logs-panel-B1AysC8S.js} +1 -1
- package/dist/assets/{markdown-renderer-B4-BiMy9.js → markdown-renderer-BiKTlki_.js} +1 -1
- package/dist/assets/{mermaid-DDNZ06H7.js → mermaid-BJFSZcG6.js} +3 -3
- package/dist/assets/{name-cell-input-CUG9-cgv.js → name-cell-input-BA5B0KJl.js} +1 -1
- package/dist/assets/{outline-panel-BXefyCJ4.js → outline-panel-BfGPA_Sj.js} +1 -1
- package/dist/assets/{packages-panel-Bc42thuF.js → packages-panel-BgoT3rrV.js} +1 -1
- package/dist/assets/{panels-xqtEg2DV.js → panels-BeW4RaML.js} +1 -1
- package/dist/assets/{pieDiagram-ADFJNKIX-BeLuFsHa.js → pieDiagram-ADFJNKIX-ixj1Ihpk.js} +1 -1
- package/dist/assets/{precisionRound-D8yxZYIF.js → precisionRound-CU2C3Vxx.js} +1 -1
- package/dist/assets/{process-output-C-VBRULx.js → process-output-MnxG8jwi.js} +1 -1
- package/dist/assets/{quadrantDiagram-AYHSOK5B-7-MiutmN.js → quadrantDiagram-AYHSOK5B-DAgQxEHI.js} +1 -1
- package/dist/assets/{react-vega-LNfJwi6n.js → react-vega-BVBnH7ue.js} +1 -1
- package/dist/assets/react-vega-BfEZWy9T.js +1 -0
- package/dist/assets/{readonly-python-code-DinZuT8P.js → readonly-python-code-DuH_nOq_.js} +1 -1
- package/dist/assets/{run-page-GmVLTzzU.js → run-page-kI3bwb2R.js} +1 -1
- package/dist/assets/{sankeyDiagram-TZEHDZUN-DuPJkvrj.js → sankeyDiagram-TZEHDZUN-DAWWzAvZ.js} +1 -1
- package/dist/assets/{scratchpad-panel-CnzHN40A.js → scratchpad-panel-617FvSKA.js} +1 -1
- package/dist/assets/{secrets-panel-DxBoNgTM.js → secrets-panel-C6X5jB8Q.js} +1 -1
- package/dist/assets/{session-panel-CpeJADG_.js → session-panel-D6Sf5vhq.js} +1 -1
- package/dist/assets/snippets-panel-DfWq0wh2.js +1 -0
- package/dist/assets/{state-9-n7I_Bo.js → state-BgrGQPFs.js} +1 -1
- package/dist/assets/{state-DuVk71Dw.js → state-Blw6taKi.js} +1 -1
- package/dist/assets/{state-oW8A8maF.js → state-urfwd716.js} +2 -2
- package/dist/assets/{terminal-bXHNLBHU.js → terminal-BBTjIXBz.js} +3 -3
- package/dist/assets/{textarea-CI3yaazO.js → textarea-B5p9_myy.js} +1 -1
- package/dist/assets/{time-BdrzW2P6.js → time-DLcLlk0u.js} +1 -1
- package/dist/assets/{tracing-BRo4IXxX.js → tracing-CazNvlp4.js} +1 -1
- package/dist/assets/{tracing-panel-7QrwywKQ.js → tracing-panel-Bj0Bx8ZJ.js} +2 -2
- package/dist/assets/{useAddCell-BMYemCZ-.js → useAddCell-g3zSMJKs.js} +1 -1
- package/dist/assets/{useAsyncData-CaAFMbY9.js → useAsyncData-aCoWDe-l.js} +1 -1
- package/dist/assets/useBoolean-ugd5JdXd.js +1 -0
- package/dist/assets/{useCellActionButton-DMySRby1.js → useCellActionButton-DdsVswP2.js} +1 -1
- package/dist/assets/{useDateFormatter-BBQkEV05.js → useDateFormatter-BEz9SEXo.js} +1 -1
- package/dist/assets/{useDeleteCell-6SLN_jZa.js → useDeleteCell-CIdiI4Pk.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-DRoK7Mvg.js → useDependencyPanelTab-DhXqfAqL.js} +1 -1
- package/dist/assets/{useNotebookActions-SGiWvk1I.js → useNotebookActions-ULfiGMMl.js} +1 -1
- package/dist/assets/{useNumberFormatter-DIM21HH4.js → useNumberFormatter-wQU1z0W_.js} +1 -1
- package/dist/assets/{usePress-CLNv4Iws.js → usePress-BXMIcLWP.js} +3 -3
- package/dist/assets/{useRunCells-a5YC9YVQ.js → useRunCells-q5CA-QoL.js} +1 -1
- package/dist/assets/{useSplitCell-Dn4N4Evl.js → useSplitCell-B0jDwUEM.js} +1 -1
- package/dist/assets/{utils-BaSt_0sN.js → utils-BZwMGX81.js} +1 -1
- package/dist/assets/{vega-component-B_GT243z.js → vega-component-B2_J2GQq.js} +1 -1
- package/dist/assets/{vega-loader.browser-DLukqq1q.js → vega-loader.browser-DXARUlxo.js} +1 -1
- package/dist/assets/{write-secret-modal-C87c9nwO.js → write-secret-modal-CHfFN0H8.js} +1 -1
- package/dist/assets/{xychartDiagram-PRI3JC2R-BRVF_pwk.js → xychartDiagram-PRI3JC2R-DgjhbmH4.js} +1 -1
- package/dist/index.html +52 -51
- package/package.json +2 -2
- package/src/components/data-table/__tests__/columns.test.tsx +92 -13
- package/src/components/data-table/column-header.tsx +81 -56
- package/src/components/data-table/columns.tsx +25 -32
- package/src/components/data-table/data-table.tsx +8 -1
- package/src/components/data-table/renderers.tsx +19 -6
- package/src/components/data-table/types.ts +4 -0
- package/src/components/editor/errors/traceback-modal.tsx +6 -5
- package/src/components/editor/output/MarimoErrorOutput.tsx +7 -14
- package/src/components/editor/output/MarimoTracebackOutput.tsx +4 -3
- package/src/core/cells/document-changes.ts +12 -0
- package/src/core/saving/file-state.ts +16 -0
- package/src/hooks/useAsyncData.ts +1 -1
- package/src/mount.tsx +17 -1
- package/src/plugins/impl/DataTablePlugin.tsx +1 -1
- package/src/plugins/impl/plotly/__tests__/selection.test.ts +22 -0
- package/src/plugins/impl/plotly/selection.ts +1 -0
- package/dist/assets/JsonOutput-C0_rp6zm.js +0 -49
- package/dist/assets/MarimoErrorOutput-C3-dwG-M.js +0 -7
- package/dist/assets/VisuallyHidden-CuyBIaeU.js +0 -1
- package/dist/assets/app-config-button-2bbgrHC2.js +0 -1
- package/dist/assets/index-B2hkIK4p.js +0 -42
- package/dist/assets/index-BNN_F0CC.css +0 -2
- package/dist/assets/input-DfDSaPYh.js +0 -1
- package/dist/assets/react-vega-Bpff0f7C.js +0 -1
- package/dist/assets/snippets-panel-Z3fr4trp.js +0 -1
- package/dist/assets/useBoolean-Dsw5twOt.js +0 -1
- /package/dist/assets/{blob-Brr8JjWU.js → blob-CTort_or.js} +0 -0
- /package/dist/assets/{context-BoP98Msj.js → context-DGqo1TbK.js} +0 -0
- /package/dist/assets/{copy-Acb9G8ns.js → copy-Bizk-4hH.js} +0 -0
- /package/dist/assets/{defaultLocale-B8Omxjnr.js → defaultLocale-BLne0bXb.js} +0 -0
- /package/dist/assets/{defaultLocale-Cyhs3Xd2.js → defaultLocale-JieDVWC_.js} +0 -0
- /package/dist/assets/{dialog-Do1NuJPs.js → dialog-BYjetQgE.js} +0 -0
- /package/dist/assets/{errors-Dn17Z1-5.js → errors-CZb6hI2x.js} +0 -0
- /package/dist/assets/{numbers--q6KLqqK.js → numbers--nDjbAPa.js} +0 -0
- /package/dist/assets/{ordinal-CN_bk_zt.js → ordinal-DuTuuUgV.js} +0 -0
- /package/dist/assets/{range-BmYMHsC2.js → range-1DwpgXvM.js} +0 -0
- /package/dist/assets/{react-icons.esm-3sYgjjif.js → react-icons.esm-BUYTQ32a.js} +0 -0
- /package/dist/assets/{share-CkOka71S.js → share-0LPgOyiW.js} +0 -0
- /package/dist/assets/{useHotkey-CX3-tpiy.js → useHotkey-DALUNe8I.js} +0 -0
|
@@ -206,41 +206,30 @@ export function generateColumns<T>({
|
|
|
206
206
|
</div>
|
|
207
207
|
) : null;
|
|
208
208
|
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
const headerWithType = (
|
|
212
|
-
<div
|
|
209
|
+
const headerName = (
|
|
210
|
+
<span
|
|
213
211
|
className={cn(
|
|
214
|
-
"
|
|
215
|
-
|
|
216
|
-
justify === "right" && "items-end",
|
|
212
|
+
"font-bold",
|
|
213
|
+
headerTitle && "underline decoration-dotted",
|
|
217
214
|
)}
|
|
218
215
|
>
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
"font-bold",
|
|
222
|
-
headerTitle && "underline decoration-dotted",
|
|
223
|
-
)}
|
|
224
|
-
>
|
|
225
|
-
{key === "" ? " " : key}
|
|
226
|
-
</span>
|
|
227
|
-
{dtypeHeader}
|
|
228
|
-
</div>
|
|
216
|
+
{key === "" ? " " : key}
|
|
217
|
+
</span>
|
|
229
218
|
);
|
|
230
219
|
|
|
231
220
|
const headerWithTooltip = headerTitle ? (
|
|
232
221
|
<Tooltip content={headerTitle} delayDuration={300}>
|
|
233
|
-
{
|
|
222
|
+
{headerName}
|
|
234
223
|
</Tooltip>
|
|
235
224
|
) : (
|
|
236
|
-
|
|
225
|
+
headerName
|
|
237
226
|
);
|
|
238
227
|
|
|
239
228
|
const dataTableColumnHeader = (
|
|
240
229
|
<DataTableColumnHeader
|
|
241
230
|
header={headerWithTooltip}
|
|
231
|
+
subheader={dtypeHeader}
|
|
242
232
|
column={column}
|
|
243
|
-
justify={justify}
|
|
244
233
|
calculateTopKRows={calculateTopKRows}
|
|
245
234
|
table={table}
|
|
246
235
|
/>
|
|
@@ -255,8 +244,6 @@ export function generateColumns<T>({
|
|
|
255
244
|
<div
|
|
256
245
|
className={cn(
|
|
257
246
|
"flex flex-col h-full pt-0.5 pb-3 justify-between items-start",
|
|
258
|
-
justify === "center" && "items-center",
|
|
259
|
-
justify === "right" && "items-end",
|
|
260
247
|
)}
|
|
261
248
|
>
|
|
262
249
|
{dataTableColumnHeader}
|
|
@@ -283,13 +270,13 @@ export function generateColumns<T>({
|
|
|
283
270
|
|
|
284
271
|
const dataType = column.columnDef.meta?.dataType;
|
|
285
272
|
const isNumeric = dataType === "number" || dataType === "integer";
|
|
286
|
-
const cellStyles = getCellStyleClass(
|
|
273
|
+
const cellStyles = getCellStyleClass({
|
|
287
274
|
justify,
|
|
288
275
|
wrapped,
|
|
289
276
|
canSelectCell,
|
|
290
|
-
isCellSelected,
|
|
277
|
+
isSelected: isCellSelected,
|
|
291
278
|
isNumeric,
|
|
292
|
-
);
|
|
279
|
+
});
|
|
293
280
|
|
|
294
281
|
const renderedCell = renderCellValue({
|
|
295
282
|
column,
|
|
@@ -448,13 +435,19 @@ function getFilterTypeForFieldType(
|
|
|
448
435
|
}
|
|
449
436
|
}
|
|
450
437
|
|
|
451
|
-
function getCellStyleClass(
|
|
452
|
-
justify
|
|
453
|
-
wrapped
|
|
454
|
-
canSelectCell
|
|
455
|
-
isSelected
|
|
456
|
-
isNumeric
|
|
457
|
-
|
|
438
|
+
function getCellStyleClass({
|
|
439
|
+
justify = "left",
|
|
440
|
+
wrapped,
|
|
441
|
+
canSelectCell,
|
|
442
|
+
isSelected,
|
|
443
|
+
isNumeric = false,
|
|
444
|
+
}: {
|
|
445
|
+
justify: "left" | "center" | "right" | undefined;
|
|
446
|
+
wrapped: boolean | undefined;
|
|
447
|
+
canSelectCell: boolean;
|
|
448
|
+
isSelected: boolean;
|
|
449
|
+
isNumeric?: boolean;
|
|
450
|
+
}): string {
|
|
458
451
|
return cn(
|
|
459
452
|
canSelectCell && "cursor-pointer",
|
|
460
453
|
isSelected &&
|
|
@@ -47,6 +47,7 @@ import { DataTableBody, renderTableHeader } from "./renderers";
|
|
|
47
47
|
import { TableBottomBar } from "./TableBottomBar";
|
|
48
48
|
import { TableTopBar } from "./TableTopBar";
|
|
49
49
|
import {
|
|
50
|
+
AUTO_WIDTH_MAX_COLUMNS,
|
|
50
51
|
type DataTableSelection,
|
|
51
52
|
MIN_ROWS_TO_VIRTUALIZE,
|
|
52
53
|
type TooManyRows,
|
|
@@ -300,7 +301,13 @@ const DataTableInternal = <TData,>({
|
|
|
300
301
|
isAnyPanelOpen={isAnyPanelOpen}
|
|
301
302
|
downloadAs={downloadAs}
|
|
302
303
|
/>
|
|
303
|
-
<Table
|
|
304
|
+
<Table
|
|
305
|
+
className={cn(
|
|
306
|
+
"relative",
|
|
307
|
+
columns.length <= AUTO_WIDTH_MAX_COLUMNS ? "w-auto" : "w-full",
|
|
308
|
+
)}
|
|
309
|
+
ref={tableRef}
|
|
310
|
+
>
|
|
304
311
|
{showLoadingBar && (
|
|
305
312
|
<thead className="absolute top-0 left-0 h-[3px] w-1/2 bg-primary animate-slide" />
|
|
306
313
|
)}
|
|
@@ -27,7 +27,7 @@ import { DataTableContextMenu } from "./context-menu";
|
|
|
27
27
|
import { CellRangeSelectionIndicator } from "./range-focus/cell-selection-indicator";
|
|
28
28
|
import { useCellRangeSelection } from "./range-focus/use-cell-range-selection";
|
|
29
29
|
import { useScrollIntoViewOnFocus } from "./range-focus/use-scroll-into-view";
|
|
30
|
-
import { TABLE_ROW_HEIGHT_PX } from "./types";
|
|
30
|
+
import { AUTO_WIDTH_MAX_COLUMNS, TABLE_ROW_HEIGHT_PX } from "./types";
|
|
31
31
|
import { stringifyUnknownValue } from "./utils";
|
|
32
32
|
|
|
33
33
|
export function renderTableHeader<TData>(
|
|
@@ -46,7 +46,7 @@ export function renderTableHeader<TData>(
|
|
|
46
46
|
<TableHead
|
|
47
47
|
key={header.id}
|
|
48
48
|
className={cn(
|
|
49
|
-
"h-auto min-h-10 whitespace-pre align-top",
|
|
49
|
+
"h-auto min-h-10 whitespace-pre align-top border-r border-r-border/75",
|
|
50
50
|
className,
|
|
51
51
|
)}
|
|
52
52
|
style={style}
|
|
@@ -69,6 +69,13 @@ export function renderTableHeader<TData>(
|
|
|
69
69
|
{renderHeaderGroup(table.getLeftHeaderGroups())}
|
|
70
70
|
{renderHeaderGroup(table.getCenterHeaderGroups())}
|
|
71
71
|
{renderHeaderGroup(table.getRightHeaderGroups())}
|
|
72
|
+
{table.getAllColumns().length <= AUTO_WIDTH_MAX_COLUMNS && (
|
|
73
|
+
<th
|
|
74
|
+
className="w-full border-0"
|
|
75
|
+
aria-hidden="true"
|
|
76
|
+
role="presentation"
|
|
77
|
+
/>
|
|
78
|
+
)}
|
|
72
79
|
</TableRow>
|
|
73
80
|
</TableHeader>
|
|
74
81
|
);
|
|
@@ -163,7 +170,7 @@ export const DataTableBody = <TData,>({
|
|
|
163
170
|
{...getCellDomProps(cell.id)}
|
|
164
171
|
key={cell.id}
|
|
165
172
|
className={cn(
|
|
166
|
-
"whitespace-pre truncate max-w-[300px] outline-hidden",
|
|
173
|
+
"whitespace-pre truncate max-w-[300px] outline-hidden border-r border-r-border/75",
|
|
167
174
|
cell.column.getColumnWrapping &&
|
|
168
175
|
cell.column.getColumnWrapping?.() === "wrap" &&
|
|
169
176
|
COLUMN_WRAPPING_STYLES,
|
|
@@ -230,15 +237,21 @@ export const DataTableBody = <TData,>({
|
|
|
230
237
|
{renderCells(row.getLeftVisibleCells())}
|
|
231
238
|
{renderCells(row.getCenterVisibleCells())}
|
|
232
239
|
{renderCells(row.getRightVisibleCells())}
|
|
240
|
+
{columns.length <= AUTO_WIDTH_MAX_COLUMNS && (
|
|
241
|
+
<td className="border-0" aria-hidden="true" role="presentation" />
|
|
242
|
+
)}
|
|
233
243
|
</TableRow>
|
|
234
244
|
);
|
|
235
245
|
};
|
|
236
246
|
|
|
247
|
+
const hasFillerColumn = columns.length <= AUTO_WIDTH_MAX_COLUMNS;
|
|
248
|
+
const totalColSpan = columns.length + (hasFillerColumn ? 1 : 0);
|
|
249
|
+
|
|
237
250
|
const renderRows = () => {
|
|
238
251
|
if (rows.length === 0) {
|
|
239
252
|
return (
|
|
240
253
|
<TableRow>
|
|
241
|
-
<TableCell colSpan={
|
|
254
|
+
<TableCell colSpan={totalColSpan} className="h-24 text-center">
|
|
242
255
|
No results.
|
|
243
256
|
</TableCell>
|
|
244
257
|
</TableRow>
|
|
@@ -255,7 +268,7 @@ export const DataTableBody = <TData,>({
|
|
|
255
268
|
data-virtual-spacer=""
|
|
256
269
|
style={{ height: virtualItems[0].start }}
|
|
257
270
|
>
|
|
258
|
-
<td colSpan={
|
|
271
|
+
<td colSpan={totalColSpan} />
|
|
259
272
|
</tr>
|
|
260
273
|
)}
|
|
261
274
|
{virtualItems.map((vItem) => renderRow(rows[vItem.index]))}
|
|
@@ -266,7 +279,7 @@ export const DataTableBody = <TData,>({
|
|
|
266
279
|
height: totalSize - (virtualItems.at(-1)?.end ?? totalSize),
|
|
267
280
|
}}
|
|
268
281
|
>
|
|
269
|
-
<td colSpan={
|
|
282
|
+
<td colSpan={totalColSpan} />
|
|
270
283
|
</tr>
|
|
271
284
|
)}
|
|
272
285
|
</>
|
|
@@ -16,6 +16,10 @@ declare module "@tanstack/react-table" {
|
|
|
16
16
|
export const TABLE_ROW_HEIGHT_PX = 24;
|
|
17
17
|
export const TABLE_HEADER_HEIGHT_PX = 40;
|
|
18
18
|
|
|
19
|
+
// Below this column count, the table uses w-auto with a filler column
|
|
20
|
+
// to prevent columns from stretching unnecessarily
|
|
21
|
+
export const AUTO_WIDTH_MAX_COLUMNS = 4;
|
|
22
|
+
|
|
19
23
|
// Default number of visible rows when virtualizing without an explicit maxHeight.
|
|
20
24
|
export const DEFAULT_VIRTUAL_ROWS = 15;
|
|
21
25
|
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
} from "@/components/ui/alert-dialog";
|
|
13
13
|
import { CopyIcon } from "lucide-react";
|
|
14
14
|
import { toast } from "@/components/ui/use-toast";
|
|
15
|
+
import { renderHTML } from "@/plugins/core/RenderHTML";
|
|
16
|
+
import { sanitizeHtml } from "@/plugins/core/sanitize-html";
|
|
15
17
|
|
|
16
18
|
interface TracebackModalProps {
|
|
17
19
|
isOpen: boolean;
|
|
@@ -29,7 +31,7 @@ export const TracebackModal: React.FC<TracebackModalProps> = ({
|
|
|
29
31
|
const handleCopy = async () => {
|
|
30
32
|
// Strip HTML tags for clipboard
|
|
31
33
|
const tempDiv = document.createElement("div");
|
|
32
|
-
tempDiv.innerHTML = traceback;
|
|
34
|
+
tempDiv.innerHTML = sanitizeHtml(traceback);
|
|
33
35
|
const textContent = tempDiv.textContent || tempDiv.innerText || "";
|
|
34
36
|
|
|
35
37
|
try {
|
|
@@ -73,10 +75,9 @@ export const TracebackModal: React.FC<TracebackModalProps> = ({
|
|
|
73
75
|
Copy
|
|
74
76
|
</Button>
|
|
75
77
|
</div>
|
|
76
|
-
<div
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
/>
|
|
78
|
+
<div className="font-code text-sm p-4 bg-muted rounded border overflow-auto max-h-[50vh] cursor-text select-text">
|
|
79
|
+
{renderHTML({ html: traceback })}
|
|
80
|
+
</div>
|
|
80
81
|
</div>
|
|
81
82
|
<AlertDialogFooter>
|
|
82
83
|
<AlertDialogAction onClick={onClose}>Close</AlertDialogAction>
|
|
@@ -25,6 +25,7 @@ import { useChromeActions } from "../chrome/state";
|
|
|
25
25
|
import { AutoFixButton } from "../errors/auto-fix";
|
|
26
26
|
import { CellLinkError } from "../links/cell-link";
|
|
27
27
|
import { processTextForUrls } from "./console/text-rendering";
|
|
28
|
+
import { renderHTML } from "@/plugins/core/RenderHTML";
|
|
28
29
|
|
|
29
30
|
const Tip = (props: {
|
|
30
31
|
title?: string;
|
|
@@ -486,13 +487,9 @@ export const MarimoErrorOutput = ({
|
|
|
486
487
|
{processTextForUrls(error.msg, `exception-${idx}`)}
|
|
487
488
|
</p>
|
|
488
489
|
{"traceback" in error && error.traceback ? (
|
|
489
|
-
<div
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
dangerouslySetInnerHTML={{
|
|
493
|
-
__html: error.traceback,
|
|
494
|
-
}}
|
|
495
|
-
/>
|
|
490
|
+
<div className="font-code text-sm mt-2 p-3 bg-muted rounded border overflow-auto max-h-[50vh] cursor-text select-text">
|
|
491
|
+
{renderHTML({ html: error.traceback })}
|
|
492
|
+
</div>
|
|
496
493
|
) : (
|
|
497
494
|
<div className="text-muted-foreground mt-2">
|
|
498
495
|
See the console area for a traceback.
|
|
@@ -504,13 +501,9 @@ export const MarimoErrorOutput = ({
|
|
|
504
501
|
{processTextForUrls(error.msg, `exception-${idx}`)}
|
|
505
502
|
<CellLinkError cellId={error.raising_cell} />
|
|
506
503
|
{"traceback" in error && error.traceback && (
|
|
507
|
-
<div
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
dangerouslySetInnerHTML={{
|
|
511
|
-
__html: error.traceback,
|
|
512
|
-
}}
|
|
513
|
-
/>
|
|
504
|
+
<div className="font-code text-sm mt-2 p-3 bg-muted rounded border overflow-auto max-h-[50vh] cursor-text select-text">
|
|
505
|
+
{renderHTML({ html: error.traceback })}
|
|
506
|
+
</div>
|
|
514
507
|
)}
|
|
515
508
|
</div>
|
|
516
509
|
)}
|
|
@@ -34,6 +34,7 @@ import { getRequestClient } from "@/core/network/requests";
|
|
|
34
34
|
import { isStaticNotebook } from "@/core/static/static-state";
|
|
35
35
|
import { isWasm } from "@/core/wasm/utils";
|
|
36
36
|
import { renderHTML } from "@/plugins/core/RenderHTML";
|
|
37
|
+
import { sanitizeHtml } from "@/plugins/core/sanitize-html";
|
|
37
38
|
import { copyToClipboard } from "@/utils/copy";
|
|
38
39
|
import {
|
|
39
40
|
elementContainsMarimoCellFile,
|
|
@@ -173,9 +174,9 @@ export const MarimoTracebackOutput = ({
|
|
|
173
174
|
</DropdownMenuItem>
|
|
174
175
|
<DropdownMenuItem
|
|
175
176
|
onClick={() => {
|
|
176
|
-
// Strip HTML from the traceback
|
|
177
|
+
// Strip HTML from the traceback (sanitize first to prevent XSS)
|
|
177
178
|
const div = document.createElement("div");
|
|
178
|
-
div.innerHTML = traceback;
|
|
179
|
+
div.innerHTML = sanitizeHtml(traceback);
|
|
179
180
|
const textContent = div.textContent || "";
|
|
180
181
|
copyToClipboard(textContent);
|
|
181
182
|
}}
|
|
@@ -193,7 +194,7 @@ export const MarimoTracebackOutput = ({
|
|
|
193
194
|
|
|
194
195
|
function lastLine(text: string): string {
|
|
195
196
|
const el = document.createElement("div");
|
|
196
|
-
el.innerHTML = text;
|
|
197
|
+
el.innerHTML = sanitizeHtml(text);
|
|
197
198
|
const lines = el.textContent?.split("\n").filter(Boolean);
|
|
198
199
|
return lines?.at(-1) || "";
|
|
199
200
|
}
|
|
@@ -25,6 +25,7 @@ import type { NotebookDocumentTransactionRequest } from "../network/types";
|
|
|
25
25
|
import { store } from "../state/jotai";
|
|
26
26
|
import type { CellActions, NotebookState } from "./cells";
|
|
27
27
|
import type { CellId } from "./ids";
|
|
28
|
+
import { SCRATCH_CELL_ID } from "./ids";
|
|
28
29
|
import type { CellData } from "./types";
|
|
29
30
|
|
|
30
31
|
export type DocumentChange =
|
|
@@ -572,10 +573,21 @@ const flushChanges = debounce(() => {
|
|
|
572
573
|
void getRequestClient().sendDocumentTransaction({ changes });
|
|
573
574
|
}, 400);
|
|
574
575
|
|
|
576
|
+
function isScratchChange(change: DocumentChange): boolean {
|
|
577
|
+
if ("cellId" in change && change.cellId === SCRATCH_CELL_ID) {
|
|
578
|
+
return true;
|
|
579
|
+
}
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
|
|
575
583
|
function enqueue(change: DocumentChange) {
|
|
576
584
|
if (store.get(kioskModeAtom)) {
|
|
577
585
|
return;
|
|
578
586
|
}
|
|
587
|
+
// The scratchpad cell is local-only — don't sync it to the document.
|
|
588
|
+
if (isScratchChange(change)) {
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
579
591
|
pendingChanges.push(change);
|
|
580
592
|
flushChanges();
|
|
581
593
|
}
|
|
@@ -16,6 +16,22 @@ export const filenameAtom = atom<string | null>(getFilenameFromDOM());
|
|
|
16
16
|
*/
|
|
17
17
|
export const cwdAtom = atom<string | null>(null);
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* LSP workspace information from the backend.
|
|
21
|
+
* Contains the project root and the document's file URI.
|
|
22
|
+
*/
|
|
23
|
+
export interface LspWorkspace {
|
|
24
|
+
rootUri: string;
|
|
25
|
+
documentUri: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Atom for storing the LSP workspace information.
|
|
30
|
+
* This is populated during active notebook sessions
|
|
31
|
+
* and null for other pages.
|
|
32
|
+
*/
|
|
33
|
+
export const lspWorkspaceAtom = atom<LspWorkspace | null>(null);
|
|
34
|
+
|
|
19
35
|
/**
|
|
20
36
|
* Set for static notebooks.
|
|
21
37
|
*/
|
|
@@ -341,7 +341,7 @@ export function useAsyncData<T>(
|
|
|
341
341
|
};
|
|
342
342
|
setResult((prevResult) => {
|
|
343
343
|
// If we have previous data, show reloading state
|
|
344
|
-
if (prevResult.status === "success") {
|
|
344
|
+
if (prevResult.status === "success" || prevResult.status === "loading") {
|
|
345
345
|
return Result.loading(prevResult.data);
|
|
346
346
|
}
|
|
347
347
|
// Otherwise, show initial loading state
|
package/src/mount.tsx
CHANGED
|
@@ -36,7 +36,12 @@ import {
|
|
|
36
36
|
DEFAULT_RUNTIME_CONFIG,
|
|
37
37
|
runtimeConfigAtom,
|
|
38
38
|
} from "./core/runtime/config";
|
|
39
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
codeAtom,
|
|
41
|
+
cwdAtom,
|
|
42
|
+
filenameAtom,
|
|
43
|
+
lspWorkspaceAtom,
|
|
44
|
+
} from "./core/saving/file-state";
|
|
40
45
|
import { store } from "./core/state/jotai";
|
|
41
46
|
import { patchFetch, patchVegaLoader } from "./core/static/files";
|
|
42
47
|
import {
|
|
@@ -150,6 +155,16 @@ const mountOptionsSchema = z.object({
|
|
|
150
155
|
* absolute working directory of the notebook
|
|
151
156
|
*/
|
|
152
157
|
cwd: z.string().nullish().default(null),
|
|
158
|
+
/**
|
|
159
|
+
* LSP workspace information
|
|
160
|
+
*/
|
|
161
|
+
lspWorkspace: z
|
|
162
|
+
.object({
|
|
163
|
+
rootUri: z.string(),
|
|
164
|
+
documentUri: z.string(),
|
|
165
|
+
})
|
|
166
|
+
.nullish()
|
|
167
|
+
.default(null),
|
|
153
168
|
/**
|
|
154
169
|
* notebook code
|
|
155
170
|
*/
|
|
@@ -287,6 +302,7 @@ function initStore(options: unknown) {
|
|
|
287
302
|
// Files
|
|
288
303
|
store.set(filenameAtom, parsedOptions.data.filename);
|
|
289
304
|
store.set(cwdAtom, parsedOptions.data.cwd ?? null);
|
|
305
|
+
store.set(lspWorkspaceAtom, parsedOptions.data.lspWorkspace);
|
|
290
306
|
store.set(codeAtom, parsedOptions.data.code);
|
|
291
307
|
store.set(initialModeAtom, mode);
|
|
292
308
|
|
|
@@ -117,6 +117,14 @@ describe("shouldHandleClickSelection", () => {
|
|
|
117
117
|
expect(shouldHandleClickSelection([linePoint])).toBe(true);
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
+
it("accepts waterfall clicks", () => {
|
|
121
|
+
const waterfallPoint = createPlotDatum({
|
|
122
|
+
data: { type: "waterfall" },
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
expect(shouldHandleClickSelection([waterfallPoint])).toBe(true);
|
|
126
|
+
});
|
|
127
|
+
|
|
120
128
|
it("rejects non-line scatter marker clicks", () => {
|
|
121
129
|
const markerPoint = createPlotDatum({
|
|
122
130
|
data: { type: "scatter", mode: "markers" },
|
|
@@ -196,4 +204,18 @@ describe("extractPoints", () => {
|
|
|
196
204
|
|
|
197
205
|
expect(extractPoints([point])).toEqual([{ x: 1, y: 2, z: 3 }]);
|
|
198
206
|
});
|
|
207
|
+
|
|
208
|
+
it("returns x/y/pointIndex for waterfall clicks", () => {
|
|
209
|
+
const point = createPlotDatum({
|
|
210
|
+
x: "Revenue",
|
|
211
|
+
y: 400,
|
|
212
|
+
pointIndex: 1,
|
|
213
|
+
curveNumber: 0,
|
|
214
|
+
data: { type: "waterfall" },
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
expect(extractPoints([point])).toEqual([
|
|
218
|
+
{ x: "Revenue", y: 400, pointIndex: 1, curveNumber: 0 },
|
|
219
|
+
]);
|
|
220
|
+
});
|
|
199
221
|
});
|