diff --git a/packages/website/src/components/App.jsx b/packages/website/src/components/App.jsx index 8bc96d15..6380f0ee 100644 --- a/packages/website/src/components/App.jsx +++ b/packages/website/src/components/App.jsx @@ -7,6 +7,7 @@ import Editor from "./Editor.jsx"; import OutputToolbar from "./OutputToolbar.jsx"; import Output from "./Output.jsx"; import Errors from "./Errors.jsx"; +import Resize from "./Resize.jsx"; const worker = new ReloadablePromiseWorker(() => new Worker(new URL("../worker.js", import.meta.url), { type: "module" })); @@ -28,8 +29,10 @@ export default function App({ initialSrc }) { const [errors, setErrors] = useState([]); const [zoom, setZoom] = useState("fit"); const [isValid, setValid] = useState(false); - const imageZoomRef = useRef(null); + + const appRef = useRef(null); const editorRef = useRef(null); + const imageZoomRef = useRef(null); function handleCopyLink() { copyLink(src); @@ -50,6 +53,10 @@ export default function App({ initialSrc }) { setDebouncedSrc(example); } + function handleResize(width) { + appRef.current.style.setProperty("--editor-width", width + "px"); + } + const handleSrcChangeDebounced = useMemo(() => { return debounce(setDebouncedSrc, 750); }, []); @@ -88,12 +95,13 @@ export default function App({ initialSrc }) { const zoomEnabled = result?.format == "svg-image"; return ( - <> +
+ imageZoomRef.current?.zoomIn()} onZoomOut={() => imageZoomRef.current?.zoomOut()} /> - +
); } diff --git a/packages/website/src/components/Resize.jsx b/packages/website/src/components/Resize.jsx new file mode 100644 index 00000000..8a02a720 --- /dev/null +++ b/packages/website/src/components/Resize.jsx @@ -0,0 +1,40 @@ +import { useEffect, useRef } from "react"; + +let dragging = false; +let dragOffset; + +export default function Resize({ onResize }) { + function handleMouseDown(e) { + e.preventDefault(); + + const rect = e.target.getBoundingClientRect(); + + dragging = true; + dragOffset = Math.round(e.clientX - rect.left); + } + + function handleMouseMove(e) { + if (dragging) { + let width = Math.max(0, e.clientX - dragOffset); + onResize(width); + } + } + + function handleMouseUp() { + dragging = false; + } + + useEffect(() => { + window.addEventListener("mousemove", handleMouseMove); + window.addEventListener("mouseup", handleMouseUp); + }, []); + + let resizeRef = useRef(null); + + return ( +
+
+
+
+ ); +} diff --git a/packages/website/src/index.html b/packages/website/src/index.html index 4e51596b..cdd4efdc 100644 --- a/packages/website/src/index.html +++ b/packages/website/src/index.html @@ -21,7 +21,7 @@ -
+
diff --git a/packages/website/src/index.jsx b/packages/website/src/index.jsx index 91e73713..56dd6a2f 100644 --- a/packages/website/src/index.jsx +++ b/packages/website/src/index.jsx @@ -6,7 +6,7 @@ import { getExample, defaultExampleName } from "./examples.js"; const initialSrc = getInputFromSearch(window.location.search, getExample(defaultExampleName)); -const root = createRoot(document.getElementById("app")); +const root = createRoot(document.getElementById("root")); root.render( diff --git a/packages/website/src/styles/app.css b/packages/website/src/styles/app.css index c387b813..c02b89da 100644 --- a/packages/website/src/styles/app.css +++ b/packages/website/src/styles/app.css @@ -17,17 +17,22 @@ body { grid-template-rows: max-content minmax(0, 1fr); } -#app { +#root { + display: grid; grid-area: app; +} + +#app { + --editor-width: 50%; + display: grid; - grid-template-areas: "editor-toolbar output-toolbar" "editor output" "editor errors"; - grid-template-columns: 50% 1fr; + grid-template-areas: "editor-toolbar resize output-toolbar" "editor resize output" "editor resize errors"; + grid-template-columns: minmax(300px, var(--editor-width)) 1px minmax(450px, 1fr); grid-template-rows: max-content 1fr fit-content(20%); } .editor { grid-area: editor; - border-right: 1px solid #ccc; } .cm-editor { @@ -91,7 +96,6 @@ body { .editor-toolbar { grid-area: editor-toolbar; - border-right: 1px solid #ccc; justify-content: center; } @@ -160,17 +164,9 @@ body { grid-template-rows: max-content 30% max-content 1fr fit-content(20%); } - .editor { - border-right: none; - } - .output-toolbar { border-top: 1px solid #ccc; } - - .editor-toolbar { - border-right: none; - } } @media (max-width: 450px) { @@ -178,3 +174,26 @@ body { font-size: 16px; } } + + +.resize { + grid-area: resize; + background: #ccc; + position: relative; + z-index: 1; +} + +.resize-handle { + width: 7px; + left: -3px; + position: absolute; + top: 0; + bottom: 0; + cursor: ew-resize; +} + +@media (max-width: 750px) { + .resize { + display: none; + } +}