@marimo-team/islands 0.16.2 → 0.16.3
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-KvtsEmcw.js → ConnectedDataExplorerComponent-CareOso9.js} +2 -2
- package/dist/{ImageComparisonComponent-R2tjqLSx.js → ImageComparisonComponent-I_Z738Uj.js} +1 -1
- package/dist/{_baseUniq-BykZEXIq.js → _baseUniq-D-Kb4EU4.js} +1 -1
- package/dist/{any-language-editor-CMt4Y6oz.js → any-language-editor-BRWmYor8.js} +1 -1
- package/dist/{architectureDiagram-W76B3OCA-mQ3sJdEW.js → architectureDiagram-W76B3OCA-bZJcJYGH.js} +4 -4
- package/dist/assets/{worker-B0C57BK8.js → worker-DMlIUTIq.js} +18 -17
- package/dist/{blockDiagram-QIGZ2CNN-BxLRv5EM.js → blockDiagram-QIGZ2CNN-DyXjO8fR.js} +5 -5
- package/dist/{c4Diagram-FPNF74CW-Cfz16aWq.js → c4Diagram-FPNF74CW-Bfs9ui2r.js} +2 -2
- package/dist/{channel-zr1uJJ5g.js → channel-CMup9X3Z.js} +1 -1
- package/dist/{chunk-4BX2VUAB-B8iHvpDe.js → chunk-4BX2VUAB-CW-ni6M_.js} +1 -1
- package/dist/{chunk-55IACEB6-CJs4dL1H.js → chunk-55IACEB6-Bj-Indya.js} +1 -1
- package/dist/{chunk-FMBD7UC4-C5irHg20.js → chunk-FMBD7UC4-9IC8qSSk.js} +1 -1
- package/dist/{chunk-K7UQS3LO-B2XW75WS.js → chunk-K7UQS3LO-aapkEuWN.js} +4 -4
- package/dist/{chunk-QN33PNHL-BtwctqGa.js → chunk-QN33PNHL-Bo5dJ5T5.js} +1 -1
- package/dist/{chunk-QZHKN3VN-Sb8ZD0FY.js → chunk-QZHKN3VN-BkMzjJYY.js} +1 -1
- package/dist/{chunk-TVAH2DTR-CEJ5zkLX.js → chunk-TVAH2DTR-Wqy_C_Rn.js} +3 -3
- package/dist/{chunk-TZMSLE5B-Ccm4T92V.js → chunk-TZMSLE5B-DjBmEAUz.js} +1 -1
- package/dist/{classDiagram-v2-RKCZMP56-DWTbT0ww.js → classDiagram-KNZD7YFC-DUsaN1O4.js} +2 -2
- package/dist/{classDiagram-KNZD7YFC-DWTbT0ww.js → classDiagram-v2-RKCZMP56-DUsaN1O4.js} +2 -2
- package/dist/{clone-CDDiMerE.js → clone-Dkt_7KOK.js} +1 -1
- package/dist/{cose-bilkent-S5V4N54A-B74aLjZ_.js → cose-bilkent-S5V4N54A-ClBuGZWI.js} +2 -2
- package/dist/{dagre-5GWH7T2D-Cie_wUzI.js → dagre-5GWH7T2D-BzmDIGaM.js} +6 -6
- package/dist/{data-grid-overlay-editor-OsCMRzfP.js → data-grid-overlay-editor-NiU9Ea77.js} +2 -2
- package/dist/{diagram-N5W7TBWH-CCeFeV2B.js → diagram-N5W7TBWH-BlO1yw_g.js} +5 -5
- package/dist/{diagram-QEK2KX5R-BPROiVV7.js → diagram-QEK2KX5R-BvK83LUx.js} +3 -3
- package/dist/{diagram-S2PKOQOG-BkLFbUa_.js → diagram-S2PKOQOG-DvBzRYd7.js} +3 -3
- package/dist/{dockerfile-CuJXUZQ_.js → dockerfile-CPQG2tLO.js} +1 -1
- package/dist/{erDiagram-AWTI2OKA-CpBWOTMK.js → erDiagram-AWTI2OKA-Doy9FRTX.js} +4 -4
- package/dist/{flowDiagram-PVAE7QVJ-C_X4bmq3.js → flowDiagram-PVAE7QVJ-D_tX_HU1.js} +5 -5
- package/dist/{ganttDiagram-OWAHRB6G-CruldwEp.js → ganttDiagram-OWAHRB6G-CV03BHVY.js} +4 -4
- package/dist/{gitGraphDiagram-NY62KEGX-ZJnVxaQP.js → gitGraphDiagram-NY62KEGX-w3szEguZ.js} +4 -4
- package/dist/{glide-data-editor-CnOBht4I.js → glide-data-editor-akznFrmp.js} +3 -3
- package/dist/{graph-DjTtWtcG.js → graph-CjrrDHdT.js} +3 -3
- package/dist/index-CIJJs0Tu.js +40382 -0
- package/dist/{index-CZ9vIBEc.js → index-DMo6cbcV.js} +3 -3
- package/dist/{index-saLjL5eo.js → index-DlV2CtJb.js} +1 -1
- package/dist/{index-DSpjUDnr.js → index-Y-Vbae6Z.js} +1 -1
- package/dist/{infoDiagram-STP46IZ2-RZgl96nR.js → infoDiagram-STP46IZ2-BcBV2j75.js} +2 -2
- package/dist/{journeyDiagram-BIP6EPQ6-9ytZy-zY.js → journeyDiagram-BIP6EPQ6-BTGMSgvB.js} +3 -3
- package/dist/{kanban-definition-6OIFK2YF-CpjPWkgX.js → kanban-definition-6OIFK2YF-aopNqZ1Y.js} +2 -2
- package/dist/{layout-BAvhX25D.js → layout-Dvo9pb_w.js} +4 -4
- package/dist/{linear-BKZuvJrK.js → linear-CHnELER9.js} +1 -1
- package/dist/{main-pE28kbH0.js → main-kLZGkzVQ.js} +34849 -34052
- package/dist/main.js +1 -1
- package/dist/{mermaid-BGd7kEsf.js → mermaid-DgM4_4bD.js} +30 -30
- package/dist/{min-DmsBJf5S.js → min-cX4DuL_n.js} +2 -2
- package/dist/{mindmap-definition-Q6HEUPPD-BerypnVD.js → mindmap-definition-Q6HEUPPD-DZjbYryy.js} +3 -3
- package/dist/{number-overlay-editor-A7ZQ6sSs.js → number-overlay-editor-8MpIObf7.js} +2 -2
- package/dist/{pieDiagram-ADFJNKIX-ChcQLZM2.js → pieDiagram-ADFJNKIX-D6L1IYAc.js} +3 -3
- package/dist/{quadrantDiagram-LMRXKWRM-BOMxo-5G.js → quadrantDiagram-LMRXKWRM-nOyuc3Bf.js} +2 -2
- package/dist/{react-plotly-8f0vAPdB.js → react-plotly-ChkfYiVe.js} +1 -1
- package/dist/{requirementDiagram-4UW4RH46-rql0vkIr.js → requirementDiagram-4UW4RH46-OVV8wsju.js} +3 -3
- package/dist/{sankeyDiagram-GR3RE2ED-BMz3hqw4.js → sankeyDiagram-GR3RE2ED-qZHMdnE_.js} +1 -1
- package/dist/{sequenceDiagram-C3RYC4MD-DFK39LUK.js → sequenceDiagram-C3RYC4MD-D0bOqf-t.js} +3 -3
- package/dist/{slides-component-BNsZuUgg.js → slides-component-CNzLDdA3.js} +1 -1
- package/dist/{stateDiagram-KXAO66HF-B_3SWOCl.js → stateDiagram-KXAO66HF-CFNCnNJS.js} +4 -4
- package/dist/{stateDiagram-v2-UMBNRL4Z-BWAYN6aU.js → stateDiagram-v2-UMBNRL4Z-CnIh27m8.js} +2 -2
- package/dist/style.css +1 -1
- package/dist/{time-DCvYzQ5t.js → time-Z7CJSfOW.js} +2 -2
- package/dist/{timeline-definition-XQNQX7LJ-CSbxJ5mV.js → timeline-definition-XQNQX7LJ-BYLMfrvK.js} +1 -1
- package/dist/{treemap-75Q7IDZK-LMXGKln_.js → treemap-75Q7IDZK-BEh1HacP.js} +5 -5
- package/dist/{vega-component-CRmon7pH.js → vega-component-iMjXd3tD.js} +2 -2
- package/dist/{xychartDiagram-6GGTOJPD-DaUD4dq3.js → xychartDiagram-6GGTOJPD-Bmi13ZSG.js} +2 -2
- package/package.json +6 -6
- package/src/__mocks__/common.ts +5 -3
- package/src/__mocks__/notebook.ts +2 -2
- package/src/__tests__/main.test.tsx +2 -2
- package/src/components/ai/ai-provider-icon.tsx +2 -0
- package/src/components/app-config/ai-config.tsx +32 -1
- package/src/components/app-config/common.tsx +2 -2
- package/src/components/app-config/user-config-form.tsx +26 -0
- package/src/components/audio/audio-recorder.tsx +0 -1
- package/src/components/chat/acp/blocks.tsx +2 -2
- package/src/components/chat/acp/thread.tsx +3 -5
- package/src/components/chat/acp/utils.ts +5 -5
- package/src/components/chat/chat-panel.tsx +1 -1
- package/src/components/data-table/__tests__/data-table.test.tsx +2 -2
- package/src/components/data-table/charts/__tests__/altair-generator.test.ts +1 -1
- package/src/components/data-table/charts/chart-spec/tooltips.ts +3 -3
- package/src/components/data-table/charts/components/chart-items.tsx +1 -1
- package/src/components/data-table/charts/components/form-fields.tsx +2 -2
- package/src/components/data-table/charts/constants.ts +1 -1
- package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
- package/src/components/data-table/column-summary/chart-spec-model.tsx +2 -2
- package/src/components/data-table/columns.tsx +1 -1
- package/src/components/data-table/data-table.tsx +35 -3
- package/src/components/data-table/date-popover.tsx +1 -1
- package/src/components/data-table/download-actions.tsx +1 -1
- package/src/components/data-table/range-focus/__tests__/utils.test.ts +5 -5
- package/src/components/data-table/renderers.tsx +6 -5
- package/src/components/data-table/row-viewer-panel/row-viewer.tsx +1 -1
- package/src/components/data-table/types.ts +4 -3
- package/src/components/datasources/column-preview.tsx +9 -6
- package/src/components/debugger/debugger-code.tsx +1 -1
- package/src/components/dependency-graph/custom-node.tsx +15 -6
- package/src/components/dependency-graph/dependency-graph-minimap.tsx +2 -2
- package/src/components/dependency-graph/dependency-graph-tree.tsx +2 -2
- package/src/components/dependency-graph/dependency-graph.tsx +1 -1
- package/src/components/dependency-graph/elements.ts +7 -7
- package/src/components/dependency-graph/utils/changes.ts +4 -4
- package/src/components/editor/Cell.tsx +6 -2
- package/src/components/editor/ai/transport/chat-transport.tsx +1 -1
- package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +1 -1
- package/src/components/editor/chrome/panels/packages-panel.tsx +1 -1
- package/src/components/editor/columns/storage.ts +1 -1
- package/src/components/editor/database/__tests__/__snapshots__/as-code.test.ts.snap +36 -0
- package/src/components/editor/database/__tests__/as-code.test.ts +30 -7
- package/src/components/editor/database/add-database-form.tsx +11 -0
- package/src/components/editor/database/as-code.ts +104 -5
- package/src/components/editor/database/schemas.ts +36 -18
- package/src/components/editor/errors/auto-fix.tsx +12 -2
- package/src/components/editor/errors/sql-validation-errors.tsx +12 -6
- package/src/components/editor/navigation/clipboard.ts +2 -2
- package/src/components/editor/output/ConsoleOutput.tsx +1 -1
- package/src/components/editor/output/JsonOutput.tsx +1 -1
- package/src/components/editor/output/MarimoErrorOutput.tsx +25 -25
- package/src/components/editor/output/MarimoTracebackOutput.tsx +17 -2
- package/src/components/editor/renderers/grid-layout/types.ts +2 -2
- package/src/components/editor/renderers/plugins.ts +1 -1
- package/src/components/editor/renderers/types.ts +1 -1
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +7 -7
- package/src/components/forms/form.tsx +5 -5
- package/src/components/ui/links.tsx +1 -0
- package/src/core/ai/__tests__/model-registry.test.ts +0 -10
- package/src/core/ai/context/providers/error.ts +2 -2
- package/src/core/ai/ids/ids.ts +1 -0
- package/src/core/ai/model-registry.ts +2 -1
- package/src/core/cells/cells.ts +5 -5
- package/src/core/cells/logs.ts +1 -1
- package/src/core/cells/types.ts +1 -1
- package/src/core/codemirror/__tests__/format.test.ts +6 -0
- package/src/core/codemirror/cells/traceback-decorations.ts +1 -1
- package/src/core/codemirror/editing/commands.ts +2 -2
- package/src/core/codemirror/find-replace/navigate.ts +1 -1
- package/src/core/codemirror/language/__tests__/extension.test.ts +1 -1
- package/src/core/codemirror/language/__tests__/sql-validation.test.ts +1 -1
- package/src/core/codemirror/language/__tests__/sql.test.ts +764 -79
- package/src/core/codemirror/language/languages/markdown.ts +4 -1
- package/src/core/codemirror/language/languages/sql/{validation-errors.ts → banner-validation-errors.ts} +9 -3
- package/src/core/codemirror/language/languages/sql/completion-builder.ts +160 -0
- package/src/core/codemirror/language/languages/sql/completion-sources.tsx +9 -3
- package/src/core/codemirror/language/languages/sql/completion-store.ts +46 -50
- package/src/core/codemirror/language/languages/sql/renderers.tsx +485 -0
- package/src/core/codemirror/language/languages/sql/sql.ts +151 -24
- package/src/core/codemirror/language/languages/sql/utils.ts +4 -1
- package/src/core/codemirror/language/panel/sql.tsx +6 -1
- package/src/core/codemirror/language/utils/ast.ts +3 -3
- package/src/core/codemirror/lsp/federated-lsp.ts +4 -4
- package/src/core/codemirror/lsp/lens.ts +4 -4
- package/src/core/codemirror/lsp/notebook-lsp.ts +1 -1
- package/src/core/codemirror/lsp/types.ts +1 -1
- package/src/core/codemirror/markdown/completions.ts +1 -1
- package/src/core/codemirror/reactive-references/analyzer.ts +2 -2
- package/src/core/codemirror/rtc/loro/awareness.ts +1 -1
- package/src/core/config/config-schema.ts +1 -0
- package/src/core/config/feature-flag.tsx +3 -1
- package/src/core/datasets/request-registry.ts +17 -10
- package/src/core/dom/events.ts +1 -1
- package/src/core/dom/outline.ts +2 -2
- package/src/core/dom/uiregistry.ts +2 -8
- package/src/core/errors/__tests__/errors.test.ts +22 -4
- package/src/core/errors/errors.ts +29 -1
- package/src/core/errors/state.ts +1 -1
- package/src/core/islands/main.ts +2 -2
- package/src/core/islands/parse.ts +1 -3
- package/src/core/kernel/messages.ts +1 -1
- package/src/core/network/CachingRequestRegistry.ts +74 -0
- package/src/core/network/DeferredRequestRegistry.ts +3 -1
- package/src/core/network/__tests__/CachingRequestRegistry.test.ts +73 -0
- package/src/core/network/types.ts +1 -1
- package/src/core/variables/state.ts +2 -2
- package/src/core/wasm/__tests__/state.test.ts +1 -1
- package/src/core/websocket/useMarimoWebSocket.tsx +5 -2
- package/src/custom.d.ts +1 -1
- package/src/hooks/useCellRenderCount.ts +1 -0
- package/src/hooks/useResizeHandle.ts +4 -1
- package/src/plugins/core/RenderHTML.tsx +1 -2
- package/src/plugins/impl/DataTablePlugin.tsx +7 -2
- package/src/plugins/impl/FileUploadPlugin.tsx +1 -1
- package/src/plugins/impl/RefreshPlugin.tsx +1 -1
- package/src/plugins/impl/SliderPlugin.tsx +4 -0
- package/src/plugins/impl/anywidget/AnyWidgetPlugin.tsx +27 -9
- package/src/plugins/impl/anywidget/__tests__/AnyWidgetPlugin.test.tsx +58 -2
- package/src/plugins/impl/anywidget/__tests__/model.test.ts +3 -4
- package/src/plugins/impl/anywidget/model.ts +2 -3
- package/src/plugins/impl/data-editor/types.ts +1 -1
- package/src/plugins/impl/data-explorer/components/query-form.tsx +1 -1
- package/src/plugins/impl/data-frames/types.ts +1 -1
- package/src/plugins/impl/panel/PanelPlugin.tsx +2 -2
- package/src/plugins/impl/plotly/PlotlyPlugin.tsx +3 -3
- package/src/plugins/impl/vega/__tests__/loader.test.ts +2 -2
- package/src/plugins/impl/vega/loader.ts +1 -1
- package/src/plugins/impl/vega/vega-component.tsx +1 -1
- package/src/plugins/impl/vega/vega-loader.ts +2 -2
- package/src/plugins/layout/NavigationMenuPlugin.tsx +1 -1
- package/src/plugins/layout/RoutesPlugin.tsx +1 -2
- package/src/plugins/plugins.ts +2 -2
- package/src/utils/Logger.ts +1 -1
- package/src/utils/__tests__/data-views.test.ts +30 -68
- package/src/utils/__tests__/dom.test.ts +10 -10
- package/src/utils/__tests__/id-tree.test.ts +49 -1
- package/src/utils/__tests__/storage.test.ts +1 -1
- package/src/utils/__tests__/traceback.test.ts +13 -2
- package/src/utils/arrays.ts +1 -1
- package/src/utils/createReducer.ts +1 -5
- package/src/utils/data-views.ts +6 -19
- package/src/utils/edit-distance.ts +1 -1
- package/src/utils/fileToBase64.ts +1 -1
- package/src/utils/id-tree.tsx +20 -18
- package/src/utils/json/base64.ts +13 -0
- package/src/utils/json/json-parser.ts +2 -2
- package/src/utils/lru.ts +4 -0
- package/src/utils/mergeRefs.ts +1 -1
- package/src/utils/objects.ts +3 -3
- package/src/utils/pluralize.ts +1 -1
- package/src/utils/routes.ts +2 -2
- package/src/utils/sets.ts +1 -1
- package/src/utils/traceback.ts +45 -15
- package/src/utils/tracer.ts +11 -9
- package/dist/index-DeOkA9fC.js +0 -40315
- package/src/__tests__/lru.test.ts +0 -74
|
@@ -26,12 +26,13 @@ import { useScrollIntoViewOnFocus } from "./range-focus/use-scroll-into-view";
|
|
|
26
26
|
|
|
27
27
|
export function renderTableHeader<TData>(
|
|
28
28
|
table: Table<TData>,
|
|
29
|
+
isSticky?: boolean,
|
|
29
30
|
): JSX.Element | null {
|
|
30
31
|
if (!table.getRowModel().rows?.length) {
|
|
31
32
|
return null;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
const renderHeaderGroup = (headerGroups:
|
|
35
|
+
const renderHeaderGroup = (headerGroups: HeaderGroup<TData>[]) => {
|
|
35
36
|
return headerGroups.map((headerGroup) =>
|
|
36
37
|
headerGroup.headers.map((header) => {
|
|
37
38
|
const { className, style } = getPinningStyles(header.column);
|
|
@@ -57,7 +58,7 @@ export function renderTableHeader<TData>(
|
|
|
57
58
|
};
|
|
58
59
|
|
|
59
60
|
return (
|
|
60
|
-
<TableHeader>
|
|
61
|
+
<TableHeader className={cn(isSticky && "sticky top-0 z-10")}>
|
|
61
62
|
<TableRow>
|
|
62
63
|
{renderHeaderGroup(table.getLeftHeaderGroups())}
|
|
63
64
|
{renderHeaderGroup(table.getCenterHeaderGroups())}
|
|
@@ -69,7 +70,7 @@ export function renderTableHeader<TData>(
|
|
|
69
70
|
|
|
70
71
|
interface DataTableBodyProps<TData> {
|
|
71
72
|
table: Table<TData>;
|
|
72
|
-
columns:
|
|
73
|
+
columns: ColumnDef<TData>[];
|
|
73
74
|
rowViewerPanelOpen: boolean;
|
|
74
75
|
getRowIndex?: (row: TData, idx: number) => number;
|
|
75
76
|
viewedRowIdx?: number;
|
|
@@ -95,7 +96,7 @@ export const DataTableBody = <TData,>({
|
|
|
95
96
|
|
|
96
97
|
function applyHoverTemplate(
|
|
97
98
|
template: string,
|
|
98
|
-
cells:
|
|
99
|
+
cells: Cell<TData, unknown>[],
|
|
99
100
|
): string {
|
|
100
101
|
const variableRegex = /{{(\w+)}}/g;
|
|
101
102
|
// Map column id -> stringified value
|
|
@@ -112,7 +113,7 @@ export const DataTableBody = <TData,>({
|
|
|
112
113
|
});
|
|
113
114
|
}
|
|
114
115
|
|
|
115
|
-
const renderCells = (cells:
|
|
116
|
+
const renderCells = (cells: Cell<TData, unknown>[]) => {
|
|
116
117
|
return cells.map((cell) => {
|
|
117
118
|
const { className, style: pinningstyle } = getPinningStyles(cell.column);
|
|
118
119
|
const style = Object.assign(
|
|
@@ -188,7 +188,7 @@ export const RowViewerPanel: React.FC<RowViewerPanelProps> = ({
|
|
|
188
188
|
</TableRow>
|
|
189
189
|
</TableHeader>
|
|
190
190
|
<TableBody>
|
|
191
|
-
{fieldTypes?.map(([columnName, [dataType,
|
|
191
|
+
{fieldTypes?.map(([columnName, [dataType, _externalType]]) => {
|
|
192
192
|
const columnValue = rowValues[columnName];
|
|
193
193
|
|
|
194
194
|
if (!inSearchQuery({ columnName, columnValue, searchQuery })) {
|
|
@@ -27,9 +27,10 @@ export type ColumnHeaderStats = Record<
|
|
|
27
27
|
number | string | null
|
|
28
28
|
>;
|
|
29
29
|
|
|
30
|
-
export type FieldTypesWithExternalType =
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
export type FieldTypesWithExternalType = [
|
|
31
|
+
columnName: string,
|
|
32
|
+
[dataType: DataType, externalType: string],
|
|
33
|
+
][];
|
|
33
34
|
export type FieldTypes = Record<string, DataType>;
|
|
34
35
|
|
|
35
36
|
export function toFieldTypes(
|
|
@@ -110,7 +110,8 @@ export const DatasetColumnPreview: React.FC<{
|
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
const stats =
|
|
113
|
-
preview.stats &&
|
|
113
|
+
preview.stats &&
|
|
114
|
+
renderStats({ stats: preview.stats, dataType: column.type, locale });
|
|
114
115
|
|
|
115
116
|
const chart = preview.chart_spec && renderChart(preview.chart_spec, theme);
|
|
116
117
|
|
|
@@ -175,11 +176,13 @@ export function renderPreviewError({
|
|
|
175
176
|
);
|
|
176
177
|
}
|
|
177
178
|
|
|
178
|
-
|
|
179
|
-
stats: Partial<Record<ColumnHeaderStatsKey, unknown
|
|
180
|
-
dataType: DataType
|
|
181
|
-
locale: string
|
|
182
|
-
|
|
179
|
+
interface RenderStatsProps {
|
|
180
|
+
stats: Partial<Record<ColumnHeaderStatsKey, unknown>>;
|
|
181
|
+
dataType: DataType;
|
|
182
|
+
locale: string;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function renderStats({ stats, dataType, locale }: RenderStatsProps) {
|
|
183
186
|
return (
|
|
184
187
|
<div className="gap-x-16 gap-y-1 grid grid-cols-2-fit border rounded p-2 empty:hidden">
|
|
185
188
|
{Object.entries(stats).map(([key, value]) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* Copyright 2024 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { useAtomValue } from "jotai";
|
|
4
|
-
import React, { memo, use } from "react";
|
|
4
|
+
import React, { memo, use, useId } from "react";
|
|
5
5
|
import { Handle, Position, useStore } from "reactflow";
|
|
6
6
|
import { TinyCode } from "@/components/editor/cell/TinyCode";
|
|
7
7
|
import { useCellIds } from "@/core/cells/cells";
|
|
@@ -23,7 +23,7 @@ const EQUALITY_CHECK = (
|
|
|
23
23
|
prevProps: CustomNodeProps,
|
|
24
24
|
nextProps: CustomNodeProps,
|
|
25
25
|
) => {
|
|
26
|
-
const keys:
|
|
26
|
+
const keys: (keyof CustomNodeProps)[] = ["data", "selected", "id"];
|
|
27
27
|
return keys.every((key) => prevProps[key] === nextProps[key]);
|
|
28
28
|
};
|
|
29
29
|
|
|
@@ -37,18 +37,25 @@ export const CustomNode = memo((props: CustomNodeProps) => {
|
|
|
37
37
|
const reactFlowWidth = useStore(({ width }) => width);
|
|
38
38
|
const edgeMarkers = use(EdgeMarkerContext);
|
|
39
39
|
|
|
40
|
+
const inputOneId = useId();
|
|
41
|
+
const inputTwoId = useId();
|
|
42
|
+
const outputOneId = useId();
|
|
43
|
+
const outputTwoId = useId();
|
|
44
|
+
|
|
40
45
|
const linesOfCode = cell.code.split("\n").length;
|
|
41
46
|
return (
|
|
42
47
|
<div>
|
|
43
48
|
<Handle
|
|
44
49
|
type="target"
|
|
45
|
-
id=
|
|
50
|
+
id={inputOneId}
|
|
51
|
+
data-testid="input-one"
|
|
46
52
|
position={edgeMarkers === "LR" ? Position.Left : Position.Top}
|
|
47
53
|
style={{ background: color }}
|
|
48
54
|
/>
|
|
49
55
|
<Handle
|
|
50
56
|
type="source"
|
|
51
|
-
id=
|
|
57
|
+
id={inputTwoId}
|
|
58
|
+
data-testid="input-two"
|
|
52
59
|
position={edgeMarkers === "LR" ? Position.Left : Position.Top}
|
|
53
60
|
style={{ background: color }}
|
|
54
61
|
/>
|
|
@@ -69,13 +76,15 @@ export const CustomNode = memo((props: CustomNodeProps) => {
|
|
|
69
76
|
</div>
|
|
70
77
|
<Handle
|
|
71
78
|
type="source"
|
|
72
|
-
id=
|
|
79
|
+
id={outputOneId}
|
|
80
|
+
data-testid="output-one"
|
|
73
81
|
position={edgeMarkers === "LR" ? Position.Right : Position.Bottom}
|
|
74
82
|
style={{ background: color }}
|
|
75
83
|
/>
|
|
76
84
|
<Handle
|
|
77
85
|
type="target"
|
|
78
|
-
id=
|
|
86
|
+
id={outputTwoId}
|
|
87
|
+
data-testid="output-two"
|
|
79
88
|
position={edgeMarkers === "LR" ? Position.Right : Position.Bottom}
|
|
80
89
|
style={{ background: color }}
|
|
81
90
|
/>
|
|
@@ -31,7 +31,7 @@ import { useFitToViewOnDimensionChange } from "./utils/useFitToViewOnDimensionCh
|
|
|
31
31
|
interface Props {
|
|
32
32
|
cellIds: CellId[];
|
|
33
33
|
variables: Variables;
|
|
34
|
-
cellAtoms:
|
|
34
|
+
cellAtoms: Atom<CellData>[];
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
const elementsBuilder = new VerticalElementsBuilder();
|
|
@@ -57,7 +57,7 @@ export const DependencyGraphMinimap: React.FC<PropsWithChildren<Props>> = ({
|
|
|
57
57
|
|
|
58
58
|
// If the cellIds change, update the nodes.
|
|
59
59
|
const syncChanges = useEvent(
|
|
60
|
-
(elements: { nodes:
|
|
60
|
+
(elements: { nodes: Node<NodeData>[]; edges: Edge[] }) => {
|
|
61
61
|
setNodes(elements.nodes);
|
|
62
62
|
setEdges([]);
|
|
63
63
|
},
|
|
@@ -36,7 +36,7 @@ import { useFitToViewOnDimensionChange } from "./utils/useFitToViewOnDimensionCh
|
|
|
36
36
|
interface Props {
|
|
37
37
|
cellIds: CellId[];
|
|
38
38
|
variables: Variables;
|
|
39
|
-
cellAtoms:
|
|
39
|
+
cellAtoms: Atom<CellData>[];
|
|
40
40
|
layoutDirection: LayoutDirection;
|
|
41
41
|
settings: GraphSettings;
|
|
42
42
|
}
|
|
@@ -74,7 +74,7 @@ export const DependencyGraphTree: React.FC<PropsWithChildren<Props>> = ({
|
|
|
74
74
|
const api = useReactFlow();
|
|
75
75
|
|
|
76
76
|
const syncChanges = useEvent(
|
|
77
|
-
(elements: { nodes:
|
|
77
|
+
(elements: { nodes: Node<NodeData>[]; edges: Edge[] }) => {
|
|
78
78
|
// Layout the elements
|
|
79
79
|
const result = layoutElements({
|
|
80
80
|
nodes: elements.nodes,
|
|
@@ -22,10 +22,10 @@ export function getNodeHeight(linesOfCode: number) {
|
|
|
22
22
|
interface ElementsBuilder {
|
|
23
23
|
createElements: (
|
|
24
24
|
cellIds: CellId[],
|
|
25
|
-
cellAtoms:
|
|
25
|
+
cellAtoms: Atom<CellData>[],
|
|
26
26
|
variables: Variables,
|
|
27
27
|
hidePureMarkdown: boolean,
|
|
28
|
-
) => { nodes:
|
|
28
|
+
) => { nodes: Node<NodeData>[]; edges: Edge[] };
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export class VerticalElementsBuilder implements ElementsBuilder {
|
|
@@ -69,12 +69,12 @@ export class VerticalElementsBuilder implements ElementsBuilder {
|
|
|
69
69
|
|
|
70
70
|
createElements(
|
|
71
71
|
cellIds: CellId[],
|
|
72
|
-
cellAtoms:
|
|
72
|
+
cellAtoms: Atom<CellData>[],
|
|
73
73
|
variables: Variables,
|
|
74
|
-
|
|
74
|
+
_hidePureMarkdown: boolean,
|
|
75
75
|
) {
|
|
76
76
|
let prevY = 0;
|
|
77
|
-
const nodes:
|
|
77
|
+
const nodes: Node<NodeData>[] = [];
|
|
78
78
|
const edges: Edge[] = [];
|
|
79
79
|
for (const [cellId, cellAtom] of Arrays.zip(cellIds, cellAtoms)) {
|
|
80
80
|
const node = this.createNode(cellId, cellAtom, prevY);
|
|
@@ -135,11 +135,11 @@ export class TreeElementsBuilder implements ElementsBuilder {
|
|
|
135
135
|
|
|
136
136
|
createElements(
|
|
137
137
|
cellIds: CellId[],
|
|
138
|
-
cellAtoms:
|
|
138
|
+
cellAtoms: Atom<CellData>[],
|
|
139
139
|
variables: Variables,
|
|
140
140
|
hidePureMarkdown: boolean,
|
|
141
141
|
) {
|
|
142
|
-
const nodes:
|
|
142
|
+
const nodes: Node<NodeData>[] = [];
|
|
143
143
|
const edges: Edge[] = [];
|
|
144
144
|
|
|
145
145
|
const nodesWithEdges = new Set<CellId>();
|
|
@@ -11,8 +11,8 @@ import type {
|
|
|
11
11
|
export function getNodeChanges(
|
|
12
12
|
prevNodes: Node[],
|
|
13
13
|
nextNodes: Node[],
|
|
14
|
-
):
|
|
15
|
-
const changes:
|
|
14
|
+
): (NodeAddChange | NodeRemoveChange)[] {
|
|
15
|
+
const changes: (NodeAddChange | NodeRemoveChange)[] = [];
|
|
16
16
|
const prevNodeIds = new Set(prevNodes.map((node) => node.id));
|
|
17
17
|
const nextNodeIds = new Set(nextNodes.map((node) => node.id));
|
|
18
18
|
|
|
@@ -33,8 +33,8 @@ export function getNodeChanges(
|
|
|
33
33
|
export function getEdgeChanges(
|
|
34
34
|
prevEdges: Edge[],
|
|
35
35
|
nextEdges: Edge[],
|
|
36
|
-
):
|
|
37
|
-
const changes:
|
|
36
|
+
): (EdgeAddChange | EdgeRemoveChange)[] {
|
|
37
|
+
const changes: (EdgeAddChange | EdgeRemoveChange)[] = [];
|
|
38
38
|
const prevEdgeIds = new Set(prevEdges.map((edge) => edge.id));
|
|
39
39
|
const nextEdgeIds = new Set(nextEdges.map((edge) => edge.id));
|
|
40
40
|
|
|
@@ -451,6 +451,7 @@ const EditableCellComponent = ({
|
|
|
451
451
|
});
|
|
452
452
|
const canCollapse = canCollapseOutline(cellRuntime.outline);
|
|
453
453
|
const hasOutput = !isOutputEmpty(cellRuntime.output);
|
|
454
|
+
const isStaleCell = outputIsStale(cellRuntime, cellData.edited);
|
|
454
455
|
const hasConsoleOutput = cellRuntime.consoleOutputs.length > 0;
|
|
455
456
|
const cellOutput = userConfig.display.cell_output;
|
|
456
457
|
|
|
@@ -511,7 +512,7 @@ const EditableCellComponent = ({
|
|
|
511
512
|
className="output-area"
|
|
512
513
|
cellId={cellId}
|
|
513
514
|
output={cellRuntime.output}
|
|
514
|
-
stale={
|
|
515
|
+
stale={isStaleCell}
|
|
515
516
|
loading={outputIsLoading(cellRuntime.status)}
|
|
516
517
|
/>
|
|
517
518
|
{isMarkdownCodeHidden &&
|
|
@@ -654,7 +655,10 @@ const EditableCellComponent = ({
|
|
|
654
655
|
)}
|
|
655
656
|
</div>
|
|
656
657
|
</div>
|
|
657
|
-
<SqlValidationErrorBanner
|
|
658
|
+
<SqlValidationErrorBanner
|
|
659
|
+
cellId={cellId}
|
|
660
|
+
hide={cellRuntime.errored && !isStaleCell}
|
|
661
|
+
/>
|
|
658
662
|
{cellOutput === "below" && outputArea}
|
|
659
663
|
{cellRuntime.serialization && (
|
|
660
664
|
<div className="py-1 px-2 flex items-center justify-end gap-2 last:rounded-b">
|
|
@@ -16,7 +16,7 @@ export class StreamingChunkTransport<
|
|
|
16
16
|
private onChunkReceived: (chunk: UIMessageChunk) => void;
|
|
17
17
|
|
|
18
18
|
constructor(
|
|
19
|
-
options: HttpChatTransportInitOptions<UI_MESSAGE
|
|
19
|
+
options: HttpChatTransportInitOptions<UI_MESSAGE>,
|
|
20
20
|
onChunkReceived: (chunk: UIMessageChunk) => void,
|
|
21
21
|
) {
|
|
22
22
|
super(options);
|
|
@@ -18,7 +18,7 @@ function getRootScrollableElement() {
|
|
|
18
18
|
* React hook to find the active header in the outline
|
|
19
19
|
*/
|
|
20
20
|
export function useActiveOutline(
|
|
21
|
-
headerElements:
|
|
21
|
+
headerElements: (readonly [HTMLElement, string])[],
|
|
22
22
|
) {
|
|
23
23
|
const [activeHeaderId, setActiveHeaderId] = useState<string | undefined>(
|
|
24
24
|
undefined,
|
|
@@ -300,7 +300,7 @@ const InstallPackageForm: React.FC<{
|
|
|
300
300
|
|
|
301
301
|
const PackagesList: React.FC<{
|
|
302
302
|
onSuccess: () => void;
|
|
303
|
-
packages:
|
|
303
|
+
packages: { name: string; version: string }[];
|
|
304
304
|
}> = ({ onSuccess, packages }) => {
|
|
305
305
|
if (packages.length === 0) {
|
|
306
306
|
return (
|
|
@@ -7,7 +7,7 @@ import { NotebookScopedLocalStorage } from "@/utils/localStorage";
|
|
|
7
7
|
const BASE_KEY = "marimo:notebook-col-sizes";
|
|
8
8
|
|
|
9
9
|
interface ColumnSizes {
|
|
10
|
-
widths:
|
|
10
|
+
widths: (number | "contentWidth")[];
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
function initialState(): ColumnSizes {
|
|
@@ -28,6 +28,42 @@ engine = clickhouse_connect.get_client(
|
|
|
28
28
|
)"
|
|
29
29
|
`;
|
|
30
30
|
|
|
31
|
+
exports[`generateDatabaseCode > basic connections > databricks 1`] = `
|
|
32
|
+
"import os
|
|
33
|
+
import sqlalchemy
|
|
34
|
+
|
|
35
|
+
_access_token = os.environ.get("DATABRICKS_ACCESS_TOKEN", "my_access_token")
|
|
36
|
+
_server_hostname = os.environ.get("DATABRICKS_SERVER_HOSTNAME", "localhost")
|
|
37
|
+
_http_path = os.environ.get("DATABRICKS_HTTP_PATH", "http://localhost:8080")
|
|
38
|
+
DATABASE_URL = f"databricks://token:{_access_token}@{_server_hostname}?http_path={_http_path}"
|
|
39
|
+
engine = sqlalchemy.create_engine(DATABASE_URL)"
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
exports[`generateDatabaseCode > basic connections > databricks with catalog and schema 1`] = `
|
|
43
|
+
"import os
|
|
44
|
+
import sqlalchemy
|
|
45
|
+
|
|
46
|
+
_access_token = os.environ.get("DATABRICKS_ACCESS_TOKEN", "my_access_token")
|
|
47
|
+
_server_hostname = os.environ.get("DATABRICKS_SERVER_HOSTNAME", "localhost")
|
|
48
|
+
_http_path = os.environ.get("DATABRICKS_HTTP_PATH", "http://localhost:8080")
|
|
49
|
+
DATABASE_URL = f"databricks://token:{_access_token}@{_server_hostname}?http_path={_http_path}&catalog=my_catalog&schema=my_schema"
|
|
50
|
+
engine = sqlalchemy.create_engine(DATABASE_URL)"
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
exports[`generateDatabaseCode > basic connections > databricks with ibis 1`] = `
|
|
54
|
+
"import ibis
|
|
55
|
+
import os
|
|
56
|
+
|
|
57
|
+
_access_token = os.environ.get("DATABRICKS_ACCESS_TOKEN", "my_access_token")
|
|
58
|
+
_server_hostname = os.environ.get("DATABRICKS_SERVER_HOSTNAME", "localhost")
|
|
59
|
+
_http_path = os.environ.get("DATABRICKS_HTTP_PATH", "http://localhost:8080")
|
|
60
|
+
engine = ibis.databricks.connect(
|
|
61
|
+
server_hostname=_server_hostname,
|
|
62
|
+
http_path=_http_path,
|
|
63
|
+
access_token=_access_token
|
|
64
|
+
)"
|
|
65
|
+
`;
|
|
66
|
+
|
|
31
67
|
exports[`generateDatabaseCode > basic connections > datafusion 1`] = `
|
|
32
68
|
"from datafusion import SessionContext
|
|
33
69
|
import ibis
|
|
@@ -192,8 +192,24 @@ describe("generateDatabaseCode", () => {
|
|
|
192
192
|
},
|
|
193
193
|
};
|
|
194
194
|
|
|
195
|
+
const databricksConnection: DatabaseConnection = {
|
|
196
|
+
type: "databricks",
|
|
197
|
+
access_token: "my_access_token",
|
|
198
|
+
server_hostname: "localhost",
|
|
199
|
+
http_path: "http://localhost:8080",
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const databricksWithCatalogSchema: DatabaseConnection = {
|
|
203
|
+
type: "databricks",
|
|
204
|
+
access_token: "my_access_token",
|
|
205
|
+
server_hostname: "localhost",
|
|
206
|
+
http_path: "http://localhost:8080",
|
|
207
|
+
catalog: "my_catalog",
|
|
208
|
+
schema: "my_schema",
|
|
209
|
+
};
|
|
210
|
+
|
|
195
211
|
describe("basic connections", () => {
|
|
196
|
-
const testCases:
|
|
212
|
+
const testCases: [string, DatabaseConnection, ConnectionLibrary][] = [
|
|
197
213
|
["postgres with SQLModel", basePostgres, "sqlmodel"],
|
|
198
214
|
["postgres with SQLAlchemy", basePostgres, "sqlalchemy"],
|
|
199
215
|
["mysql with SQLModel", baseMysql, "sqlmodel"],
|
|
@@ -218,9 +234,16 @@ describe("generateDatabaseCode", () => {
|
|
|
218
234
|
["pyspark with session", pysparkConnSession, "ibis"],
|
|
219
235
|
["redshift with DB credentials", redshiftDBConnection, "redshift"],
|
|
220
236
|
["redshift with IAM credentials", redshiftIAMConnection, "redshift"],
|
|
237
|
+
["databricks", databricksConnection, "sqlalchemy"],
|
|
238
|
+
[
|
|
239
|
+
"databricks with catalog and schema",
|
|
240
|
+
databricksWithCatalogSchema,
|
|
241
|
+
"sqlalchemy",
|
|
242
|
+
],
|
|
243
|
+
["databricks with ibis", databricksConnection, "ibis"],
|
|
221
244
|
];
|
|
222
245
|
|
|
223
|
-
it.each(testCases)("%s", (
|
|
246
|
+
it.each(testCases)("%s", (_name, connection, orm) => {
|
|
224
247
|
expect(generateDatabaseCode(connection, orm)).toMatchSnapshot();
|
|
225
248
|
});
|
|
226
249
|
});
|
|
@@ -292,7 +315,7 @@ describe("generateDatabaseCode", () => {
|
|
|
292
315
|
},
|
|
293
316
|
"duckdb",
|
|
294
317
|
],
|
|
295
|
-
])("%s", (
|
|
318
|
+
])("%s", (_name, connection, orm) => {
|
|
296
319
|
expect(
|
|
297
320
|
generateDatabaseCode(connection, orm as ConnectionLibrary),
|
|
298
321
|
).toMatchSnapshot();
|
|
@@ -300,7 +323,7 @@ describe("generateDatabaseCode", () => {
|
|
|
300
323
|
});
|
|
301
324
|
|
|
302
325
|
describe("edge cases", () => {
|
|
303
|
-
const testCases:
|
|
326
|
+
const testCases: [string, DatabaseConnection, string][] = [
|
|
304
327
|
[
|
|
305
328
|
"ENV with special chars SQLModel",
|
|
306
329
|
{
|
|
@@ -504,7 +527,7 @@ describe("generateDatabaseCode", () => {
|
|
|
504
527
|
],
|
|
505
528
|
];
|
|
506
529
|
|
|
507
|
-
it.each(testCases)("%s", (
|
|
530
|
+
it.each(testCases)("%s", (_name, connection, orm) => {
|
|
508
531
|
expect(
|
|
509
532
|
generateDatabaseCode(connection, orm as ConnectionLibrary),
|
|
510
533
|
).toMatchSnapshot();
|
|
@@ -548,7 +571,7 @@ describe("generateDatabaseCode", () => {
|
|
|
548
571
|
credentials_json: '{"type": "service_account", "project_id": "test"',
|
|
549
572
|
},
|
|
550
573
|
],
|
|
551
|
-
])("%s", (
|
|
574
|
+
])("%s", (_name, connection) => {
|
|
552
575
|
expect(generateDatabaseCode(connection, "sqlmodel")).toMatchSnapshot();
|
|
553
576
|
expect(generateDatabaseCode(connection, "sqlalchemy")).toMatchSnapshot();
|
|
554
577
|
});
|
|
@@ -591,7 +614,7 @@ describe("generateDatabaseCode", () => {
|
|
|
591
614
|
"sqlmodel",
|
|
592
615
|
),
|
|
593
616
|
],
|
|
594
|
-
])("%s", (
|
|
617
|
+
])("%s", (_name, fn) => {
|
|
595
618
|
expect(fn).toThrow();
|
|
596
619
|
});
|
|
597
620
|
});
|
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
ChdbConnectionSchema,
|
|
40
40
|
ClickhouseConnectionSchema,
|
|
41
41
|
type DatabaseConnection,
|
|
42
|
+
DatabricksConnectionSchema,
|
|
42
43
|
DataFusionConnectionSchema,
|
|
43
44
|
DuckDBConnectionSchema,
|
|
44
45
|
IcebergConnectionSchema,
|
|
@@ -210,6 +211,16 @@ const DATABASES = [
|
|
|
210
211
|
preferred: "redshift",
|
|
211
212
|
},
|
|
212
213
|
},
|
|
214
|
+
{
|
|
215
|
+
name: "Databricks",
|
|
216
|
+
schema: DatabricksConnectionSchema,
|
|
217
|
+
color: "#c41e0c",
|
|
218
|
+
logo: "databricks",
|
|
219
|
+
connectionLibraries: {
|
|
220
|
+
libraries: ["sqlalchemy", "sqlmodel", "ibis"],
|
|
221
|
+
preferred: "sqlalchemy",
|
|
222
|
+
},
|
|
223
|
+
},
|
|
213
224
|
] satisfies ConnectionSchema[];
|
|
214
225
|
|
|
215
226
|
const DATA_CATALOGS = [
|