@marimo-team/islands 0.23.16-dev6 → 0.23.16-dev62
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-CJaUI-S-.js → ConnectedDataExplorerComponent-f9vLjQiF.js} +13 -13
- package/dist/{ErrorBoundary-DXlxsrTF.js → ErrorBoundary-DhLqwSWA.js} +3 -3
- package/dist/{any-language-editor-P9tjkj4n.js → any-language-editor-DifE-fl7.js} +5 -5
- package/dist/{button-BcSml68y.js → button-BSm8IXRU.js} +2 -4
- package/dist/{capabilities-BYLFYTYv.js → capabilities-C6OQ5YBO.js} +1 -1
- package/dist/{chat-ui-BdSDiVjk.js → chat-ui-DsZJj75A.js} +3117 -3120
- package/dist/{check-Cs-KV5XY.js → check-DP7U0H0G.js} +1 -1
- package/dist/{code-visibility-CfBftiVM.js → common-Bpnmu1Yz.js} +1085 -1053
- package/dist/{copy-Cs3yt6Vt.js → copy-DNq8q3zw.js} +2 -2
- package/dist/{dist-B96tMAst.js → dist-DIlxLFXG.js} +2 -2
- package/dist/{error-banner-DR7o3CbX.js → error-banner-B_GQfxxD.js} +2 -2
- package/dist/{esm-k8PIvuZW.js → esm-DzZVaNH4.js} +1 -1
- package/dist/{extends-Cq2JYHKy.js → extends-w2_S44bV.js} +4 -4
- package/dist/{formats-BFhkZJwd.js → formats-Dwq1THhr.js} +3 -3
- package/dist/{glide-data-editor--CaN-f27.js → glide-data-editor-B9K6-MJe.js} +9 -9
- package/dist/{html-to-image-DDENewl2.js → html-to-image-CZ1kLKkq.js} +7350 -6356
- package/dist/{input-DStQIuqD.js → input-C5K4VBvB.js} +7 -7
- package/dist/{label-DIk0QoFe.js → label-DjoYwqmj.js} +2 -2
- package/dist/{loader-CTHCI-qe.js → loader-DX-IDS7n.js} +1 -1
- package/dist/main.js +259 -194
- package/dist/{mermaid-CdSvixW2.js → mermaid-hv6IckVw.js} +5 -5
- package/dist/{node-sql-parser-DLl_zNw0.js → node-sql-parser-v1Vi-Fft.js} +16867 -16665
- package/dist/{process-output-2QPcgBQg.js → process-output-bVfbcx5_.js} +32 -28
- package/dist/{reveal-component-BclLkYnV.js → reveal-component-JIt3oSeU.js} +642 -634
- package/dist/{spec-CnaxwDqy.js → spec-CQKL_D3i.js} +4 -4
- package/dist/{strings-BYAhZnQi.js → strings-DIy9NAmg.js} +4 -4
- package/dist/style.css +1 -1
- package/dist/{swiper-component-DE94711u.js → swiper-component-CEdAYjb7.js} +2 -2
- package/dist/toDate-CqhBWjvO.js +713 -0
- package/dist/{tooltip-B-qh7UPB.js → tooltip-f-qR0iUx.js} +3 -3
- package/dist/{types-DQl7jVYK.js → types-DicH9Oi0.js} +1 -1
- package/dist/{useAsyncData-CvO8WUy3.js → useAsyncData-CYOQb1EW.js} +1 -1
- package/dist/{useDateFormatter-BSoGim-G.js → useDateFormatter-Bt2qr_XS.js} +2 -2
- package/dist/{useDeepCompareMemoize-J3MKRdA4.js → useDeepCompareMemoize-CSHQeQEI.js} +1 -1
- package/dist/{useIframeCapabilities-POcFXHbw.js → useIframeCapabilities-kA09ykNq.js} +1 -1
- package/dist/{useLifecycle-DqPxHgAN.js → useLifecycle-CMJGqBaY.js} +3 -3
- package/dist/{useTheme-XMq9mNf_.js → useTheme-DYfby65G.js} +2 -2
- package/dist/{vega-component-CrFoZT1S.js → vega-component-C7nO5zcf.js} +10 -10
- package/dist/{zod-D0yOqoGe.js → zod-BUcyXSdR.js} +1 -1
- package/package.json +3 -4
- package/src/__mocks__/requests.ts +56 -4
- package/src/components/data-table/__tests__/__snapshots__/chart-spec-model.test.ts.snap +174 -21
- package/src/components/data-table/__tests__/chart-spec-model.test.ts +102 -1
- package/src/components/data-table/__tests__/columns.test.tsx +9 -1
- package/src/components/data-table/column-summary/chart-spec-model.tsx +163 -103
- package/src/components/data-table/column-summary/legacy-chart-spec.ts +15 -7
- package/src/components/data-table/column-summary/utils.ts +26 -7
- package/src/components/data-table/columns.tsx +11 -1
- package/src/components/data-table/types.ts +1 -1
- package/src/components/editor/__tests__/viewer-banner.test.tsx +14 -0
- package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +99 -18
- package/src/components/editor/actions/__tests__/pdf-export.test.ts +32 -13
- package/src/components/editor/actions/pair-with-agent-commands.ts +21 -10
- package/src/components/editor/actions/pair-with-agent-modal.tsx +2 -2
- package/src/components/editor/actions/pdf-export.ts +11 -14
- package/src/components/editor/actions/useNotebookActions.tsx +28 -19
- package/src/components/editor/cell/code/__tests__/cell-editor-activity-lifecycle.test.ts +250 -0
- package/src/components/editor/cell/code/cell-editor.tsx +13 -7
- package/src/components/editor/chrome/__tests__/state.test.ts +7 -1
- package/src/components/editor/chrome/panels/__tests__/logs-panel.test.tsx +25 -0
- package/src/components/editor/chrome/panels/__tests__/panel-accordion-state.test.ts +42 -0
- package/src/components/editor/chrome/panels/file-explorer-panel.tsx +6 -17
- package/src/components/editor/chrome/panels/logs-panel.tsx +12 -2
- package/src/components/editor/chrome/panels/panel-accordion-state.ts +51 -0
- package/src/components/editor/chrome/panels/session-panel.tsx +5 -16
- package/src/components/editor/chrome/panels/write-secret-modal.tsx +40 -12
- package/src/components/editor/chrome/state.ts +10 -0
- package/src/components/editor/connections/__tests__/json-credentials.test.ts +114 -0
- package/src/components/editor/connections/__tests__/paths.test.ts +39 -0
- package/src/components/editor/connections/__tests__/quick-add-data-sources.test.tsx +113 -0
- package/src/components/editor/connections/add-connection-dialog.tsx +2 -0
- package/src/components/editor/connections/components.tsx +6 -2
- package/src/components/editor/connections/database/__tests__/__snapshots__/as-code.test.ts.snap +27 -5
- package/src/components/editor/connections/database/__tests__/as-code.test.ts +33 -0
- package/src/components/editor/connections/database/as-code.ts +37 -13
- package/src/components/editor/connections/database/schemas.ts +6 -5
- package/src/components/editor/connections/form-renderers.tsx +99 -1
- package/src/components/editor/connections/json-credentials.ts +57 -0
- package/src/components/editor/connections/paths.ts +21 -0
- package/src/components/editor/connections/quick-add-data-sources.tsx +106 -0
- package/src/components/editor/connections/secret-combobox.tsx +41 -20
- package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap +88 -2
- package/src/components/editor/connections/storage/__tests__/as-code.test.ts +128 -8
- package/src/components/editor/connections/storage/as-code.ts +79 -36
- package/src/components/editor/connections/storage/schemas.ts +85 -44
- package/src/components/editor/file-tree/__tests__/renderers.test.ts +31 -0
- package/src/components/editor/file-tree/file-viewer.tsx +11 -7
- package/src/components/editor/file-tree/renderers.tsx +21 -0
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +2 -2
- package/src/components/editor/viewer-banner.tsx +6 -1
- package/src/components/forms/form.tsx +59 -24
- package/src/components/forms/options.ts +2 -1
- package/src/components/slides/__tests__/cell-output-block.test.tsx +40 -0
- package/src/components/slides/__tests__/slide-cell-view.test.tsx +33 -0
- package/src/components/slides/reveal-component.tsx +22 -17
- package/src/components/slides/slide-cell-view.tsx +1 -1
- package/src/components/slides/slides.css +4 -2
- package/src/components/static-html/share-modal.tsx +1 -1
- package/src/components/ui/input.tsx +1 -1
- package/src/core/ai/context/providers/file.ts +8 -29
- package/src/core/cells/__tests__/cells.test.ts +12 -2
- package/src/core/cells/__tests__/logs.test.ts +5 -5
- package/src/core/cells/cells.ts +17 -4
- package/src/core/cells/document-changes.ts +1 -0
- package/src/core/cells/logs.ts +14 -4
- package/src/core/codemirror/cm.ts +3 -0
- package/src/core/codemirror/code-lens/__tests__/actions.test.ts +68 -0
- package/src/core/codemirror/code-lens/__tests__/analyzer.test.ts +224 -0
- package/src/core/codemirror/code-lens/__tests__/entities.test.ts +175 -0
- package/src/core/codemirror/code-lens/__tests__/extension.test.ts +325 -0
- package/src/core/codemirror/code-lens/__tests__/perf.test.ts +121 -0
- package/src/core/codemirror/code-lens/__tests__/popover.test.ts +93 -0
- package/src/core/codemirror/code-lens/actions.ts +33 -0
- package/src/core/codemirror/code-lens/analyzer.ts +284 -0
- package/src/core/codemirror/code-lens/entities.ts +123 -0
- package/src/core/codemirror/code-lens/extension.ts +298 -0
- package/src/core/codemirror/code-lens/icons.ts +36 -0
- package/src/core/codemirror/code-lens/popover.tsx +240 -0
- package/src/core/codemirror/copilot/__tests__/language-server.test.ts +396 -100
- package/src/core/codemirror/copilot/__tests__/transport.test.ts +128 -540
- package/src/core/codemirror/copilot/language-server.ts +182 -70
- package/src/core/codemirror/copilot/transport.ts +15 -207
- package/src/core/codemirror/copilot/types.ts +9 -2
- package/src/core/codemirror/find-replace/__tests__/navigate.test.ts +42 -30
- package/src/core/codemirror/find-replace/navigate.ts +2 -0
- package/src/core/codemirror/go-to-definition/__tests__/commands.test.ts +24 -3
- package/src/core/codemirror/go-to-definition/commands.ts +93 -90
- package/src/core/codemirror/keymaps/__tests__/keymaps.test.ts +31 -2
- package/src/core/codemirror/keymaps/keymaps.ts +12 -0
- package/src/core/codemirror/language/__tests__/sql.test.ts +627 -61
- package/src/core/codemirror/language/languages/python.ts +23 -11
- package/src/core/codemirror/language/languages/sql/completion-store.ts +5 -1
- package/src/core/codemirror/language/languages/sql/renderers.tsx +3 -3
- package/src/core/codemirror/language/languages/sql/sql.ts +251 -16
- package/src/core/codemirror/lsp/__tests__/federated-lsp.test.ts +161 -0
- package/src/core/codemirror/lsp/__tests__/log-messages.test.ts +53 -0
- package/src/core/codemirror/lsp/__tests__/normalize-markdown-math.test.ts +25 -0
- package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +598 -156
- package/src/core/codemirror/lsp/__tests__/transports.test.ts +112 -0
- package/src/core/codemirror/lsp/federated-lsp.ts +76 -23
- package/src/core/codemirror/lsp/log-messages.ts +37 -0
- package/src/core/codemirror/lsp/normalize-markdown-math.ts +8 -4
- package/src/core/codemirror/lsp/notebook-lsp.ts +220 -56
- package/src/core/codemirror/lsp/transports.ts +8 -1
- package/src/core/codemirror/lsp/types.ts +68 -8
- package/src/core/codemirror/lsp/utils.ts +14 -0
- package/src/core/codemirror/python-node-names.ts +90 -0
- package/src/core/codemirror/reactive-references/analyzer.ts +52 -57
- package/src/core/codemirror/utils.ts +28 -0
- package/src/core/config/feature-flag.tsx +3 -1
- package/src/core/datasets/data-source-discovery.ts +5 -0
- package/src/core/datasets/request-registry.ts +11 -0
- package/src/core/edit-app.tsx +1 -2
- package/src/core/export/__tests__/hooks.test.ts +2 -4
- package/src/core/export/hooks.ts +4 -3
- package/src/core/hotkeys/hotkeys.ts +0 -2
- package/src/core/islands/__tests__/bridge.test.ts +107 -0
- package/src/core/islands/bootstrap.ts +1 -0
- package/src/core/islands/bridge.ts +18 -0
- package/src/core/kernel/messages.ts +2 -0
- package/src/core/lsp/__tests__/transport.test.ts +509 -337
- package/src/core/lsp/transport.ts +304 -132
- package/src/core/mode.ts +10 -0
- package/src/core/network/__tests__/api.test.ts +42 -0
- package/src/core/network/__tests__/connection.test.ts +45 -0
- package/src/core/network/__tests__/requests-lazy.test.ts +47 -1
- package/src/core/network/__tests__/requests-network.test.ts +48 -0
- package/src/core/network/api.ts +27 -0
- package/src/core/network/connection.ts +15 -0
- package/src/core/network/requests-lazy.ts +3 -0
- package/src/core/network/requests-network.ts +31 -8
- package/src/core/network/requests-static.ts +3 -0
- package/src/core/network/requests-toasting.tsx +3 -0
- package/src/core/network/types.ts +27 -6
- package/src/core/rtc/state.ts +9 -0
- package/src/core/static/download-html.ts +5 -14
- package/src/core/wasm/__tests__/bridge.test.ts +99 -5
- package/src/core/wasm/bridge.ts +42 -9
- package/src/core/wasm/worker/types.ts +10 -3
- package/src/core/wasm/worker/worker.ts +7 -8
- package/src/core/websocket/useMarimoKernelConnection.tsx +4 -0
- package/src/css/app/codemirror.css +16 -2
- package/src/hooks/__tests__/useDataSourceDiscovery.test.ts +80 -0
- package/src/hooks/useDataSourceDiscovery.ts +18 -0
- package/src/plugins/impl/DataTablePlugin.tsx +4 -1
- package/src/plugins/impl/FormPlugin.tsx +1 -1
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +158 -0
- package/src/plugins/impl/__tests__/FormPlugin.test.tsx +162 -0
- package/src/plugins/impl/anywidget/__tests__/model.test.ts +55 -0
- package/src/plugins/impl/anywidget/model.ts +20 -5
- package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +33 -21
- package/src/plugins/impl/data-frames/forms/renderers.tsx +11 -8
- package/src/stories/log-viewer.stories.tsx +12 -6
- package/src/utils/__tests__/blob.test.ts +27 -1
- package/src/utils/__tests__/download.test.tsx +44 -4
- package/src/utils/blob.ts +24 -1
- package/src/utils/download.ts +14 -15
- package/dist/toDate-B3IRfHhw.js +0 -692
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import type { CodeLensKind } from "./entities";
|
|
4
|
+
|
|
5
|
+
// Inline SVG markup mirroring the lucide icons used by the target panels:
|
|
6
|
+
// table-2 (dataframes), database (SQL engines), hard-drive (Remote storage),
|
|
7
|
+
// database-zap (Cache).
|
|
8
|
+
const svg = (contents: string) =>
|
|
9
|
+
`<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${contents}</svg>`;
|
|
10
|
+
|
|
11
|
+
const TABLE = svg(
|
|
12
|
+
'<path d="M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18"/>',
|
|
13
|
+
);
|
|
14
|
+
const DATABASE = svg(
|
|
15
|
+
'<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 21 19V5"/><path d="M3 12A9 3 0 0 0 21 12"/>',
|
|
16
|
+
);
|
|
17
|
+
const HARD_DRIVE = svg(
|
|
18
|
+
'<line x1="22" x2="2" y1="12" y2="12"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/><line x1="6" x2="6.01" y1="16" y2="16"/><line x1="10" x2="10.01" y1="16" y2="16"/>',
|
|
19
|
+
);
|
|
20
|
+
const DATABASE_ZAP = svg(
|
|
21
|
+
'<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5V19A9 3 0 0 0 15 21.84"/><path d="M21 5V8"/><path d="M21 12L18 17H22L19 22"/><path d="M3 12A9 3 0 0 0 14.59 14.87"/>',
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export const LENS_ICONS: Record<CodeLensKind, string> = {
|
|
25
|
+
table: TABLE,
|
|
26
|
+
connection: DATABASE,
|
|
27
|
+
bucket: HARD_DRIVE,
|
|
28
|
+
cache: DATABASE_ZAP,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const LENS_TOOLTIPS: Record<CodeLensKind, string> = {
|
|
32
|
+
table: "Open in data sources",
|
|
33
|
+
connection: "Open in data sources",
|
|
34
|
+
bucket: "Open in remote storage",
|
|
35
|
+
cache: "Open cache panel",
|
|
36
|
+
};
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { Provider, useAtomValue } from "jotai";
|
|
4
|
+
import { DatabaseZapIcon } from "lucide-react";
|
|
5
|
+
import type React from "react";
|
|
6
|
+
import { useEffect } from "react";
|
|
7
|
+
import { createRoot } from "react-dom/client";
|
|
8
|
+
import { useLocale } from "react-aria";
|
|
9
|
+
import { ProtocolIcon } from "@/components/storage/components";
|
|
10
|
+
import { Badge } from "@/components/ui/badge";
|
|
11
|
+
import { cacheInfoAtom } from "@/core/cache/requests";
|
|
12
|
+
import { dataConnectionsMapAtom } from "@/core/datasets/data-source-connections";
|
|
13
|
+
import type { ConnectionName } from "@/core/datasets/engines";
|
|
14
|
+
import { datasetTablesAtom } from "@/core/datasets/state";
|
|
15
|
+
import { getRequestClient } from "@/core/network/requests";
|
|
16
|
+
import { store } from "@/core/state/jotai";
|
|
17
|
+
import { storageNamespacesAtom } from "@/core/storage/state";
|
|
18
|
+
import { variablesAtom } from "@/core/variables/state";
|
|
19
|
+
import type { VariableName } from "@/core/variables/types";
|
|
20
|
+
import { assertNever } from "@/utils/assertNever";
|
|
21
|
+
import { formatTime } from "@/utils/formatting";
|
|
22
|
+
import { prettyNumber } from "@/utils/numbers";
|
|
23
|
+
import {
|
|
24
|
+
CONTAINER_STYLES,
|
|
25
|
+
MetadataRow,
|
|
26
|
+
renderDatasourceInfo,
|
|
27
|
+
renderEmptyInfo,
|
|
28
|
+
renderTableInfo,
|
|
29
|
+
SectionHeader,
|
|
30
|
+
} from "../language/languages/sql/renderers";
|
|
31
|
+
import type { CodeLensSpec } from "./entities";
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Mounts the hover popover for a code lens into `dom`; returns a dispose
|
|
35
|
+
* function.
|
|
36
|
+
*/
|
|
37
|
+
export function mountLensPopover(
|
|
38
|
+
dom: HTMLElement,
|
|
39
|
+
spec: CodeLensSpec,
|
|
40
|
+
): () => void {
|
|
41
|
+
const root = createRoot(dom);
|
|
42
|
+
root.render(
|
|
43
|
+
<Provider store={store}>
|
|
44
|
+
<LensPopover spec={spec} />
|
|
45
|
+
</Provider>,
|
|
46
|
+
);
|
|
47
|
+
// Defer so tearing the tooltip down from inside a React event (e.g. the
|
|
48
|
+
// icon's click handler) doesn't unmount mid-render
|
|
49
|
+
return () => queueMicrotask(() => root.unmount());
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const LensPopover: React.FC<{ spec: CodeLensSpec }> = ({ spec }) => {
|
|
53
|
+
switch (spec.kind) {
|
|
54
|
+
case "table":
|
|
55
|
+
return <TablePopover name={spec.name} />;
|
|
56
|
+
case "connection":
|
|
57
|
+
return <ConnectionPopover name={spec.name} />;
|
|
58
|
+
case "bucket":
|
|
59
|
+
return <BucketPopover name={spec.name} />;
|
|
60
|
+
case "cache":
|
|
61
|
+
return (
|
|
62
|
+
<CachePopover
|
|
63
|
+
boundName={spec.cache?.boundName ?? null}
|
|
64
|
+
cacheName={spec.cache?.cacheName ?? null}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
default:
|
|
68
|
+
assertNever(spec.kind);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const TablePopover: React.FC<{ name: string }> = ({ name }) => {
|
|
73
|
+
const tables = useAtomValue(datasetTablesAtom);
|
|
74
|
+
const table = tables.find((t) => t.variable_name === name);
|
|
75
|
+
return table ? renderTableInfo(table) : renderEmptyInfo("table");
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const ConnectionPopover: React.FC<{ name: string }> = ({ name }) => {
|
|
79
|
+
const connections = useAtomValue(dataConnectionsMapAtom);
|
|
80
|
+
const connection = connections.get(name as ConnectionName);
|
|
81
|
+
if (!connection) {
|
|
82
|
+
return renderEmptyInfo("database");
|
|
83
|
+
}
|
|
84
|
+
return renderDatasourceInfo(connection);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const BucketPopover: React.FC<{ name: string }> = ({ name }) => {
|
|
88
|
+
const namespaces = useAtomValue(storageNamespacesAtom);
|
|
89
|
+
const namespace = namespaces.find((ns) => ns.name === name);
|
|
90
|
+
if (!namespace) {
|
|
91
|
+
return (
|
|
92
|
+
<div className={CONTAINER_STYLES}>
|
|
93
|
+
<span className="text-xs text-(--slate-11)">
|
|
94
|
+
No storage information available.
|
|
95
|
+
</span>
|
|
96
|
+
</div>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
return (
|
|
100
|
+
<div className={CONTAINER_STYLES}>
|
|
101
|
+
<SectionHeader
|
|
102
|
+
icon={
|
|
103
|
+
<ProtocolIcon protocol={namespace.protocol} className="w-4 h-4" />
|
|
104
|
+
}
|
|
105
|
+
title={namespace.displayName}
|
|
106
|
+
badge={
|
|
107
|
+
<Badge variant="outline" className="text-xs">
|
|
108
|
+
{namespace.protocol}
|
|
109
|
+
</Badge>
|
|
110
|
+
}
|
|
111
|
+
/>
|
|
112
|
+
<div className="flex flex-col gap-2 py-2">
|
|
113
|
+
<MetadataRow
|
|
114
|
+
label="Variable"
|
|
115
|
+
value={
|
|
116
|
+
<code className="text-xs bg-(--slate-4) px-1 rounded">
|
|
117
|
+
{namespace.name}
|
|
118
|
+
</code>
|
|
119
|
+
}
|
|
120
|
+
/>
|
|
121
|
+
<MetadataRow
|
|
122
|
+
label="Root"
|
|
123
|
+
value={
|
|
124
|
+
<code className="text-xs bg-(--slate-4) px-1 rounded">
|
|
125
|
+
{namespace.rootPath || "(root)"}
|
|
126
|
+
</code>
|
|
127
|
+
}
|
|
128
|
+
/>
|
|
129
|
+
<MetadataRow
|
|
130
|
+
label="Backend"
|
|
131
|
+
value={<span className="font-medium">{namespace.backendType}</span>}
|
|
132
|
+
/>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// `_cache_call.__repr__` starts with "hits=N misses=N", which survives the
|
|
139
|
+
// variable-preview truncation
|
|
140
|
+
const CACHE_STATS_PATTERN = /\bhits=(\d+) misses=(\d+)/;
|
|
141
|
+
|
|
142
|
+
// The popover remounts on every hover (see `mountLensPopover`), so this has
|
|
143
|
+
// to live at module scope rather than in component state: it debounces the
|
|
144
|
+
// notebook-wide `getCacheInfo` fetch across repeated hovers.
|
|
145
|
+
let lastCacheInfoFetchAt: number | null = null;
|
|
146
|
+
const CACHE_INFO_REFETCH_INTERVAL_MS = 5000;
|
|
147
|
+
|
|
148
|
+
function maybeFetchCacheInfo(): void {
|
|
149
|
+
const now = Date.now();
|
|
150
|
+
if (
|
|
151
|
+
lastCacheInfoFetchAt != null &&
|
|
152
|
+
now - lastCacheInfoFetchAt < CACHE_INFO_REFETCH_INTERVAL_MS
|
|
153
|
+
) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
lastCacheInfoFetchAt = now;
|
|
157
|
+
getRequestClient()
|
|
158
|
+
.getCacheInfo()
|
|
159
|
+
.catch(() => {
|
|
160
|
+
// Allow the next hover to retry rather than waiting out the interval.
|
|
161
|
+
lastCacheInfoFetchAt = null;
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const CachePopover: React.FC<{
|
|
166
|
+
boundName: string | null;
|
|
167
|
+
cacheName: string | null;
|
|
168
|
+
}> = ({ boundName, cacheName }) => {
|
|
169
|
+
const { locale } = useLocale();
|
|
170
|
+
const variables = useAtomValue(variablesAtom);
|
|
171
|
+
const cacheInfo = useAtomValue(cacheInfoAtom);
|
|
172
|
+
|
|
173
|
+
const variable = boundName ? variables[boundName as VariableName] : undefined;
|
|
174
|
+
const stats = variable?.dataType?.startsWith("_cache_call")
|
|
175
|
+
? variable.value?.match(CACHE_STATS_PATTERN)
|
|
176
|
+
: undefined;
|
|
177
|
+
const hasLocalStats = Boolean(stats);
|
|
178
|
+
|
|
179
|
+
// Only fetch the notebook-wide fallback when there are no per-cache stats
|
|
180
|
+
// to show, and throttle across repeated hovers so mousing over a lens
|
|
181
|
+
// several times in a row doesn't fire a fresh request every time.
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
if (hasLocalStats) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
maybeFetchCacheInfo();
|
|
187
|
+
}, [hasLocalStats]);
|
|
188
|
+
|
|
189
|
+
return (
|
|
190
|
+
<div className={CONTAINER_STYLES}>
|
|
191
|
+
<SectionHeader
|
|
192
|
+
icon={<DatabaseZapIcon className="w-4 h-4 text-(--amber-9)" />}
|
|
193
|
+
title={cacheName ?? boundName ?? "Cache"}
|
|
194
|
+
/>
|
|
195
|
+
{stats ? (
|
|
196
|
+
<div className="flex flex-col gap-2 py-2">
|
|
197
|
+
<MetadataRow
|
|
198
|
+
label="Hits"
|
|
199
|
+
value={
|
|
200
|
+
<span className="font-medium">
|
|
201
|
+
{prettyNumber(Number(stats[1]), locale)}
|
|
202
|
+
</span>
|
|
203
|
+
}
|
|
204
|
+
/>
|
|
205
|
+
<MetadataRow
|
|
206
|
+
label="Misses"
|
|
207
|
+
value={
|
|
208
|
+
<span className="font-medium">
|
|
209
|
+
{prettyNumber(Number(stats[2]), locale)}
|
|
210
|
+
</span>
|
|
211
|
+
}
|
|
212
|
+
/>
|
|
213
|
+
</div>
|
|
214
|
+
) : (
|
|
215
|
+
cacheInfo && (
|
|
216
|
+
<div className="flex flex-col gap-2 py-2">
|
|
217
|
+
<span className="text-xs font-medium text-(--slate-11)">
|
|
218
|
+
Notebook-wide
|
|
219
|
+
</span>
|
|
220
|
+
<MetadataRow
|
|
221
|
+
label="Hits"
|
|
222
|
+
value={prettyNumber(cacheInfo.hits, locale)}
|
|
223
|
+
/>
|
|
224
|
+
<MetadataRow
|
|
225
|
+
label="Misses"
|
|
226
|
+
value={prettyNumber(cacheInfo.misses, locale)}
|
|
227
|
+
/>
|
|
228
|
+
<MetadataRow
|
|
229
|
+
label="Time saved"
|
|
230
|
+
value={formatTime(cacheInfo.time, locale)}
|
|
231
|
+
/>
|
|
232
|
+
</div>
|
|
233
|
+
)
|
|
234
|
+
)}
|
|
235
|
+
<div className="pt-2 text-xs text-(--slate-10)">
|
|
236
|
+
Click to open the cache panel
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
);
|
|
240
|
+
};
|