@marimo-team/islands 0.25.3-dev13 → 0.25.3-dev134
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/{ConnectedDataExplorerComponent-CNMliVzw.js → ConnectedDataExplorerComponent-BAiSVaHj.js} +17 -15
- package/dist/{ErrorBoundary-BWYjMPq8.js → ErrorBoundary-CImYa86e.js} +16 -16
- package/dist/{abnfDiagram-VCTEODGH-D-Ez91gV.js → abnfDiagram-VCTEODGH-BBHN92-F.js} +2 -2
- package/dist/any-language-editor-3E24SnCV.js +75 -0
- package/dist/{architectureDiagram-5GKGNRK7-CTpcNtO8.js → architectureDiagram-5GKGNRK7-C0Rd64qh.js} +1 -1
- package/dist/{arrays-CN1djC4k.js → arrays-R6JsImiT.js} +8 -0
- package/dist/assets/__vite-browser-external-SaDYcg7x.js +1 -0
- package/dist/assets/{worker-HPY9fbhz.js → worker-CfME3uyi.js} +3 -2
- package/dist/{button-CvjkwdSk.js → button-BQRdqQi1.js} +199 -192
- package/dist/{capabilities-CQ5IjhzL.js → capabilities-CI4xUPsp.js} +2 -2
- package/dist/{chat-ui-DaHynk8g.js → chat-ui-DqcauBr6.js} +1142 -1141
- package/dist/{check-EDwSwP89.js → check-SpOMoCLP.js} +1 -1
- package/dist/{chunk-IMKFNOWR-DGxi-zeo.js → chunk-IMKFNOWR-hJXey5p2.js} +1 -1
- package/dist/{chunk-SHT3W25Y-CV9J3rAB.js → chunk-SHT3W25Y-JMzTmmVW.js} +1 -1
- package/dist/{chunk-SVP7TREG-BL-9Fqgg.js → chunk-SVP7TREG-BIyoHTXi.js} +1 -1
- package/dist/{chunk-TICWLB2K-Cu_XMjDM.js → chunk-TICWLB2K-CCzH2Uwa.js} +1 -1
- package/dist/{chunk-YOKDWASO-DPZk8vhS.js → chunk-YOKDWASO-DKplTrBY.js} +20 -20
- package/dist/{classDiagram-ZZMXUADV-BXXV13Hq.js → classDiagram-ZZMXUADV-DB1kOPS6.js} +2 -2
- package/dist/{classDiagram-v2-VYDZK3BY-B7FXJ1Cp.js → classDiagram-v2-VYDZK3BY-CPaFL0OB.js} +2 -2
- package/dist/{code-visibility-O0uJkFyz.js → code-visibility-BZoWT5f1.js} +6 -6
- package/dist/{common-PAvTWnXO.js → common-CGmIoGK3.js} +6762 -6586
- package/dist/{copy-icon-Ft7t9bqz.js → copy-icon-C1trdvVt.js} +3 -3
- package/dist/{cynefinDiagram-5FMLGOSQ-CH96rwba.js → cynefinDiagram-5FMLGOSQ-CF93uliH.js} +1 -1
- package/dist/{dagre-GXQ25YYZ-BD3PmpFY.js → dagre-GXQ25YYZ-BBB-_p9D.js} +1 -1
- package/dist/{data-grid-overlay-editor-DeWySy0K.js → data-grid-overlay-editor-CtOna148.js} +5 -5
- package/dist/{data-grid-types-BH_r7g7l.js → data-grid-types-0PJ-9N5n.js} +1 -1
- package/dist/{diagram-S7CK7UJ4-BsSJJldB.js → diagram-S7CK7UJ4-BynCnbyt.js} +1 -1
- package/dist/{diagram-UQ7AKVKN-muQtNZc4.js → diagram-UQ7AKVKN-svOxikMa.js} +1 -1
- package/dist/{diagram-VX7I27RA-CdhuZAqR.js → diagram-VX7I27RA-BVQSnPx0.js} +1 -1
- package/dist/{diagram-Z3DM3KII-BD8mXjOj.js → diagram-Z3DM3KII-nR1J0BH5.js} +1 -1
- package/dist/{dialog-CEBFZNyc.js → dialog-DgeqyrEZ.js} +3 -3
- package/dist/{dist-DpBpA_n1.js → dist-Lm-D-Vr6.js} +3 -3
- package/dist/{dropdown-menu-CP_qCYHC.js → dropdown-menu-CgL3fm8P.js} +1262 -1229
- package/dist/{ebnfDiagram-PWID7BFC-BIN1sweE.js → ebnfDiagram-PWID7BFC-C9tq9-Qo.js} +2 -2
- package/dist/{erDiagram-RLTQ6QDP-Ctp5cfoN.js → erDiagram-RLTQ6QDP-BiaeB7Fi.js} +1 -1
- package/dist/{error-banner-D-WCIiMt.js → error-banner-D40pmfQQ.js} +83 -83
- package/dist/{error-entries-Bv6bZPF3.js → error-entries-CmFDQ9CA.js} +1018 -977
- package/dist/{feedback-button-WbN_sdUE.js → feedback-button-7ZbDdjfz.js} +23 -23
- package/dist/{flowDiagram-HODETNUW-3EfLrlFb.js → flowDiagram-HODETNUW-f-sLm87k.js} +2 -2
- package/dist/{formats-27CW_UP4.js → formats-CCxaLPNs.js} +3 -3
- package/dist/{ganttDiagram-EL5Y4UJY-BQT16JSc.js → ganttDiagram-EL5Y4UJY-Dh_4cBJZ.js} +2 -2
- package/dist/{glide-data-editor-_oc1WE9x.js → glide-data-editor-D72zmCan.js} +370 -368
- package/dist/{glide-utils-DJyqh0EM.js → glide-utils-Dz_F4pAY.js} +16 -16
- package/dist/{globals-C-fUiztk.js → globals-DE2S2io9.js} +3 -3
- package/dist/{highlighted-body-KPVGNVTW-zwjq21tf.js → highlighted-body-KPVGNVTW-3Ziwfz-V.js} +2 -2
- package/dist/{html-to-image-Bf8QMGi4.js → html-to-image-CfgsWObF.js} +630 -593
- package/dist/{infoDiagram-27XIBGKW-DipQoHxl.js → infoDiagram-27XIBGKW-BHrWywBe.js} +1 -1
- package/dist/{ishikawaDiagram-5VMMS53U-DgFMjSGz.js → ishikawaDiagram-5VMMS53U-Da4s0Reg.js} +1 -1
- package/dist/{kanban-definition-UXKFOSKX-w1ACVjgl.js → kanban-definition-UXKFOSKX-DDf1GVLj.js} +1 -1
- package/dist/{label-BDKF3Afc.js → label-D9_-zSg-.js} +3 -3
- package/dist/{linear-Cnaq3Tfb.js → linear-DWERh7eI.js} +121 -73
- package/dist/{loader-BQOfjTIJ.js → loader-DOVB0Syl.js} +12 -12
- package/dist/main.js +7441 -7115
- package/dist/{mermaid-CHo49Yv-.js → mermaid-ClwTt7OD.js} +38 -38
- package/dist/mermaid-HWGCJPDP-Du3-HPQA.js +2 -0
- package/dist/{mindmap-definition-YA3MSWOX-CrT0KSfX.js → mindmap-definition-YA3MSWOX-D60oMZtT.js} +1 -1
- package/dist/{number-overlay-editor-DdPkN3h1.js → number-overlay-editor-Br0lPnFE.js} +3 -3
- package/dist/{objects-CzUgoMIF.js → objects-DCmMvZtn.js} +1 -3
- package/dist/{once-BtE-wKRL.js → once-eG8Vmvjd.js} +1 -1
- package/dist/{pegDiagram-XKGWAZYB-BqvywNJA.js → pegDiagram-XKGWAZYB-B9wFpMga.js} +2 -2
- package/dist/{pieDiagram-E7YTZNPT-BfxJ_XCc.js → pieDiagram-E7YTZNPT-BZwvMuBT.js} +1 -1
- package/dist/precisionRound-DhAzeRcm.js +49 -0
- package/dist/{process-output-BZg56CCb.js → process-output-B64ZYWuI.js} +5 -5
- package/dist/{quadrantDiagram-AXDQQJYC-Ccw0xMjN.js → quadrantDiagram-AXDQQJYC-Blrm7V7_.js} +1 -1
- package/dist/{railroadDiagram-O6MQD6OU-8vFLVTPu.js → railroadDiagram-O6MQD6OU-DqhZGsN2.js} +2 -2
- package/dist/{react-vega-BED0DjiB.js → react-vega-C4T9Rb_w.js} +12284 -12270
- package/dist/{requirementDiagram-BXWQKSXE-a_MxGvxe.js → requirementDiagram-BXWQKSXE-CL5dYARV.js} +1 -1
- package/dist/{reveal-component-Bs9X_N3n.js → reveal-component-DnbPU885.js} +14 -14
- package/dist/{select-BButFi-d.js → select-CkF_GBxO.js} +537 -458
- package/dist/{sequenceDiagram-WJ2MYXX4-CXFMnxGh.js → sequenceDiagram-WJ2MYXX4-BSUCRd2x.js} +1 -1
- package/dist/{spec-BwarBpUJ.js → spec-DiSh_qJC.js} +41 -11
- package/dist/{stateDiagram-D77RDMKH-DQeA_CwI.js → stateDiagram-D77RDMKH-B-1Hvyb0.js} +2 -2
- package/dist/{stateDiagram-v2-MP3YSRHH-BxxQucm1.js → stateDiagram-v2-MP3YSRHH--HtiR4yB.js} +2 -2
- package/dist/style.css +1 -1
- package/dist/{swimlanes-42K2YHIH-Do6L-cYg.js → swimlanes-42K2YHIH-Bdfhrd-2.js} +1 -1
- package/dist/{swimlanesDiagram-VR7AAH4N-DUzPvSVU.js → swimlanesDiagram-VR7AAH4N-BJIfxSz0.js} +2 -2
- package/dist/{swiper-component-DKntyn8p.js → swiper-component-BkCm-kLg.js} +2 -2
- package/dist/{time-BieKwdYS.js → time-BaMbJs4z.js} +18 -18
- package/dist/{timeline-definition-24CTP7MA-D3c46WM5.js → timeline-definition-24CTP7MA-Cs4EfFD3.js} +1 -1
- package/dist/{toDate-UtiwmnH2.js → toDate-DGvRHwTk.js} +19 -18
- package/dist/{toast-B9UMEi8u.js → toast-Btbve3Lm.js} +231 -213
- package/dist/{tooltip-BO1REbqs.js → tooltip-CJ4Rqasp.js} +327 -303
- package/dist/{use-restore-focus-BEM7sFWl.js → use-restore-focus-CmGwRNId.js} +1482 -1433
- package/dist/{useAsyncData-Deh5kszT.js → useAsyncData-BmVgnMP5.js} +15 -14
- package/dist/{useDateFormatter-D8XruNGG.js → useDateFormatter-eCL_SdeG.js} +2 -2
- package/dist/{useDeepCompareMemoize-DXwzRINI.js → useDeepCompareMemoize-Ch_AeGu6.js} +1 -1
- package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-CSdWn6NP.js} +1 -1
- package/dist/{useLifecycle-j7D9uD1o.js → useLifecycle-B5BX921H.js} +3 -3
- package/dist/{useTheme-CRnjkku0.js → useTheme-Bq9pi_vz.js} +6 -6
- package/dist/{vega-component-BeF9dfyO.js → vega-component-BgyZ-COt.js} +147 -147
- package/dist/{vega-embed-container-BNHE18G9.js → vega-embed-container--LYZqguO.js} +2 -2
- package/dist/{vega-loader.browser-DNST6uVf.js → vega-loader.browser-B9Pz0EGP.js} +298 -507
- package/dist/{vennDiagram-4TSXK5OY-BSZD8JcZ.js → vennDiagram-4TSXK5OY-DRu0vRjO.js} +1 -1
- package/dist/{wardleyDiagram-VM6X3IG4-48cUWkfA.js → wardleyDiagram-VM6X3IG4-DzbDxwDY.js} +1 -1
- package/dist/{xychartDiagram-S5SC5T6Z-CswYgYeu.js → xychartDiagram-S5SC5T6Z-CLWj6ZFQ.js} +2 -2
- package/package.json +14 -14
- package/src/__tests__/host-imports.test.ts +1 -0
- package/src/__tests__/module-entry.test.ts +32 -0
- package/src/__tests__/mount.test.ts +0 -20
- package/src/components/ai/__tests__/ai-model-dropdown.test.tsx +63 -0
- package/src/components/ai/ai-model-dropdown.tsx +11 -6
- package/src/components/app-config/ai-config.tsx +7 -2
- package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
- package/src/components/chat/acp/__tests__/session-tabs.test.tsx +43 -0
- package/src/components/chat/acp/__tests__/state.test.ts +2 -2
- package/src/components/chat/acp/blocks.tsx +3 -2
- package/src/components/chat/acp/session-tabs.tsx +8 -3
- package/src/components/chat/chat-components.tsx +2 -0
- package/src/components/chat/chat-panel.tsx +9 -8
- package/src/components/chat/chat-utils.ts +4 -8
- package/src/components/data-table/TableTopBar.tsx +2 -0
- package/src/components/data-table/__tests__/chart-spec-model.test.ts +195 -195
- package/src/components/data-table/__tests__/column-explorer.test.tsx +27 -1
- package/src/components/data-table/__tests__/columns.test.tsx +105 -0
- package/src/components/data-table/__tests__/context-menu-interaction.test.tsx +130 -0
- package/src/components/data-table/__tests__/data-table.test.tsx +1 -0
- package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
- package/src/components/data-table/__tests__/export-actions.test.tsx +105 -0
- package/src/components/data-table/__tests__/keyboard-selection.test.tsx +188 -0
- package/src/components/data-table/__tests__/search-highlight.test.tsx +109 -0
- package/src/components/data-table/__tests__/url-detector.test.tsx +74 -0
- package/src/components/data-table/cell-selection/feature.ts +2 -2
- package/src/components/data-table/cell-selection/types.ts +2 -2
- package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
- package/src/components/data-table/charts/__tests__/spec-snapshot.test.ts +20 -20
- package/src/components/data-table/charts/__tests__/spec.test.ts +78 -52
- package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
- package/src/components/data-table/charts/chart-spec/spec.ts +68 -43
- package/src/components/data-table/charts/charts.tsx +40 -30
- package/src/components/data-table/charts/storage.ts +16 -5
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
- package/src/components/data-table/column-summary/chart-spec-model.tsx +23 -16
- package/src/components/data-table/column-summary/column-summary.tsx +2 -4
- package/src/components/data-table/column-visibility-dropdown.tsx +8 -13
- package/src/components/data-table/columns.tsx +45 -46
- package/src/components/data-table/context-menu.tsx +36 -20
- package/src/components/data-table/data-table.tsx +13 -1
- package/src/components/data-table/date-popover.tsx +6 -4
- package/src/components/data-table/export-actions.tsx +76 -48
- package/src/components/data-table/range-focus/atoms.ts +4 -6
- package/src/components/data-table/range-focus/use-cell-range-selection.ts +65 -38
- package/src/components/data-table/range-focus/use-scroll-into-view.ts +21 -2
- package/src/components/data-table/renderers.tsx +16 -7
- package/src/components/data-table/row-viewer-panel/__tests__/row-viewer.test.tsx +24 -1
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +4 -4
- package/src/components/data-table/search-highlight.tsx +79 -0
- package/src/components/data-table/types.ts +1 -0
- package/src/components/data-table/url-detector.tsx +49 -9
- package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
- package/src/components/datasources/__tests__/column-preview.test.tsx +63 -2
- package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
- package/src/components/datasources/column-preview.tsx +8 -2
- package/src/components/datasources/datasources.tsx +48 -35
- package/src/components/debugger/debugger-code.tsx +5 -0
- package/src/components/dependency-graph/dependency-graph-tree.tsx +8 -8
- package/src/components/dependency-graph/elements.ts +24 -21
- package/src/components/dependency-graph/panels.tsx +2 -1
- package/src/components/dependency-graph/utils/__tests__/layout.test.ts +18 -11
- package/src/components/editor/SortableCell.tsx +1 -3
- package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
- package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
- package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +24 -0
- package/src/components/editor/actions/pair-with-agent-modal.tsx +18 -15
- package/src/components/editor/ai/add-cell-with-ai.tsx +3 -3
- package/src/components/editor/ai/ai-completion-editor.tsx +1 -0
- package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
- package/src/components/editor/cell/CreateCellButton.tsx +8 -10
- package/src/components/editor/cell/DeleteButton.tsx +1 -0
- package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
- package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
- package/src/components/editor/cell/code/cell-editor.tsx +1 -1
- package/src/components/editor/cell/code/language-toggle.tsx +8 -7
- package/src/components/editor/cell/collapse.tsx +5 -3
- package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
- package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +30 -1
- package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/outline/__tests__/outline-keyboard.test.tsx +84 -0
- package/src/components/editor/chrome/panels/outline/floating-outline.tsx +39 -14
- package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +3 -2
- package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
- package/src/components/editor/chrome/panels/secrets-panel.tsx +1 -0
- package/src/components/editor/chrome/panels/snippets-panel.tsx +5 -1
- package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +12 -18
- package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +58 -1
- package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
- package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +12 -2
- package/src/components/editor/chrome/wrapper/storage.ts +1 -1
- package/src/components/editor/connections/components.tsx +1 -1
- package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
- package/src/components/editor/controls/__tests__/keyboard-shortcuts.test.tsx +61 -0
- package/src/components/editor/controls/command-palette.tsx +22 -10
- package/src/components/editor/controls/keyboard-shortcuts.tsx +14 -5
- package/src/components/editor/dynamic-favicon.tsx +21 -40
- package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +12 -23
- package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
- package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +47 -0
- package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
- package/src/components/editor/file-tree/file-explorer.tsx +45 -8
- package/src/components/editor/file-tree/file-name-input.tsx +1 -0
- package/src/components/editor/file-tree/file-viewer.tsx +4 -2
- package/src/components/editor/file-tree/use-file-search.ts +35 -21
- package/src/components/editor/header/status.tsx +28 -5
- package/src/components/editor/links/__tests__/cell-link.test.tsx +146 -0
- package/src/components/editor/links/cell-link.tsx +14 -5
- package/src/components/editor/navigation/focus-utils.ts +4 -4
- package/src/components/editor/notebook-banner.tsx +1 -0
- package/src/components/editor/notebook-cell.tsx +11 -2
- package/src/components/editor/output/MarimoTracebackOutput.tsx +19 -17
- package/src/components/editor/output/__tests__/traceback.test.tsx +27 -1
- package/src/components/editor/output/ansi-reduce.ts +33 -20
- package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
- package/src/components/editor/package-alert.tsx +14 -7
- package/src/components/editor/renderers/grid-layout/grid-layout.tsx +12 -6
- package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
- package/src/components/home/components.tsx +17 -31
- package/src/components/icons/__tests__/large-spinner.test.tsx +39 -0
- package/src/components/icons/large-spinner.tsx +3 -14
- package/src/components/icons/spinner.tsx +1 -1
- package/src/components/mcp/mcp-status-indicator.tsx +1 -1
- package/src/components/pages/__tests__/home-page.test.tsx +116 -0
- package/src/components/pages/home-page.tsx +164 -91
- package/src/components/scratchpad/scratchpad.test.tsx +95 -0
- package/src/components/scratchpad/scratchpad.tsx +16 -3
- package/src/components/slides/reveal-component.tsx +4 -2
- package/src/components/slides/slide-cell-view.tsx +1 -1
- package/src/components/slides/slide-form.tsx +1 -0
- package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
- package/src/components/tracing/tracing.tsx +45 -41
- package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
- package/src/components/ui/alert-dialog.tsx +1 -1
- package/src/components/ui/draggable-popover.tsx +24 -2
- package/src/core/ai/context/providers/datasource.ts +6 -2
- package/src/core/ai/tools/base.ts +16 -7
- package/src/core/ai/tools/edit-notebook-tool.ts +47 -45
- package/src/core/ai/tools/registry.ts +13 -8
- package/src/core/ai/tools/sample-tool.ts +6 -7
- package/src/core/attachments/state.ts +5 -8
- package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -0
- package/src/core/cells/__tests__/cell.test.ts +39 -0
- package/src/core/cells/__tests__/cells.test.ts +3 -1
- package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
- package/src/core/cells/__tests__/notebook-outline.test.ts +113 -0
- package/src/core/cells/__tests__/session.test.ts +117 -36
- package/src/core/cells/cell.ts +14 -3
- package/src/core/cells/cells.ts +3 -1
- package/src/core/cells/pending-delete-service.ts +2 -6
- package/src/core/cells/session.ts +1 -1
- package/src/core/cells/types.ts +10 -1
- package/src/core/codemirror/__tests__/setup.test.ts +29 -29
- package/src/core/codemirror/cells/__tests__/extensions.test.ts +15 -0
- package/src/core/codemirror/cells/extensions.ts +7 -3
- package/src/core/codemirror/keymaps/vim.ts +2 -6
- package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
- package/src/core/codemirror/language/extension.ts +8 -8
- package/src/core/codemirror/language/languages/markdown.ts +8 -6
- package/src/core/codemirror/language/languages/python.ts +16 -10
- package/src/core/codemirror/language/languages/sql/sql.ts +9 -7
- package/src/core/codemirror/language/panel/panel.tsx +1 -0
- package/src/core/codemirror/language/types.ts +7 -7
- package/src/core/codemirror/rtc/extension.ts +24 -12
- package/src/core/codemirror/rtc/loro/awareness.ts +34 -19
- package/src/core/codemirror/rtc/loro/sync.ts +1 -0
- package/src/core/codemirror/utils.ts +1 -0
- package/src/core/datasets/__tests__/data-source-discovery.test.ts +4 -4
- package/src/core/datasets/data-source-discovery.ts +4 -6
- package/src/core/document/__tests__/codemirror.test.ts +485 -0
- package/src/core/document/__tests__/draft.test.ts +322 -0
- package/src/core/document/__tests__/fixtures.ts +92 -0
- package/src/core/document/__tests__/hooks.test.tsx +386 -0
- package/src/core/document/__tests__/lifecycle-scenarios.test.ts +61 -0
- package/src/core/document/__tests__/model.test.ts +191 -0
- package/src/core/document/__tests__/protocol-fixtures.ts +38 -0
- package/src/core/document/__tests__/recovery-scenarios.test.ts +230 -0
- package/src/core/document/__tests__/scenario-fixture.ts +43 -0
- package/src/core/document/__tests__/scenarios.test.ts +205 -0
- package/src/core/document/__tests__/state.test.ts +438 -0
- package/src/core/document/__tests__/submission.test.ts +203 -0
- package/src/core/document/__tests__/test-host.test.ts +92 -0
- package/src/core/document/__tests__/test-host.ts +247 -0
- package/src/core/document/__tests__/test-notebook.ts +149 -0
- package/src/core/document/__tests__/user.ts +61 -0
- package/src/core/document/codemirror.ts +311 -0
- package/src/core/document/draft.ts +472 -0
- package/src/core/document/hooks.tsx +118 -0
- package/src/core/document/index.ts +15 -0
- package/src/core/document/model.ts +55 -0
- package/src/core/document/select.ts +41 -0
- package/src/core/document/state.ts +374 -0
- package/src/core/document/sync.ts +369 -0
- package/src/core/host/AGENTS.md +8 -2
- package/src/core/host/__tests__/attachments.test.ts +56 -0
- package/src/core/host/__tests__/document.test.ts +126 -0
- package/src/core/host/__tests__/fixtures.ts +71 -0
- package/src/core/host/__tests__/replica.test.ts +550 -0
- package/src/core/host/__tests__/static.test.ts +169 -0
- package/src/core/host/__tests__/wasm.test.ts +162 -0
- package/src/core/host/backend.ts +19 -0
- package/src/core/host/connection.ts +1 -40
- package/src/core/host/index.ts +14 -0
- package/src/core/host/replica.ts +286 -0
- package/src/core/host/resources/attachments.ts +22 -0
- package/src/core/host/resources/document.ts +101 -0
- package/src/core/host/static.ts +72 -0
- package/src/core/host/wasm.ts +102 -0
- package/src/core/hotkeys/actions.ts +2 -4
- package/src/core/islands/__tests__/bootstrap.test.ts +0 -26
- package/src/core/islands/bootstrap.ts +0 -1
- package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
- package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
- package/src/core/network/connection.ts +4 -2
- package/src/core/network/useConnectionNotice.ts +8 -2
- package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
- package/src/core/runtime/__tests__/runtime.test.ts +32 -58
- package/src/core/runtime/runtime.ts +38 -42
- package/src/core/runtime/types.ts +0 -2
- package/src/core/state/__tests__/jotai.test.tsx +108 -0
- package/src/core/state/jotai.ts +1 -1
- package/src/core/static/__tests__/files.test.ts +38 -10
- package/src/core/static/files.ts +2 -0
- package/src/core/wasm/bridge.ts +38 -10
- package/src/core/wasm/store.ts +3 -3
- package/src/core/wasm/worker/bootstrap.ts +2 -1
- package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
- package/src/core/wasm/worker/types.ts +11 -0
- package/src/core/wasm/worker/worker.ts +48 -0
- package/src/core/websocket/__tests__/backend.test.ts +200 -0
- package/src/core/websocket/__tests__/connection-state.test.ts +0 -12
- package/src/core/websocket/__tests__/useNotebookReplica.hook.test.tsx +141 -0
- package/src/core/websocket/__tests__/useNotebookSession.hook.test.tsx +154 -428
- package/src/core/websocket/backend.ts +106 -0
- package/src/core/websocket/connection-state.ts +1 -11
- package/src/core/websocket/state.ts +7 -0
- package/src/core/websocket/transports/__tests__/notebook.test.ts +445 -0
- package/src/core/websocket/transports/notebook.ts +190 -0
- package/src/core/websocket/types.ts +2 -2
- package/src/core/websocket/useNotebookReplica.ts +69 -0
- package/src/core/websocket/useNotebookSession.tsx +10 -22
- package/src/css/globals.css +5 -0
- package/src/hooks/__tests__/useAsyncData.test.tsx +148 -0
- package/src/hooks/__tests__/useDebounce.test.tsx +51 -0
- package/src/hooks/__tests__/useDeepCompareMemoize.test.tsx +39 -0
- package/src/hooks/__tests__/useDelayElapsed.test.tsx +28 -0
- package/src/hooks/__tests__/useInternalStateWithSync.test.tsx +20 -0
- package/src/hooks/__tests__/useScript.test.tsx +77 -0
- package/src/hooks/__tests__/useStateForKey.test.tsx +257 -0
- package/src/hooks/useAsyncData.ts +3 -3
- package/src/hooks/useDataSourceDiscovery.ts +6 -4
- package/src/hooks/useDebounce.ts +6 -10
- package/src/hooks/useDeepCompareMemoize.ts +1 -1
- package/src/hooks/useDelayElapsed.ts +14 -10
- package/src/hooks/useElapsedTime.ts +3 -3
- package/src/hooks/useEventListener.ts +1 -2
- package/src/hooks/useInputHistory.ts +4 -7
- package/src/hooks/useInternalStateWithSync.ts +6 -6
- package/src/hooks/useResizeObserver.ts +4 -7
- package/src/hooks/useScript.ts +67 -70
- package/src/hooks/useStateForKey.ts +93 -0
- package/src/mount.tsx +0 -4
- package/src/plugins/__tests__/plugin-object-schemas.test.ts +104 -0
- package/src/plugins/core/registerReactComponent.tsx +1 -1
- package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataEditorPlugin.tsx +1 -1
- package/src/plugins/impl/DataTablePlugin.tsx +29 -33
- package/src/plugins/impl/DropdownPlugin.tsx +2 -6
- package/src/plugins/impl/FileBrowserPlugin.tsx +4 -16
- package/src/plugins/impl/FormPlugin.tsx +1 -1
- package/src/plugins/impl/RangeSliderPlugin.tsx +0 -1
- package/src/plugins/impl/RefreshPlugin.tsx +1 -0
- package/src/plugins/impl/SliderPlugin.tsx +6 -8
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +117 -1
- package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
- package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
- package/src/plugins/impl/anywidget/__tests__/registry.test.ts +2 -0
- package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
- package/src/plugins/impl/anywidget/runtime.ts +21 -9
- package/src/plugins/impl/anywidget/widget-binding.ts +160 -82
- package/src/plugins/impl/chat/__tests__/chat-prompts.test.tsx +93 -0
- package/src/plugins/impl/chat/chat-ui.tsx +14 -11
- package/src/plugins/impl/code/any-language-editor.tsx +2 -2
- package/src/plugins/impl/data-editor/glide-data-editor.tsx +8 -5
- package/src/plugins/impl/data-editor/glide-utils.ts +3 -1
- package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
- package/src/plugins/impl/data-explorer/components/column-summary.tsx +4 -2
- package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
- package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -2
- package/src/plugins/impl/data-frames/__tests__/sidebar.test.tsx +160 -0
- package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +66 -66
- package/src/plugins/impl/data-frames/panel.tsx +43 -16
- package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
- package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
- package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
- package/src/plugins/impl/panel/utils.ts +17 -0
- package/src/plugins/impl/plotly/PlotlyPlugin.tsx +2 -5
- package/src/plugins/impl/plotly/selection.ts +25 -19
- package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
- package/src/plugins/impl/vega/make-selectable.ts +4 -7
- package/src/plugins/layout/RoutesPlugin.tsx +1 -1
- package/src/stories/__tests__/editor-story.test.tsx +33 -0
- package/src/stories/button.stories.tsx +1 -0
- package/src/stories/editor.stories.tsx +24 -17
- package/src/stories/form-wrapper.stories.tsx +2 -2
- package/src/stories/select.stories.tsx +2 -2
- package/src/stories/switchable-multi-select.stories.tsx +1 -1
- package/src/utils/__tests__/arrays.test.ts +35 -0
- package/src/utils/__tests__/batch-requests.test.ts +3 -3
- package/src/utils/__tests__/numbers.test.ts +48 -1
- package/src/utils/__tests__/objects.test.ts +21 -0
- package/src/utils/arrays.ts +10 -0
- package/src/utils/blob.ts +1 -1
- package/src/utils/numbers.ts +28 -17
- package/src/utils/objects.ts +3 -7
- package/src/utils/once.ts +19 -19
- package/src/utils/tracer.ts +9 -5
- package/src/utils/zod-utils.ts +1 -3
- package/dist/any-language-editor-DZ_YTVus.js +0 -76
- package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
- package/dist/mermaid-HWGCJPDP-ByCsZnYF.js +0 -2
- package/dist/precisionRound-DMIVQrt2.js +0 -97
- package/src/core/host/__tests__/events.test.ts +0 -46
- package/src/core/host/__tests__/notebook-client.test.ts +0 -191
- package/src/core/host/__tests__/protocol.test.ts +0 -214
- package/src/core/host/events.ts +0 -60
- package/src/core/host/notebook-client.ts +0 -226
- package/src/core/host/protocol.ts +0 -1943
- package/src/core/state/__tests__/jotai.test.ts +0 -25
- package/src/core/websocket/__tests__/createConnectionTransport.test.ts +0 -49
- package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +0 -140
- package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
- package/src/core/websocket/transports/__tests__/sse.test.ts +0 -335
- package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
- package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
- package/src/core/websocket/transports/basic.ts +0 -102
- package/src/core/websocket/transports/create.ts +0 -31
- package/src/core/websocket/transports/sse.ts +0 -308
- package/src/core/websocket/transports/transport.ts +0 -50
- package/src/core/websocket/transports/ws.ts +0 -98
- package/src/core/websocket/useNotebookClient.ts +0 -80
|
@@ -41,6 +41,7 @@ import {
|
|
|
41
41
|
isNumericType,
|
|
42
42
|
} from "./types";
|
|
43
43
|
import { SentinelCell, WhitespaceMarkers } from "./sentinel-cell";
|
|
44
|
+
import { highlightMatches } from "./search-highlight";
|
|
44
45
|
import { detectSentinel, splitLeadingTrailingWhitespace } from "./utils";
|
|
45
46
|
import { uniformSample } from "./uniformSample";
|
|
46
47
|
import { MarkdownUrlDetector, UrlDetector } from "./url-detector";
|
|
@@ -135,6 +136,7 @@ export function generateColumns<T>({
|
|
|
135
136
|
}): ColumnDef<T>[] {
|
|
136
137
|
// Row-headers are typically index columns
|
|
137
138
|
const rowHeadersSet = new Set(rowHeaders.map(([columnName]) => columnName));
|
|
139
|
+
const wrappedColumnsSet = new Set(wrappedColumns);
|
|
138
140
|
|
|
139
141
|
const typesByColumn = Maps.keyBy(fieldTypes, (entry) => entry[0]);
|
|
140
142
|
|
|
@@ -277,7 +279,7 @@ export function generateColumns<T>({
|
|
|
277
279
|
);
|
|
278
280
|
},
|
|
279
281
|
|
|
280
|
-
cell: ({ column, renderValue, getValue, cell }) => {
|
|
282
|
+
cell: ({ column, renderValue, getValue, cell, table }) => {
|
|
281
283
|
function selectCell() {
|
|
282
284
|
if (selection !== "single-cell" && selection !== "multi-cell") {
|
|
283
285
|
return;
|
|
@@ -287,7 +289,7 @@ export function generateColumns<T>({
|
|
|
287
289
|
}
|
|
288
290
|
|
|
289
291
|
const justify = getJustify(key);
|
|
290
|
-
const wrapped =
|
|
292
|
+
const wrapped = wrappedColumnsSet.has(key);
|
|
291
293
|
const isCellSelected = cell?.getIsSelected?.() || false;
|
|
292
294
|
const canSelectCell =
|
|
293
295
|
(selection === "single-cell" || selection === "multi-cell") &&
|
|
@@ -309,6 +311,7 @@ export function generateColumns<T>({
|
|
|
309
311
|
getValue,
|
|
310
312
|
selectCell,
|
|
311
313
|
cellStyles,
|
|
314
|
+
highlightPattern: table.options.meta?.highlightPattern,
|
|
312
315
|
});
|
|
313
316
|
|
|
314
317
|
// Row headers are bold
|
|
@@ -585,12 +588,14 @@ function renderDate({
|
|
|
585
588
|
dtype,
|
|
586
589
|
displayValue,
|
|
587
590
|
locale,
|
|
591
|
+
highlightPattern,
|
|
588
592
|
}: {
|
|
589
593
|
value: Date;
|
|
590
594
|
dataType?: DataType;
|
|
591
595
|
dtype?: string;
|
|
592
596
|
displayValue?: string;
|
|
593
597
|
locale: string;
|
|
598
|
+
highlightPattern?: RegExp;
|
|
594
599
|
}): React.ReactNode {
|
|
595
600
|
const type = dataType === "date" ? "date" : "datetime";
|
|
596
601
|
const timezone = extractTimezone(dtype);
|
|
@@ -599,7 +604,7 @@ function renderDate({
|
|
|
599
604
|
|
|
600
605
|
return (
|
|
601
606
|
<DatePopover date={value} type={type}>
|
|
602
|
-
{exactValue}
|
|
607
|
+
{highlightMatches(exactValue, highlightPattern)}
|
|
603
608
|
</DatePopover>
|
|
604
609
|
);
|
|
605
610
|
}
|
|
@@ -610,12 +615,14 @@ export function renderCellValue<TData, TValue>({
|
|
|
610
615
|
getValue,
|
|
611
616
|
selectCell,
|
|
612
617
|
cellStyles,
|
|
618
|
+
highlightPattern,
|
|
613
619
|
}: {
|
|
614
620
|
column: Column<TData, TValue>;
|
|
615
621
|
renderValue: () => TValue | null;
|
|
616
622
|
getValue: () => TValue;
|
|
617
623
|
selectCell?: () => void;
|
|
618
624
|
cellStyles?: string;
|
|
625
|
+
highlightPattern?: RegExp;
|
|
619
626
|
}) {
|
|
620
627
|
const value = getValue();
|
|
621
628
|
const format = column.getColumnFormatting?.();
|
|
@@ -625,6 +632,28 @@ export function renderCellValue<TData, TValue>({
|
|
|
625
632
|
|
|
626
633
|
const isWrapped = column.getColumnWrapping?.() === "wrap";
|
|
627
634
|
|
|
635
|
+
const textCell = (text: string) => (
|
|
636
|
+
<div onClick={selectCell} className={cellStyles}>
|
|
637
|
+
{highlightMatches(text, highlightPattern)}
|
|
638
|
+
</div>
|
|
639
|
+
);
|
|
640
|
+
const dateCell = (date: Date, displayValue?: string) => (
|
|
641
|
+
<div onClick={selectCell} className={cellStyles}>
|
|
642
|
+
<WithLocale>
|
|
643
|
+
{(locale) =>
|
|
644
|
+
renderDate({
|
|
645
|
+
value: date,
|
|
646
|
+
dataType,
|
|
647
|
+
dtype,
|
|
648
|
+
displayValue,
|
|
649
|
+
locale,
|
|
650
|
+
highlightPattern,
|
|
651
|
+
})
|
|
652
|
+
}
|
|
653
|
+
</WithLocale>
|
|
654
|
+
</div>
|
|
655
|
+
);
|
|
656
|
+
|
|
628
657
|
// Sentinel values (null, whitespace, NaN, Infinity, NaT) rendered specially.
|
|
629
658
|
// Empty strings are left as-is
|
|
630
659
|
const sentinel = detectSentinel(value, dataType, dtype);
|
|
@@ -640,23 +669,10 @@ export function renderCellValue<TData, TValue>({
|
|
|
640
669
|
try {
|
|
641
670
|
const date = new Date(value);
|
|
642
671
|
if (!format || !isValid(date)) {
|
|
643
|
-
return (
|
|
644
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
645
|
-
{value}
|
|
646
|
-
</div>
|
|
647
|
-
);
|
|
672
|
+
return textCell(value);
|
|
648
673
|
}
|
|
649
674
|
|
|
650
|
-
|
|
651
|
-
return (
|
|
652
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
653
|
-
<WithLocale>
|
|
654
|
-
{(locale) =>
|
|
655
|
-
renderDate({ value: date, dataType, dtype, displayValue, locale })
|
|
656
|
-
}
|
|
657
|
-
</WithLocale>
|
|
658
|
-
</div>
|
|
659
|
-
);
|
|
675
|
+
return dateCell(date, String(column.applyColumnFormatting(value)));
|
|
660
676
|
} catch (error) {
|
|
661
677
|
Logger.error("Error parsing datetime, fallback to string", error);
|
|
662
678
|
}
|
|
@@ -672,17 +688,9 @@ export function renderCellValue<TData, TValue>({
|
|
|
672
688
|
}
|
|
673
689
|
|
|
674
690
|
// e.g. 2010-10-07 17:15:00
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
: undefined
|
|
678
|
-
return (
|
|
679
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
680
|
-
<WithLocale>
|
|
681
|
-
{(locale) =>
|
|
682
|
-
renderDate({ value, dataType, dtype, displayValue, locale })
|
|
683
|
-
}
|
|
684
|
-
</WithLocale>
|
|
685
|
-
</div>
|
|
691
|
+
return dateCell(
|
|
692
|
+
value,
|
|
693
|
+
format ? String(column.applyColumnFormatting(value)) : undefined,
|
|
686
694
|
);
|
|
687
695
|
}
|
|
688
696
|
|
|
@@ -728,7 +736,7 @@ export function renderCellValue<TData, TValue>({
|
|
|
728
736
|
className={cn(cellStyles, isWrapped && COLUMN_WRAPPING_STYLES)}
|
|
729
737
|
>
|
|
730
738
|
<WhitespaceMarkers value={leading} />
|
|
731
|
-
<UrlDetector parts={parts} />
|
|
739
|
+
<UrlDetector parts={parts} highlightPattern={highlightPattern} />
|
|
732
740
|
<WhitespaceMarkers value={trailing} />
|
|
733
741
|
</div>
|
|
734
742
|
);
|
|
@@ -754,11 +762,7 @@ export function renderCellValue<TData, TValue>({
|
|
|
754
762
|
}
|
|
755
763
|
|
|
756
764
|
if (format) {
|
|
757
|
-
return (
|
|
758
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
759
|
-
{column.applyColumnFormatting(value)}
|
|
760
|
-
</div>
|
|
761
|
-
);
|
|
765
|
+
return textCell(String(column.applyColumnFormatting(value)));
|
|
762
766
|
}
|
|
763
767
|
|
|
764
768
|
// Format to the correct locale
|
|
@@ -768,26 +772,19 @@ export function renderCellValue<TData, TValue>({
|
|
|
768
772
|
<LocaleNumber
|
|
769
773
|
value={value}
|
|
770
774
|
minFractionDigits={column.columnDef.meta?.minFractionDigits}
|
|
775
|
+
highlightPattern={highlightPattern}
|
|
771
776
|
/>
|
|
772
777
|
</div>
|
|
773
778
|
);
|
|
774
779
|
}
|
|
775
780
|
|
|
776
781
|
if (typeof value === "boolean") {
|
|
777
|
-
return (
|
|
778
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
779
|
-
{value ? "True" : "False"}
|
|
780
|
-
</div>
|
|
781
|
-
);
|
|
782
|
+
return textCell(value ? "True" : "False");
|
|
782
783
|
}
|
|
783
784
|
|
|
784
785
|
if (isPrimitiveOrNullish(value)) {
|
|
785
786
|
const rendered = renderValue();
|
|
786
|
-
return (
|
|
787
|
-
<div onClick={selectCell} className={cellStyles}>
|
|
788
|
-
{rendered == null ? "" : String(rendered)}
|
|
789
|
-
</div>
|
|
790
|
-
);
|
|
787
|
+
return textCell(rendered == null ? "" : String(rendered));
|
|
791
788
|
}
|
|
792
789
|
|
|
793
790
|
const mimeValues = getMimeValues(value);
|
|
@@ -825,14 +822,16 @@ export function renderCellValue<TData, TValue>({
|
|
|
825
822
|
export const LocaleNumber = ({
|
|
826
823
|
value,
|
|
827
824
|
minFractionDigits,
|
|
825
|
+
highlightPattern,
|
|
828
826
|
}: {
|
|
829
827
|
value: number;
|
|
830
828
|
minFractionDigits?: number;
|
|
829
|
+
highlightPattern?: RegExp;
|
|
831
830
|
}) => {
|
|
832
831
|
const { locale } = useLocale();
|
|
833
832
|
const format = useNumberFormatter({
|
|
834
833
|
minimumFractionDigits: minFractionDigits,
|
|
835
834
|
maximumFractionDigits: maxFractionalDigits(locale),
|
|
836
835
|
});
|
|
837
|
-
return format.format(value);
|
|
836
|
+
return highlightMatches(format.format(value), highlightPattern);
|
|
838
837
|
};
|
|
@@ -12,7 +12,7 @@ import { Logger } from "@/utils/Logger";
|
|
|
12
12
|
import type { Cell } from "@tanstack/react-table";
|
|
13
13
|
import { useAtomValue } from "jotai";
|
|
14
14
|
import { CopyIcon, FilterIcon, SquareStack } from "lucide-react";
|
|
15
|
-
import type
|
|
15
|
+
import { type RefObject, useRef, useState } from "react";
|
|
16
16
|
import useEvent from "react-use-event-hook";
|
|
17
17
|
import {
|
|
18
18
|
ContextMenu,
|
|
@@ -123,8 +123,21 @@ export const DataTableContextMenu = <TData,>({
|
|
|
123
123
|
tableRef: RefObject<HTMLTableSectionElement | null>;
|
|
124
124
|
copyAllCells: () => void;
|
|
125
125
|
}) => {
|
|
126
|
+
const [activeCell, setActiveCell] = useState<Cell<TData, unknown> | null>(
|
|
127
|
+
null,
|
|
128
|
+
);
|
|
129
|
+
const highlightedCell = useRef<Element | null>(null);
|
|
126
130
|
const handleContextMenuChange = useEvent((open: boolean) => {
|
|
131
|
+
highlightedCell.current?.classList.remove("bg-(--green-4)");
|
|
132
|
+
highlightedCell.current = null;
|
|
133
|
+
if (!open) {
|
|
134
|
+
// Forget the cell so a later right-click outside any cell can't reuse it
|
|
135
|
+
contextMenuRef.current = null;
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
127
139
|
const cell = contextMenuRef.current;
|
|
140
|
+
setActiveCell(cell);
|
|
128
141
|
if (!cell) {
|
|
129
142
|
return;
|
|
130
143
|
}
|
|
@@ -138,42 +151,45 @@ export const DataTableContextMenu = <TData,>({
|
|
|
138
151
|
return;
|
|
139
152
|
}
|
|
140
153
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
} else {
|
|
144
|
-
cellElement.classList.remove("bg-(--green-4)");
|
|
145
|
-
}
|
|
154
|
+
cellElement.classList.add("bg-(--green-4)");
|
|
155
|
+
highlightedCell.current = cellElement;
|
|
146
156
|
});
|
|
147
157
|
|
|
148
158
|
return (
|
|
149
|
-
|
|
150
|
-
|
|
159
|
+
// Open via the trigger so a right-click while already open retargets the
|
|
160
|
+
// menu; Radix only reports open changes, so use it for closing.
|
|
161
|
+
<ContextMenu
|
|
162
|
+
onOpenChange={(open) => {
|
|
163
|
+
if (!open) {
|
|
164
|
+
handleContextMenuChange(false);
|
|
165
|
+
}
|
|
166
|
+
}}
|
|
167
|
+
>
|
|
168
|
+
<ContextMenuTrigger
|
|
169
|
+
asChild={true}
|
|
170
|
+
onContextMenu={() => handleContextMenuChange(true)}
|
|
171
|
+
>
|
|
172
|
+
{tableBody}
|
|
173
|
+
</ContextMenuTrigger>
|
|
151
174
|
<ContextMenuPortal>
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
/>
|
|
175
|
+
{activeCell && (
|
|
176
|
+
<CellContextMenu cell={activeCell} copySelectedCells={copyAllCells} />
|
|
177
|
+
)}
|
|
156
178
|
</ContextMenuPortal>
|
|
157
179
|
</ContextMenu>
|
|
158
180
|
);
|
|
159
181
|
};
|
|
160
182
|
|
|
161
183
|
export const CellContextMenu = <TData,>({
|
|
162
|
-
|
|
184
|
+
cell,
|
|
163
185
|
copySelectedCells,
|
|
164
186
|
}: {
|
|
165
|
-
|
|
187
|
+
cell: Cell<TData, unknown>;
|
|
166
188
|
copySelectedCells: () => void;
|
|
167
189
|
}) => {
|
|
168
190
|
const selectedCells = useAtomValue(selectedCellsAtom);
|
|
169
191
|
const multipleSelectedCells = selectedCells.size > 1;
|
|
170
192
|
|
|
171
|
-
const cell = cellRef.current;
|
|
172
|
-
if (!cell) {
|
|
173
|
-
Logger.error("No cell found in context menu");
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
193
|
const table = cell.getContext().table;
|
|
178
194
|
const displayedValue = cell.getValue();
|
|
179
195
|
const rawValue =
|
|
@@ -58,6 +58,7 @@ import { useColumnPinning } from "./hooks/use-column-pinning";
|
|
|
58
58
|
import { useScrollContainerHeight } from "./hooks/use-scroll-container-height";
|
|
59
59
|
import { CellSelectionProvider } from "./range-focus/provider";
|
|
60
60
|
import { DataTableBody, renderTableHeader } from "./renderers";
|
|
61
|
+
import { buildHighlightPattern } from "./search-highlight";
|
|
61
62
|
import { TableBottomBar } from "./TableBottomBar";
|
|
62
63
|
import { TableTopBar } from "./TableTopBar";
|
|
63
64
|
import {
|
|
@@ -231,6 +232,11 @@ const DataTableInternal = <TData,>({
|
|
|
231
232
|
return idx + offset;
|
|
232
233
|
}
|
|
233
234
|
|
|
235
|
+
const highlightPattern = React.useMemo(
|
|
236
|
+
() => buildHighlightPattern(searchQuery),
|
|
237
|
+
[searchQuery],
|
|
238
|
+
);
|
|
239
|
+
|
|
234
240
|
const table = useReactTable<TData>({
|
|
235
241
|
_features: [
|
|
236
242
|
ColumnPinning,
|
|
@@ -245,7 +251,7 @@ const DataTableInternal = <TData,>({
|
|
|
245
251
|
],
|
|
246
252
|
data,
|
|
247
253
|
columns,
|
|
248
|
-
meta: { rawData },
|
|
254
|
+
meta: { rawData, highlightPattern },
|
|
249
255
|
getCoreRowModel: getCoreRowModel(),
|
|
250
256
|
// pagination
|
|
251
257
|
rowCount: totalRows === "too_many" ? undefined : totalRows,
|
|
@@ -396,6 +402,12 @@ const DataTableInternal = <TData,>({
|
|
|
396
402
|
</Banner>
|
|
397
403
|
)}
|
|
398
404
|
<Table
|
|
405
|
+
role={table.options.enableCellSelection ? "grid" : undefined}
|
|
406
|
+
aria-multiselectable={
|
|
407
|
+
table.options.enableCellSelection
|
|
408
|
+
? table.options.enableMultiCellSelection
|
|
409
|
+
: undefined
|
|
410
|
+
}
|
|
399
411
|
className={cn(
|
|
400
412
|
"relative",
|
|
401
413
|
columns.length <= AUTO_WIDTH_MAX_COLUMNS ? "w-auto" : "w-full",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
import React from "react";
|
|
2
|
+
import React, { useMemo } from "react";
|
|
3
3
|
import { useDateFormatter, useLocale } from "react-aria";
|
|
4
4
|
import { Tooltip } from "@/components/ui/tooltip";
|
|
5
5
|
|
|
@@ -45,6 +45,7 @@ export const DatePopover: React.FC<DatePopoverProps> = ({
|
|
|
45
45
|
|
|
46
46
|
const TimezoneDisplay = ({ date }: { date: Date }) => {
|
|
47
47
|
const { locale } = useLocale();
|
|
48
|
+
// The system timezone can change without the locale changing.
|
|
48
49
|
const localTimezone = new Intl.DateTimeFormat(locale).resolvedOptions()
|
|
49
50
|
.timeZone;
|
|
50
51
|
const hasSubSeconds = date.getUTCMilliseconds() !== 0;
|
|
@@ -116,9 +117,10 @@ const RelativeTime = ({ date }: { date: Date }) => {
|
|
|
116
117
|
const { locale } = useLocale();
|
|
117
118
|
|
|
118
119
|
// Initialize relative time formatter with current locale and "auto" numeric style
|
|
119
|
-
const relativeTimeFormatter =
|
|
120
|
-
numeric: "auto",
|
|
121
|
-
|
|
120
|
+
const relativeTimeFormatter = useMemo(
|
|
121
|
+
() => new Intl.RelativeTimeFormat(locale, { numeric: "auto" }),
|
|
122
|
+
[locale],
|
|
123
|
+
);
|
|
122
124
|
|
|
123
125
|
const currentTime = new Date();
|
|
124
126
|
// Get difference in seconds between now and the input date
|
|
@@ -24,6 +24,7 @@ import type {
|
|
|
24
24
|
GetExportMetadata,
|
|
25
25
|
} from "./schemas";
|
|
26
26
|
import { useAsyncData } from "@/hooks/useAsyncData";
|
|
27
|
+
import { useStateForKey } from "@/hooks/useStateForKey";
|
|
27
28
|
import { logNever } from "@/utils/assertNever";
|
|
28
29
|
import { cn } from "@/utils/cn";
|
|
29
30
|
import { copyToClipboard } from "@/utils/copy";
|
|
@@ -354,7 +355,6 @@ interface ExportContext {
|
|
|
354
355
|
export const ExportActions: React.FC<ExportActionProps> = (props) => {
|
|
355
356
|
const { getExportMetadata, metadataSource } = props;
|
|
356
357
|
const [exportDialogOpen, setExportDialogOpen] = React.useState(false);
|
|
357
|
-
const [failure, setFailure] = React.useState<ExportFailure | null>(null);
|
|
358
358
|
const [settings, setSettings] =
|
|
359
359
|
React.useState<ExportSettings>(DEFAULT_SETTINGS);
|
|
360
360
|
const [exportContext, setExportContext] = React.useState<ExportContext>(
|
|
@@ -363,6 +363,10 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
|
|
|
363
363
|
if (exportContext.source !== metadataSource) {
|
|
364
364
|
setExportContext({ source: metadataSource });
|
|
365
365
|
}
|
|
366
|
+
const [failure, setFailure] = useStateForKey<ExportFailure | null>(
|
|
367
|
+
exportContext,
|
|
368
|
+
() => null,
|
|
369
|
+
);
|
|
366
370
|
const mounted = React.useRef(false);
|
|
367
371
|
const isCurrentContext = useEvent(
|
|
368
372
|
(context: ExportContext) => mounted.current && context === exportContext,
|
|
@@ -416,7 +420,6 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
|
|
|
416
420
|
}, []);
|
|
417
421
|
React.useEffect(() => {
|
|
418
422
|
latestActionId.current += 1;
|
|
419
|
-
setFailure(null);
|
|
420
423
|
}, [metadataSource]);
|
|
421
424
|
const policy = useAtomValue(downloadSizeLimitAtom);
|
|
422
425
|
const overLimit = !!(
|
|
@@ -452,7 +455,6 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
|
|
|
452
455
|
setExportDialogOpen(open);
|
|
453
456
|
if (!open) {
|
|
454
457
|
latestActionId.current += 1;
|
|
455
|
-
setFailure(null);
|
|
456
458
|
setExpandedFormat(null);
|
|
457
459
|
setSettings(DEFAULT_SETTINGS);
|
|
458
460
|
setGeometryColumn(null);
|
|
@@ -761,7 +763,10 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
|
|
|
761
763
|
const expanded =
|
|
762
764
|
configurableFormat !== null &&
|
|
763
765
|
expandedFormat === configurableFormat;
|
|
766
|
+
const FormatHeader = configurableFormat ? "button" : "div";
|
|
764
767
|
const panelId = `export-options-${option.format}`;
|
|
768
|
+
const descriptionId = `${panelId}-description`;
|
|
769
|
+
const summaryId = `${panelId}-summary`;
|
|
765
770
|
const rowFailure =
|
|
766
771
|
failure?.action.format === option.format ? failure : null;
|
|
767
772
|
const summary =
|
|
@@ -802,55 +807,78 @@ export const ExportActions: React.FC<ExportActionProps> = (props) => {
|
|
|
802
807
|
data-testid={`export-row-${option.format}`}
|
|
803
808
|
className={cn(expanded && "bg-muted/40")}
|
|
804
809
|
>
|
|
805
|
-
<div className="grid
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
810
|
+
<div className="grid grid-cols-[minmax(0,1fr)_auto] items-center hover:bg-accent/50">
|
|
811
|
+
<FormatHeader
|
|
812
|
+
type={configurableFormat ? "button" : undefined}
|
|
813
|
+
className={cn(
|
|
814
|
+
"grid min-h-[60px] min-w-0 grid-cols-[28px_minmax(0,1fr)] items-center gap-x-1 py-2 pl-2.5 pr-1 text-left",
|
|
815
|
+
configurableFormat &&
|
|
816
|
+
"cursor-pointer focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
|
|
817
|
+
)}
|
|
818
|
+
aria-label={
|
|
819
|
+
configurableFormat ? `${optionLabel} options` : undefined
|
|
820
|
+
}
|
|
821
|
+
aria-describedby={
|
|
822
|
+
configurableFormat
|
|
823
|
+
? [descriptionId, summary && summaryId]
|
|
824
|
+
.filter(Boolean)
|
|
825
|
+
.join(" ")
|
|
826
|
+
: undefined
|
|
827
|
+
}
|
|
828
|
+
aria-expanded={configurableFormat ? expanded : undefined}
|
|
829
|
+
aria-controls={configurableFormat ? panelId : undefined}
|
|
830
|
+
onClick={
|
|
831
|
+
configurableFormat
|
|
832
|
+
? () => toggleExpanded(option.format)
|
|
833
|
+
: undefined
|
|
834
|
+
}
|
|
835
|
+
>
|
|
836
|
+
<span
|
|
837
|
+
aria-hidden={true}
|
|
838
|
+
className="inline-flex h-6 w-6 items-center justify-center"
|
|
815
839
|
>
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
840
|
+
{configurableFormat && (
|
|
841
|
+
<ChevronRightIcon
|
|
842
|
+
className={cn(
|
|
843
|
+
"h-4 w-4 text-muted-foreground transition-transform",
|
|
844
|
+
expanded && "rotate-90",
|
|
845
|
+
)}
|
|
846
|
+
/>
|
|
847
|
+
)}
|
|
848
|
+
</span>
|
|
849
|
+
<span className="flex min-w-0 items-center gap-3 pl-1">
|
|
850
|
+
<option.icon
|
|
851
|
+
aria-hidden={true}
|
|
852
|
+
data-testid={`export-format-icon-${option.format}`}
|
|
853
|
+
className="h-4 w-4 shrink-0 text-muted-foreground"
|
|
821
854
|
/>
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
<div className="flex min-w-0 items-center gap-3 pl-1">
|
|
827
|
-
<option.icon
|
|
828
|
-
aria-hidden={true}
|
|
829
|
-
data-testid={`export-format-icon-${option.format}`}
|
|
830
|
-
className="h-4 w-4 shrink-0 text-muted-foreground"
|
|
831
|
-
/>
|
|
832
|
-
<div className="grid min-w-0 gap-1">
|
|
833
|
-
<span className="flex min-w-0 items-baseline gap-x-2">
|
|
834
|
-
<span className="text-sm font-medium leading-tight">
|
|
835
|
-
{optionLabel}
|
|
836
|
-
</span>
|
|
837
|
-
{summary && (
|
|
838
|
-
<span
|
|
839
|
-
data-testid={`export-summary-${option.format}`}
|
|
840
|
-
className="min-w-0 truncate text-xs text-muted-foreground"
|
|
841
|
-
>
|
|
842
|
-
{summary}
|
|
855
|
+
<span className="grid min-w-0 gap-1">
|
|
856
|
+
<span className="flex min-w-0 items-baseline gap-x-2">
|
|
857
|
+
<span className="text-sm font-medium leading-tight">
|
|
858
|
+
{optionLabel}
|
|
843
859
|
</span>
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
860
|
+
{summary && (
|
|
861
|
+
<span
|
|
862
|
+
id={summaryId}
|
|
863
|
+
data-testid={`export-summary-${option.format}`}
|
|
864
|
+
className="min-w-0 truncate text-xs text-muted-foreground"
|
|
865
|
+
>
|
|
866
|
+
{summary}
|
|
867
|
+
</span>
|
|
868
|
+
)}
|
|
869
|
+
</span>
|
|
870
|
+
<span
|
|
871
|
+
id={descriptionId}
|
|
872
|
+
className="text-xs text-muted-foreground leading-tight"
|
|
873
|
+
>
|
|
874
|
+
{option.format === "parquet" && hasGeometry
|
|
875
|
+
? "Parquet with geometry and CRS metadata"
|
|
876
|
+
: option.description}
|
|
877
|
+
</span>
|
|
850
878
|
</span>
|
|
851
|
-
</
|
|
852
|
-
</
|
|
853
|
-
<div className="flex items-center gap-0.5">
|
|
879
|
+
</span>
|
|
880
|
+
</FormatHeader>
|
|
881
|
+
<div className="flex items-center gap-0.5 pr-2.5">
|
|
854
882
|
<Tooltip
|
|
855
883
|
content={
|
|
856
884
|
option.canDownload
|
|
@@ -244,15 +244,13 @@ const {
|
|
|
244
244
|
cellId: nextCell.id,
|
|
245
245
|
};
|
|
246
246
|
|
|
247
|
-
if (isShiftKey
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
state.selectedStartCell,
|
|
251
|
-
newCell,
|
|
252
|
-
);
|
|
247
|
+
if (isShiftKey) {
|
|
248
|
+
const anchor = state.selectedStartCell ?? currentCell;
|
|
249
|
+
const cellsInRange = getCellsBetween(table, anchor, newCell);
|
|
253
250
|
return {
|
|
254
251
|
...state,
|
|
255
252
|
selectedCells: new Set(cellsInRange),
|
|
253
|
+
selectedStartCell: anchor,
|
|
256
254
|
focusedCell: newCell,
|
|
257
255
|
};
|
|
258
256
|
} else {
|