Skip to content

Commit

Permalink
code cell has resizable components
Browse files Browse the repository at this point in the history
  • Loading branch information
nicholeuf committed Dec 16, 2023
1 parent 529a06c commit a192ade
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 18 deletions.
43 changes: 43 additions & 0 deletions course-react-ts-portfolio/jbook/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions course-react-ts-portfolio/jbook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"@types/prettier": "^2.7.3",
"@types/react": "^18.2.45",
"@types/react-dom": "^18.2.17",
"@types/react-resizable": "3.0.2",
"axios": "^1.6.2",
"bulmaswatch": "^0.8.1",
"esbuild-wasm": "0.8.27",
Expand All @@ -23,6 +24,7 @@
"prettier": "^2.8.8",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-resizable": "3.0.4",
"react-scripts": "5.0.1",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4"
Expand Down
20 changes: 11 additions & 9 deletions course-react-ts-portfolio/jbook/src/components/code-cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useState } from 'react';
import CodeEditor from './code-editor';
import Preview from './preview';
import bundle from '../bundler';
import Resizable from './resizeable';

const CodeCell = () => {
const [input, setInput] = useState('');
Expand All @@ -14,16 +15,17 @@ const CodeCell = () => {
};

return (
<div>
<CodeEditor
initialValue='const a = 1;'
onChange={(value) => setInput(value)}
/>
<div>
<button onClick={onClick}>Submit</button>
<Resizable direction='vertical'>
<div style={{ height: '100%', display: 'flex', flexDirection: 'row' }}>
<Resizable direction='horizontal'>
<CodeEditor
initialValue='const a = 1;'
onChange={(value) => setInput(value)}
/>
</Resizable>
<Preview code={code} />
</div>
<Preview code={code} />
</div>
</Resizable>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.editor-wrapper {
position: relative;
height: 100%;
width: calc(100% - 10px);
}

.editor-wrapper .button-format {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const CodeEditor: React.FC<CodeEditorProps> = ({ initialValue, onChange }) => {
value={initialValue}
language='javascript'
theme='dark'
height='500px'
height='100%'
options={{
wordWrap: 'on',
minimap: { enabled: false },
Expand Down
20 changes: 20 additions & 0 deletions course-react-ts-portfolio/jbook/src/components/preview.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.preview-wrapper {
position: relative;
height: 100%;
flex-grow: 1;
}

.preview-wrapper iframe {
height: 100%;
width: 100%;
}

.react-draggable-transparent-selection .preview-wrapper::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0;
}
19 changes: 12 additions & 7 deletions course-react-ts-portfolio/jbook/src/components/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import './preview.css';
import { useEffect, useRef } from 'react';

interface PreviewProps {
Expand All @@ -7,7 +8,9 @@ interface PreviewProps {
// place code inside script tag of iframe html document
const html = `
<html>
<head></head>
<head>
<style> html { background-color: white; }</style>
</head>
<body>
<div id="root"></div>
<script>
Expand Down Expand Up @@ -37,12 +40,14 @@ const Preview: React.FC<PreviewProps> = ({ code }) => {
}, [code]);

return (
<iframe
ref={iFrame}
sandbox='allow-scripts'
srcDoc={html}
title='preview'
/>
<div className='preview-wrapper'>
<iframe
ref={iFrame}
sandbox='allow-scripts'
srcDoc={html}
title='preview'
/>
</div>
);
};

Expand Down
26 changes: 26 additions & 0 deletions course-react-ts-portfolio/jbook/src/components/resizeable.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.react-resizable-handle {
display: block;
background-color: #37414b;
background-repeat: no-repeat;
background-position: 50%;
}

.resize-horizontal {
display: flex;
flex-direction: row;
}

.react-resizable-handle-s {
height: 10px;
width: 100%;
cursor: row-resize;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=');
}

.react-resizable-handle-e {
width: 10px;
min-width: 10px;
height: 100%;
cursor: col-resize;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
}
63 changes: 63 additions & 0 deletions course-react-ts-portfolio/jbook/src/components/resizeable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import './resizeable.css';
import { useEffect, useState } from 'react';
import { ResizableBox, ResizableBoxProps } from 'react-resizable';

interface ResizeableProps {
direction: 'horizontal' | 'vertical';
children?: React.ReactNode;
}

const Resizable: React.FC<ResizeableProps> = ({ direction, children }) => {
let resizeableProps: ResizableBoxProps;
const [innerHeight, setInnerHeight] = useState(window.innerHeight);
const [innerWidth, setInnerWidth] = useState(window.innerWidth);
const [width, setWidth] = useState(window.innerWidth * 0.75);

useEffect(() => {
let timer: any;
const listener = () => {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
setInnerHeight(window.innerHeight);
setInnerWidth(window.innerWidth);
if (window.innerWidth * 0.75 < width) {
setWidth(window.innerWidth * 0.75);
}
}, 100);
};

window.addEventListener('resize', listener);

return () => {
window.removeEventListener('resize', listener);
};
}, []);

if (direction === 'horizontal') {
resizeableProps = {
className: 'resize-horizontal',
maxConstraints: [innerWidth * 0.75, Infinity],
minConstraints: [innerWidth * 0.2, Infinity],
resizeHandles: ['e'],
height: Infinity,
width,
onResizeStop: (event, data) => {
setWidth(data.size.width);
},
};
} else {
resizeableProps = {
maxConstraints: [Infinity, innerHeight * 0.9],
minConstraints: [Infinity, 24],
resizeHandles: ['s'],
height: 300,
width: Infinity,
};
}

return <ResizableBox {...resizeableProps}>{children}</ResizableBox>;
};

export default Resizable;
2 changes: 1 addition & 1 deletion course-react-ts-portfolio/jbook/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const App = () => {
return (
<div>
<CodeCell />
<CodeCell />
{/* <CodeCell /> */}
</div>
);
};
Expand Down

0 comments on commit a192ade

Please sign in to comment.