refactor PaneWithPanel

pull/12817/head
Ottomated 2 years ago
parent b8539aeb5c
commit 89ebeb91c9

@ -48,6 +48,9 @@
"pnpm": {
"overrides": {
"xml2js": "^0.6.0"
},
"patchedDependencies": {
"@rich_harris/svelte-split-pane@1.1.3": "patches/@rich_harris__svelte-split-pane@1.1.3.patch"
}
}
}

@ -0,0 +1,44 @@
diff --git a/dist/SplitPane.svelte b/dist/SplitPane.svelte
index e5f8455e87d1fef63f63b912eeb6f6be60a268e6..39af9ec886ae9c7a06ecb571efaff783efaccb50 100644
--- a/dist/SplitPane.svelte
+++ b/dist/SplitPane.svelte
@@ -2,7 +2,7 @@
import { createEventDispatcher } from 'svelte';
import { constrain } from './utils.js';
- /** @type {ReturnType<typeof createEventDispatcher<{ change: undefined }>>} */
+ /** @type {ReturnType<typeof createEventDispatcher<{ change: import('./types').Length }>>} */
const dispatch = createEventDispatcher();
/** @type {string | undefined} */
@@ -54,7 +54,7 @@
position = pos.endsWith('%') ? `${(100 * pos_px) / size}%` : `${pos_px}px`;
- dispatch('change');
+ dispatch('change', position);
}
/**
diff --git a/dist/SplitPane.svelte.d.ts b/dist/SplitPane.svelte.d.ts
index 861240ad71a00ae4a0838eedbbf4892bac57fd0c..9afa30f1023167c63d25ef8e984ab521dfe152a4 100644
--- a/dist/SplitPane.svelte.d.ts
+++ b/dist/SplitPane.svelte.d.ts
@@ -10,7 +10,7 @@ export default class SplitPane extends SvelteComponentTyped<{
disabled?: boolean | undefined;
priority?: "min" | "max" | undefined;
}, {
- change: CustomEvent<any>;
+ change: CustomEvent<import("./types").Length>;
} & {
[evt: string]: CustomEvent<any>;
}, {
@@ -33,7 +33,7 @@ declare const __propDef: {
priority?: "min" | "max" | undefined;
};
events: {
- change: CustomEvent<any>;
+ change: CustomEvent<import("./types").Length>;
} & {
[evt: string]: CustomEvent<any>;
};

@ -7,6 +7,11 @@ settings:
overrides:
xml2js: ^0.6.0
patchedDependencies:
'@rich_harris/svelte-split-pane@1.1.3':
hash: h33vpjiugsmycujzfbdpoxeb2m
path: patches/@rich_harris__svelte-split-pane@1.1.3.patch
importers:
.:
@ -16,7 +21,7 @@ importers:
version: 2.27.6
'@sveltejs/eslint-config':
specifier: ^8.0.1
version: 8.0.1(@stylistic/eslint-plugin-js@1.8.0(eslint@9.6.0))(eslint-config-prettier@9.1.0(eslint@9.6.0))(eslint-plugin-n@17.9.0(eslint@9.6.0))(eslint-plugin-svelte@2.38.0(eslint@9.6.0)(svelte@5.0.0-next.179))(eslint@9.6.0)(typescript-eslint@8.0.0-alpha.34(eslint@9.6.0)(typescript@5.5.2))(typescript@5.5.2)
version: 8.0.1(@stylistic/eslint-plugin-js@1.8.0(eslint@9.6.0))(eslint-config-prettier@9.1.0(eslint@9.6.0))(eslint-plugin-n@17.9.0(eslint@9.6.0))(eslint-plugin-svelte@2.38.0(eslint@9.6.0)(svelte@5.0.0-next.218))(eslint@9.6.0)(typescript-eslint@8.0.0-alpha.34(eslint@9.6.0)(typescript@5.5.2))(typescript@5.5.2)
'@svitejs/changesets-changelog-github-compact':
specifier: ^1.1.0
version: 1.1.0
@ -43,7 +48,7 @@ importers:
version: 3.2.4
prettier-plugin-svelte:
specifier: ^3.1.2
version: 3.1.2(prettier@3.2.4)(svelte@5.0.0-next.179)
version: 3.1.2(prettier@3.2.4)(svelte@5.0.0-next.218)
typescript:
specifier: ^5.5.2
version: 5.5.2
@ -212,7 +217,7 @@ importers:
version: 6.0.0(@codemirror/autocomplete@6.12.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.0)(@codemirror/view@6.24.0)(@lezer/common@1.2.1))(@codemirror/lang-css@6.2.1(@codemirror/view@6.24.0))(@codemirror/lang-html@6.4.9)(@codemirror/lang-javascript@6.2.1)(@codemirror/language@6.10.1)(@codemirror/state@6.4.0)(@codemirror/view@6.24.0)(@lezer/common@1.2.1)(@lezer/highlight@1.2.0)(@lezer/javascript@1.4.15)(@lezer/lr@1.4.0)
'@rich_harris/svelte-split-pane':
specifier: ^1.1.3
version: 1.1.3(svelte@packages+svelte)
version: 1.1.3(patch_hash=h33vpjiugsmycujzfbdpoxeb2m)(svelte@packages+svelte)
'@rollup/browser':
specifier: ^3.28.0
version: 3.29.4
@ -3633,8 +3638,8 @@ packages:
resolution: {integrity: sha512-hsoB/WZGEPFXeRRLPhPrbRz67PhP6sqYgvwcAs+gWdSQSvNDw+/lTeUJSWe5h2xC97Fz/8QxAOqItwBzNJPU8w==}
engines: {node: '>=16'}
svelte@5.0.0-next.179:
resolution: {integrity: sha512-z2x/RcctbQ95vNt52p/+fCJzyU2RVmK03V6thiFT/gblNHw/qONb6hZXfxfCgIsCWjm8thDcgDcmRClZj/Ging==}
svelte@5.0.0-next.218:
resolution: {integrity: sha512-W78C3CwFb1wssmXLAN/8G4lJCaYnXOCogIJSeS3c6Pw/34sUZnd+sSrE3azw9hhAM0Gvo2uQFQEOWtnnAvIpWQ==}
engines: {node: '>=18'}
symbol-tree@3.2.4:
@ -5019,7 +5024,7 @@ snapshots:
dependencies:
svelte: 4.2.9
'@rich_harris/svelte-split-pane@1.1.3(svelte@packages+svelte)':
'@rich_harris/svelte-split-pane@1.1.3(patch_hash=h33vpjiugsmycujzfbdpoxeb2m)(svelte@packages+svelte)':
dependencies:
svelte: link:packages/svelte
@ -5191,13 +5196,13 @@ snapshots:
- encoding
- supports-color
'@sveltejs/eslint-config@8.0.1(@stylistic/eslint-plugin-js@1.8.0(eslint@9.6.0))(eslint-config-prettier@9.1.0(eslint@9.6.0))(eslint-plugin-n@17.9.0(eslint@9.6.0))(eslint-plugin-svelte@2.38.0(eslint@9.6.0)(svelte@5.0.0-next.179))(eslint@9.6.0)(typescript-eslint@8.0.0-alpha.34(eslint@9.6.0)(typescript@5.5.2))(typescript@5.5.2)':
'@sveltejs/eslint-config@8.0.1(@stylistic/eslint-plugin-js@1.8.0(eslint@9.6.0))(eslint-config-prettier@9.1.0(eslint@9.6.0))(eslint-plugin-n@17.9.0(eslint@9.6.0))(eslint-plugin-svelte@2.38.0(eslint@9.6.0)(svelte@5.0.0-next.218))(eslint@9.6.0)(typescript-eslint@8.0.0-alpha.34(eslint@9.6.0)(typescript@5.5.2))(typescript@5.5.2)':
dependencies:
'@stylistic/eslint-plugin-js': 1.8.0(eslint@9.6.0)
eslint: 9.6.0
eslint-config-prettier: 9.1.0(eslint@9.6.0)
eslint-plugin-n: 17.9.0(eslint@9.6.0)
eslint-plugin-svelte: 2.38.0(eslint@9.6.0)(svelte@5.0.0-next.179)
eslint-plugin-svelte: 2.38.0(eslint@9.6.0)(svelte@5.0.0-next.218)
globals: 15.6.0
typescript: 5.5.2
typescript-eslint: 8.0.0-alpha.34(eslint@9.6.0)(typescript@5.5.2)
@ -6033,7 +6038,7 @@ snapshots:
minimatch: 9.0.5
semver: 7.6.2
eslint-plugin-svelte@2.38.0(eslint@9.6.0)(svelte@5.0.0-next.179):
eslint-plugin-svelte@2.38.0(eslint@9.6.0)(svelte@5.0.0-next.218):
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@9.6.0)
'@jridgewell/sourcemap-codec': 1.5.0
@ -6047,9 +6052,9 @@ snapshots:
postcss-safe-parser: 6.0.0(postcss@8.4.39)
postcss-selector-parser: 6.1.0
semver: 7.6.2
svelte-eslint-parser: 0.39.2(svelte@5.0.0-next.179)
svelte-eslint-parser: 0.39.2(svelte@5.0.0-next.218)
optionalDependencies:
svelte: 5.0.0-next.179
svelte: 5.0.0-next.218
transitivePeerDependencies:
- supports-color
- ts-node
@ -7075,10 +7080,10 @@ snapshots:
prettier: 3.2.4
svelte: 4.2.9
prettier-plugin-svelte@3.1.2(prettier@3.2.4)(svelte@5.0.0-next.179):
prettier-plugin-svelte@3.1.2(prettier@3.2.4)(svelte@5.0.0-next.218):
dependencies:
prettier: 3.2.4
svelte: 5.0.0-next.179
svelte: 5.0.0-next.218
prettier@2.8.8: {}
@ -7479,7 +7484,7 @@ snapshots:
- stylus
- sugarss
svelte-eslint-parser@0.39.2(svelte@5.0.0-next.179):
svelte-eslint-parser@0.39.2(svelte@5.0.0-next.218):
dependencies:
eslint-scope: 7.2.2
eslint-visitor-keys: 3.4.3
@ -7487,7 +7492,7 @@ snapshots:
postcss: 8.4.39
postcss-scss: 4.0.9(postcss@8.4.39)
optionalDependencies:
svelte: 5.0.0-next.179
svelte: 5.0.0-next.218
svelte-hmr@0.16.0(svelte@4.2.9):
dependencies:
@ -7558,7 +7563,7 @@ snapshots:
magic-string: 0.30.5
periscopic: 3.1.0
svelte@5.0.0-next.179:
svelte@5.0.0-next.218:
dependencies:
'@ampproject/remapping': 2.3.0
'@jridgewell/sourcemap-codec': 1.5.0

@ -17,7 +17,7 @@
import { svelteTheme } from './theme.js';
import { autocomplete } from './autocomplete.js';
/** @type {{ diagnostics: import('@codemirror/lint').LintSource | undefined, readonly?: boolean, tab?: boolean, onchange: (value: string) => void }} */
/** @type {{ diagnostics?: import('@codemirror/lint').LintSource, readonly?: boolean, tab?: boolean, onchange?: (value: string) => void }} */
const { diagnostics = undefined, readonly = false, tab = true, onchange } = $props();
let code = $state('');

@ -7,7 +7,7 @@
* details?: import('./types').MessageDetails | undefined,
* filename?: string | undefined,
* truncate?: boolean,
* children: import('svelte').Snippet,
* children?: import('svelte').Snippet,
* }} */
const { kind = 'info', details = undefined, filename = undefined, truncate = false, children } = $props();
@ -37,7 +37,7 @@
{message(details)}
</button>
{:else}
{@render children()}
{@render children?.()}
{/if}
</div>

@ -91,14 +91,14 @@
{#if embedded}
<CodeMirror bind:this={js_editor} readonly />
{:else}
<PaneWithPanel pos="50%" panel="Compiler options">
<div slot="main">
<PaneWithPanel pos={50} title="Compiler options">
{#snippet main()}
<CodeMirror bind:this={js_editor} readonly />
</div>
{/snippet}
<div slot="panel-body">
{#snippet body()}
<CompilerOptions />
</div>
{/snippet}
</PaneWithPanel>
{/if}
</div>

@ -1,57 +1,68 @@
<script>
/** @import { Snippet } from 'svelte' */
import { spring } from 'svelte/motion';
import { SplitPane } from '@rich_harris/svelte-split-pane';
const UNIT_REGEX = /(\d+)(?:(px|rem|%|em))/i;
/** @type {{ title: string; pos: number, main?: Snippet, header?: Snippet, body?: Snippet }} */
let { title, pos, main, header, body } = $props();
/** @type {string} */
export let panel;
let expanded_pos = Math.min(pos, 70);
/** @type {Exclude<import('@rich_harris/svelte-split-pane/dist/SplitPane.svelte').SplitPaneProps['max'], undefined>} */
export let pos = '90%';
const max = 90;
$: previous_pos = Math.min(+pos.replace(UNIT_REGEX, '$1'), 70);
/** @type {Exclude<import('@rich_harris/svelte-split-pane/dist/SplitPane.svelte').SplitPaneProps['max'], undefined>} */
let max = '90%';
// we can't bind to the spring itself, but we
// can still use the spring to drive `pos`
const driver = spring(+pos.replace(UNIT_REGEX, '$1'), {
const driver = spring(pos, {
stiffness: 0.2,
damping: 0.5
});
// @ts-ignore
$: pos = $driver + '%';
const expanded = $derived(pos < 80);
const toggle = () => {
const numeric_pos = +pos.replace(UNIT_REGEX, '$1');
// The spring might be out of date, so snap it before animating the toggle
driver.set(numeric_pos, { hard: true });
if (numeric_pos > 80) {
driver.set(previous_pos);
if (expanded) {
expanded_pos = pos;
driver.set(max);
pos = max;
} else {
previous_pos = numeric_pos;
driver.set(+max.replace(UNIT_REGEX, '$1'));
driver.set(expanded_pos);
pos = expanded_pos;
}
};
</script>
<SplitPane {max} min="10%" type="vertical" bind:pos priority="max">
<SplitPane
max="{max}%"
min="10%"
type="vertical"
pos="{$driver}%"
priority="max"
on:change={(ev) => {
pos = Number(ev.detail.substring(0, ev.detail.length - 1));
}}
>
<section slot="a">
<slot name="main" />
{@render main?.()}
</section>
<section slot="b">
<div class="panel-header">
<button class="panel-heading" on:click={toggle}>{panel}</button>
<slot name="panel-header" />
<button class="panel-heading" onclick={toggle}>
<svg viewBox="0 0 20 20" fill="currentColor" class="chevron" class:expanded>
<path
fill-rule="evenodd"
d="M9.47 6.47a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 1 1-1.06 1.06L10 8.06l-3.72 3.72a.75.75 0 0 1-1.06-1.06l4.25-4.25Z"
clip-rule="evenodd"
/>
</svg>
{title}
</button>
{@render header?.()}
</div>
<div class="panel-body">
<slot name="panel-body" />
{@render body?.()}
</div>
</section>
</SplitPane>
@ -66,6 +77,13 @@
cursor: pointer;
}
.chevron {
transition: transform 0.2s ease-in-out;
}
.chevron.expanded {
transform: rotate(180deg);
}
.panel-body {
overflow: auto;
}
@ -75,6 +93,8 @@
color: var(--sk-text-1, #333);
flex: 1;
text-align: left;
display: flex;
align-items: center;
}
section {

@ -249,43 +249,49 @@
</script>
<div class="iframe-container">
<PaneWithPanel pos="90%" panel="Console">
<div slot="main">
<iframe
title="Result"
class:inited
bind:this={iframe}
sandbox={[
'allow-popups-to-escape-sandbox',
'allow-scripts',
'allow-popups',
'allow-forms',
'allow-pointer-lock',
'allow-top-navigation',
'allow-modals',
relaxed ? 'allow-same-origin' : ''
].join(' ')}
class={error || pending || pending_imports ? 'greyed-out' : ''}
srcdoc={BROWSER ? srcdoc : ''}
></iframe>
{#if $bundle?.error}
<ErrorOverlay error={$bundle.error} />
{/if}
</div>
<div slot="panel-header">
<button on:click|stopPropagation={clear_logs}>
{#if logs.length > 0}
({logs.length})
<PaneWithPanel pos={90} title="Console">
{#snippet main()}
<div>
<iframe
title="Result"
class:inited
bind:this={iframe}
sandbox={[
'allow-popups-to-escape-sandbox',
'allow-scripts',
'allow-popups',
'allow-forms',
'allow-pointer-lock',
'allow-top-navigation',
'allow-modals',
relaxed ? 'allow-same-origin' : ''
].join(' ')}
class={error || pending || pending_imports ? 'greyed-out' : ''}
srcdoc={BROWSER ? srcdoc : ''}
></iframe>
{#if $bundle?.error}
<ErrorOverlay error={$bundle.error} />
{/if}
Clear
</button>
</div>
<section slot="panel-body">
<Console {logs} />
</section>
</div>
{/snippet}
{#snippet header()}
<div>
<button on:click|stopPropagation={clear_logs}>
{#if logs.length > 0}
({logs.length})
{/if}
Clear
</button>
</div>
{/snippet}
{#snippet body()}
<section>
<Console {logs} />
</section>
{/snippet}
</PaneWithPanel>
<div class="overlay">

Loading…
Cancel
Save