@malloy-publisher/sdk 0.0.118 → 0.0.120
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/ServerProvider-49yj-aFb.cjs.js +1 -0
- package/dist/{ServerProvider-v0TajMUn.es.js → ServerProvider-BDgL8SVP.es.js} +355 -429
- package/dist/client/api.d.ts +285 -276
- package/dist/client/configuration.d.ts +1 -1
- package/dist/client/index.cjs.js +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.es.js +43 -46
- package/dist/components/ServerProvider.d.ts +1 -3
- package/dist/index.cjs.js +111 -111
- package/dist/index.es.js +33143 -30265
- package/package.json +1 -1
- package/src/components/Connections/common.ts +2 -0
- package/src/components/Home/DeleteProjectDialog.tsx +10 -0
- package/src/components/Home/Home.tsx +1 -1
- package/src/components/Model/Model.tsx +19 -13
- package/src/components/Model/ModelCell.tsx +10 -8
- package/src/components/Model/ModelExplorer.tsx +91 -56
- package/src/components/Model/SourcesExplorer.tsx +7 -6
- package/src/components/Notebook/NotebookCell.tsx +4 -4
- package/src/components/Package/FileTreeView.tsx +3 -3
- package/src/components/Package/Package.tsx +7 -11
- package/src/components/Project/About.tsx +63 -8
- package/src/components/Project/ConnectionExplorer.tsx +123 -160
- package/src/components/Project/DeletePackageDialog.tsx +10 -0
- package/src/components/QueryResult/QueryResult.tsx +9 -7
- package/src/components/ServerProvider.tsx +0 -4
- package/src/hooks/useRawQueryData.ts +8 -6
- package/src/utils/formatting.ts +2 -1
- package/src/utils/parsing.ts +1 -1
- package/dist/ServerProvider-Bx3fsDOb.cjs.js +0 -1
- package/dist/components/Package/Schedules.d.ts +0 -5
- package/src/components/Package/Schedules.tsx +0 -114
package/package.json
CHANGED
|
@@ -188,6 +188,7 @@ export const connectionFieldsByType: Record<
|
|
|
188
188
|
type: "text",
|
|
189
189
|
},
|
|
190
190
|
],
|
|
191
|
+
duckdb: [],
|
|
191
192
|
};
|
|
192
193
|
|
|
193
194
|
export const attributesFieldName: Record<ConnectionTypeEnum, string> = {
|
|
@@ -196,4 +197,5 @@ export const attributesFieldName: Record<ConnectionTypeEnum, string> = {
|
|
|
196
197
|
snowflake: "snowflakeConnection",
|
|
197
198
|
trino: "trinoConnection",
|
|
198
199
|
mysql: "mysqlConnection",
|
|
200
|
+
duckdb: "duckdbConnection",
|
|
199
201
|
};
|
|
@@ -84,6 +84,16 @@ export default function DeleteProjectDialog({
|
|
|
84
84
|
</Typography>
|
|
85
85
|
</DialogContent>
|
|
86
86
|
<DialogActions>
|
|
87
|
+
<Button
|
|
88
|
+
variant="outlined"
|
|
89
|
+
onClick={handleClose}
|
|
90
|
+
style={{
|
|
91
|
+
borderColor: "#14b3cb",
|
|
92
|
+
color: "#14b3cb",
|
|
93
|
+
}}
|
|
94
|
+
>
|
|
95
|
+
Cancel
|
|
96
|
+
</Button>
|
|
87
97
|
<Button
|
|
88
98
|
loading={deleteProject.isPending}
|
|
89
99
|
variant="contained"
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "@malloydata/malloy-explorer/styles.css";
|
|
2
|
+
import LinkOutlinedIcon from "@mui/icons-material/LinkOutlined";
|
|
3
|
+
import ZoomOutMapIcon from "@mui/icons-material/ZoomOutMap";
|
|
2
4
|
import {
|
|
3
5
|
Box,
|
|
4
6
|
IconButton,
|
|
@@ -7,17 +9,15 @@ import {
|
|
|
7
9
|
Tooltip,
|
|
8
10
|
Typography,
|
|
9
11
|
} from "@mui/material";
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import "
|
|
13
|
-
import { QueryExplorerResult } from "./SourcesExplorer";
|
|
12
|
+
import React, { useState } from "react";
|
|
13
|
+
import { parseResourceUri } from "../../utils/formatting";
|
|
14
|
+
import { ApiErrorDisplay } from "../ApiErrorDisplay";
|
|
14
15
|
import { Loading } from "../Loading";
|
|
16
|
+
import { ModelCell } from "./ModelCell";
|
|
15
17
|
import { ModelExplorer } from "./ModelExplorer";
|
|
16
18
|
import { ModelExplorerDialog } from "./ModelExplorerDialog";
|
|
17
|
-
import {
|
|
19
|
+
import { QueryExplorerResult } from "./SourcesExplorer";
|
|
18
20
|
import { useModelData } from "./useModelData";
|
|
19
|
-
import React, { useState } from "react";
|
|
20
|
-
import { parseResourceUri } from "../../utils/formatting";
|
|
21
21
|
|
|
22
22
|
interface ModelProps {
|
|
23
23
|
onChange?: (query: QueryExplorerResult) => void;
|
|
@@ -103,8 +103,8 @@ export default function Model({ onChange, resourceUri }: ModelProps) {
|
|
|
103
103
|
>
|
|
104
104
|
Sources
|
|
105
105
|
</Typography>
|
|
106
|
-
<Tooltip title="Click to copy
|
|
107
|
-
<
|
|
106
|
+
<Tooltip title="Click to copy link">
|
|
107
|
+
<LinkOutlinedIcon
|
|
108
108
|
sx={{
|
|
109
109
|
fontSize: "24px",
|
|
110
110
|
color: "#666666",
|
|
@@ -140,9 +140,15 @@ export default function Model({ onChange, resourceUri }: ModelProps) {
|
|
|
140
140
|
}}
|
|
141
141
|
onClick={() => setDialogOpen(true)}
|
|
142
142
|
>
|
|
143
|
-
<
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
<Tooltip title="Expanded view">
|
|
144
|
+
<ZoomOutMapIcon
|
|
145
|
+
sx={{
|
|
146
|
+
fontSize: "18px",
|
|
147
|
+
color: "#666666",
|
|
148
|
+
marginBottom: "5px",
|
|
149
|
+
}}
|
|
150
|
+
/>
|
|
151
|
+
</Tooltip>
|
|
146
152
|
</IconButton>
|
|
147
153
|
</Stack>
|
|
148
154
|
)}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { Box, Typography, IconButton } from "@mui/material";
|
|
2
1
|
import SearchIcon from "@mui/icons-material/Search";
|
|
2
|
+
import { Box, IconButton, Typography } from "@mui/material";
|
|
3
3
|
import React, { useEffect } from "react";
|
|
4
4
|
import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
|
|
5
|
+
import { parseResourceUri } from "../../utils/formatting";
|
|
5
6
|
import { highlight } from "../highlighter";
|
|
6
7
|
import ResultContainer from "../RenderedResult/ResultContainer";
|
|
7
8
|
import ResultsDialog from "../ResultsDialog";
|
|
8
|
-
import { CleanMetricCard, CleanNotebookCell } from "../styles";
|
|
9
|
-
import { parseResourceUri } from "../../utils/formatting";
|
|
10
9
|
import { useServer } from "../ServerProvider";
|
|
10
|
+
import { CleanMetricCard, CleanNotebookCell } from "../styles";
|
|
11
11
|
|
|
12
12
|
interface ModelCellProps {
|
|
13
13
|
sourceName?: string;
|
|
@@ -37,14 +37,16 @@ export function ModelCell({
|
|
|
37
37
|
} = useQueryWithApiError({
|
|
38
38
|
queryKey: ["namedQueryResult", resourceUri, queryName],
|
|
39
39
|
queryFn: () =>
|
|
40
|
-
apiClients.
|
|
40
|
+
apiClients.models.executeQueryModel(
|
|
41
41
|
projectName,
|
|
42
42
|
packageName,
|
|
43
43
|
modelPath,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
{
|
|
45
|
+
query: undefined,
|
|
46
|
+
sourceName: undefined,
|
|
47
|
+
queryName: queryName,
|
|
48
|
+
versionId: versionId,
|
|
49
|
+
},
|
|
48
50
|
),
|
|
49
51
|
enabled: true, // Always execute
|
|
50
52
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Box,
|
|
2
|
-
import
|
|
1
|
+
import { Box, Stack } from "@mui/material";
|
|
2
|
+
import Autocomplete from "@mui/material/Autocomplete";
|
|
3
|
+
import TextField from "@mui/material/TextField";
|
|
3
4
|
import React from "react";
|
|
4
5
|
import { CompiledModel } from "../../client";
|
|
5
6
|
import { parseResourceUri } from "../../utils/formatting";
|
|
@@ -10,33 +11,33 @@ import { QueryExplorerResult, SourcesExplorer } from "./SourcesExplorer";
|
|
|
10
11
|
import { useModelData } from "./useModelData";
|
|
11
12
|
|
|
12
13
|
// Add a styled component for the multi-row tab bar
|
|
13
|
-
const MultiRowTabBar = styled(Box)(({ theme }) => ({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}));
|
|
14
|
+
// const MultiRowTabBar = styled(Box)(({ theme }) => ({
|
|
15
|
+
// display: "flex",
|
|
16
|
+
// flexWrap: "wrap",
|
|
17
|
+
// gap: theme.spacing(1),
|
|
18
|
+
// borderBottom: "1px solid #f0f0f0",
|
|
19
|
+
// minHeight: 48,
|
|
20
|
+
// paddingBottom: "8px",
|
|
21
|
+
// }));
|
|
21
22
|
|
|
22
|
-
const MultiRowTab = styled(Button)<{ selected?: boolean }>(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
);
|
|
23
|
+
// const MultiRowTab = styled(Button)<{ selected?: boolean }>(
|
|
24
|
+
// ({ theme, selected }) => ({
|
|
25
|
+
// minHeight: 32,
|
|
26
|
+
// padding: theme.spacing(0.75, 2),
|
|
27
|
+
// borderRadius: "6px",
|
|
28
|
+
// background: selected ? "#f8f9fa" : "transparent",
|
|
29
|
+
// color: selected ? "#495057" : "#666666",
|
|
30
|
+
// fontWeight: selected ? 600 : 500,
|
|
31
|
+
// border: selected ? "1px solid #e9ecef" : "1px solid transparent",
|
|
32
|
+
// boxShadow: "none",
|
|
33
|
+
// textTransform: "none",
|
|
34
|
+
// fontSize: "15px",
|
|
35
|
+
// "&:hover": {
|
|
36
|
+
// background: selected ? "#f8f9fa" : "#fafafa",
|
|
37
|
+
// border: selected ? "1px solid #e9ecef" : "1px solid #f0f0f0",
|
|
38
|
+
// },
|
|
39
|
+
// }),
|
|
40
|
+
// );
|
|
40
41
|
|
|
41
42
|
export interface ModelExplorerProps {
|
|
42
43
|
data?: CompiledModel;
|
|
@@ -103,43 +104,77 @@ export function ModelExplorer({
|
|
|
103
104
|
return <Loading text="Loading..." />;
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
const sourceOptions = (effectiveData?.sourceInfos || []).map(
|
|
108
|
+
(source, idx) => {
|
|
109
|
+
try {
|
|
110
|
+
const parsed = JSON.parse(source);
|
|
111
|
+
return parsed?.name || `Source ${idx + 1}`;
|
|
112
|
+
} catch {
|
|
113
|
+
return `Source ${idx + 1}`;
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
);
|
|
117
|
+
const selectedName = sourceOptions[selectedTab] || "";
|
|
118
|
+
|
|
106
119
|
return (
|
|
107
120
|
<StyledCard variant="outlined">
|
|
108
121
|
<StyledCardContent>
|
|
109
122
|
<Stack
|
|
110
123
|
sx={{
|
|
111
124
|
flexDirection: "row",
|
|
112
|
-
justifyContent: "space-between",
|
|
113
125
|
}}
|
|
114
126
|
>
|
|
115
127
|
{/* Render the tabs for source selection */}
|
|
116
|
-
{Array.isArray(effectiveData.sourceInfos) &&
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
128
|
+
{/* {Array.isArray(effectiveData.sourceInfos) &&
|
|
129
|
+
effectiveData.sourceInfos.length > 0 && (
|
|
130
|
+
<MultiRowTabBar>
|
|
131
|
+
{effectiveData.sourceInfos.map((source, idx) => {
|
|
132
|
+
let sourceInfo;
|
|
133
|
+
try {
|
|
134
|
+
sourceInfo = JSON.parse(source);
|
|
135
|
+
} catch {
|
|
136
|
+
sourceInfo = { name: String(idx) };
|
|
137
|
+
}
|
|
138
|
+
return (
|
|
139
|
+
<MultiRowTab
|
|
140
|
+
key={sourceInfo.name || idx}
|
|
141
|
+
selected={selectedTab === idx}
|
|
142
|
+
onClick={() => {
|
|
143
|
+
setSelectedTab(idx);
|
|
144
|
+
if (onSourceChange) {
|
|
145
|
+
onSourceChange(idx);
|
|
146
|
+
}
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
{sourceInfo.name || `Source ${idx + 1}`}
|
|
150
|
+
</MultiRowTab>
|
|
151
|
+
);
|
|
152
|
+
})}
|
|
153
|
+
</MultiRowTabBar>
|
|
154
|
+
)} */}
|
|
155
|
+
<Autocomplete
|
|
156
|
+
size="small"
|
|
157
|
+
id="size-small-standard"
|
|
158
|
+
disablePortal
|
|
159
|
+
options={sourceOptions}
|
|
160
|
+
value={selectedName}
|
|
161
|
+
onChange={(_e, newValue) => {
|
|
162
|
+
if (!newValue) return;
|
|
163
|
+
|
|
164
|
+
const idx = sourceOptions.indexOf(newValue);
|
|
165
|
+
if (idx >= 0) {
|
|
166
|
+
setSelectedTab(idx);
|
|
167
|
+
onSourceChange?.(idx);
|
|
168
|
+
}
|
|
169
|
+
}}
|
|
170
|
+
renderInput={(params) => <TextField {...params} />}
|
|
171
|
+
style={{
|
|
172
|
+
width: 350,
|
|
173
|
+
marginTop: "3px",
|
|
174
|
+
marginLeft: "6px",
|
|
175
|
+
marginBottom: "8px",
|
|
176
|
+
}}
|
|
177
|
+
/>
|
|
143
178
|
</Stack>
|
|
144
179
|
</StyledCardContent>
|
|
145
180
|
<StyledCardMedia>
|
|
@@ -173,15 +173,16 @@ function SourceExplorerComponentInner({
|
|
|
173
173
|
...query,
|
|
174
174
|
query: malloy,
|
|
175
175
|
});
|
|
176
|
-
return apiClients.
|
|
176
|
+
return apiClients.models.executeQueryModel(
|
|
177
177
|
projectName,
|
|
178
178
|
packageName,
|
|
179
179
|
sourceAndPath.modelPath,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
180
|
+
{
|
|
181
|
+
query: malloy,
|
|
182
|
+
sourceName: undefined,
|
|
183
|
+
queryName: undefined,
|
|
184
|
+
versionId: versionId,
|
|
185
|
+
},
|
|
185
186
|
);
|
|
186
187
|
},
|
|
187
188
|
onSuccess: (data) => {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import CloseIcon from "@mui/icons-material/Close";
|
|
2
2
|
import CodeIcon from "@mui/icons-material/Code";
|
|
3
3
|
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
|
|
4
|
+
import LinkOutlinedIcon from "@mui/icons-material/LinkOutlined";
|
|
4
5
|
import SearchIcon from "@mui/icons-material/Search";
|
|
5
|
-
import ShareIcon from "@mui/icons-material/Share";
|
|
6
6
|
import {
|
|
7
7
|
Box,
|
|
8
8
|
Dialog,
|
|
9
9
|
DialogContent,
|
|
10
10
|
DialogTitle,
|
|
11
11
|
IconButton,
|
|
12
|
+
Snackbar,
|
|
12
13
|
Stack,
|
|
13
14
|
Tooltip,
|
|
14
15
|
Typography,
|
|
15
|
-
Snackbar,
|
|
16
16
|
} from "@mui/material";
|
|
17
17
|
import Markdown from "markdown-to-jsx";
|
|
18
18
|
import React, { useEffect, useState } from "react";
|
|
@@ -176,8 +176,8 @@ export function NotebookCell({
|
|
|
176
176
|
justifyContent="space-between"
|
|
177
177
|
>
|
|
178
178
|
<Markdown>{cell.text}</Markdown>
|
|
179
|
-
<Tooltip title="Click to copy
|
|
180
|
-
<
|
|
179
|
+
<Tooltip title="Click to copy link">
|
|
180
|
+
<LinkOutlinedIcon
|
|
181
181
|
sx={{
|
|
182
182
|
fontSize: "24px",
|
|
183
183
|
color: "#666666",
|
|
@@ -222,16 +222,16 @@ function getTreeViewRecursive(
|
|
|
222
222
|
});
|
|
223
223
|
} else {
|
|
224
224
|
// This is a directory.
|
|
225
|
-
path
|
|
225
|
+
const childPath = path + key + "/";
|
|
226
226
|
treeViewItems.push({
|
|
227
|
-
id:
|
|
227
|
+
id: childPath,
|
|
228
228
|
label: key,
|
|
229
229
|
fileType: "directory",
|
|
230
230
|
selectable: true,
|
|
231
231
|
link: undefined,
|
|
232
232
|
children: getTreeViewRecursive(
|
|
233
233
|
value as Map<string, unknown>,
|
|
234
|
-
|
|
234
|
+
childPath,
|
|
235
235
|
onClickNode,
|
|
236
236
|
),
|
|
237
237
|
});
|
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Box, Grid } from "@mui/material";
|
|
2
|
+
import { encodeResourceUri, parseResourceUri } from "../../utils/formatting";
|
|
2
3
|
import { Notebook } from "../Notebook";
|
|
3
|
-
import Config from "./Config";
|
|
4
|
-
import Connections from "./Connections";
|
|
5
|
-
import Databases from "./Databases";
|
|
6
|
-
import Models from "./Models";
|
|
7
|
-
import Notebooks from "./Notebooks";
|
|
8
|
-
import Schedules from "./Schedules";
|
|
9
4
|
import {
|
|
10
5
|
PackageCard,
|
|
11
6
|
PackageCardContent,
|
|
12
7
|
PackageSectionTitle,
|
|
13
8
|
} from "../styles";
|
|
14
|
-
import
|
|
9
|
+
import Config from "./Config";
|
|
10
|
+
import Connections from "./Connections";
|
|
11
|
+
import Databases from "./Databases";
|
|
12
|
+
import Models from "./Models";
|
|
13
|
+
import Notebooks from "./Notebooks";
|
|
15
14
|
|
|
16
15
|
const README_NOTEBOOK = "README.malloynb";
|
|
17
16
|
|
|
@@ -59,9 +58,6 @@ export default function Package({
|
|
|
59
58
|
<Grid size={{ xs: 12, md: 6 }}>
|
|
60
59
|
<Connections resourceUri={resourceUri} />
|
|
61
60
|
</Grid>
|
|
62
|
-
<Grid size={{ xs: 12, md: 12 }}>
|
|
63
|
-
<Schedules resourceUri={resourceUri} />
|
|
64
|
-
</Grid>
|
|
65
61
|
<Grid size={{ xs: 12, md: 12 }}>
|
|
66
62
|
<PackageCard>
|
|
67
63
|
<PackageCardContent>
|
|
@@ -1,38 +1,93 @@
|
|
|
1
|
-
import { Box } from "@mui/material";
|
|
1
|
+
import { Box, Button } from "@mui/material";
|
|
2
2
|
import Markdown from "markdown-to-jsx";
|
|
3
|
+
import { useState } from "react";
|
|
3
4
|
import { useQueryWithApiError } from "../../hooks/useQueryWithApiError";
|
|
5
|
+
import { parseResourceUri } from "../../utils/formatting";
|
|
4
6
|
import { ApiErrorDisplay } from "../ApiErrorDisplay";
|
|
5
7
|
import { Loading } from "../Loading";
|
|
8
|
+
import { useServer } from "../ServerProvider";
|
|
6
9
|
import {
|
|
7
10
|
PackageCard,
|
|
8
11
|
PackageCardContent,
|
|
9
12
|
PackageSectionTitle,
|
|
10
13
|
} from "../styles";
|
|
11
|
-
import { parseResourceUri } from "../../utils/formatting";
|
|
12
|
-
import { useServer } from "../ServerProvider";
|
|
13
|
-
|
|
14
14
|
interface AboutProps {
|
|
15
15
|
resourceUri: string;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export default function About({ resourceUri }: AboutProps) {
|
|
19
|
-
const { projectName
|
|
19
|
+
const { projectName } = parseResourceUri(resourceUri);
|
|
20
20
|
const { apiClients } = useServer();
|
|
21
|
+
const [expanded, setExpanded] = useState(false);
|
|
22
|
+
const wordLimit = 90;
|
|
21
23
|
|
|
22
24
|
const { data, isSuccess, isError, error } = useQueryWithApiError({
|
|
23
25
|
queryKey: ["about", projectName],
|
|
24
26
|
queryFn: () => apiClients.projects.getProject(projectName, false),
|
|
25
27
|
});
|
|
26
28
|
|
|
29
|
+
const readmeContent = data?.data?.readme || "";
|
|
30
|
+
const words = readmeContent.split(/\s+/);
|
|
31
|
+
const shouldTruncate = words.length > wordLimit;
|
|
32
|
+
const preview = words.slice(0, wordLimit).join(" ");
|
|
33
|
+
|
|
27
34
|
return (
|
|
28
35
|
<>
|
|
29
36
|
{!isSuccess && !isError && <Loading text="Fetching About..." />}
|
|
30
|
-
{isSuccess &&
|
|
37
|
+
{isSuccess && readmeContent && (
|
|
31
38
|
<PackageCard>
|
|
32
39
|
<PackageCardContent>
|
|
33
40
|
<PackageSectionTitle>Readme</PackageSectionTitle>
|
|
34
|
-
<Box sx={{ mt: 1 }}>
|
|
35
|
-
<Markdown
|
|
41
|
+
<Box sx={{ mt: 1, fontSize: "0.875rem", lineHeight: 1.6 }}>
|
|
42
|
+
<Markdown
|
|
43
|
+
options={{
|
|
44
|
+
overrides: {
|
|
45
|
+
h1: {
|
|
46
|
+
component: "p",
|
|
47
|
+
props: {
|
|
48
|
+
style: {
|
|
49
|
+
fontSize: "inherit",
|
|
50
|
+
fontWeight: "italic",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
h2: {
|
|
55
|
+
component: "p",
|
|
56
|
+
props: {
|
|
57
|
+
style: {
|
|
58
|
+
fontSize: "inherit",
|
|
59
|
+
fontWeight: "italic",
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
h3: {
|
|
64
|
+
component: "p",
|
|
65
|
+
props: {
|
|
66
|
+
style: {
|
|
67
|
+
fontSize: "inherit",
|
|
68
|
+
fontWeight: "italic",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
{expanded || !shouldTruncate ? readmeContent : preview}
|
|
76
|
+
</Markdown>
|
|
77
|
+
|
|
78
|
+
{shouldTruncate && (
|
|
79
|
+
<Box sx={{ mt: 1 }}>
|
|
80
|
+
{" "}
|
|
81
|
+
{/* separate line */}
|
|
82
|
+
<Button
|
|
83
|
+
variant="text"
|
|
84
|
+
size="small"
|
|
85
|
+
onClick={() => setExpanded(!expanded)}
|
|
86
|
+
>
|
|
87
|
+
{expanded ? "Read less" : "Read more"}
|
|
88
|
+
</Button>
|
|
89
|
+
</Box>
|
|
90
|
+
)}
|
|
36
91
|
</Box>
|
|
37
92
|
</PackageCardContent>
|
|
38
93
|
</PackageCard>
|