Skip to content

Commit 3a37ec4

Browse files
nibilin33lihebi
andauthored
feat: add width ajustment (#69)
* feat: add width ajustment * formatting Co-authored-by: Hebi Li <[email protected]>
1 parent 0625e62 commit 3a37ec4

File tree

4 files changed

+171
-95
lines changed

4 files changed

+171
-95
lines changed

ui/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"react-icons": "^4.6.0",
3333
"react-monaco-editor": "^0.50.1",
3434
"react-moveable": "^0.40.0",
35+
"react-resizable": "^3.0.4",
3536
"react-router-dom": "^6.4.2",
3637
"react-scripts": "5.0.1",
3738
"slate": "^0.82.1",
@@ -95,6 +96,7 @@
9596
"@storybook/preset-create-react-app": "^4.1.2",
9697
"@storybook/react": "^6.5.12",
9798
"@storybook/testing-library": "^0.0.13",
99+
"@types/react-resizable": "^3.0.3",
98100
"babel-plugin-named-exports-order": "^0.0.2",
99101
"prop-types": "^15.8.1",
100102
"react-app-rewired": "^2.2.1",

ui/src/components/Canvas.tsx

Lines changed: 121 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import CheckCircleIcon from "@mui/icons-material/CheckCircle";
3333
import Grid from "@mui/material/Grid";
3434

3535
import Moveable from "react-moveable";
36+
import { ResizableBox } from "react-resizable";
3637
import Ansi from "ansi-to-react";
3738

3839
import { customAlphabet } from "nanoid";
@@ -234,23 +235,30 @@ function ResultBlock({ pod, id }) {
234235
<Box overflow="scroll" maxHeight="145px" border="1px">
235236
{/* <Box bgcolor="lightgray">Error</Box> */}
236237
{pod.stdout && (
237-
<Box whiteSpace="pre-wrap" sx={{fontSize: 10}}>
238+
<Box whiteSpace="pre-wrap" sx={{ fontSize: 10 }}>
238239
<Ansi>{pod.stdout}</Ansi>
239240
</Box>
240241
)}
241242
{pod?.result?.text && pod?.result?.count > 0 && (
242-
<Box sx={{ display: "flex", fontSize: 10, flexDirection: "row", alignItems: 'center' }}>
243+
<Box
244+
sx={{
245+
display: "flex",
246+
fontSize: 10,
247+
flexDirection: "row",
248+
alignItems: "center",
249+
}}
250+
>
243251
<Box>Result[{pod.result.count}]:</Box>
244252
<Box component="pre" whiteSpace="pre-wrap">
245-
{pod.result.text}
253+
{pod.result.text}
246254
</Box>
247255
</Box>
248256
)}
249257
{pod?.error && <Box color="red">{pod?.error?.evalue}</Box>}
250258
{pod?.error?.stacktrace && (
251259
<Box>
252260
<Box>StackTrace</Box>
253-
<Box whiteSpace="pre-wrap" sx={{fontSize: 10}}>
261+
<Box whiteSpace="pre-wrap" sx={{ fontSize: 10 }}>
254262
<Ansi>{pod.error.stacktrace.join("\n")}</Ansi>
255263
</Box>
256264
</Box>
@@ -289,6 +297,22 @@ const CodeNode = memo<Props>(({ data, id, isConnectable }) => {
289297
state.pods[id]?.stdout ||
290298
state.pods[id]?.stderr
291299
);
300+
const updatePod = useStore(store, (state) => state.updatePod);
301+
const onResize = useCallback((e, data) => {
302+
const { size } = data;
303+
const node = nodesMap.get(id);
304+
if (node) {
305+
node.style = { ...node.style, width: size.width };
306+
nodesMap.set(id, node);
307+
updatePod({
308+
id,
309+
data: {
310+
width: size.width,
311+
height: pod.height,
312+
},
313+
});
314+
}
315+
}, []);
292316
const nodesMap = useStore(store, (state) => state.ydoc.getMap<Node>("pods"));
293317
const apolloClient = useApolloClient();
294318
const deletePod = useStore(store, (state) => state.deletePod);
@@ -315,100 +339,108 @@ const CodeNode = memo<Props>(({ data, id, isConnectable }) => {
315339
}, []);
316340
if (!pod) return null;
317341
return (
318-
<Box
319-
sx={{
320-
border: "solid 1px #d6dee6",
321-
borderRadius: "4px",
322-
width: "100%",
323-
height: "100%",
324-
backgroundColor: "rgb(244, 246, 248)",
325-
borderColor: isEditorBlur ? "#d6dee6" : "#3182ce",
326-
}}
327-
ref={ref}
342+
<ResizableBox
343+
onResizeStop={onResize}
344+
height={pod.height || 100}
345+
width={pod.width}
346+
axis="x"
347+
minConstraints={[200, 200]}
328348
>
329-
<Handle
330-
type="source"
331-
position={Position.Top}
332-
id="top"
333-
isConnectable={isConnectable}
334-
/>
335-
<Handle
336-
type="source"
337-
position={Position.Bottom}
338-
id="bottom"
339-
isConnectable={isConnectable}
340-
/>
341-
<Handle
342-
type="source"
343-
position={Position.Left}
344-
id="left"
345-
isConnectable={isConnectable}
346-
/>
347-
<Handle
348-
type="source"
349-
position={Position.Right}
350-
id="right"
351-
isConnectable={isConnectable}
352-
/>
353-
{/* The header of code pods. */}
354-
<Box className="custom-drag-handle">
355-
<Box sx={styles["pod-index"]}>[{pod.index}]</Box>
356-
<ToolBox data={{ id }} onRunTask={runToolBoxTask}></ToolBox>
357-
</Box>
358349
<Box
359350
sx={{
360-
height: "90%",
361-
}}
362-
onClick={(e) => {
363-
// If the node is selected (for resize), the cursor is not shown. So
364-
// we need to deselect it when we re-focus on the editor.
365-
setSelected(null);
366-
setNodes((nds) =>
367-
applyNodeChanges(
368-
[
369-
{
370-
id,
371-
type: "select",
372-
selected: false,
373-
},
374-
],
375-
nds
376-
)
377-
);
351+
border: "solid 1px #d6dee6",
352+
borderRadius: "4px",
353+
width: "100%",
354+
height: "100%",
355+
backgroundColor: "rgb(244, 246, 248)",
356+
borderColor: isEditorBlur ? "#d6dee6" : "#3182ce",
378357
}}
358+
ref={ref}
379359
>
380-
<MyMonaco
381-
id={id}
382-
gitvalue=""
383-
onBlur={() => {
384-
setIsEditorBlur(true);
360+
<Handle
361+
type="source"
362+
position={Position.Top}
363+
id="top"
364+
isConnectable={isConnectable}
365+
/>
366+
<Handle
367+
type="source"
368+
position={Position.Bottom}
369+
id="bottom"
370+
isConnectable={isConnectable}
371+
/>
372+
<Handle
373+
type="source"
374+
position={Position.Left}
375+
id="left"
376+
isConnectable={isConnectable}
377+
/>
378+
<Handle
379+
type="source"
380+
position={Position.Right}
381+
id="right"
382+
isConnectable={isConnectable}
383+
/>
384+
{/* The header of code pods. */}
385+
<Box className="custom-drag-handle">
386+
<Box sx={styles["pod-index"]}>[{pod.index}]</Box>
387+
<ToolBox data={{ id }} onRunTask={runToolBoxTask}></ToolBox>
388+
</Box>
389+
<Box
390+
sx={{
391+
height: "90%",
385392
}}
386-
onFocus={() => {
387-
setIsEditorBlur(false);
393+
onClick={(e) => {
394+
// If the node is selected (for resize), the cursor is not shown. So
395+
// we need to deselect it when we re-focus on the editor.
396+
setSelected(null);
397+
setNodes((nds) =>
398+
applyNodeChanges(
399+
[
400+
{
401+
id,
402+
type: "select",
403+
selected: false,
404+
},
405+
],
406+
nds
407+
)
408+
);
388409
}}
389-
/>
390-
{showResult && (
391-
<Box
392-
className="nowheel"
393-
sx={{
394-
border: "solid 1px #d6dee6",
395-
borderRadius: "4px",
396-
position: "absolute",
397-
top: isRightLayout ? 0 : "100%",
398-
left: isRightLayout ? "100%" : 0,
399-
maxHeight: "158px",
400-
minWidth: isRightLayout ? "200px" : "100%",
401-
boxSizing: "border-box",
402-
backgroundColor: "white",
403-
zIndex: 100,
404-
padding: "0 10px",
410+
>
411+
<MyMonaco
412+
id={id}
413+
gitvalue=""
414+
onBlur={() => {
415+
setIsEditorBlur(true);
405416
}}
406-
>
407-
<ResultBlock pod={pod} id={id} />
408-
</Box>
409-
)}
417+
onFocus={() => {
418+
setIsEditorBlur(false);
419+
}}
420+
/>
421+
{showResult && (
422+
<Box
423+
className="nowheel"
424+
sx={{
425+
border: "solid 1px #d6dee6",
426+
borderRadius: "4px",
427+
position: "absolute",
428+
top: isRightLayout ? 0 : "100%",
429+
left: isRightLayout ? "100%" : 0,
430+
maxHeight: "158px",
431+
minWidth: isRightLayout ? "200px" : "100%",
432+
boxSizing: "border-box",
433+
backgroundColor: "white",
434+
zIndex: 100,
435+
padding: "0 10px",
436+
}}
437+
>
438+
<ResultBlock pod={pod} id={id} />
439+
</Box>
440+
)}
441+
</Box>
410442
</Box>
411-
</Box>
443+
</ResizableBox>
412444
);
413445
});
414446

ui/src/index.css

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,32 @@
11
body {
22
margin: 0;
3-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4-
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
3+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
4+
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
55
sans-serif;
66
-webkit-font-smoothing: antialiased;
77
-moz-osx-font-smoothing: grayscale;
88
}
99

1010
code {
11-
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
11+
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
1212
monospace;
13-
}
13+
}
14+
.react-resizable {
15+
position: relative;
16+
height: auto !important;
17+
}
18+
.react-resizable-handle {
19+
position: absolute;
20+
width: 20px;
21+
height: 20px;
22+
bottom: 0;
23+
right: 0;
24+
background-image: url("data:image/svg+xml,%3Csvg t='1668935417997' viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' p-id='3474' width='32' height='32'%3E%3Cpath d='M426.666667 256a42.666667 42.666667 0 0 0-42.666667 42.666667v170.666666H230.826667l34.133333-33.706666a42.666667 42.666667 0 0 0-60.586667-60.586667l-106.666666 106.666667a42.666667 42.666667 0 0 0-8.96 14.08 42.666667 42.666667 0 0 0 0 32.426666 42.666667 42.666667 0 0 0 8.96 14.08l106.666666 106.666667a42.666667 42.666667 0 0 0 60.586667 0 42.666667 42.666667 0 0 0 0-60.586667l-34.133333-33.706666H384v170.666666a42.666667 42.666667 0 0 0 85.333333 0V298.666667a42.666667 42.666667 0 0 0-42.666666-42.666667z m508.586666 239.786667a42.666667 42.666667 0 0 0-8.96-14.08l-106.666666-106.666667a42.666667 42.666667 0 0 0-60.586667 60.586667l34.133333 33.706666H640V298.666667a42.666667 42.666667 0 0 0-85.333333 0v426.666666a42.666667 42.666667 0 0 0 85.333333 0v-170.666666h153.173333l-34.133333 33.706666a42.666667 42.666667 0 0 0 0 60.586667 42.666667 42.666667 0 0 0 60.586667 0l106.666666-106.666667a42.666667 42.666667 0 0 0 8.96-14.08 42.666667 42.666667 0 0 0 0-32.426666z' p-id='3475' fill='%231296db'%3E%3C/path%3E%3C/svg%3E");
25+
background-position: bottom right;
26+
background-size: contain;
27+
padding: 0 3px 3px 0;
28+
background-repeat: no-repeat;
29+
background-origin: content-box;
30+
box-sizing: border-box;
31+
cursor: se-resize;
32+
}

ui/yarn.lock

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3897,6 +3897,13 @@
38973897
dependencies:
38983898
"@types/react" "*"
38993899

3900+
"@types/react-resizable@^3.0.3":
3901+
version "3.0.3"
3902+
resolved "https://registry.npmmirror.com/@types/react-resizable/-/react-resizable-3.0.3.tgz#76952da74820fae0dbd9669861514c836d5f1e83"
3903+
integrity sha512-W/QsUOZoXBAIBQNhNm95A5ohoaiUA874lWQytO2UP9dOjp5JHO9+a0cwYNabea7sA12ZDJnGVUFZxcNaNksAWA==
3904+
dependencies:
3905+
"@types/react" "*"
3906+
39003907
"@types/react-transition-group@^4.4.5":
39013908
version "4.4.5"
39023909
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416"
@@ -5875,7 +5882,7 @@ [email protected]:
58755882
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702"
58765883
integrity sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==
58775884

5878-
clsx@^1.0.4, clsx@^1.1.0, clsx@^1.2.1:
5885+
clsx@^1.0.4, clsx@^1.1.0, clsx@^1.1.1, clsx@^1.2.1:
58795886
version "1.2.1"
58805887
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
58815888
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
@@ -12519,7 +12526,7 @@ prompts@^2.0.1, prompts@^2.4.0, prompts@^2.4.2:
1251912526
kleur "^3.0.3"
1252012527
sisteransi "^1.0.5"
1252112528

12522-
prop-types@^15.0.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
12529+
prop-types@15.x, prop-types@^15.0.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
1252312530
version "15.8.1"
1252412531
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
1252512532
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@@ -12778,6 +12785,14 @@ react-dom@^18.2.0:
1277812785
loose-envify "^1.1.0"
1277912786
scheduler "^0.23.0"
1278012787

12788+
react-draggable@^4.0.3:
12789+
version "4.4.5"
12790+
resolved "https://registry.npmmirror.com/react-draggable/-/react-draggable-4.4.5.tgz#9e37fe7ce1a4cf843030f521a0a4cc41886d7e7c"
12791+
integrity sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g==
12792+
dependencies:
12793+
clsx "^1.1.1"
12794+
prop-types "^15.8.1"
12795+
1278112796
react-element-to-jsx-string@^14.3.4:
1278212797
version "14.3.4"
1278312798
resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-14.3.4.tgz#709125bc72f06800b68f9f4db485f2c7d31218a8"
@@ -12875,6 +12890,14 @@ react-refresh@^0.11.0:
1287512890
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
1287612891
integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
1287712892

12893+
react-resizable@^3.0.4:
12894+
version "3.0.4"
12895+
resolved "https://registry.npmmirror.com/react-resizable/-/react-resizable-3.0.4.tgz#aa20108eff28c52c6fddaa49abfbef8abf5e581b"
12896+
integrity sha512-StnwmiESiamNzdRHbSSvA65b0ZQJ7eVQpPusrSmcpyGKzC0gojhtO62xxH6YOBmepk9dQTBi9yxidL3W4s3EBA==
12897+
dependencies:
12898+
prop-types "15.x"
12899+
react-draggable "^4.0.3"
12900+
1287812901
react-router-dom@^6.4.2:
1287912902
version "6.4.2"
1288012903
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.4.2.tgz#115b37d501d6d8ac870683694978c51c43e6c0d2"

0 commit comments

Comments
 (0)