fix: Resizing, card

This commit is contained in:
Sidharth Vinod
2025-03-06 12:24:19 +05:30
parent 4968e224ae
commit 9c5ef434dc
8 changed files with 186 additions and 118 deletions
+2
View File
@@ -58,7 +58,9 @@
"husky": "^8.0.3",
"jsdom": "^25.0.1",
"lint-staged": "^15.2.0",
"lucide-svelte": "^0.477.0",
"node-html-parser": "^6.1.5",
"paneforge": "^1.0.0-next.4",
"postcss": "^8.4.33",
"postcss-load-config": "5.1.0",
"prettier": "^3.1.0",
+5 -4
View File
@@ -9,7 +9,7 @@
isOpen?: boolean;
tabs?: Tab[];
activeTabID?: string;
title: string;
title?: string;
onselect?: (tab: Tab) => void;
actions?: Snippet;
children?: Snippet;
@@ -35,11 +35,12 @@
let isTabsShown = $derived(isOpen && tabs.length > 0);
</script>
<div class="card m-2 flex flex-grow flex-col overflow-hidden rounded shadow-2xl">
<div
class="card flex h-fit {isOpen ? 'flex-grow' : ''} flex-col overflow-hidden rounded-2xl border-2">
<div
role="toolbar"
tabindex="0"
class="bg-primary p-2 {isTabsShown ? 'pb-0' : ''} flex-none cursor-pointer"
class="bg-border p-2 {isTabsShown ? 'pb-0' : ''} flex-none cursor-pointer"
onclick={toggleCardOpen}
onkeypress={toggleCardOpen}>
<div class="flex justify-between">
@@ -50,7 +51,7 @@
</div>
</div>
{#if isOpen}
<div class="card-body flex-grow overflow-auto p-0 text-base-content" transition:slide>
<div class="card-body text-base-content flex-grow overflow-auto p-0" transition:slide>
{@render children?.()}
</div>
{/if}
+1 -1
View File
@@ -12,7 +12,7 @@
}: {
isClosable?: boolean;
tabs: Tab[];
title: string;
title?: string;
isOpen?: boolean;
activeTabID: string;
onselect?: (tab: Tab) => void;
+13
View File
@@ -0,0 +1,13 @@
import { Pane } from "paneforge";
import Handle from "./resizable-handle.svelte";
import PaneGroup from "./resizable-pane-group.svelte";
export {
PaneGroup,
Pane,
Handle,
//
PaneGroup as ResizablePaneGroup,
Pane as ResizablePane,
Handle as ResizableHandle,
};
@@ -0,0 +1,30 @@
<script lang="ts">
import GripVertical from "lucide-svelte/icons/grip-vertical";
import * as ResizablePrimitive from "paneforge";
import type { WithoutChildrenOrChild } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
withHandle = false,
...restProps
}: WithoutChildrenOrChild<ResizablePrimitive.PaneResizerProps> & {
withHandle?: boolean;
} = $props();
</script>
<ResizablePrimitive.PaneResizer
bind:ref
class={cn(
"bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-1 data-[direction=vertical]:h-px data-[direction=vertical]:w-full data-[direction=vertical]:after:left-0 data-[direction=vertical]:after:h-1 data-[direction=vertical]:after:w-full data-[direction=vertical]:after:-translate-y-1/2 data-[direction=vertical]:after:translate-x-0 [&[data-direction=vertical]>div]:rotate-90",
className
)}
{...restProps}
>
{#if withHandle}
<div class="bg-border z-10 flex h-4 w-3 items-center justify-center rounded-sm border">
<GripVertical class="size-2.5" />
</div>
{/if}
</ResizablePrimitive.PaneResizer>
@@ -0,0 +1,22 @@
<script lang="ts">
import * as ResizablePrimitive from "paneforge";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
direction,
this: paneGroup = $bindable(),
...restProps
}: ResizablePrimitive.PaneGroupProps & {
this?: ResizablePrimitive.PaneGroup;
} = $props();
</script>
<ResizablePrimitive.PaneGroup
bind:ref
bind:this={paneGroup}
{direction}
class={cn("flex h-full w-full data-[direction=vertical]:flex-col", className)}
{...restProps}
/>
+101 -113
View File
@@ -6,6 +6,7 @@
import History from '$lib/components/History/History.svelte';
import Navbar from '$lib/components/Navbar.svelte';
import Preset from '$lib/components/Preset.svelte';
import * as Resizable from '$lib/components/ui/resizable/index.js';
import View from '$lib/components/View.svelte';
import type { DocumentationConfig, EditorMode, Tab, ValidatedState } from '$lib/types';
import { env } from '$lib/util/env';
@@ -115,130 +116,117 @@
onMount(async () => {
await initHandler();
const resizer = document.querySelector<HTMLElement>('#resizeHandler');
const element = document.querySelector<HTMLElement>('#editorPane');
if (!resizer || !element) {
console.debug('Failed to find resize handler or editor pane', { resizer, element });
return;
}
const resize = ({ pageX }: { pageX: number }) => {
const newWidth = pageX - element.getBoundingClientRect().left;
if (newWidth > 50) {
element.style.width = `${newWidth}px`;
}
};
const stopResize = () => {
window.removeEventListener('mousemove', resize);
};
resizer.addEventListener('mousedown', (event) => {
event.preventDefault();
window.addEventListener('mousemove', resize);
window.addEventListener('mouseup', stopResize);
});
});
</script>
<div class="flex h-full flex-col overflow-hidden">
<Navbar />
<div class="flex flex-1 overflow-hidden">
<div class="hidden flex-col md:flex" id="editorPane" style="width: 40%">
<Card onselect={tabSelectHandler} {tabs} isClosable={false} {activeTabID} title="Mermaid">
{#snippet actions()}
<div class="flex flex-row items-center">
<div class="form-control flex-row items-center">
<label class="label cursor-pointer" for="autoSync">
<span> Auto sync</span>
<input
type="checkbox"
class="toggle {$stateStore.autoSync ? 'btn-secondary' : 'toggle-primary'} ml-1"
id="autoSync"
bind:checked={$inputStateStore.autoSync} />
</label>
</div>
<Resizable.PaneGroup direction="horizontal" class="p-2">
<Resizable.Pane defaultSize={40}>
<div class="hidden h-full flex-col gap-2 md:flex" id="editorPane">
<Card onselect={tabSelectHandler} {tabs} isClosable={false} {activeTabID}>
{#snippet actions()}
<div class="flex flex-row items-center">
<div class="form-control flex-row items-center">
<label class="label cursor-pointer" for="autoSync">
<span> Auto sync</span>
<input
type="checkbox"
class="toggle {$stateStore.autoSync
? 'btn-secondary'
: 'toggle-primary'} ml-1"
id="autoSync"
bind:checked={$inputStateStore.autoSync} />
</label>
</div>
{#if !$stateStore.autoSync}
<button
class="btn btn-secondary btn-xs mr-1"
title="Sync Diagram ({cmdKey} + Enter)"
aria-label="Sync Diagram"
data-cy="sync"
onclick={syncDiagram}><i class="fas fa-sync"></i></button>
{/if}
{#if !$stateStore.autoSync}
<button
class="btn btn-secondary btn-xs mr-1"
title="Sync Diagram ({cmdKey} + Enter)"
aria-label="Sync Diagram"
data-cy="sync"
onclick={syncDiagram}><i class="fas fa-sync"></i></button>
{/if}
<button
class="btn btn-secondary btn-xs"
title="View documentation for {docKey.replace('Diagram', '')} diagram">
<a target="_blank" href={docURL} data-cy="docs">
<i class="fas fa-book mr-1"></i>Docs
</a>
</button>
</div>
{/snippet}
<button
class="btn btn-secondary btn-xs"
title="View documentation for {docKey.replace('Diagram', '')} diagram">
<a target="_blank" href={docURL} data-cy="docs">
<i class="fas fa-book mr-1"></i>Docs
</a>
</button>
</div>
{/snippet}
<Editor />
</Card>
<Editor />
</Card>
<div class="-mt-2">
<Preset />
<History />
<Actions />
</div>
</div>
<div id="resizeHandler" class="hidden md:block"></div>
<div class="flex flex-1 flex-col overflow-hidden">
<Card title="Diagram" isClosable={false}>
{#snippet actions()}
<div class="flex flex-row items-center gap-2">
<label
class="label flex cursor-pointer gap-1 py-0"
title="Rough mode is in beta. Features like clickable nodes, Pan & Zoom, will be disabled."
for="rough">
<span>Rough</span>
<input
type="checkbox"
class="toggle {$stateStore.rough ? 'btn-secondary' : 'toggle-primary'}"
id="rough"
bind:checked={$inputStateStore.rough} />
</label>
<label
class="label flex cursor-pointer gap-1 py-0"
title={$stateStore.rough ? 'Pan & Zoom is disabled in rough mode.' : ''}
for="panZoom">
<span>Pan & Zoom</span>
<input
type="checkbox"
class="toggle {$stateStore.panZoom ? 'btn-secondary' : 'toggle-primary'}"
id="panZoom"
disabled={$stateStore.rough}
bind:checked={$inputStateStore.panZoom} />
</label>
<a
href={`${base}/view#${$stateStore.serialized}`}
target="_blank"
class="btn btn-secondary btn-xs gap-1"
title="View diagram in new page"
><i class="fas fa-external-link-alt"></i>Full screen</a>
{#if env.isEnabledMermaidChartLinks}
<a
href={`${MCBaseURL}/app/plugin/save?state=${$stateStore.serialized}`}
target="_blank"
class="btn btn-secondary btn-xs gap-1 bg-[#FF3570]"
title="Save diagram in Mermaid Chart"
><img src="./mermaidchart-logo.svg" class="h-5 w-5" alt="Mermaid chart logo" />Save
to Mermaid Chart</a>
{/if}
</div>
{/snippet}
<div class="flex-1 overflow-auto">
<View />
<Preset />
<History />
<Actions />
</div>
</Card>
<div class="mx-2 rounded p-2 shadow md:hidden">
Code editing not supported on mobile. Please use a desktop browser.
</div>
</div>
</Resizable.Pane>
<Resizable.Handle class="mx-2" />
<Resizable.Pane>
<div class="flex h-full flex-1 flex-col overflow-hidden">
<Card title="Diagram" isClosable={false}>
{#snippet actions()}
<div class="flex flex-row items-center gap-2">
<label
class="label flex cursor-pointer gap-1 py-0"
title="Rough mode is in beta. Features like clickable nodes, Pan & Zoom, will be disabled."
for="rough">
<span>Rough</span>
<input
type="checkbox"
class="toggle {$stateStore.rough ? 'btn-secondary' : 'toggle-primary'}"
id="rough"
bind:checked={$inputStateStore.rough} />
</label>
<label
class="label flex cursor-pointer gap-1 py-0"
title={$stateStore.rough ? 'Pan & Zoom is disabled in rough mode.' : ''}
for="panZoom">
<span>Pan & Zoom</span>
<input
type="checkbox"
class="toggle {$stateStore.panZoom ? 'btn-secondary' : 'toggle-primary'}"
id="panZoom"
disabled={$stateStore.rough}
bind:checked={$inputStateStore.panZoom} />
</label>
<a
href={`${base}/view#${$stateStore.serialized}`}
target="_blank"
class="btn btn-secondary btn-xs gap-1"
title="View diagram in new page"
><i class="fas fa-external-link-alt"></i>Full screen</a>
{#if env.isEnabledMermaidChartLinks}
<a
href={`${MCBaseURL}/app/plugin/save?state=${$stateStore.serialized}`}
target="_blank"
class="btn btn-secondary btn-xs gap-1 bg-[#FF3570]"
title="Save diagram in Mermaid Chart"
><img
src="./mermaidchart-logo.svg"
class="size-5"
alt="Mermaid chart logo" />Save to Mermaid Chart</a>
{/if}
</div>
{/snippet}
<div class="flex-1 overflow-auto">
<View />
</div>
</Card>
<div class="mx-2 rounded p-2 shadow md:hidden">
Code editing not supported on mobile. Please use a desktop browser.
</div>
</div>
</Resizable.Pane>
</Resizable.PaneGroup>
</div>
</div>
+12
View File
@@ -4459,6 +4459,11 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
lucide-svelte@^0.477.0:
version "0.477.0"
resolved "https://registry.yarnpkg.com/lucide-svelte/-/lucide-svelte-0.477.0.tgz#85d80c9a7787b4b3ff8f5faed2f41182c8c4e303"
integrity sha512-w/zj6/CXTtTizIeo8SuWGYu0u45CJ7cD2AtNzIObVHZrWXNgaIIX/2cI25wybjSmYHIi4pub2TLv/kNPKiB3ww==
lz-string@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
@@ -4900,6 +4905,13 @@ pako@2.1.0:
resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86"
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==
paneforge@^1.0.0-next.4:
version "1.0.0-next.4"
resolved "https://registry.yarnpkg.com/paneforge/-/paneforge-1.0.0-next.4.tgz#99887329c5cab35b83beac2700540a7b765a62cf"
integrity sha512-xB7iqIx6sT+XDRx/Eps+lddN3X7zRy8RIqXXFimGuFF6d+3s4YoXrk8SdNwEK5U/mqwupeKX0BbSfy0z9W9feA==
dependencies:
svelte-toolbelt "^0.7.1"
parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"