@marimo-team/frontend 0.25.3-dev92 → 0.25.3-dev94
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-DwPjR2_8.js → CellStatus-CplYFNTy.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-D9UK8o9A.js → ConnectedDataExplorerComponent-Dft8R6l5.js} +1 -1
- package/dist/assets/{ErrorBoundary-BhXbaVBa.js → ErrorBoundary-CdGuz4a_.js} +2 -2
- package/dist/assets/{JsonOutput-Dti6dc1X.js → JsonOutput-Csbov8Fx.js} +1 -1
- package/dist/assets/{MarimoErrorOutput-BKvntkfq.js → MarimoErrorOutput-czclLlOn.js} +1 -1
- package/dist/assets/{RenderHTML-DUI47UDk.js → RenderHTML-CNDedpS4.js} +1 -1
- package/dist/assets/{RunButton-CLhvSMZG.js → RunButton-CRfdOxVd.js} +1 -1
- package/dist/assets/{add-cell-with-ai-ev63rhN4.js → add-cell-with-ai-BAIX7r0P.js} +1 -1
- package/dist/assets/{add-connection-dialog-2Tgl7Mjn.js → add-connection-dialog-DrDuM-tI.js} +1 -1
- package/dist/assets/{agent-panel-D4lNacey.js → agent-panel-CoXq_rlA.js} +1 -1
- package/dist/assets/{ai-model-dropdown-BqjVBWQp.js → ai-model-dropdown-COvWn46z.js} +1 -1
- package/dist/assets/{app-config-button-BToMQZBN.js → app-config-button-CtxoYG4F.js} +1 -1
- package/dist/assets/{blob-DMgg2NZo.js → blob-DCjrjZKW.js} +1 -1
- package/dist/assets/{cache-panel-Byolv2ht.js → cache-panel-CbWZcBu0.js} +1 -1
- package/dist/assets/{cell-editor-DGRa0o5e.js → cell-editor-BnL0Sorl.js} +1 -1
- package/dist/assets/{cell-link-D6rI90gy.js → cell-link-BFbgKiRH.js} +1 -1
- package/dist/assets/{cells-Cetiartc.js → cells-yOs72eZm.js} +1 -1
- package/dist/assets/{chat-display-CgpJ6XM4.js → chat-display-DwRM41t_.js} +1 -1
- package/dist/assets/{chat-panel-Djs36Uy4.js → chat-panel-DeTEdjxF.js} +1 -1
- package/dist/assets/{chat-ui-B_JGdp0E.js → chat-ui-D6XucD07.js} +1 -1
- package/dist/assets/{code-visibility-ny5n3-GH.js → code-visibility-DYDagVy7.js} +1 -1
- package/dist/assets/{column-preview-BIpGfTJf.js → column-preview-DXM8SqGY.js} +1 -1
- package/dist/assets/{command-palette-9pxpuKHs.js → command-palette-CA6yfNLb.js} +1 -1
- package/dist/assets/{common-D0jeQZnr.js → common-B-ZYnO1x.js} +1 -1
- package/dist/assets/{components-CJRBUI2s.js → components-CBE8cOLK.js} +1 -1
- package/dist/assets/{components-DrU8dOzy.js → components-DCo7mAWO.js} +1 -1
- package/dist/assets/{components-DkQChRNr.js → components-vu2jLG08.js} +1 -1
- package/dist/assets/{config-BWKfkUWA.js → config-CD1IuZFJ.js} +1 -1
- package/dist/assets/{config-CP8Y8_R0.js → config-DMz7oN0r.js} +1 -1
- package/dist/assets/{config-DGX7JYor.js → config-DpY86_Yq.js} +1 -1
- package/dist/assets/{createReducer-HKXUbqyz.js → createReducer-CaI_Oa0v.js} +1 -1
- package/dist/assets/{datasource-BXFNO5td.js → datasource-BakEOWsf.js} +1 -1
- package/dist/assets/{dependency-graph-panel-BFVIEz0s.js → dependency-graph-panel-DCGB3_id.js} +1 -1
- package/dist/assets/{documentation-panel-CaUMsgkg.js → documentation-panel-CpGZ2Dfn.js} +1 -1
- package/dist/assets/{download-C-q7-OBT.js → download-CV1k4XQ4.js} +1 -1
- package/dist/assets/{edit-page-VhYLLklC.js → edit-page-By7n2M84.js} +4 -4
- package/dist/assets/{error-entries-p_IDc4iy.js → error-entries-JgrZYMbe.js} +1 -1
- package/dist/assets/{error-panel-B0BwSTRv.js → error-panel-DS7HWph-.js} +1 -1
- package/dist/assets/feedback-button-Dgs_HOOC.js +1 -0
- package/dist/assets/{feedback-button-D0HjY39R.js → feedback-button-eYsTCK-g.js} +1 -1
- package/dist/assets/{file-explorer-panel-BLIEpQzW.js → file-explorer-panel-BTLwwwD4.js} +1 -1
- package/dist/assets/{file-name-input-CZ_W4QXG.js → file-name-input-BaR4h2Ud.js} +1 -1
- package/dist/assets/{floating-outline-D7DFh_29.js → floating-outline-Drd73Quo.js} +1 -1
- package/dist/assets/{gallery-page-BLgoybvc.js → gallery-page-DXUD11Rm.js} +1 -1
- package/dist/assets/{glide-data-editor-DVpOmYXo.js → glide-data-editor-DqBBoQBl.js} +1 -1
- package/dist/assets/{home-page--OLVJPiE.js → home-page-DrRto2-v.js} +1 -1
- package/dist/assets/{hooks-D0Pzb8Q4.js → hooks-D25kP4Sr.js} +1 -1
- package/dist/assets/{index-DB50a7AR.js → index-vBuAUWEe.js} +6 -6
- package/dist/assets/{input-BZdRe7pb.js → input-DmHMEZGh.js} +1 -1
- package/dist/assets/kiosk-mode-DFS6HopF.js +1 -0
- package/dist/assets/{layout-HYpXx9Kc.js → layout-DLHIGZTK.js} +3 -3
- package/dist/assets/links-DX2w97N9.js +1 -0
- package/dist/assets/{logs-panel-Cbx5BJ3w.js → logs-panel-D5AAD2s9.js} +1 -1
- package/dist/assets/{markdown-renderer-B1GLwS-C.js → markdown-renderer--CwVm4kJ.js} +1 -1
- package/dist/assets/{mermaid-B6mqMm5_.js → mermaid-BKXlWk4F.js} +1 -1
- package/dist/assets/{name-cell-input-CgINqxMv.js → name-cell-input-BFKZaNI5.js} +1 -1
- package/dist/assets/{outline-panel-DaCt5blP.js → outline-panel-qcwRnl0R.js} +1 -1
- package/dist/assets/{package-data-dv4FBHxR.js → package-data-CKPmBDtg.js} +1 -1
- package/dist/assets/{packages-panel-DRKwpeJ2.js → packages-panel-DnSryNcz.js} +1 -1
- package/dist/assets/{panel-accordion-state-C4fxJULv.js → panel-accordion-state-BwJpDMVt.js} +1 -1
- package/dist/assets/{panels-D_TmFEit.js → panels-Aqzwb3UR.js} +1 -1
- package/dist/assets/{process-output-D1KxMfN7.js → process-output-DuUfHYSr.js} +1 -1
- package/dist/assets/{readonly-code-display-DVn7_uLn.js → readonly-code-display-BY-9I_Yk.js} +1 -1
- package/dist/assets/{readonly-python-code-5F8u1711.js → readonly-python-code-DSyr-yE2.js} +1 -1
- package/dist/assets/{renderShortcut-H60uiHBp.js → renderShortcut-rUwGqKgC.js} +1 -1
- package/dist/assets/{requests-lt0JK8Jt.js → requests-BIFR-h4M.js} +1 -1
- package/dist/assets/requests-DuLJN9Tf.js +1 -0
- package/dist/assets/{reveal-component-B4rC_fg1.js → reveal-component-C_Lb7Mom.js} +1 -1
- package/dist/assets/{run-page-BHdHPiQA.js → run-page-ZTw-kCU-.js} +1 -1
- package/dist/assets/{runs-6lJxKV1w.js → runs-C49hleBy.js} +1 -1
- package/dist/assets/{runtime-details-state-BLDCeDBF.js → runtime-details-state-B7gpnuXx.js} +1 -1
- package/dist/assets/{scratchpad-panel-ChSdhkiu.js → scratchpad-panel-D2IHkKoG.js} +1 -1
- package/dist/assets/{secrets-panel-Dh3v7XPE.js → secrets-panel-bcfEKxRx.js} +1 -1
- package/dist/assets/{session-B8Y-GJnS.js → session-CMLIzZKw.js} +1 -1
- package/dist/assets/session-panel-cOSO3WCX.js +1 -0
- package/dist/assets/{snippets-panel-D7PPIwX1.js → snippets-panel-BNadUJLU.js} +1 -1
- package/dist/assets/{state-BY4_P6ko.js → state-3mcyTS9q.js} +1 -1
- package/dist/assets/{state-C0irhlOZ.js → state-B_MCKzBL.js} +1 -1
- package/dist/assets/{state-Bd_wAeZf.js → state-BaYudep3.js} +1 -1
- package/dist/assets/{state-DaWgt-rn.js → state-C5WAeuTu.js} +1 -1
- package/dist/assets/{state-Ck7FMD5A.js → state-Cv2JW3l9.js} +1 -1
- package/dist/assets/{state-pXUWLVXv.js → state-_1LTGJQM.js} +1 -1
- package/dist/assets/{switch-IoWE8PbW.js → switch-DYjBfpNJ.js} +1 -1
- package/dist/assets/{terminal-BwLC9HS5.js → terminal-Ca-kubKb.js} +1 -1
- package/dist/assets/{tracing-WN4XSiAm.js → tracing-DbTgS4u9.js} +1 -1
- package/dist/assets/{tracing-panel-BVC4DsH6.js → tracing-panel-CjlrpXPy.js} +2 -2
- package/dist/assets/{tree-actions-MaUvbTxA.js → tree-actions-C_KYlaSv.js} +1 -1
- package/dist/assets/{useAddCell-D7SKNQll.js → useAddCell-C0J8quGE.js} +1 -1
- package/dist/assets/{useAsyncData-DhhdOGGd.js → useAsyncData-qvoPYHtx.js} +1 -1
- package/dist/assets/{useBoolean-WABMLM83.js → useBoolean-Dd2nWXFJ.js} +1 -1
- package/dist/assets/{useCellActionButton-Byz7LlUo.js → useCellActionButton-CbkOj6BE.js} +1 -1
- package/dist/assets/{useDebounce-k9QTpQ9-.js → useDebounce-DwTQ_1Pu.js} +1 -1
- package/dist/assets/{useDeepCompareMemoize-DFIVN9dn.js → useDeepCompareMemoize-B2DVK2De.js} +1 -1
- package/dist/assets/{useDeleteCell-D-k2fD1X.js → useDeleteCell-DHkF5wgS.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-neRJ4T16.js → useDependencyPanelTab--yXJW6X5.js} +1 -1
- package/dist/assets/{useEvent-Dfcbgjhg.js → useEvent-BDjgaBtz.js} +1 -1
- package/dist/assets/{useInstallPackage-CWcPxSLP.js → useInstallPackage-wcDq9hYT.js} +1 -1
- package/dist/assets/{useNotebookActions-Df_jxEKJ.js → useNotebookActions-dJQalORg.js} +1 -1
- package/dist/assets/{useRunCells-AZJD5ITo.js → useRunCells-C_IwVJR_.js} +1 -1
- package/dist/assets/{useSplitCell-CgiU_w77.js → useSplitCell-Ci4MEUj8.js} +1 -1
- package/dist/assets/{useTheme-DLtPc-39.js → useTheme-BAA27lh7.js} +1 -1
- package/dist/assets/{vega-component-CY6HmM06.js → vega-component-BeyxAJad.js} +1 -1
- package/dist/assets/{write-secret-modal-7DzehGyr.js → write-secret-modal-BEx-EUlh.js} +1 -1
- package/dist/index.html +40 -40
- package/package.json +1 -1
- package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
- package/src/components/datasources/datasources.tsx +35 -21
- package/src/core/document/__tests__/draft.test.ts +322 -0
- package/src/core/document/__tests__/fixtures.ts +92 -0
- package/src/core/document/__tests__/model.test.ts +434 -0
- package/src/core/document/__tests__/submission.test.ts +334 -0
- package/src/core/document/draft.ts +472 -0
- package/src/core/document/model.ts +395 -0
- package/src/core/state/__tests__/jotai.test.tsx +108 -0
- package/src/core/state/jotai.ts +1 -1
- package/dist/assets/feedback-button-BFoleTOt.js +0 -1
- package/dist/assets/kiosk-mode-BGmMSc7A.js +0 -1
- package/dist/assets/links-CXcpNIM0.js +0 -1
- package/dist/assets/requests-CgSY1X4a.js +0 -1
- package/dist/assets/session-panel-CtQgwbFW.js +0 -1
- package/src/core/state/__tests__/jotai.test.ts +0 -25
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { dequal } from "dequal";
|
|
4
|
+
import {
|
|
5
|
+
atom,
|
|
6
|
+
type Atom,
|
|
7
|
+
type createStore,
|
|
8
|
+
type WritableAtom,
|
|
9
|
+
} from "jotai/vanilla";
|
|
10
|
+
import { selectAtom } from "jotai/vanilla/utils";
|
|
11
|
+
import type { Document } from "../host/resources/document";
|
|
12
|
+
import * as Protocol from "@marimo-team/client/protocol";
|
|
13
|
+
import {
|
|
14
|
+
acknowledge,
|
|
15
|
+
type CellEdit,
|
|
16
|
+
createCell,
|
|
17
|
+
deleteCell,
|
|
18
|
+
type Draft,
|
|
19
|
+
type EditableCell,
|
|
20
|
+
type EditableDocument,
|
|
21
|
+
editCell,
|
|
22
|
+
EMPTY_DRAFT,
|
|
23
|
+
isEmptyDraft,
|
|
24
|
+
type Placement,
|
|
25
|
+
prune,
|
|
26
|
+
sameCell,
|
|
27
|
+
setOrder,
|
|
28
|
+
toChanges,
|
|
29
|
+
viewDocument,
|
|
30
|
+
} from "./draft";
|
|
31
|
+
|
|
32
|
+
/** Operations on a working draft, valid only during the edit callback. */
|
|
33
|
+
export interface DocumentEditor {
|
|
34
|
+
setCode(id: Protocol.CellId, code: string): void;
|
|
35
|
+
setName(id: Protocol.CellId, name: string): void;
|
|
36
|
+
updateConfig(id: Protocol.CellId, patch: Partial<Protocol.CellConfig>): void;
|
|
37
|
+
createCell(cell: Protocol.CellInput, placement?: Placement): void;
|
|
38
|
+
deleteCell(id: Protocol.CellId): void;
|
|
39
|
+
/** A permutation of the cells present at this point in the transaction. */
|
|
40
|
+
setOrder(order: readonly Protocol.CellId[]): void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Synchronous; a thrown error discards the entire transaction. */
|
|
44
|
+
export type DocumentEdit = (editor: DocumentEditor) => void;
|
|
45
|
+
|
|
46
|
+
/** A captured edit request. Return this same object when reporting its result. */
|
|
47
|
+
export interface DocumentSubmission {
|
|
48
|
+
readonly notebookId: Protocol.NotebookId;
|
|
49
|
+
readonly changes: readonly Protocol.Change[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type ResponseRevision = Pick<Protocol.Document, "notebook_id" | "version">;
|
|
53
|
+
|
|
54
|
+
interface PendingSubmission {
|
|
55
|
+
readonly submission: DocumentSubmission;
|
|
56
|
+
readonly draft: Draft;
|
|
57
|
+
readonly responseRevision: ResponseRevision | null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface ModelState {
|
|
61
|
+
readonly confirmed: Document | null;
|
|
62
|
+
readonly drafts: ReadonlyMap<Protocol.NotebookId, Draft>;
|
|
63
|
+
readonly pending: PendingSubmission | null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Local edits over confirmed host state, with one submission in flight.
|
|
68
|
+
*
|
|
69
|
+
* A reset retains the submission so its receipt can reconcile a new snapshot.
|
|
70
|
+
* Switching notebook identity invalidates it, retaining each notebook's draft.
|
|
71
|
+
*/
|
|
72
|
+
export interface DocumentModel {
|
|
73
|
+
/** Hold onto the selector; its value is stable until the cell changes. */
|
|
74
|
+
cellAtom(id: Protocol.CellId): Atom<EditableCell | undefined>;
|
|
75
|
+
readonly orderAtom: Atom<readonly Protocol.CellId[] | null>;
|
|
76
|
+
readonly appConfigAtom: Atom<Readonly<
|
|
77
|
+
Protocol.Document["app_config"]
|
|
78
|
+
> | null>;
|
|
79
|
+
/** Null when the document or source needed by a put is unavailable. */
|
|
80
|
+
readonly changesAtom: Atom<readonly Protocol.Change[] | null>;
|
|
81
|
+
/** Remains pending until both the response and its streamed revision arrive. */
|
|
82
|
+
readonly pendingAtom: Atom<DocumentSubmission | null>;
|
|
83
|
+
readonly editAtom: WritableAtom<null, [edit: DocumentEdit], void>;
|
|
84
|
+
/** Capture a request, or null when unavailable, unchanged, or already sending. */
|
|
85
|
+
readonly submitAtom: WritableAtom<null, [], DocumentSubmission | null>;
|
|
86
|
+
/**
|
|
87
|
+
* Report the response revision, or null for a rejected request.
|
|
88
|
+
*
|
|
89
|
+
* Success waits for a complete streamed document at that version or later.
|
|
90
|
+
* Duplicate replies and replies for another notebook are ignored. Retry an
|
|
91
|
+
* uncertain request with the same body and idempotency key; do not reject it
|
|
92
|
+
* or capture a new request until its outcome is known.
|
|
93
|
+
*/
|
|
94
|
+
readonly settleAtom: WritableAtom<
|
|
95
|
+
null,
|
|
96
|
+
[submission: DocumentSubmission, responseRevision: ResponseRevision | null],
|
|
97
|
+
void
|
|
98
|
+
>;
|
|
99
|
+
/** Stop observing the source and invalidate pending work. Safe to repeat. */
|
|
100
|
+
dispose(): void;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function draftOf(state: ModelState): Draft {
|
|
104
|
+
return state.confirmed === null
|
|
105
|
+
? EMPTY_DRAFT
|
|
106
|
+
: (state.drafts.get(state.confirmed.revision.notebook_id) ?? EMPTY_DRAFT);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function withDraft(state: ModelState, draft: Draft): ModelState {
|
|
110
|
+
if (state.confirmed === null || draft === draftOf(state)) {
|
|
111
|
+
return state;
|
|
112
|
+
}
|
|
113
|
+
const drafts = new Map(state.drafts);
|
|
114
|
+
const notebookId = state.confirmed.revision.notebook_id;
|
|
115
|
+
if (isEmptyDraft(draft)) {
|
|
116
|
+
drafts.delete(notebookId);
|
|
117
|
+
} else {
|
|
118
|
+
drafts.set(notebookId, draft);
|
|
119
|
+
}
|
|
120
|
+
return { ...state, drafts };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Publish the confirmed document and any released fields together. */
|
|
124
|
+
function reconcile(state: ModelState): ModelState {
|
|
125
|
+
const { confirmed, pending } = state;
|
|
126
|
+
if (confirmed === null) {
|
|
127
|
+
return state;
|
|
128
|
+
}
|
|
129
|
+
let draft = draftOf(state);
|
|
130
|
+
if (
|
|
131
|
+
pending !== null &&
|
|
132
|
+
pending.responseRevision !== null &&
|
|
133
|
+
confirmed.revision.version >= pending.responseRevision.version
|
|
134
|
+
) {
|
|
135
|
+
draft = acknowledge(draft, pending.draft);
|
|
136
|
+
state = { ...state, pending: null };
|
|
137
|
+
}
|
|
138
|
+
return withDraft(state, prune(confirmed, draft, state.pending?.draft));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Create once per source and store; the owner must dispose the model. */
|
|
142
|
+
export function createDocumentModel(
|
|
143
|
+
store: ReturnType<typeof createStore>,
|
|
144
|
+
source: Atom<Document | null>,
|
|
145
|
+
): DocumentModel {
|
|
146
|
+
const stateAtom = atom<ModelState>({
|
|
147
|
+
confirmed: store.get(source),
|
|
148
|
+
drafts: new Map(),
|
|
149
|
+
pending: null,
|
|
150
|
+
});
|
|
151
|
+
let disposed = false;
|
|
152
|
+
const documentAtom = atom((get): EditableDocument | null => {
|
|
153
|
+
const state = get(stateAtom);
|
|
154
|
+
return state.confirmed === null
|
|
155
|
+
? null
|
|
156
|
+
: viewDocument(state.confirmed, draftOf(state));
|
|
157
|
+
});
|
|
158
|
+
const cellAtom = (id: Protocol.CellId) =>
|
|
159
|
+
selectAtom(
|
|
160
|
+
documentAtom,
|
|
161
|
+
(document) => document?.cells.get(id),
|
|
162
|
+
(a, b) =>
|
|
163
|
+
a === b || (a !== undefined && b !== undefined && sameCell(a, b)),
|
|
164
|
+
);
|
|
165
|
+
const orderAtom = selectAtom(
|
|
166
|
+
documentAtom,
|
|
167
|
+
(document) => document?.order ?? null,
|
|
168
|
+
dequal,
|
|
169
|
+
);
|
|
170
|
+
const appConfigAtom = selectAtom(
|
|
171
|
+
stateAtom,
|
|
172
|
+
(state) => state.confirmed?.revision.app_config ?? null,
|
|
173
|
+
dequal,
|
|
174
|
+
);
|
|
175
|
+
const changesAtom = atom((get): readonly Protocol.Change[] | null => {
|
|
176
|
+
const state = get(stateAtom);
|
|
177
|
+
return state.confirmed === null
|
|
178
|
+
? null
|
|
179
|
+
: toChanges(state.confirmed, draftOf(state));
|
|
180
|
+
});
|
|
181
|
+
const pendingAtom = atom((get) => get(stateAtom).pending?.submission ?? null);
|
|
182
|
+
|
|
183
|
+
const unsubscribe = store.sub(source, () => {
|
|
184
|
+
const confirmed = store.get(source);
|
|
185
|
+
store.set(stateAtom, (state) =>
|
|
186
|
+
reconcile({
|
|
187
|
+
...state,
|
|
188
|
+
confirmed,
|
|
189
|
+
pending:
|
|
190
|
+
confirmed !== null &&
|
|
191
|
+
state.pending !== null &&
|
|
192
|
+
confirmed.revision.notebook_id !== state.pending.submission.notebookId
|
|
193
|
+
? null
|
|
194
|
+
: state.pending,
|
|
195
|
+
}),
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
let editing = false;
|
|
200
|
+
const editAtom = atom(null, (get, set, edit: DocumentEdit) => {
|
|
201
|
+
if (editing) {
|
|
202
|
+
throw new Error("Document transactions cannot be nested");
|
|
203
|
+
}
|
|
204
|
+
const state = get(stateAtom);
|
|
205
|
+
if (disposed || state.confirmed === null) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
editing = true;
|
|
209
|
+
try {
|
|
210
|
+
const draft = editDocument(
|
|
211
|
+
state.confirmed,
|
|
212
|
+
draftOf(state),
|
|
213
|
+
edit,
|
|
214
|
+
state.pending?.draft,
|
|
215
|
+
);
|
|
216
|
+
if (
|
|
217
|
+
disposed ||
|
|
218
|
+
get(stateAtom) !== state ||
|
|
219
|
+
get(source) !== state.confirmed
|
|
220
|
+
) {
|
|
221
|
+
throw new Error("The document changed during the transaction");
|
|
222
|
+
}
|
|
223
|
+
set(stateAtom, withDraft(state, draft));
|
|
224
|
+
} finally {
|
|
225
|
+
editing = false;
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const submitAtom = atom(null, (get, set): DocumentSubmission | null => {
|
|
230
|
+
const state = get(stateAtom);
|
|
231
|
+
if (disposed || state.confirmed === null || state.pending !== null) {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
const draft = draftOf(state);
|
|
235
|
+
const changes = toChanges(state.confirmed, draft);
|
|
236
|
+
if (changes === null) {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
if (changes.length === 0) {
|
|
240
|
+
set(stateAtom, withDraft(state, EMPTY_DRAFT));
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
const submission = {
|
|
244
|
+
notebookId: state.confirmed.revision.notebook_id,
|
|
245
|
+
changes,
|
|
246
|
+
};
|
|
247
|
+
set(stateAtom, {
|
|
248
|
+
...state,
|
|
249
|
+
pending: { submission, draft, responseRevision: null },
|
|
250
|
+
});
|
|
251
|
+
return submission;
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
const settleAtom = atom(
|
|
255
|
+
null,
|
|
256
|
+
(
|
|
257
|
+
get,
|
|
258
|
+
set,
|
|
259
|
+
submission: DocumentSubmission,
|
|
260
|
+
responseRevision: ResponseRevision | null,
|
|
261
|
+
) => {
|
|
262
|
+
const state = get(stateAtom);
|
|
263
|
+
if (
|
|
264
|
+
disposed ||
|
|
265
|
+
state.pending?.submission !== submission ||
|
|
266
|
+
state.pending.responseRevision !== null
|
|
267
|
+
) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (
|
|
271
|
+
responseRevision !== null &&
|
|
272
|
+
responseRevision.notebook_id !== submission.notebookId
|
|
273
|
+
) {
|
|
274
|
+
throw new Error("Edit response belongs to another notebook");
|
|
275
|
+
}
|
|
276
|
+
set(
|
|
277
|
+
stateAtom,
|
|
278
|
+
reconcile({
|
|
279
|
+
...state,
|
|
280
|
+
pending:
|
|
281
|
+
responseRevision === null
|
|
282
|
+
? null
|
|
283
|
+
: { ...state.pending, responseRevision },
|
|
284
|
+
}),
|
|
285
|
+
);
|
|
286
|
+
},
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
cellAtom,
|
|
291
|
+
orderAtom,
|
|
292
|
+
appConfigAtom,
|
|
293
|
+
changesAtom,
|
|
294
|
+
pendingAtom,
|
|
295
|
+
editAtom,
|
|
296
|
+
submitAtom,
|
|
297
|
+
settleAtom,
|
|
298
|
+
dispose() {
|
|
299
|
+
if (!disposed) {
|
|
300
|
+
disposed = true;
|
|
301
|
+
unsubscribe();
|
|
302
|
+
store.set(stateAtom, {
|
|
303
|
+
confirmed: null,
|
|
304
|
+
drafts: new Map(),
|
|
305
|
+
pending: null,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function editDocument(
|
|
313
|
+
confirmed: Document,
|
|
314
|
+
draft: Draft,
|
|
315
|
+
edit: DocumentEdit,
|
|
316
|
+
sent: Draft = EMPTY_DRAFT,
|
|
317
|
+
): Draft {
|
|
318
|
+
let next = draft;
|
|
319
|
+
let active = true;
|
|
320
|
+
|
|
321
|
+
function assertActive() {
|
|
322
|
+
if (!active) {
|
|
323
|
+
throw new Error("The document transaction has ended");
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function hasCell(id: Protocol.CellId): boolean {
|
|
328
|
+
const local = next.cells.get(id);
|
|
329
|
+
return (
|
|
330
|
+
local?.kind === "create" ||
|
|
331
|
+
(local?.kind !== "delete" && confirmed.cells.has(id))
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function requireCell(id: Protocol.CellId) {
|
|
336
|
+
assertActive();
|
|
337
|
+
if (!hasCell(id)) {
|
|
338
|
+
throw new Error(`Cell ${id} does not exist`);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function updateCell(id: Protocol.CellId, patch: CellEdit) {
|
|
343
|
+
requireCell(id);
|
|
344
|
+
next = editCell(confirmed, next, id, patch);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const editor: DocumentEditor = {
|
|
348
|
+
setCode: (id, code) => updateCell(id, { code }),
|
|
349
|
+
setName: (id, name) => updateCell(id, { name }),
|
|
350
|
+
updateConfig: (id, patch) =>
|
|
351
|
+
updateCell(id, { config: Protocol.CellConfig.partial().parse(patch) }),
|
|
352
|
+
createCell: (cell, placement = {}) => {
|
|
353
|
+
assertActive();
|
|
354
|
+
if (confirmed.cells.has(cell.id) || hasCell(cell.id)) {
|
|
355
|
+
throw new Error(`Cell ${cell.id} already exists`);
|
|
356
|
+
}
|
|
357
|
+
if (placement.after !== undefined && placement.before !== undefined) {
|
|
358
|
+
throw new Error("Specify either before or after for cell placement");
|
|
359
|
+
}
|
|
360
|
+
const anchor = placement.after ?? placement.before;
|
|
361
|
+
if (anchor !== undefined) {
|
|
362
|
+
requireCell(anchor);
|
|
363
|
+
}
|
|
364
|
+
next = createCell(next, cell, { ...placement });
|
|
365
|
+
},
|
|
366
|
+
deleteCell: (id) => {
|
|
367
|
+
requireCell(id);
|
|
368
|
+
next = deleteCell(next, id, sent);
|
|
369
|
+
},
|
|
370
|
+
setOrder: (order) => {
|
|
371
|
+
assertActive();
|
|
372
|
+
const { cells } = viewDocument(confirmed, next);
|
|
373
|
+
if (
|
|
374
|
+
order.length !== cells.size ||
|
|
375
|
+
new Set(order).size !== cells.size ||
|
|
376
|
+
order.some((id) => !cells.has(id))
|
|
377
|
+
) {
|
|
378
|
+
throw new Error("Cell order must contain every cell exactly once");
|
|
379
|
+
}
|
|
380
|
+
next = setOrder(next, order);
|
|
381
|
+
},
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
try {
|
|
385
|
+
const result: unknown = edit(editor);
|
|
386
|
+
if (result instanceof Promise) {
|
|
387
|
+
// Observe a rejected async callback without publishing its partial draft.
|
|
388
|
+
result.catch(() => undefined);
|
|
389
|
+
throw new Error("Document edit callbacks must be synchronous");
|
|
390
|
+
}
|
|
391
|
+
return next;
|
|
392
|
+
} finally {
|
|
393
|
+
active = false;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { act, renderHook } from "@testing-library/react";
|
|
4
|
+
import { atom, Provider } from "jotai";
|
|
5
|
+
import type React from "react";
|
|
6
|
+
import { describe, expect, it, vi } from "vitest";
|
|
7
|
+
import { store, useJotaiEffect, waitFor } from "../jotai";
|
|
8
|
+
|
|
9
|
+
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
|
10
|
+
<Provider store={store}>{children}</Provider>
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
describe("waitFor function", () => {
|
|
14
|
+
it("should resolve when the atom satisfies the predicate", async () => {
|
|
15
|
+
const testAtom = atom(0);
|
|
16
|
+
store.set(testAtom, 10);
|
|
17
|
+
|
|
18
|
+
const result = await waitFor(testAtom, (value) => value === 10);
|
|
19
|
+
expect(result).toBe(10);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should resolve when the atom changes to satisfy the predicate", async () => {
|
|
23
|
+
const testAtom = atom(0);
|
|
24
|
+
|
|
25
|
+
setTimeout(() => store.set(testAtom, 15), 5);
|
|
26
|
+
setTimeout(() => store.set(testAtom, 20), 10);
|
|
27
|
+
|
|
28
|
+
const result = await waitFor(testAtom, (value) => value === 20);
|
|
29
|
+
expect(result).toBe(20);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe("useJotaiEffect", () => {
|
|
34
|
+
it("calls the effect with the new and previous values", () => {
|
|
35
|
+
const testAtom = atom(0);
|
|
36
|
+
const effect = vi.fn();
|
|
37
|
+
renderHook(() => useJotaiEffect(testAtom, effect), { wrapper });
|
|
38
|
+
|
|
39
|
+
act(() => store.set(testAtom, 1));
|
|
40
|
+
act(() => store.set(testAtom, 2));
|
|
41
|
+
|
|
42
|
+
expect(effect.mock.calls).toEqual([
|
|
43
|
+
[1, 0],
|
|
44
|
+
[2, 1],
|
|
45
|
+
]);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("calls only the latest callback after a rerender", () => {
|
|
49
|
+
const testAtom = atom(0);
|
|
50
|
+
const first = vi.fn();
|
|
51
|
+
const second = vi.fn();
|
|
52
|
+
const { rerender } = renderHook(
|
|
53
|
+
({ effect }) => useJotaiEffect(testAtom, effect),
|
|
54
|
+
{ initialProps: { effect: first }, wrapper },
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
rerender({ effect: second });
|
|
58
|
+
act(() => store.set(testAtom, 1));
|
|
59
|
+
|
|
60
|
+
expect(first).not.toHaveBeenCalled();
|
|
61
|
+
expect(second).toHaveBeenCalledTimes(1);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("subscribes once per rerender with an inline callback", () => {
|
|
65
|
+
const testAtom = atom(0);
|
|
66
|
+
const calls: number[] = [];
|
|
67
|
+
const { rerender } = renderHook(
|
|
68
|
+
() => useJotaiEffect(testAtom, (value) => calls.push(value)),
|
|
69
|
+
{ wrapper },
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
rerender();
|
|
73
|
+
rerender();
|
|
74
|
+
act(() => store.set(testAtom, 1));
|
|
75
|
+
|
|
76
|
+
expect(calls).toEqual([1]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("stops listening to the previous atom when the atom changes", () => {
|
|
80
|
+
const firstAtom = atom(0);
|
|
81
|
+
const secondAtom = atom(0);
|
|
82
|
+
const effect = vi.fn();
|
|
83
|
+
const { rerender } = renderHook(
|
|
84
|
+
({ target }) => useJotaiEffect(target, effect),
|
|
85
|
+
{ initialProps: { target: firstAtom }, wrapper },
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
rerender({ target: secondAtom });
|
|
89
|
+
act(() => store.set(firstAtom, 1));
|
|
90
|
+
expect(effect).not.toHaveBeenCalled();
|
|
91
|
+
|
|
92
|
+
act(() => store.set(secondAtom, 1));
|
|
93
|
+
expect(effect).toHaveBeenCalledTimes(1);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("unsubscribes on unmount", () => {
|
|
97
|
+
const testAtom = atom(0);
|
|
98
|
+
const effect = vi.fn();
|
|
99
|
+
const { unmount } = renderHook(() => useJotaiEffect(testAtom, effect), {
|
|
100
|
+
wrapper,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
unmount();
|
|
104
|
+
act(() => store.set(testAtom, 1));
|
|
105
|
+
|
|
106
|
+
expect(effect).not.toHaveBeenCalled();
|
|
107
|
+
});
|
|
108
|
+
});
|
package/src/core/state/jotai.ts
CHANGED
|
@@ -42,7 +42,7 @@ export function useJotaiEffect<T>(
|
|
|
42
42
|
const store = useStore();
|
|
43
43
|
useEffect(() => {
|
|
44
44
|
let prevValue = store.get(atom);
|
|
45
|
-
store.sub(atom, () => {
|
|
45
|
+
return store.sub(atom, () => {
|
|
46
46
|
const value = store.get(atom);
|
|
47
47
|
effect(value, prevValue);
|
|
48
48
|
prevValue = value;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./feedback-button-D0HjY39R.js";export{e as FeedbackModal};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{l as e}from"./useEvent-Dfcbgjhg.js";import{m as t}from"./session-B8Y-GJnS.js";var n=n=>{let{children:r}=n;return e(t)?null:r},r=n=>{let{children:r}=n;return e(t)?r:null};export{r as n,n as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{l as e}from"./session-B8Y-GJnS.js";function t(t){window.open(e(`?file=${encodeURIComponent(t)}`).toString(),`_blank`)}export{t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{f as e}from"./useEvent-Dfcbgjhg.js";var t=e(null);export{t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as e}from"./rolldown-runtime-B0Z9INg1.js";import{c as t,f as n,l as r,u as i}from"./useEvent-Dfcbgjhg.js";import{t as a}from"./react-DVplv7_D.js";import{$r as o,Ai as s,Bi as c,Bt as l,Cn as u,D as d,Gn as f,Ha as p,Hi as m,Ii as h,Ji as g,Ki as _,Kn as v,Li as y,M as b,Mi as x,P as S,Qr as C,Ri as w,Rn as T,Rt as E,Ui as D,Wa as O,Wi as k,Xi as A,Yi as j,Zi as M,_n as ee,c as N,fn as P,gn as F,i as I,jn as L,qi as R,qn as z,ro as te,ti as ne,to as B,yr as V,yt as H,zi as U}from"./cells-Cetiartc.js";import{t as W}from"./compiler-runtime-BrajqUja.js";import{s as re}from"./config-DGX7JYor.js";import{r as ie}from"./config-CP8Y8_R0.js";import{O as ae}from"./config-BWKfkUWA.js";import{t as G}from"./ErrorBoundary-BhXbaVBa.js";import{t as oe}from"./cn-ldLVeaqm.js";import{t as se}from"./jsx-runtime-B74pBk57.js";import{_ as ce,at as K,et as q,f as J,g as le,h as ue,it as de,m as fe,nt as pe,rt as me,tt as he,v as ge}from"./JsonOutput-Dti6dc1X.js";import{t as _e}from"./tooltip-CkGm8X7m.js";import{r as ve,t as ye}from"./button-D8gVKwe-.js";import{t as be}from"./createLucideIcon-DfJ2oMlA.js";import{i as xe}from"./paths-bkIFVj8h.js";import{r as Se}from"./useNumberFormatter-D7O_26UI.js";import{a as Ce,r as we}from"./tree-actions-MaUvbTxA.js";import{a as Te}from"./input-BZdRe7pb.js";import{n as Ee,o as De}from"./column-preview-BIpGfTJf.js";import{t as Oe}from"./workflow-cw-0b9g5.js";import{t as ke}from"./copy-icon-8-a5vovc.js";import{l as Ae}from"./arrays-0R2reF2y.js";import{i as je}from"./strings-C25fhMR_.js";import{r as Me}from"./requests-lt0JK8Jt.js";import{t as Ne}from"./I18nProvider-Cg2I_s1_.js";import{n as Pe}from"./useAsyncData-DhhdOGGd.js";import{t as Fe}from"./cell-link-D6rI90gy.js";import{a as Ie,i as Le,n as Re,o as ze,r as Be,t as Ve}from"./table-vrvqpuKJ.js";import{n as He}from"./icons-CiZ_8zS-.js";import{t as Ue}from"./useDeepCompareMemoize-DFIVN9dn.js";import{t as We}from"./useAddCell-D7SKNQll.js";import{t as Ge}from"./empty-state-BaCKb7o3.js";import{n as Ke,t as qe}from"./common-D0jeQZnr.js";import{a as Je,i as Ye,n as Xe,o as Ze,r as Qe,s as $e,t as et}from"./components-DkQChRNr.js";import{r as tt}from"./panel-accordion-state-C4fxJULv.js";var nt=be(`square-equal`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M7 10h10`,key:`1101jm`}],[`path`,{d:`M7 14h10`,key:`1mhdw3`}]]),Y=W(),X=e(a(),1),Z=se(),rt=1;function it(e){return 1.75+e*rt}function at(e){return 3+e*rt}function ot(e){return 3.25+e*rt}var Q={engineEmpty:.75,engine:.75,database:1,tableLoading:2.75,tableSchemaless:2,columnLocal:1.25,columnPreview:2.5};function $(e){return{paddingLeft:`${e}rem`}}var st=n(e=>{let t=e(w),n=e(ne),r=e(I);return Ae(t,e=>{if(!e.variable_name)return-1;let t=Object.values(n).find(t=>t.name===e.variable_name);if(!t)return 0;let i=r.inOrderIds.indexOf(t.declaredBy[0]);return i===-1?0:i})}),ct=ae(`marimo:datasources:hideEmpty`,!1,C,{getOnInit:!0});function lt(e){let t=!1,n=[];for(let r of e){if(!k(r)||!m(r)){n.push(r);continue}let e=r.child_schemas??[],i=lt(e);if(r.tables.length===0&&i.length===0){t=!0;continue}if(i===e){n.push(r);continue}t=!0,n.push({...r,child_schemas:i})}return t?n:e}function ut(e){let t=!1,n=[];for(let r of e){if(D(r)&&r.schemas.length===0){t=!0;continue}if(r.schemas.length===0){n.push(r);continue}let e=lt(r.schemas);if(e.length===0){t=!0;continue}if(e===r.schemas){n.push(r);continue}t=!0,n.push({...r,schemas:e})}return t?n:e}var dt=()=>{let e=(0,Y.c)(42),[n,a]=X.useState(``),[o,s]=t(ct),c=i(y),l=r(st),d=r(x),f;bb0:{if(!o){f=d;break bb0}let t,n;e[0]===d?(t=e[1],n=e[2]):(t=!1,n=d.map(e=>{let n=ut(e.databases);return n===e.databases?e:(t=!0,{...e,databases:n})}),e[0]=d,e[1]=t,e[2]=n),f=t?n:d}let p=f;if(l.length===0&&p.length===0){let t;return e[3]===Symbol.for(`react.memo_cache_sentinel`)?(t=(0,Z.jsx)(Ge,{title:`No tables found`,description:`Any datasets/dataframes in the global scope will be shown here.`,action:(0,Z.jsx)(Ze,{group:`database`,label:`Add database or catalog`,variant:`outline`,size:`sm`}),icon:(0,Z.jsx)(xe,{})}),e[3]=t):t=e[3],t}let m;e[4]===n?m=e[5]:(m=n.trim(),e[4]=n,e[5]=m);let h=!!m,g;e[6]===c?g=e[7]:(g=e=>{c(e.length>0),a(e)},e[6]=c,e[7]=g);let _;e[8]!==n||e[9]!==g?(_=(0,Z.jsx)(F,{placeholder:`Search tables...`,className:`h-6 m-1`,value:n,onValueChange:g,rootClassName:`flex-1 border-r border-b-0`}),e[8]=n,e[9]=g,e[10]=_):_=e[10];let v;e[11]===h?v=e[12]:(v=h&&(0,Z.jsx)(`button`,{type:`button`,className:`float-right border-b px-2 m-0 h-full hover:bg-accent hover:text-accent-foreground`,onClick:()=>a(``),children:(0,Z.jsx)(Se,{className:`h-4 w-4`})}),e[11]=h,e[12]=v);let b=!o,S;e[13]!==o||e[14]!==s?(S=()=>s(!o),e[13]=o,e[14]=s,e[15]=S):S=e[15];let C;e[16]!==b||e[17]!==S?(C=(0,Z.jsx)(Ce,{"data-testid":`datasources-hide-empty-button`,isVisible:b,onToggle:S,showTooltip:`Show empty schemas and databases`,hideTooltip:`Hide empty schemas and databases`,size:`sm`,className:`px-2 rounded-none focus-visible:outline-hidden`}),e[16]=b,e[17]=S,e[18]=C):C=e[18];let w;e[19]===Symbol.for(`react.memo_cache_sentinel`)?(w=(0,Z.jsx)(Ze,{group:`database`,label:`Add database or catalog`,compact:!0,variant:`ghost`,size:`sm`,className:`px-2 rounded-none focus-visible:outline-hidden`}),e[19]=w):w=e[19];let T;e[20]!==_||e[21]!==v||e[22]!==C?(T=(0,Z.jsxs)(`div`,{className:`flex items-center w-full border-b`,children:[_,v,C,w]}),e[20]=_,e[21]=v,e[22]=C,e[23]=T):T=e[23];let E;if(e[24]!==p||e[25]!==n){let t;e[27]===n?t=e[28]:(t=e=>(0,Z.jsx)(ft,{connection:e,hasChildren:e.databases.length>0,children:e.databases.map(t=>(0,Z.jsx)(gt,{connection:e,database:t,searchValue:n},t.name))},e.name),e[27]=n,e[28]=t),E=p.map(t),e[24]=p,e[25]=n,e[26]=E}else E=e[26];let D;e[29]!==p.length||e[30]!==l.length?(D=p.length>0&&l.length>0&&(0,Z.jsxs)(fe,{className:`pr-2`,style:$(Q.engine),children:[(0,Z.jsx)(He,{className:`h-4 w-4 text-muted-foreground`}),(0,Z.jsx)(`span`,{className:`text-xs`,children:`Python`})]}),e[29]=p.length,e[30]=l.length,e[31]=D):D=e[31];let O;e[32]!==n||e[33]!==l?(O=l.length>0&&(0,Z.jsx)(bt,{tables:l,searchValue:n}),e[32]=n,e[33]=l,e[34]=O):O=e[34];let k;e[35]!==E||e[36]!==D||e[37]!==O?(k=(0,Z.jsxs)(u,{className:`flex flex-col`,children:[E,D,O]}),e[35]=E,e[36]=D,e[37]=O,e[38]=k):k=e[38];let A;return e[39]!==k||e[40]!==T?(A=(0,Z.jsxs)(P,{className:`border-b bg-background rounded-none h-full pb-10 overflow-auto outline-hidden`,shouldFilter:!1,children:[T,k]}),e[39]=k,e[40]=T,e[41]=A):A=e[41],A},ft=e=>{let t=(0,Y.c)(26),{connection:n,children:r,hasChildren:i}=e,a=n.name===M,o=a?`In-Memory`:n.name,{previewDataSourceConnection:c}=Me(),l;t[0]!==n.name||t[1]!==c?(l=async()=>{await c({engine:n.name})},t[0]=n.name,t[1]=c,t[2]=l):l=t[2];let u=l,d;t[3]===Symbol.for(`react.memo_cache_sentinel`)?(d=$(Q.engine),t[3]=d):d=t[3];let f;t[4]===n.dialect?f=t[5]:(f=(0,Z.jsx)(L,{className:`h-4 w-4 text-muted-foreground`,name:n.dialect}),t[4]=n.dialect,t[5]=f);let p;t[6]===n.dialect?p=t[7]:(p=s(n.dialect),t[6]=n.dialect,t[7]=p);let m;t[8]===p?m=t[9]:(m=(0,Z.jsx)(`span`,{className:`text-xs`,children:p}),t[8]=p,t[9]=m);let h=o,g;t[10]===h?g=t[11]:(g=(0,Z.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[`(`,(0,Z.jsx)($e,{variableName:h}),`)`]}),t[10]=h,t[11]=g);let _;t[12]!==u||t[13]!==a?(_=!a&&(0,Z.jsx)(we,{onClick:u,tooltip:`Refresh connection`,className:`ml-auto h-4 p-0`,iconClassName:`h-3.5 w-3.5`}),t[12]=u,t[13]=a,t[14]=_):_=t[14];let v;t[15]!==f||t[16]!==m||t[17]!==g||t[18]!==_?(v=(0,Z.jsxs)(fe,{className:`pr-2`,style:d,children:[f,m,g,_]}),t[15]=f,t[16]=m,t[17]=g,t[18]=_,t[19]=v):v=t[19];let y;t[20]!==r||t[21]!==i?(y=i?r:(0,Z.jsx)(ue,{content:`No databases available`,style:$(Q.engineEmpty)}),t[20]=r,t[21]=i,t[22]=y):y=t[22];let b;return t[23]!==y||t[24]!==v?(b=(0,Z.jsxs)(Z.Fragment,{children:[v,y]}),t[23]=y,t[24]=v,t[25]=b):b=t[25],b},pt=X.createContext(null);function mt(){let e=X.useContext(pt);if(e==null)throw Error(`useDataSourceTree must be used within a DataSourceTreeContext.Provider`);return e}function ht(e,{schema:t,schemaPath:n}){return{engine:e.engineName,database:e.databaseName,schema:t,schemaPath:n,defaultSchema:e.defaultSchema,defaultDatabase:e.defaultDatabase,dialect:e.dialect}}var gt=e=>{let t=(0,Y.c)(21),{connection:n,database:r,searchValue:i}=e,a;t[0]!==n.default_database||t[1]!==n.default_schema||t[2]!==n.dialect||t[3]!==n.name||t[4]!==r.name||t[5]!==i?(a={engineName:n.name,databaseName:r.name,dialect:n.dialect,defaultSchema:n.default_schema,defaultDatabase:n.default_database,searchValue:i},t[0]=n.default_database,t[1]=n.default_schema,t[2]=n.dialect,t[3]=n.name,t[4]=r.name,t[5]=i,t[6]=a):a=t[6];let o=a,s=n.name,c=r.schemas,l;t[7]===r?l=t[8]:(l=D(r),t[7]=r,t[8]=l);let u;t[9]===Symbol.for(`react.memo_cache_sentinel`)?(u=[],t[9]=u):u=t[9];let d;t[10]!==r.schemas||t[11]!==l?(d=(0,Z.jsx)(vt,{schemas:c,schemasResolved:l,schemaPath:u,depth:0}),t[10]=r.schemas,t[11]=l,t[12]=d):d=t[12];let f;t[13]!==d||t[14]!==o?(f=(0,Z.jsx)(pt.Provider,{value:o,children:d}),t[13]=d,t[14]=o,t[15]=f):f=t[15];let p;return t[16]!==n.name||t[17]!==r||t[18]!==i||t[19]!==f?(p=(0,Z.jsx)(_t,{engineName:s,database:r,searchValue:i,children:f}),t[16]=n.name,t[17]=r,t[18]=i,t[19]=f,t[20]=p):p=t[20],p},_t=e=>{let t=(0,Y.c)(29),{searchValue:n,engineName:r,database:i,children:a}=e,o;t[0]!==i||t[1]!==n?(o=g(i,n),t[0]=i,t[1]=n,t[2]=o):o=t[2];let s=o,[c,l]=X.useState(s),[u,d]=X.useState(!1),[f,p]=X.useState(n),[m,h]=X.useState(s);(f!==n||m!==s)&&(p(n),h(s),l(s));let _;t[3]===Symbol.for(`react.memo_cache_sentinel`)?(_=$(Q.database),t[3]=_):_=t[3];let v;t[4]!==c||t[5]!==u?(v=()=>{l(!c),d(!u)},t[4]=c,t[5]=u,t[6]=v):v=t[6];let y=`${r}:${i.name}`,b;t[7]===c?b=t[8]:(b=(0,Z.jsx)(ge,{isExpanded:c}),t[7]=c,t[8]=b);let x=u&&c?`text-foreground`:`text-muted-foreground`,S;t[9]===x?S=t[10]:(S=oe(`h-4 w-4`,x),t[9]=x,t[10]=S);let C;t[11]===S?C=t[12]:(C=(0,Z.jsx)(xe,{className:S}),t[11]=S,t[12]=C);let w=u&&c&&`font-semibold`,T;t[13]===w?T=t[14]:(T=oe(w),t[13]=w,t[14]=T);let E;t[15]===i.name?E=t[16]:(E=i.name===``?(0,Z.jsx)(`i`,{children:`Not connected`}):i.name,t[15]=i.name,t[16]=E);let D;t[17]!==T||t[18]!==E?(D=(0,Z.jsx)(`span`,{className:T,children:E}),t[17]=T,t[18]=E,t[19]=D):D=t[19];let O;t[20]!==D||t[21]!==v||t[22]!==y||t[23]!==b||t[24]!==C?(O=(0,Z.jsxs)(ee,{className:`text-sm flex flex-row gap-1 items-center cursor-pointer rounded-none`,style:_,onSelect:v,value:y,children:[b,C,D]}),t[20]=D,t[21]=v,t[22]=y,t[23]=b,t[24]=C,t[25]=O):O=t[25];let k=c&&a,A;return t[26]!==O||t[27]!==k?(A=(0,Z.jsxs)(Z.Fragment,{children:[O,k]}),t[26]=O,t[27]=k,t[28]=A):A=t[28],A},vt=e=>{let{schemas:t,schemasResolved:n,depth:r}=e,i=mt(),{engineName:a,databaseName:o,searchValue:s}=i,{addSchemaList:c}=h(),l=Ue(e.schemaPath),[u,d]=X.useState(!1),{isPending:p,error:m}=Pe(async()=>{if(!n&&a){d(!0);try{let e=await f.request({engine:a,database:o,schemaPath:l});c({schemas:e.schemas??[],sqlSchemaContext:{engine:a,database:o,schemaPath:l}})}finally{d(!1)}}},[n,a,o,l]),g=$(it(r));return p||u?(0,Z.jsx)(ce,{message:`Loading schemas...`,style:g}):m?(0,Z.jsx)(le,{error:m,style:g}):t.length===0?(0,Z.jsx)(ue,{content:`No schemas available`,style:g}):(0,Z.jsx)(Z.Fragment,{children:t.map(e=>_(e.name)?(0,Z.jsx)(bt,{tables:e.tables,tablesResolved:k(e),searchValue:s,sqlTableContext:ht(i,{schema:e.name,schemaPath:l})},e.name):(0,Z.jsx)(yt,{schema:e,schemaPath:[...l,e.name],depth:r},e.name))})},yt=e=>{let t=(0,Y.c)(41),{schema:n,schemaPath:r,depth:i}=e,a=mt(),{databaseName:o,searchValue:s}=a,c;t[0]!==n||t[1]!==s?(c=R(n,s),t[0]=n,t[1]=s,t[2]=c):c=t[2];let l=c,[u,d]=X.useState(l),[f,p]=X.useState(!1),[h,g]=X.useState(s),[_,v]=X.useState(l),y;t[3]===r?y=t[4]:(y=r.join(`.`),t[3]=r,t[4]=y);let b=`${o}:${y}`,x;t[5]===n.child_schemas?x=t[6]:(x=n.child_schemas??[],t[5]=n.child_schemas,t[6]=x);let S=x;(h!==s||_!==l)&&(g(s),v(l),d(l));let C;t[7]===i?C=t[8]:(C=$(it(i)),t[7]=i,t[8]=C);let w;t[9]!==u||t[10]!==f?(w=()=>{d(!u),p(!f)},t[9]=u,t[10]=f,t[11]=w):w=t[11];let T;t[12]===u?T=t[13]:(T=(0,Z.jsx)(ge,{isExpanded:u}),t[12]=u,t[13]=T);let E=f&&u&&`text-foreground`,D;t[14]===E?D=t[15]:(D=oe(`h-4 w-4 text-muted-foreground`,E),t[14]=E,t[15]=D);let O;t[16]===D?O=t[17]:(O=(0,Z.jsx)(B,{className:D}),t[16]=D,t[17]=O);let A=f&&u&&`font-semibold`,j;t[18]===A?j=t[19]:(j=oe(A),t[18]=A,t[19]=j);let M;t[20]!==n.name||t[21]!==j?(M=(0,Z.jsx)(`span`,{className:j,children:n.name}),t[20]=n.name,t[21]=j,t[22]=M):M=t[22];let N;t[23]!==M||t[24]!==C||t[25]!==w||t[26]!==T||t[27]!==O||t[28]!==b?(N=(0,Z.jsxs)(ee,{className:`text-sm flex flex-row gap-1 items-center cursor-pointer rounded-none`,style:C,onSelect:w,value:b,children:[T,O,M]}),t[23]=M,t[24]=C,t[25]=w,t[26]=T,t[27]=O,t[28]=b,t[29]=N):N=t[29];let P;t[30]!==S||t[31]!==i||t[32]!==u||t[33]!==n||t[34]!==r||t[35]!==s||t[36]!==a?(P=u&&(0,Z.jsxs)(Z.Fragment,{children:[(S.length>0||!m(n))&&(0,Z.jsx)(vt,{schemas:S,schemasResolved:m(n),schemaPath:r,depth:i+1}),(0,Z.jsx)(bt,{tables:n.tables,tablesResolved:k(n),searchValue:s,tableIndentRem:at(i),columnIndentRem:ot(i),sqlTableContext:ht(a,{schema:n.name,schemaPath:r})})]}),t[30]=S,t[31]=i,t[32]=u,t[33]=n,t[34]=r,t[35]=s,t[36]=a,t[37]=P):P=t[37];let F;return t[38]!==N||t[39]!==P?(F=(0,Z.jsxs)(Z.Fragment,{children:[N,P]}),t[38]=N,t[39]=P,t[40]=F):F=t[40],F},bt=e=>{let t=(0,Y.c)(31),{tables:n,sqlTableContext:r,searchValue:i,tablesResolved:a,tableIndentRem:o,columnIndentRem:s}=e,c=a===void 0||a,{addTableList:l}=h(),[u,d]=X.useState(!1),f;t[0]!==l||t[1]!==r||t[2]!==c?(f=async()=>{if(!c&&r){d(!0);let{engine:e,database:t,schema:n,schemaPath:i}=r,a=await z.request({engine:e,database:t,schema:n,schemaPath:i??[]});if(!a?.tables)throw d(!1),Error(`No tables available`);l({tables:a.tables,sqlTableContext:r}),d(!1)}},t[0]=l,t[1]=r,t[2]=c,t[3]=f):f=t[3];let p;t[4]!==r||t[5]!==c?(p=[c,r],t[4]=r,t[5]=c,t[6]=p):p=t[6];let{isPending:m,error:g}=Pe(f,p),_=o??Q.tableLoading,v;t[7]===_?v=t[8]:(v=$(_),t[7]=_,t[8]=v);let y=v;if(m||u){let e;return t[9]===y?e=t[10]:(e=(0,Z.jsx)(ce,{message:`Loading tables...`,style:y}),t[9]=y,t[10]=e),e}if(g){let e;return t[11]!==g||t[12]!==y?(e=(0,Z.jsx)(le,{error:g,style:y}),t[11]=g,t[12]=y,t[13]=e):e=t[13],e}if(n.length===0){let e;return t[14]===y?e=t[15]:(e=(0,Z.jsx)(ue,{content:`No tables found`,style:y}),t[14]=y,t[15]=e),e}let b;if(t[16]!==s||t[17]!==i||t[18]!==r||t[19]!==o||t[20]!==n){let e;t[22]===i?e=t[23]:(e=e=>!i||e.name.toLowerCase().includes(i.toLowerCase()),t[22]=i,t[23]=e);let a=n.filter(e),c;t[24]!==s||t[25]!==i||t[26]!==r||t[27]!==o?(c=e=>(0,Z.jsx)(xt,{table:e,sqlTableContext:r,isSearching:!!i,tableIndentRem:o,columnIndentRem:s},e.name),t[24]=s,t[25]=i,t[26]=r,t[27]=o,t[28]=c):c=t[28],b=a.map(c),t[16]=s,t[17]=i,t[18]=r,t[19]=o,t[20]=n,t[21]=b}else b=t[21];let x;return t[29]===b?x=t[30]:(x=(0,Z.jsx)(Z.Fragment,{children:b}),t[29]=b,t[30]=x),x},xt=e=>{let t=(0,Y.c)(69),{table:n,sqlTableContext:i,isSearching:a,tableIndentRem:o,columnIndentRem:s}=e,{addTable:c}=h(),[u,f]=X.useState(!1),p=n.columns.length>0,m;t[0]!==c||t[1]!==u||t[2]!==i||t[3]!==n.name||t[4]!==p?(m=async()=>{if(u&&!p&&i){let{engine:e,database:t,schema:r,schemaPath:a}=i,o=await v.request({engine:e,database:t,schema:r,tableName:n.name,schemaPath:a??[]});if(!o?.table)throw Error(`No table details available`);c({table:o.table,sqlTableContext:i})}},t[0]=c,t[1]=u,t[2]=i,t[3]=n.name,t[4]=p,t[5]=m):m=t[5];let g;t[6]!==u||t[7]!==p?(g=[u,p],t[6]=u,t[7]=p,t[8]=g):g=t[8];let{isFetching:_,isPending:y,error:b}=Pe(m,g),x=r(re),S=E(),{createNewCell:C}=d(),w=We(),T;t[9]!==w||t[10]!==x||t[11]!==C||t[12]!==S||t[13]!==i||t[14]!==n?(T=()=>{l({autoInstantiate:x,createNewCell:C,fromCellId:S}),w((()=>{if(n.source_type===`catalog`){let e=i?.database?[i.database,...i.schemaPath??[],n.name].join(`.`):n.name;return`${n.engine}.load_table("${e}")`}if(i)return j({table:n,columnName:`*`,sqlTableContext:i});switch(n.source_type){case`local`:return`mo.ui.table(${n.name})`;case`duckdb`:case`connection`:return j({table:n,columnName:`*`,sqlTableContext:i});default:return je(n.source_type),``}})())},t[9]=w,t[10]=x,t[11]=C,t[12]=S,t[13]=i,t[14]=n,t[15]=T):T=t[15];let D=T,k;t[16]!==n.num_columns||t[17]!==n.num_rows?(k=()=>{let e=[];return n.num_rows!=null&&e.push(`${n.num_rows} rows`),n.num_columns!=null&&e.push(`${n.num_columns} columns`),e.length===0?null:(0,Z.jsx)(`div`,{className:`flex flex-row gap-2 items-center pl-6 group-hover:hidden`,children:(0,Z.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:e.join(`, `)})})},t[16]=n.num_columns,t[17]=n.num_rows,t[18]=k):k=t[18];let M=k,N;t[19]!==s||t[20]!==b||t[21]!==_||t[22]!==y||t[23]!==i||t[24]!==n?(N=()=>{let e=$(s??Q.tableLoading);if(y||_)return(0,Z.jsx)(ce,{message:`Loading columns...`,style:e});if(b)return(0,Z.jsx)(le,{error:b,style:e});let t=n.columns;return t.length===0?(0,Z.jsx)(ue,{content:`No columns found`,style:e}):t.map(e=>(0,Z.jsx)(St,{table:n,column:e,sqlTableContext:i,columnIndentRem:s},e.name))},t[19]=s,t[20]=b,t[21]=_,t[22]=y,t[23]=i,t[24]=n,t[25]=N):N=t[25];let P=N,F;t[26]!==u||t[27]!==a||t[28]!==n.source_type||t[29]!==n.type?(F=()=>{if(n.source_type===`local`)return;let e=n.type===`table`?O:te;return(0,Z.jsx)(e,{className:`h-3 w-3`,strokeWidth:u||a?2.5:void 0})},t[26]=u,t[27]=a,t[28]=n.source_type,t[29]=n.type,t[30]=F):F=t[30];let I=F,L;t[31]!==i||t[32]!==n.name?(L=A(i,n.name),t[31]=i,t[32]=n.name,t[33]=L):L=t[33];let R=L,z=o??(i?Q.tableSchemaless:0),ne=(u||a)&&`font-semibold`,B;t[34]===ne?B=t[35]:(B=oe(`rounded-none group h-8 cursor-pointer`,ne),t[34]=ne,t[35]=B);let V;t[36]===z?V=t[37]:(V=$(z),t[36]=z,t[37]=V);let H;t[38]===u?H=t[39]:(H=()=>f(!u),t[38]=u,t[39]=H);let U;t[40]===I?U=t[41]:(U=I(),t[40]=I,t[41]=U);let W;t[42]===n.name?W=t[43]:(W=(0,Z.jsx)(`span`,{className:`text-sm`,children:n.name}),t[42]=n.name,t[43]=W);let ie;t[44]!==U||t[45]!==W?(ie=(0,Z.jsxs)(`div`,{className:`flex gap-2 items-center flex-1 pl-1`,children:[U,W]}),t[44]=U,t[45]=W,t[46]=ie):ie=t[46];let ae;t[47]===M?ae=t[48]:(ae=M(),t[47]=M,t[48]=ae);let G;t[49]===D?G=t[50]:(G=ve.stopPropagation(()=>D()),t[49]=D,t[50]=G);let se;t[51]===Symbol.for(`react.memo_cache_sentinel`)?(se=(0,Z.jsx)(De,{className:`h-3 w-3`}),t[51]=se):se=t[51];let K;t[52]===G?K=t[53]:(K=(0,Z.jsx)(_e,{content:`Add table to notebook`,delayDuration:400,children:(0,Z.jsx)(ye,{className:`group-hover:inline-flex hidden`,variant:`text`,size:`icon`,onClick:G,children:se})}),t[52]=G,t[53]=K);let q;t[54]!==u||t[55]!==V||t[56]!==H||t[57]!==ie||t[58]!==ae||t[59]!==K||t[60]!==B||t[61]!==R?(q=(0,Z.jsxs)(ee,{className:B,style:V,value:R,"aria-selected":u,forceMount:!0,onSelect:H,children:[ie,ae,K]}),t[54]=u,t[55]=V,t[56]=H,t[57]=ie,t[58]=ae,t[59]=K,t[60]=B,t[61]=R,t[62]=q):q=t[62];let J;t[63]!==u||t[64]!==P?(J=u&&P(),t[63]=u,t[64]=P,t[65]=J):J=t[65];let de;return t[66]!==q||t[67]!==J?(de=(0,Z.jsxs)(Z.Fragment,{children:[q,J]}),t[66]=q,t[67]=J,t[68]=de):de=t[68],de},St=e=>{let t=(0,Y.c)(51),{table:n,column:a,sqlTableContext:o,columnIndentRem:s}=e,[l,u]=X.useState(!1),d=r(y),f=i(U);d&&l&&u(!1),f(l?e=>new Set([...e,`${n.name}:${a.name}`]):e=>(e.delete(`${n.name}:${a.name}`),new Set(e)));let p=We(),{columnsPreviews:m}=c(),h;t[0]!==a.name||t[1]!==n.primary_keys?(h=n.primary_keys?.includes(a.name)||!1,t[0]=a.name,t[1]=n.primary_keys,t[2]=h):h=t[2];let g=h,_;t[3]!==a.name||t[4]!==n.indexes?(_=n.indexes?.includes(a.name)||!1,t[3]=a.name,t[4]=n.indexes,t[5]=_):_=t[5];let v=_,b;t[6]===p?b=t[7]:(b=e=>{p(e)},t[6]=p,t[7]=b);let x=b,S=Ct,C=l?`font-semibold`:``,w;t[8]!==a.name||t[9]!==C?(w=(0,Z.jsx)(`span`,{className:C,children:a.name}),t[8]=a.name,t[9]=C,t[10]=w):w=t[10];let T=w,E=`${n.name}.${a.name}`,D=`${n.name}.${a.name}`,O;t[11]===l?O=t[12]:(O=()=>u(!l),t[11]=l,t[12]=O);let k;t[13]!==s||t[14]!==o?(k=s??(o?ot(0):Q.columnLocal),t[13]=s,t[14]=o,t[15]=k):k=t[15];let A;t[16]===k?A=t[17]:(A=$(k),t[16]=k,t[17]=A);let j;t[18]!==a.type||t[19]!==T?(j=(0,Z.jsx)(J,{columnName:T,dataType:a.type}),t[18]=a.type,t[19]=T,t[20]=j):j=t[20];let M;t[21]===g?M=t[22]:(M=g&&S({tooltipContent:`Primary key`,content:`PK`}),t[21]=g,t[22]=M);let N;t[23]===v?N=t[24]:(N=v&&S({tooltipContent:`Indexed`,content:`IDX`}),t[23]=v,t[24]=N);let P;t[25]!==A||t[26]!==j||t[27]!==M||t[28]!==N?(P=(0,Z.jsxs)(`div`,{className:`flex flex-row gap-2 items-center flex-1`,style:A,children:[j,M,N]}),t[25]=A,t[26]=j,t[27]=M,t[28]=N,t[29]=P):P=t[29];let F;t[30]===a.name?F=t[31]:(F=(0,Z.jsx)(_e,{content:`Copy column name`,delayDuration:400,children:(0,Z.jsx)(ye,{variant:`text`,size:`icon`,className:`group-hover:opacity-100 opacity-0 hover:bg-muted text-muted-foreground hover:text-foreground`,children:(0,Z.jsx)(ke,{tooltip:!1,value:a.name,className:`h-3 w-3`})})}),t[30]=a.name,t[31]=F);let I;t[32]===a.external_type?I=t[33]:(I=(0,Z.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:a.external_type}),t[32]=a.external_type,t[33]=I);let L;t[34]!==P||t[35]!==F||t[36]!==I||t[37]!==E||t[38]!==D||t[39]!==O?(L=(0,Z.jsxs)(ee,{className:`rounded-none py-1 group cursor-pointer`,value:D,onSelect:O,children:[P,F,I]},E),t[34]=P,t[35]=F,t[36]=I,t[37]=E,t[38]=D,t[39]=O,t[40]=L):L=t[40];let R;t[41]!==a||t[42]!==m||t[43]!==x||t[44]!==l||t[45]!==o||t[46]!==n?(R=l&&(0,Z.jsx)(`div`,{className:`pr-2 py-2 bg-(--slate-1) shadow-inner border-b`,style:$(Q.columnPreview),children:(0,Z.jsx)(G,{children:(0,Z.jsx)(Ee,{table:n,column:a,onAddColumnChart:x,preview:m.get(o?`${o.database}.${o.schema}.${n.name}:${a.name}`:`${n.name}:${a.name}`),sqlTableContext:o})})}),t[41]=a,t[42]=m,t[43]=x,t[44]=l,t[45]=o,t[46]=n,t[47]=R):R=t[47];let z;return t[48]!==L||t[49]!==R?(z=(0,Z.jsxs)(Z.Fragment,{children:[L,R]}),t[48]=L,t[49]=R,t[50]=z):z=t[50],z};function Ct(e){let{tooltipContent:t,content:n}=e;return(0,Z.jsx)(_e,{content:t,delayDuration:100,children:(0,Z.jsx)(`span`,{className:`text-xs text-black bg-gray-100 dark:invert rounded px-1`,children:n})})}function wt(e){return e}var Tt={name:`name`,type:`type-value`,defs:`defs-refs`},Et=[wt({id:Tt.name,accessorFn:e=>[e.name,e.declaredBy],enableSorting:!0,sortingFn:`alphanumeric`,header:({column:e})=>(0,Z.jsx)(q,{header:`Name`,column:e}),cell:({getValue:e})=>{let[t,n]=e();return(0,Z.jsx)(qe,{name:t,declaredBy:n})}}),wt({id:Tt.type,accessorFn:e=>[e.dataType,e.value],enableSorting:!0,sortingFn:`alphanumeric`,header:({column:e})=>(0,Z.jsx)(q,{header:(0,Z.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,Z.jsx)(`span`,{children:`Type`}),(0,Z.jsx)(`span`,{children:`Value`})]}),column:e}),cell:({getValue:e})=>{let[t,n]=e();return(0,Z.jsxs)(`div`,{className:`max-w-[150px]`,children:[(0,Z.jsx)(`div`,{className:`text-ellipsis overflow-hidden whitespace-nowrap text-muted-foreground font-mono text-xs`,children:t}),(0,Z.jsx)(`div`,{className:`text-ellipsis overflow-hidden whitespace-nowrap`,title:n??``,children:n})]})}}),wt({id:Tt.defs,accessorFn:e=>[e.declaredBy,e.usedBy,e.name,e.declaredByNames,e.usedByNames],enableSorting:!0,sortingFn:`basic`,header:({column:e})=>(0,Z.jsx)(q,{header:(0,Z.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,Z.jsx)(`span`,{children:`Declared By`}),(0,Z.jsx)(`span`,{children:`Used By`})]}),column:e}),cell:({getValue:e})=>{let[t,n,r]=e(),i=e=>{let t=N(e);t&&V(t,r)};return(0,Z.jsxs)(`div`,{className:`flex flex-col gap-1 py-1`,children:[(0,Z.jsxs)(`div`,{className:`flex flex-row overflow-auto gap-2 items-center`,children:[(0,Z.jsx)(`span`,{title:`Declared by`,children:(0,Z.jsx)(nt,{className:`w-3.5 h-3.5 text-muted-foreground`})}),t.length===1?(0,Z.jsx)(Fe,{variant:`focus`,cellId:t[0],skipScroll:!0,onClick:()=>i(t[0])}):(0,Z.jsx)(`div`,{className:`text-destructive flex flex-row gap-2`,children:t.slice(0,3).map((e,n)=>(0,Z.jsxs)(`span`,{className:`flex`,children:[(0,Z.jsx)(Fe,{variant:`focus`,cellId:e,skipScroll:!0,className:`whitespace-nowrap text-destructive`,onClick:()=>i(e)},e),n<t.length-1&&`, `]},e))})]}),(0,Z.jsxs)(`div`,{className:`flex flex-row overflow-auto gap-2 items-baseline`,children:[(0,Z.jsx)(`span`,{title:`Used by`,children:(0,Z.jsx)(Oe,{className:`w-3.5 h-3.5 text-muted-foreground`})}),(0,Z.jsx)(Ke,{maxCount:3,cellIds:n,skipScroll:!0,onClick:i})]})]})}})];function Dt({variables:e,sort:t,cellIdToIndex:n}){t||={id:Tt.defs,desc:!1};let r=[];switch(t.id){case Tt.name:r=Ae(e,e=>e.name);break;case Tt.type:r=Ae(e,e=>e.dataType);break;case Tt.defs:r=Ae(e,e=>n.get(e.declaredBy[0]))}return t.desc?r.toReversed():r}var Ot=(0,X.memo)(({className:e,cellIds:t,variables:n})=>{let[r,i]=X.useState([]),[a,o]=X.useState(``),s=S(),{locale:c}=Ne(),l=(0,X.useMemo)(()=>{let e=e=>{let n=s[e];return T(n)?`cell-${t.indexOf(e)}`:n??`cell-${t.indexOf(e)}`};return Object.values(n).map(t=>({...t,declaredByNames:t.declaredBy.map(e),usedByNames:t.usedBy.map(e)}))},[n,s,t]),u=(0,X.useMemo)(()=>{let e=new Map;return t.forEach((t,n)=>e.set(t,n)),Dt({variables:l,sort:r[0],cellIdToIndex:e})},[l,r,t]),d=pe({data:u,columns:Et,getCoreRowModel:me(),onGlobalFilterChange:o,getFilteredRowModel:de(),enableFilters:!0,enableGlobalFilter:!0,enableColumnPinning:!1,getColumnCanGlobalFilter(e){return e.columnDef.enableGlobalFilter??!0},globalFilterFn:`auto`,manualSorting:!0,locale:c,onSortingChange:i,getSortedRowModel:K(),state:{sorting:r,globalFilter:a}});return(0,Z.jsxs)(Z.Fragment,{children:[(0,Z.jsx)(Te,{className:`w-full`,placeholder:`Search`,value:a,onChange:e=>o(e.target.value)}),(0,Z.jsxs)(Ve,{className:oe(`w-full text-sm flex-1 border-separate border-spacing-0`,e),children:[(0,Z.jsx)(Ie,{children:(0,Z.jsx)(ze,{className:`whitespace-nowrap text-xs`,children:d.getFlatHeaders().map(e=>(0,Z.jsx)(Le,{className:`sticky top-0 bg-background border-b`,children:he(e.column.columnDef.header,e.getContext())},e.id))})}),(0,Z.jsx)(Re,{children:d.getRowModel().rows.map(e=>(0,Z.jsx)(ze,{className:`hover:bg-accent`,children:e.getVisibleCells().map(e=>(0,Z.jsx)(Be,{className:`border-b`,children:he(e.column.columnDef.cell,e.getContext())},e.id))},e.id))})]})]})});Ot.displayName=`VariableTable`;var kt=()=>{let e=(0,Y.c)(30),n=o(),i=b(),a=r(w),s=r(x),c=H(`database`),[l,u]=t(tt),d=a.length+s.length,f;e[0]!==d||e[1]!==l.hasUserInteracted||e[2]!==l.openSections?(f=!l.hasUserInteracted&&d>0?[...new Set([...l.openSections,`datasources`])]:l.openSections,e[0]=d,e[1]=l.hasUserInteracted,e[2]=l.openSections,e[3]=f):f=e[3];let m=f,h;e[4]===u?h=e[5]:(h=e=>{u({openSections:e,hasUserInteracted:!0})},e[4]=u,e[5]=h);let g=h,_;e[6]===m?_=e[7]:(_=m.includes(`datasources`),e[6]=m,e[7]=_);let v=!_&&d>0,y=c.length>0,S;e[8]===Symbol.for(`react.memo_cache_sentinel`)?(S=(0,Z.jsx)(xe,{className:`w-4 h-4`}),e[8]=S):S=e[8];let C;e[9]!==d||e[10]!==v?(C=v&&(0,Z.jsx)(Je,{children:d}),e[9]=d,e[10]=v,e[11]=C):C=e[11];let T;e[12]!==c.length||e[13]!==y?(T=y&&(0,Z.jsx)(et,{count:c.length,type:`database`}),e[12]=c.length,e[13]=y,e[14]=T):T=e[14];let E;e[15]!==C||e[16]!==T?(E=(0,Z.jsxs)(Ye,{children:[S,`Data sources`,C,T]}),e[15]=C,e[16]=T,e[17]=E):E=e[17];let D;e[18]===Symbol.for(`react.memo_cache_sentinel`)?(D=(0,Z.jsx)(Xe,{children:(0,Z.jsx)(dt,{})}),e[18]=D):D=e[18];let O;e[19]===E?O=e[20]:(O=(0,Z.jsxs)(Qe,{value:`datasources`,children:[E,D]}),e[19]=E,e[20]=O);let k;e[21]===Symbol.for(`react.memo_cache_sentinel`)?(k=(0,Z.jsxs)(Ye,{children:[(0,Z.jsx)(p,{className:`w-4 h-4`}),`Variables`]}),e[21]=k):k=e[21];let A;e[22]!==i||e[23]!==n?(A=(0,Z.jsxs)(Qe,{value:`variables`,lastItem:!0,children:[k,(0,Z.jsx)(Xe,{children:Object.keys(n).length===0?(0,Z.jsx)(`div`,{className:`px-3 py-4 text-sm text-muted-foreground`,children:`No variables defined`}):(0,Z.jsx)(Ot,{cellIds:i.inOrderIds,variables:n})})]}),e[22]=i,e[23]=n,e[24]=A):A=e[24];let j;return e[25]!==g||e[26]!==m||e[27]!==A||e[28]!==O?(j=(0,Z.jsxs)(ie,{type:`multiple`,value:m,onValueChange:g,className:`flex flex-col h-full overflow-auto`,children:[O,A]}),e[25]=g,e[26]=m,e[27]=A,e[28]=O,e[29]=j):j=e[29],j};export{kt as default};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
|
|
3
|
-
import { atom } from "jotai";
|
|
4
|
-
import { describe, expect, it } from "vitest";
|
|
5
|
-
import { store, waitFor } from "../jotai";
|
|
6
|
-
|
|
7
|
-
describe("waitFor function", () => {
|
|
8
|
-
it("should resolve when the atom satisfies the predicate", async () => {
|
|
9
|
-
const testAtom = atom(0);
|
|
10
|
-
store.set(testAtom, 10);
|
|
11
|
-
|
|
12
|
-
const result = await waitFor(testAtom, (value) => value === 10);
|
|
13
|
-
expect(result).toBe(10);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it("should resolve when the atom changes to satisfy the predicate", async () => {
|
|
17
|
-
const testAtom = atom(0);
|
|
18
|
-
|
|
19
|
-
setTimeout(() => store.set(testAtom, 15), 5);
|
|
20
|
-
setTimeout(() => store.set(testAtom, 20), 10);
|
|
21
|
-
|
|
22
|
-
const result = await waitFor(testAtom, (value) => value === 20);
|
|
23
|
-
expect(result).toBe(20);
|
|
24
|
-
});
|
|
25
|
-
});
|