This commit is contained in:
Guilhem
2025-05-28 20:49:30 +02:00
parent 520c9e7016
commit 5b43fe3cc4
10 changed files with 80 additions and 73 deletions
@@ -85,9 +85,9 @@
import { Triggers } from './triggers/triggers.svelte'
import {
SplitPanesLayout,
setSplitPanesLayoutContext,
type PanesLayout
setSplitPanesLayoutContext
} from './splitPanes/SplitPanesLayout.svelte'
import type { PanesLayout } from './splitPanes/types'
import { setTabStateContext, TabsState } from './common/tabs/tabsState.svelte'
export let initialPath: string = ''
@@ -66,7 +66,6 @@
if (id) {
tabsState = getTabStateContext()
console.log('dbg tabsState', tabsState)
const tabState = tabsState?.getSelected(id)
if (tabState) {
selected = tabState
@@ -46,8 +46,8 @@
$copilotCurrentStepStore !== undefined ? 'border-gray-500/75' : ''
)}
>
<Splitpanes id="flow-editor">
<Pane minSize={15} class="h-full relative z-0" index={0} defaultSize={60}>
<Splitpanes id="flow-editor" defaultSize={[60, 40]}>
<Pane minSize={15} class="h-full relative z-0" index={0}>
<div class="grow overflow-hidden bg-gray h-full bg-surface-secondary relative">
{#if loading}
<div class="p-2 pt-10">
@@ -69,7 +69,7 @@
{/if}
</div>
</Pane>
<Pane class="relative z-10" index={1} defaultSize={40}>
<Pane class="relative z-10" index={1}>
{#if loading}
<div class="w-full h-full">
<div class="block m-auto pt-40 w-10">
@@ -376,8 +376,8 @@
{/if}
<div class="min-h-0 flex-grow" id="flow-editor-editor">
<Splitpanes id={`flow-editor-split-${flowModule.id}`} horizontal>
<Pane minSize={10} class="relative" index={0} defaultSize={panesSizes[0]}>
<Splitpanes id={`flow-editor-split-${flowModule.id}`} horizontal defaultSize={panesSizes}>
<Pane minSize={10} class="relative" index={0}>
{#if flowModule.value.type === 'rawscript'}
{#if !noEditor}
{#key flowModule.id}
@@ -453,9 +453,9 @@
{/key}
{/if}
</Pane>
<Pane minSize={20} index={1} defaultSize={panesSizes[1]}>
<Splitpanes id={`flow-editor-step-input-${flowModule.id}`}>
<Pane minSize={36} index={0} defaultSize={selected === 'inputs' ? 100 : 50}>
<Pane minSize={20} index={1}>
<Splitpanes id={`flow-editor-step-input-${flowModule.id}`} defaultSize={[50, 50]}>
<Pane minSize={36} index={0}>
<Tabs bind:selected id={`flow-editor-step-input-${flowModule.id}`}>
{#if !preprocessorModule}
<Tab value="inputs">Step Input</Tab>
@@ -784,7 +784,7 @@
</div>
</Pane>
{#if selected === 'test'}
<Pane minSize={20} index={1} defaultSize={50}>
<Pane minSize={20} index={1}>
<ModulePreviewResultViewer
lang={flowModule.value['language'] ?? 'deno'}
{editor}
@@ -104,11 +104,11 @@
<Splitpanes
class={$propPickerConfig ? 'splitpanes-remove-splitter' : ''}
id={`prop-picker-wrapper-${moduleId}`}
defaultSize={[60, 40]}
>
<Pane
index={0}
minSize={20}
defaultSize={60}
class={twMerge('relative !transition-none ', noPadding ? '' : 'p-2')}
>
<slot />
@@ -116,7 +116,6 @@
<Pane
index={1}
minSize={20}
defaultSize={40}
class="!transition-none z-1000 {$propPickerConfig ? 'ml-[-1px]' : ''} {paneClass}"
>
<AnimatedButton
@@ -1,32 +1,25 @@
<script lang="ts">
import { Pane } from 'svelte-splitpanes'
import { getSplitPanesLayout } from './SplitPanesLayout.svelte'
import type { Snippet } from 'svelte'
import { type ComponentProps, getContext, onDestroy, onMount } from 'svelte'
import { getContext, onMount, type ComponentProps } from 'svelte'
import type { SplitPanesContext } from './types'
type SplitpanesProps = ComponentProps<Pane>
type Props = SplitpanesProps & {
export type Props = SplitpanesProps & {
index: number
defaultSize: number
children?: Snippet
}
let { index, defaultSize, children, ...rest }: Props = $props()
let { index, children, ...rest }: Props = $props()
const splitPanesId = getContext<string>('splitPanesId')
const splitPanesLayout = getSplitPanesLayout()
const { sizes, setActivePane } = getContext<SplitPanesContext>('splitPanesContext') ?? {}
onMount(() => {
splitPanesLayout?.mountPane(splitPanesId, index, defaultSize)
})
onDestroy(() => {
splitPanesLayout?.unmountPane(splitPanesId, index)
setActivePane(index)
})
</script>
<Pane size={splitPanesLayout?.layout[splitPanesId]?.[index]?.size ?? defaultSize} {...rest}>
<Pane size={sizes?.(index)} {...rest}>
{@render children?.()}
</Pane>
@@ -1,14 +1,8 @@
import { setContext, getContext, tick } from 'svelte'
import type { Pane, PanesLayout } from './types'
const KEY = 'splitPanesLayout'
export type Pane = {
size: number | undefined
active: boolean
}
export type PanesLayout = Pane[]
export class SplitPanesLayout {
#layout: Record<string, PanesLayout> = $state({})
#changeCb: (() => void) | undefined = undefined
@@ -28,30 +22,27 @@ export class SplitPanesLayout {
this.#changeCb?.()
}
mountPane(layoutId: string, paneIndex: number, defaultSize: number) {
if (!this.#layout[layoutId]) {
this.#layout[layoutId] = [{ size: defaultSize, active: true }]
} else if (this.#readyPanes[layoutId]) {
// Ensure array is long enough
while (this.#layout[layoutId].length <= paneIndex) {
this.#layout[layoutId].push({ size: undefined, active: false })
}
this.#layout[layoutId][paneIndex].active = true
this.#layout[layoutId][paneIndex].size = this.#layout[layoutId][paneIndex].size ?? defaultSize
this.#scalePanes(layoutId, paneIndex)
addPane(layoutId: string, paneIndex: number) {
if (!this.#readyPanes[layoutId] || !this.#layout[layoutId][paneIndex].size) {
return
} else {
// Ensure array is long enough
while (this.#layout[layoutId].length <= paneIndex) {
this.#layout[layoutId].push({ size: undefined, active: false })
}
const currentPane = this.#layout[layoutId][paneIndex]
currentPane.active = true
currentPane.size = currentPane.size ?? defaultSize
this.#layout[layoutId][paneIndex].active = true
this.#scalePanes(layoutId, paneIndex)
}
this.#changeCb?.()
}
setPanes(layoutId: string, panes: Pane[]) {
if (!this.#layout[layoutId]) {
this.#layout[layoutId] = []
}
this.#layout[layoutId] = panes
this.#scalePanesTo100(layoutId)
this.#readyPanes[layoutId] = true
this.#changeCb?.()
}
#scalePanes(layoutId: string, paneIndex: number) {
// Scale other active panes while keeping the current pane size
const otherPanesTotal = this.#layout[layoutId]
@@ -70,6 +61,7 @@ export class SplitPanesLayout {
const activePanesTotal = this.#layout[layoutId]
.filter((pane) => pane.active)
.reduce((sum, pane) => sum + (pane.size ?? 0), 0)
if (activePanesTotal > 0) {
const scale = 100 / activePanesTotal
this.#layout[layoutId] = this.#layout[layoutId].map((pane) =>
@@ -78,10 +70,10 @@ export class SplitPanesLayout {
}
}
async unmountPane(layoutId: string, paneIndex: number) {
// Wait for the dom refresh to avoid update in the case the splitpane has been removed
async removePane(layoutId: string, paneIndex: number) {
// Wait for the dom refresh to avoid update in the case the splitpane has been removed completly
await tick()
if (this.#readyPanes[layoutId]) {
if (this.#readyPanes[layoutId] && this.#layout[layoutId][paneIndex].active) {
this.#layout[layoutId][paneIndex].active = false
this.#scalePanesTo100(layoutId)
}
@@ -98,12 +90,6 @@ export class SplitPanesLayout {
this.#changeCb?.()
}
handleSplitPaneReady(layoutId: string) {
this.#readyPanes[layoutId] = true
this.#scalePanesTo100(layoutId)
this.#changeCb?.()
}
handleSplitPaneDestroy(layoutId: string) {
this.#readyPanes[layoutId] = false
this.#changeCb?.()
@@ -1,30 +1,40 @@
<script lang="ts">
import { Splitpanes } from 'svelte-splitpanes'
import { getSplitPanesLayout } from './SplitPanesLayout.svelte'
import { onDestroy, onMount, setContext, type Snippet } from 'svelte'
import { onDestroy, setContext, type Snippet } from 'svelte'
import type { ComponentProps } from 'svelte'
import type { Pane, SplitPanesContext } from './types'
type SplitpanesProps = ComponentProps<Splitpanes>
type Props = SplitpanesProps & {
defaultSize: number[]
id: string
children?: Snippet
}
let { id, children, ...rest }: Props = $props()
let timeout: ReturnType<typeof setTimeout> | undefined = undefined
setContext<string>('splitPanesId', id)
const splitPanesLayout = getSplitPanesLayout()
onMount(() => {
splitPanesLayout?.handleSplitPaneReady(id)
let { id, children, defaultSize, ...rest }: Props = $props()
const sizes = $derived(splitPanesLayout?.layout[id]?.map((pane) => pane.size ?? 0) ?? [])
setContext<SplitPanesContext>('splitPanesContext', {
sizes: (index: number) => sizes[index],
setActivePane: (index: number) => {
panes[index].active = true
}
})
function initPane(defaultSize: number[]): Pane[] {
// Initialize all panes with default sizes
const panes = defaultSize.map((size, idx) => ({ size, active: false }))
return panes
}
let panes: Pane[] = $state(initPane(defaultSize))
onDestroy(() => {
splitPanesLayout?.handleSplitPaneDestroy(id)
clearTimeout(timeout)
})
</script>
@@ -35,6 +45,15 @@
detail.map((d, index) => ({ size: d.size, index }))
)
}}
on:pane-add={({ detail }) => {
splitPanesLayout?.addPane(id, detail.index)
}}
on:pane-remove={({ detail }) => {
splitPanesLayout?.removePane(id, detail.removed.index)
}}
on:ready={() => {
splitPanesLayout?.setPanes(id, panes)
}}
{...rest}
>
{@render children?.()}
@@ -0,0 +1,11 @@
export type Pane = {
size: number | undefined
active: boolean
}
export type PanesLayout = Pane[]
export type SplitPanesContext = {
sizes: (index: number) => number | undefined
setActivePane: (index: number) => void
}
@@ -16,7 +16,7 @@
import type { ScheduleTrigger } from '$lib/components/triggers'
import type { GetInitialAndModifiedValues } from '$lib/components/common/confirmationModal/unsavedTypes'
import type { Trigger } from '$lib/components/triggers/utils'
import type { PanesLayout } from '$lib/components/splitPanes/SplitPanesLayout.svelte'
import type { PanesLayout } from '$lib/components/splitPanes/types'
let version: undefined | number = undefined
let nodraft = $page.url.searchParams.get('nodraft')