@malloy-publisher/sdk 0.0.30 → 0.0.31
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/RenderedResult-BSo_9A4J.js +30 -0
- package/dist/RenderedResult-Bvw1-OOH.cjs +1 -0
- package/dist/client/api.d.ts +6 -0
- package/dist/components/Model/NamedQueries.d.ts +7 -0
- package/dist/components/RenderedResult/RenderedResult.d.ts +2 -1
- package/dist/components/RenderedResult/ResultContainer.d.ts +7 -0
- package/dist/components/styles.d.ts +2 -2
- package/dist/index.cjs.js +318 -318
- package/dist/index.es.js +11852 -11750
- package/dist/{vendor-C36FjD0v.js → vendor-CYQMs_sd.js} +37183 -31586
- package/dist/vendor-DldTUzr7.cjs +461 -0
- package/package.json +7 -7
- package/src/components/Model/Model.tsx +35 -30
- package/src/components/Model/NamedQueries.tsx +156 -0
- package/src/components/Model/SourcesExplorer.tsx +14 -14
- package/src/components/MutableNotebook/MutableCell.tsx +1 -1
- package/src/components/Notebook/Notebook.tsx +24 -20
- package/src/components/Notebook/NotebookCell.tsx +33 -41
- package/src/components/Package/Package.tsx +1 -0
- package/src/components/RenderedResult/RenderedResult.tsx +42 -2
- package/src/components/RenderedResult/ResultContainer.tsx +167 -0
- package/src/components/styles.ts +2 -2
- package/dist/RenderedResult-C1_N6KvU.js +0 -12
- package/dist/RenderedResult-Df-v_vru.cjs +0 -1
- package/dist/vendor-DSpmIox9.cjs +0 -360
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloy-publisher/sdk",
|
|
3
3
|
"description": "Malloy Publisher SDK",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.31",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs.js",
|
|
7
7
|
"module": "dist/index.es.js",
|
|
@@ -34,19 +34,19 @@
|
|
|
34
34
|
"@emotion/react": "^11.14.0",
|
|
35
35
|
"@emotion/styled": "^11.14.0",
|
|
36
36
|
"@malloydata/malloy-explorer": "^0.0.285-dev250530165648",
|
|
37
|
-
"@malloydata/malloy-query-builder": "^0.0.285",
|
|
38
37
|
"@malloydata/malloy-interfaces": "^0.0.285",
|
|
38
|
+
"@malloydata/malloy-query-builder": "^0.0.285",
|
|
39
39
|
"@malloydata/render": "^0.0.285",
|
|
40
|
-
"@mui/icons-material": "^7.
|
|
41
|
-
"@mui/material": "^7.
|
|
42
|
-
"@mui/system": "^7.
|
|
40
|
+
"@mui/icons-material": "^7.1.1",
|
|
41
|
+
"@mui/material": "^7.1.1",
|
|
42
|
+
"@mui/system": "^7.1.1",
|
|
43
43
|
"@mui/x-tree-view": "^7.16.0",
|
|
44
44
|
"@react-spring/web": "^10.0.1",
|
|
45
45
|
"@tanstack/react-query": "^5.59.16",
|
|
46
46
|
"@uiw/react-md-editor": "^4.0.6",
|
|
47
47
|
"axios": "^1.7.7",
|
|
48
|
-
"markdown-to-jsx": "^7.
|
|
49
|
-
"react-router-dom": "^6.
|
|
48
|
+
"markdown-to-jsx": "^7.7.6",
|
|
49
|
+
"react-router-dom": "^7.6.2"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@openapitools/openapi-generator-cli": "^2.13.5",
|
|
@@ -1,27 +1,28 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
|
|
2
|
+
import LinkOutlinedIcon from "@mui/icons-material/LinkOutlined";
|
|
2
3
|
import {
|
|
3
4
|
Box,
|
|
4
|
-
Typography,
|
|
5
|
-
Stack,
|
|
6
5
|
CardActions,
|
|
7
|
-
Tooltip,
|
|
8
|
-
IconButton,
|
|
9
6
|
Collapse,
|
|
10
7
|
Divider,
|
|
11
|
-
|
|
8
|
+
IconButton,
|
|
9
|
+
Stack,
|
|
12
10
|
Tab,
|
|
11
|
+
Tabs,
|
|
12
|
+
Tooltip,
|
|
13
|
+
Typography,
|
|
13
14
|
} from "@mui/material";
|
|
14
15
|
import { QueryClient, useQuery } from "@tanstack/react-query";
|
|
15
|
-
import
|
|
16
|
-
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
|
|
16
|
+
import React, { useEffect } from "react";
|
|
17
17
|
import { Configuration, ModelsApi } from "../../client";
|
|
18
|
-
import { ModelCell } from "./ModelCell";
|
|
19
|
-
import { StyledCard, StyledCardContent, StyledCardMedia } from "../styles";
|
|
20
18
|
import { highlight } from "../highlighter";
|
|
19
|
+
import { StyledCard, StyledCardContent, StyledCardMedia } from "../styles";
|
|
20
|
+
import { ModelCell } from "./ModelCell";
|
|
21
21
|
|
|
22
22
|
import "@malloydata/malloy-explorer/styles.css";
|
|
23
23
|
import { usePublisherPackage } from "../Package/PublisherPackageProvider";
|
|
24
24
|
import { SourceExplorerComponent } from "./SourcesExplorer";
|
|
25
|
+
import NamedQueries from "./NamedQueries";
|
|
25
26
|
const modelsApi = new ModelsApi(new Configuration());
|
|
26
27
|
|
|
27
28
|
const queryClient = new QueryClient();
|
|
@@ -136,28 +137,32 @@ export default function Model({
|
|
|
136
137
|
})}
|
|
137
138
|
</Tabs>
|
|
138
139
|
)}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
<Tooltip
|
|
147
|
-
title={
|
|
148
|
-
embeddingExpanded ? "Hide Embedding" : "View Embedding"
|
|
149
|
-
}
|
|
140
|
+
{!hideEmbeddingIcons && (
|
|
141
|
+
<CardActions
|
|
142
|
+
sx={{
|
|
143
|
+
padding: "0px 10px 0px 10px",
|
|
144
|
+
mb: "auto",
|
|
145
|
+
mt: "auto",
|
|
146
|
+
}}
|
|
150
147
|
>
|
|
151
|
-
<
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
148
|
+
<Tooltip
|
|
149
|
+
title={
|
|
150
|
+
embeddingExpanded
|
|
151
|
+
? "Hide Embedding"
|
|
152
|
+
: "View Embedding"
|
|
153
|
+
}
|
|
156
154
|
>
|
|
157
|
-
<
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
155
|
+
<IconButton
|
|
156
|
+
size="small"
|
|
157
|
+
onClick={() => {
|
|
158
|
+
setEmbeddingExpanded(!embeddingExpanded);
|
|
159
|
+
}}
|
|
160
|
+
>
|
|
161
|
+
<LinkOutlinedIcon />
|
|
162
|
+
</IconButton>
|
|
163
|
+
</Tooltip>
|
|
164
|
+
</CardActions>
|
|
165
|
+
)}
|
|
161
166
|
</Stack>
|
|
162
167
|
<Collapse in={embeddingExpanded} timeout="auto" unmountOnExit>
|
|
163
168
|
<Divider />
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Typography,
|
|
3
|
+
Accordion,
|
|
4
|
+
AccordionSummary,
|
|
5
|
+
AccordionDetails,
|
|
6
|
+
} from "@mui/material";
|
|
7
|
+
import { Box } from "@mui/system";
|
|
8
|
+
import { Query, QueryresultsApi } from "../../client/api";
|
|
9
|
+
import { StyledCard, StyledCardContent } from "../styles";
|
|
10
|
+
|
|
11
|
+
import { QueryClient, useMutation } from "@tanstack/react-query";
|
|
12
|
+
import { Configuration } from "../../client";
|
|
13
|
+
import { usePublisherPackage } from "../Package";
|
|
14
|
+
import React from "react";
|
|
15
|
+
import ResultContainer from "../RenderedResult/ResultContainer";
|
|
16
|
+
|
|
17
|
+
const queryResultsApi = new QueryresultsApi(new Configuration());
|
|
18
|
+
const queryClient = new QueryClient();
|
|
19
|
+
|
|
20
|
+
interface NamedQueryProps {
|
|
21
|
+
modelPath: string;
|
|
22
|
+
namedQueries: Array<Query>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default function NamedQueries({
|
|
26
|
+
namedQueries,
|
|
27
|
+
modelPath,
|
|
28
|
+
}: NamedQueryProps) {
|
|
29
|
+
const { server, projectName, packageName, versionId, accessToken } =
|
|
30
|
+
usePublisherPackage();
|
|
31
|
+
const [namedQueryResults, setNamedQueryResults] = React.useState<
|
|
32
|
+
Record<string, string>
|
|
33
|
+
>({});
|
|
34
|
+
const [expandedAccordions, setExpandedAccordions] = React.useState<
|
|
35
|
+
Record<string, boolean>
|
|
36
|
+
>({});
|
|
37
|
+
|
|
38
|
+
const mutation = useMutation(
|
|
39
|
+
{
|
|
40
|
+
mutationFn: ({ query }: { query: Query }) => {
|
|
41
|
+
const val = queryResultsApi.executeQuery(
|
|
42
|
+
projectName,
|
|
43
|
+
packageName,
|
|
44
|
+
modelPath,
|
|
45
|
+
undefined,
|
|
46
|
+
undefined,
|
|
47
|
+
query.name,
|
|
48
|
+
versionId,
|
|
49
|
+
{
|
|
50
|
+
baseURL: server,
|
|
51
|
+
withCredentials: !accessToken,
|
|
52
|
+
headers: {
|
|
53
|
+
Authorization: accessToken && `Bearer ${accessToken}`,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
return val;
|
|
58
|
+
},
|
|
59
|
+
onSuccess: (data, { query }: { query: Query }) => {
|
|
60
|
+
if (data) {
|
|
61
|
+
setNamedQueryResults((prev) => ({
|
|
62
|
+
...prev,
|
|
63
|
+
[query.name]: data.data.result,
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
queryClient,
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const handleAccordionChange =
|
|
72
|
+
(query: Query, queryKey: string) =>
|
|
73
|
+
(event: React.SyntheticEvent, isExpanded: boolean) => {
|
|
74
|
+
setExpandedAccordions((prev) => ({
|
|
75
|
+
...prev,
|
|
76
|
+
[queryKey]: isExpanded,
|
|
77
|
+
}));
|
|
78
|
+
|
|
79
|
+
// Trigger mutation only if expanding and we haven't executed this query before
|
|
80
|
+
if (isExpanded && !namedQueryResults[query.name]) {
|
|
81
|
+
mutation.mutate({ query });
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
if (!namedQueries) {
|
|
86
|
+
return <div> Loading Named Queries</div>;
|
|
87
|
+
}
|
|
88
|
+
if (namedQueries.length == 0) {
|
|
89
|
+
return <div> No Named Queries</div>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<StyledCard variant="outlined">
|
|
94
|
+
<StyledCardContent>
|
|
95
|
+
<Typography variant="subtitle1">Named Queries</Typography>
|
|
96
|
+
</StyledCardContent>
|
|
97
|
+
<Box>
|
|
98
|
+
{namedQueries.map((query: any, idx: number) => {
|
|
99
|
+
const queryKey = query.name || `query-${idx}`;
|
|
100
|
+
return (
|
|
101
|
+
<Accordion
|
|
102
|
+
key={queryKey}
|
|
103
|
+
expanded={expandedAccordions[queryKey] || false}
|
|
104
|
+
onChange={handleAccordionChange(query, queryKey)}
|
|
105
|
+
>
|
|
106
|
+
<AccordionSummary>
|
|
107
|
+
<Typography variant="body1">
|
|
108
|
+
{query.name || `Query ${idx + 1}`}
|
|
109
|
+
</Typography>
|
|
110
|
+
</AccordionSummary>
|
|
111
|
+
<AccordionDetails>
|
|
112
|
+
{mutation.isPending && expandedAccordions[queryKey] && (
|
|
113
|
+
<div
|
|
114
|
+
style={{
|
|
115
|
+
marginTop: "10px",
|
|
116
|
+
fontStyle: "italic",
|
|
117
|
+
}}
|
|
118
|
+
>
|
|
119
|
+
Executing query...
|
|
120
|
+
</div>
|
|
121
|
+
)}
|
|
122
|
+
<ResultContainer
|
|
123
|
+
result={namedQueryResults[query.name]}
|
|
124
|
+
minHeight={300}
|
|
125
|
+
maxHeight={900}
|
|
126
|
+
/>
|
|
127
|
+
{Array.isArray(query.annotations) &&
|
|
128
|
+
query.annotations.length > 0 && (
|
|
129
|
+
<Box sx={{ mt: 1 }}>
|
|
130
|
+
<Typography
|
|
131
|
+
variant="caption"
|
|
132
|
+
color="text.secondary"
|
|
133
|
+
>
|
|
134
|
+
Annotations:
|
|
135
|
+
</Typography>
|
|
136
|
+
<ul style={{ margin: 0, paddingLeft: 16 }}>
|
|
137
|
+
{query.annotations.map(
|
|
138
|
+
(annotation: string, aidx: number) => (
|
|
139
|
+
<li key={aidx}>
|
|
140
|
+
<Typography variant="caption">
|
|
141
|
+
{annotation}
|
|
142
|
+
</Typography>
|
|
143
|
+
</li>
|
|
144
|
+
),
|
|
145
|
+
)}
|
|
146
|
+
</ul>
|
|
147
|
+
</Box>
|
|
148
|
+
)}
|
|
149
|
+
</AccordionDetails>
|
|
150
|
+
</Accordion>
|
|
151
|
+
);
|
|
152
|
+
})}
|
|
153
|
+
</Box>
|
|
154
|
+
</StyledCard>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
@@ -87,8 +87,8 @@ export function SourcesExplorer({
|
|
|
87
87
|
const [selectedTab, setSelectedTab] = React.useState(
|
|
88
88
|
existingSourceName
|
|
89
89
|
? sourceAndPaths.findIndex(
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
(entry) => entry.sourceInfo.name === existingSourceName,
|
|
91
|
+
)
|
|
92
92
|
: 0,
|
|
93
93
|
);
|
|
94
94
|
|
|
@@ -291,7 +291,7 @@ export function SourceExplorerComponent({
|
|
|
291
291
|
>
|
|
292
292
|
<ResizableCollapsiblePanel
|
|
293
293
|
isInitiallyExpanded={true}
|
|
294
|
-
initialWidth={
|
|
294
|
+
initialWidth={180}
|
|
295
295
|
minWidth={180}
|
|
296
296
|
icon="database"
|
|
297
297
|
title={sourceAndPath.sourceInfo.name}
|
|
@@ -304,7 +304,7 @@ export function SourceExplorerComponent({
|
|
|
304
304
|
</ResizableCollapsiblePanel>
|
|
305
305
|
<ResizableCollapsiblePanel
|
|
306
306
|
isInitiallyExpanded={true}
|
|
307
|
-
initialWidth={
|
|
307
|
+
initialWidth={280}
|
|
308
308
|
minWidth={280}
|
|
309
309
|
icon="filterSliders"
|
|
310
310
|
title="Query"
|
|
@@ -324,16 +324,16 @@ export function SourceExplorerComponent({
|
|
|
324
324
|
submittedQuery={
|
|
325
325
|
query?.malloyQuery
|
|
326
326
|
? {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
327
|
+
executionState: mutation.isPending
|
|
328
|
+
? "running"
|
|
329
|
+
: "finished",
|
|
330
|
+
response: {
|
|
331
|
+
result: query.malloyResult,
|
|
332
|
+
},
|
|
333
|
+
query: query.malloyQuery,
|
|
334
|
+
queryResolutionStartMillis: Date.now(),
|
|
335
|
+
onCancel: mutation.reset,
|
|
336
|
+
}
|
|
337
337
|
: undefined
|
|
338
338
|
}
|
|
339
339
|
options={{ showRawQuery: true }}
|
|
@@ -311,7 +311,7 @@ export function MutableCell({
|
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
function useDebounce<T>(callback: (value: T) => void, delay: number = 2000) {
|
|
314
|
-
const timeoutRef = React.useRef<
|
|
314
|
+
const timeoutRef = React.useRef<ReturnType<typeof setTimeout>>();
|
|
315
315
|
|
|
316
316
|
return React.useCallback(
|
|
317
317
|
(value: T) => {
|
|
@@ -100,28 +100,32 @@ export default function Notebook({
|
|
|
100
100
|
<Typography variant="overline" fontWeight="bold">
|
|
101
101
|
Notebook
|
|
102
102
|
</Typography>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
<Tooltip
|
|
111
|
-
title={
|
|
112
|
-
embeddingExpanded ? "Hide Embedding" : "View Embedding"
|
|
113
|
-
}
|
|
103
|
+
{!hideEmbeddingIcons && (
|
|
104
|
+
<CardActions
|
|
105
|
+
sx={{
|
|
106
|
+
padding: "0px 10px 0px 10px",
|
|
107
|
+
mb: "auto",
|
|
108
|
+
mt: "auto",
|
|
109
|
+
}}
|
|
114
110
|
>
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
111
|
+
<Tooltip
|
|
112
|
+
title={
|
|
113
|
+
embeddingExpanded
|
|
114
|
+
? "Hide Embedding"
|
|
115
|
+
: "View Embedding"
|
|
116
|
+
}
|
|
120
117
|
>
|
|
121
|
-
<
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
118
|
+
<IconButton
|
|
119
|
+
size="small"
|
|
120
|
+
onClick={() => {
|
|
121
|
+
setEmbeddingExpanded(!embeddingExpanded);
|
|
122
|
+
}}
|
|
123
|
+
>
|
|
124
|
+
<LinkOutlinedIcon />
|
|
125
|
+
</IconButton>
|
|
126
|
+
</Tooltip>
|
|
127
|
+
</CardActions>
|
|
128
|
+
)}
|
|
125
129
|
</Stack>
|
|
126
130
|
<Collapse in={embeddingExpanded} timeout="auto" unmountOnExit>
|
|
127
131
|
<Divider />
|
|
@@ -4,13 +4,13 @@ import ContentCopyIcon from "@mui/icons-material/ContentCopy";
|
|
|
4
4
|
import LinkOutlinedIcon from "@mui/icons-material/LinkOutlined";
|
|
5
5
|
import {
|
|
6
6
|
CardActions,
|
|
7
|
-
CardContent,
|
|
8
7
|
Collapse,
|
|
9
8
|
Divider,
|
|
10
9
|
IconButton,
|
|
11
10
|
Stack,
|
|
12
11
|
Tooltip,
|
|
13
12
|
Typography,
|
|
13
|
+
Box,
|
|
14
14
|
} from "@mui/material";
|
|
15
15
|
import Markdown from "markdown-to-jsx";
|
|
16
16
|
import React, { Suspense, lazy, useEffect } from "react";
|
|
@@ -18,8 +18,7 @@ import { NotebookCell as ClientNotebookCell } from "../../client";
|
|
|
18
18
|
import { highlight } from "../highlighter";
|
|
19
19
|
import { SourcesExplorer } from "../Model";
|
|
20
20
|
import { StyledCard, StyledCardContent } from "../styles";
|
|
21
|
-
|
|
22
|
-
const RenderedResult = lazy(() => import("../RenderedResult/RenderedResult"));
|
|
21
|
+
import ResultContainer from "../RenderedResult/ResultContainer";
|
|
23
22
|
|
|
24
23
|
interface NotebookCellProps {
|
|
25
24
|
cell: ClientNotebookCell;
|
|
@@ -72,7 +71,7 @@ export function NotebookCell({
|
|
|
72
71
|
</StyledCard>
|
|
73
72
|
)) ||
|
|
74
73
|
(cell.type === "code" && (
|
|
75
|
-
<StyledCard variant="outlined">
|
|
74
|
+
<StyledCard variant="outlined" sx={{ height: "auto" }}>
|
|
76
75
|
{(!hideCodeCellIcon || (!hideEmbeddingIcon && cell.result)) && (
|
|
77
76
|
<Stack sx={{ flexDirection: "row", justifyContent: "right" }}>
|
|
78
77
|
<CardActions
|
|
@@ -82,6 +81,31 @@ export function NotebookCell({
|
|
|
82
81
|
mt: "auto",
|
|
83
82
|
}}
|
|
84
83
|
>
|
|
84
|
+
{cell.newSources && cell.newSources.length > 0 && (
|
|
85
|
+
<Tooltip title="Explore Data Sources">
|
|
86
|
+
<IconButton
|
|
87
|
+
size="small"
|
|
88
|
+
onClick={() => {
|
|
89
|
+
setSourcesExpanded(!sourcesExpanded);
|
|
90
|
+
setEmbeddingExpanded(false);
|
|
91
|
+
setCodeExpanded(false);
|
|
92
|
+
}}
|
|
93
|
+
>
|
|
94
|
+
<svg
|
|
95
|
+
width="24"
|
|
96
|
+
height="24"
|
|
97
|
+
viewBox="0 0 24 24"
|
|
98
|
+
fill="none"
|
|
99
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
100
|
+
>
|
|
101
|
+
<path
|
|
102
|
+
d="M3 3h18v18H3V3zm2 2v14h14V5H5zm2 2h10v2H7V7zm0 4h10v2H7v-2zm0 4h10v2H7v-2z"
|
|
103
|
+
fill="currentColor"
|
|
104
|
+
/>
|
|
105
|
+
</svg>
|
|
106
|
+
</IconButton>
|
|
107
|
+
</Tooltip>
|
|
108
|
+
)}
|
|
85
109
|
{!hideCodeCellIcon && (
|
|
86
110
|
<Tooltip
|
|
87
111
|
title={codeExpanded ? "Hide Code" : "View Code"}
|
|
@@ -114,31 +138,6 @@ export function NotebookCell({
|
|
|
114
138
|
</IconButton>
|
|
115
139
|
</Tooltip>
|
|
116
140
|
)}
|
|
117
|
-
{cell.newSources && cell.newSources.length > 0 && (
|
|
118
|
-
<Tooltip title="Explore Data Sources">
|
|
119
|
-
<IconButton
|
|
120
|
-
size="small"
|
|
121
|
-
onClick={() => {
|
|
122
|
-
setSourcesExpanded(!sourcesExpanded);
|
|
123
|
-
setEmbeddingExpanded(false);
|
|
124
|
-
setCodeExpanded(false);
|
|
125
|
-
}}
|
|
126
|
-
>
|
|
127
|
-
<svg
|
|
128
|
-
width="24"
|
|
129
|
-
height="24"
|
|
130
|
-
viewBox="0 0 24 24"
|
|
131
|
-
fill="none"
|
|
132
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
133
|
-
>
|
|
134
|
-
<path
|
|
135
|
-
d="M3 3h18v18H3V3zm2 2v14h14V5H5zm2 2h10v2H7V7zm0 4h10v2H7v-2zm0 4h10v2H7v-2z"
|
|
136
|
-
fill="currentColor"
|
|
137
|
-
/>
|
|
138
|
-
</svg>
|
|
139
|
-
</IconButton>
|
|
140
|
-
</Tooltip>
|
|
141
|
-
)}
|
|
142
141
|
</CardActions>
|
|
143
142
|
</Stack>
|
|
144
143
|
)}
|
|
@@ -212,18 +211,11 @@ export function NotebookCell({
|
|
|
212
211
|
</Collapse>
|
|
213
212
|
{cell.result && !sourcesExpanded && (
|
|
214
213
|
<>
|
|
215
|
-
<
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
overflow: "auto",
|
|
221
|
-
}}
|
|
222
|
-
>
|
|
223
|
-
<Suspense fallback="Loading malloy...">
|
|
224
|
-
<RenderedResult result={cell.result} />
|
|
225
|
-
</Suspense>
|
|
226
|
-
</CardContent>
|
|
214
|
+
<ResultContainer
|
|
215
|
+
result={cell.result}
|
|
216
|
+
minHeight={200}
|
|
217
|
+
maxHeight={800}
|
|
218
|
+
/>
|
|
227
219
|
</>
|
|
228
220
|
)}
|
|
229
221
|
</StyledCard>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable react/prop-types */
|
|
2
2
|
import type { MalloyRenderProps } from "@malloydata/render";
|
|
3
3
|
import "@malloydata/render/webcomponent";
|
|
4
|
-
import React, { useEffect, useRef } from "react";
|
|
4
|
+
import React, { useEffect, useRef, useCallback } from "react";
|
|
5
5
|
|
|
6
6
|
type MalloyRenderElement = HTMLElement & MalloyRenderProps;
|
|
7
7
|
|
|
@@ -19,14 +19,54 @@ declare global {
|
|
|
19
19
|
|
|
20
20
|
interface RenderedResultProps {
|
|
21
21
|
result: string;
|
|
22
|
+
onSizeChange?: (height: number) => void;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
export default function RenderedResult({
|
|
25
|
+
export default function RenderedResult({
|
|
26
|
+
result,
|
|
27
|
+
onSizeChange,
|
|
28
|
+
}: RenderedResultProps) {
|
|
25
29
|
const ref = useRef<MalloyRenderElement>(null);
|
|
30
|
+
|
|
26
31
|
useEffect(() => {
|
|
27
32
|
if (ref.current) {
|
|
28
33
|
ref.current.malloyResult = JSON.parse(result);
|
|
29
34
|
}
|
|
30
35
|
}, [result]);
|
|
36
|
+
|
|
37
|
+
// Set up size measurement using scrollHeight instead of ResizeObserver
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!ref.current || !onSizeChange) return;
|
|
40
|
+
|
|
41
|
+
const element = ref.current;
|
|
42
|
+
|
|
43
|
+
// Function to measure and report size
|
|
44
|
+
const measureSize = () => {
|
|
45
|
+
if (element) {
|
|
46
|
+
const height = element.offsetHeight;
|
|
47
|
+
if (height > 0) {
|
|
48
|
+
onSizeChange(height);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Initial measurement after a brief delay to let content render
|
|
54
|
+
const timeoutId = setTimeout(measureSize, 100);
|
|
55
|
+
|
|
56
|
+
// Also measure when the malloy result changes
|
|
57
|
+
const observer = new MutationObserver(measureSize);
|
|
58
|
+
observer.observe(element, {
|
|
59
|
+
childList: true,
|
|
60
|
+
subtree: true,
|
|
61
|
+
attributes: true,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Cleanup
|
|
65
|
+
return () => {
|
|
66
|
+
clearTimeout(timeoutId);
|
|
67
|
+
observer.disconnect();
|
|
68
|
+
};
|
|
69
|
+
}, [onSizeChange, result]);
|
|
70
|
+
|
|
31
71
|
return <malloy-render ref={ref} />;
|
|
32
72
|
}
|