Download frontend/src/components/window/workspace/Workspace.svelte from openfree/graphite2: direct link, hf CLI and curl.
- Browser
- Download file 8.22 kB
-
https://huggingface.co/spaces/openfree/graphite2/resolve/main/frontend/src/components/window/workspace/Workspace.svelte
- Command line
-
hf download hf://spaces/openfree/graphite2/frontend/src/components/window/workspace/Workspace.svelte
-
curl -L -o Workspace.svelte https://huggingface.co/spaces/openfree/graphite2/resolve/main/frontend/src/components/window/workspace/Workspace.svelte
8.22 kB
| <script lang="ts"> | |
| import { getContext } from "svelte"; | |
| import type { Editor } from "@graphite/editor"; | |
| import type { FrontendDocumentDetails } from "@graphite/messages"; | |
| import type { DialogState } from "@graphite/state-providers/dialog"; | |
| import type { PortfolioState } from "@graphite/state-providers/portfolio"; | |
| import Dialog from "@graphite/components/floating-menus/Dialog.svelte"; | |
| import LayoutCol from "@graphite/components/layout/LayoutCol.svelte"; | |
| import LayoutRow from "@graphite/components/layout/LayoutRow.svelte"; | |
| import Panel from "@graphite/components/window/workspace/Panel.svelte"; | |
| const MIN_PANEL_SIZE = 100; | |
| const PANEL_SIZES = { | |
| /**/ root: 100, | |
| /* ββ */ content: 80, | |
| /* β ββ */ document: 70, | |
| /* β ββ */ spreadsheet: 30, | |
| /* ββ */ details: 20, | |
| /* ββ */ properties: 45, | |
| /* ββ */ layers: 55, | |
| }; | |
| let panelSizes = PANEL_SIZES; | |
| let documentPanel: Panel | undefined; | |
| let gutterResizeRestore: [number, number] | undefined = undefined; | |
| let pointerCaptureId: number | undefined = undefined; | |
| $: documentPanel?.scrollTabIntoView($portfolio.activeDocumentIndex); | |
| $: documentTabLabels = $portfolio.documents.map((doc: FrontendDocumentDetails) => { | |
| const name = doc.displayName; | |
| if (!editor.handle.inDevelopmentMode()) return { name }; | |
| const tooltip = `Document ID: ${doc.id}`; | |
| return { name, tooltip }; | |
| }); | |
| const editor = getContext<Editor>("editor"); | |
| const portfolio = getContext<PortfolioState>("portfolio"); | |
| const dialog = getContext<DialogState>("dialog"); | |
| function resizePanel(e: PointerEvent) { | |
| const gutter = (e.target || undefined) as HTMLDivElement | undefined; | |
| const nextSibling = (gutter?.nextElementSibling || undefined) as HTMLDivElement | undefined; | |
| const prevSibling = (gutter?.previousElementSibling || undefined) as HTMLDivElement | undefined; | |
| const parentElement = (gutter?.parentElement || undefined) as HTMLDivElement | undefined; | |
| const nextSiblingName = (nextSibling?.getAttribute("data-subdivision-name") || undefined) as keyof typeof PANEL_SIZES; | |
| const prevSiblingName = (prevSibling?.getAttribute("data-subdivision-name") || undefined) as keyof typeof PANEL_SIZES; | |
| if (!gutter || !nextSibling || !prevSibling || !parentElement || !nextSiblingName || !prevSiblingName) return; | |
| // Are we resizing horizontally? | |
| const isHorizontal = gutter.getAttribute("data-gutter-horizontal") !== null; | |
| // Get the current size in px of the panels being resized and the gutter | |
| const gutterSize = isHorizontal ? gutter.getBoundingClientRect().width : gutter.getBoundingClientRect().height; | |
| const nextSiblingSize = isHorizontal ? nextSibling.getBoundingClientRect().width : nextSibling.getBoundingClientRect().height; | |
| const prevSiblingSize = isHorizontal ? prevSibling.getBoundingClientRect().width : prevSibling.getBoundingClientRect().height; | |
| const parentElementSize = isHorizontal ? parentElement.getBoundingClientRect().width : parentElement.getBoundingClientRect().height; | |
| // Measure the resizing panels as a percentage of all sibling panels | |
| const totalResizingSpaceOccupied = gutterSize + nextSiblingSize + prevSiblingSize; | |
| const proportionBeingResized = totalResizingSpaceOccupied / parentElementSize; | |
| // Prevent cursor flicker as mouse temporarily leaves the gutter | |
| pointerCaptureId = e.pointerId; | |
| gutter.setPointerCapture(pointerCaptureId); | |
| const mouseStart = isHorizontal ? e.clientX : e.clientY; | |
| const abortResize = () => { | |
| if (pointerCaptureId) gutter.releasePointerCapture(pointerCaptureId); | |
| removeListeners(); | |
| pointerCaptureId = e.pointerId; | |
| gutter.setPointerCapture(pointerCaptureId); | |
| if (gutterResizeRestore !== undefined) { | |
| panelSizes[nextSiblingName] = gutterResizeRestore[0]; | |
| panelSizes[prevSiblingName] = gutterResizeRestore[1]; | |
| gutterResizeRestore = undefined; | |
| } | |
| }; | |
| const onPointerMove = (e: PointerEvent) => { | |
| const mouseCurrent = isHorizontal ? e.clientX : e.clientY; | |
| let mouseDelta = mouseStart - mouseCurrent; | |
| mouseDelta = Math.max(nextSiblingSize + mouseDelta, MIN_PANEL_SIZE) - nextSiblingSize; | |
| mouseDelta = prevSiblingSize - Math.max(prevSiblingSize - mouseDelta, MIN_PANEL_SIZE); | |
| if (gutterResizeRestore === undefined) gutterResizeRestore = [panelSizes[nextSiblingName], panelSizes[prevSiblingName]]; | |
| panelSizes[nextSiblingName] = ((nextSiblingSize + mouseDelta) / totalResizingSpaceOccupied) * proportionBeingResized * 100; | |
| panelSizes[prevSiblingName] = ((prevSiblingSize - mouseDelta) / totalResizingSpaceOccupied) * proportionBeingResized * 100; | |
| }; | |
| const onPointerUp = () => { | |
| gutterResizeRestore = undefined; | |
| if (pointerCaptureId) gutter.releasePointerCapture(pointerCaptureId); | |
| removeListeners(); | |
| }; | |
| const onMouseDown = (e: MouseEvent) => { | |
| const BUTTONS_RIGHT = 0b0000_0010; | |
| if (e.buttons & BUTTONS_RIGHT) abortResize(); | |
| }; | |
| const onKeyDown = (e: KeyboardEvent) => { | |
| if (e.key === "Escape") abortResize(); | |
| }; | |
| const addListeners = () => { | |
| document.addEventListener("pointermove", onPointerMove); | |
| document.addEventListener("pointerup", onPointerUp); | |
| document.addEventListener("mousedown", onMouseDown); | |
| document.addEventListener("keydown", onKeyDown); | |
| }; | |
| const removeListeners = () => { | |
| document.removeEventListener("pointermove", onPointerMove); | |
| document.removeEventListener("pointerup", onPointerUp); | |
| document.removeEventListener("mousedown", onMouseDown); | |
| document.removeEventListener("keydown", onKeyDown); | |
| }; | |
| addListeners(); | |
| } | |
| </script> | |
| <LayoutRow class="workspace" data-workspace> | |
| <LayoutRow class="workspace-grid-subdivision" styles={{ "flex-grow": panelSizes["root"] }} data-subdivision-name="root"> | |
| <LayoutCol class="workspace-grid-subdivision" styles={{ "flex-grow": panelSizes["content"] }} data-subdivision-name="content"> | |
| <LayoutRow class="workspace-grid-subdivision" styles={{ "flex-grow": panelSizes["document"] }} data-subdivision-name="document"> | |
| <Panel | |
| panelType={$portfolio.documents.length > 0 ? "Document" : undefined} | |
| tabCloseButtons={true} | |
| tabMinWidths={true} | |
| tabLabels={documentTabLabels} | |
| clickAction={(tabIndex) => editor.handle.selectDocument($portfolio.documents[tabIndex].id)} | |
| closeAction={(tabIndex) => editor.handle.closeDocumentWithConfirmation($portfolio.documents[tabIndex].id)} | |
| tabActiveIndex={$portfolio.activeDocumentIndex} | |
| bind:this={documentPanel} | |
| /> | |
| </LayoutRow> | |
| {#if $portfolio.spreadsheetOpen} | |
| <LayoutRow class="workspace-grid-resize-gutter" data-gutter-vertical on:pointerdown={(e) => resizePanel(e)} /> | |
| <LayoutRow class="workspace-grid-subdivision" styles={{ "flex-grow": panelSizes["spreadsheet"] }} data-subdivision-name="spreadsheet"> | |
| <Panel panelType="Spreadsheet" tabLabels={[{ name: "Spreadsheet" }]} tabActiveIndex={0} /> | |
| </LayoutRow> | |
| {/if} | |
| </LayoutCol> | |
| <LayoutCol class="workspace-grid-resize-gutter" data-gutter-horizontal on:pointerdown={(e) => resizePanel(e)} /> | |
| <LayoutCol class="workspace-grid-subdivision" styles={{ "flex-grow": panelSizes["details"] }} data-subdivision-name="details"> | |
| <LayoutRow class="workspace-grid-subdivision" styles={{ "flex-grow": panelSizes["properties"] }} data-subdivision-name="properties"> | |
| <Panel panelType="Properties" tabLabels={[{ name: "Properties" }]} tabActiveIndex={0} /> | |
| </LayoutRow> | |
| <LayoutRow class="workspace-grid-resize-gutter" data-gutter-vertical on:pointerdown={(e) => resizePanel(e)} /> | |
| <LayoutRow class="workspace-grid-subdivision" styles={{ "flex-grow": panelSizes["layers"] }} data-subdivision-name="layers"> | |
| <Panel panelType="Layers" tabLabels={[{ name: "Layers" }]} tabActiveIndex={0} /> | |
| </LayoutRow> | |
| </LayoutCol> | |
| </LayoutRow> | |
| {#if $dialog.visible} | |
| <Dialog /> | |
| {/if} | |
| </LayoutRow> | |
| <style lang="scss" global> | |
| .workspace { | |
| position: relative; | |
| flex: 1 1 100%; | |
| .workspace-grid-subdivision { | |
| min-height: 28px; | |
| flex: 1 1 0; | |
| &.folded { | |
| flex-grow: 0; | |
| height: 0; | |
| } | |
| } | |
| .workspace-grid-resize-gutter { | |
| flex: 0 0 4px; | |
| &.layout-row { | |
| cursor: ns-resize; | |
| } | |
| &.layout-col { | |
| cursor: ew-resize; | |
| } | |
| } | |
| } | |
| </style> | |