feat(frontend): hierarchical output panel WIP
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
<script lang="ts">
|
||||
import { components } from '../component'
|
||||
import { getContext } from 'svelte'
|
||||
import type { AppEditorContext, GridItem } from '../../types'
|
||||
import ComponentOutputViewer from './ComponentOutputViewer.svelte'
|
||||
|
||||
export let gridItem: GridItem
|
||||
|
||||
const { app, staticOutputs, selectedComponent } = getContext<AppEditorContext>('AppEditorContext')
|
||||
const name = getComponentNameById(gridItem.id)
|
||||
|
||||
function getComponentNameById(componentId: string) {
|
||||
if (gridItem?.data?.type) {
|
||||
return components[gridItem?.data.type].name
|
||||
} else if (componentId == 'ctx') {
|
||||
return 'Context'
|
||||
} else if (componentId.startsWith('bg_')) {
|
||||
return 'Background'
|
||||
} else {
|
||||
return 'Table action'
|
||||
}
|
||||
}
|
||||
|
||||
let manuallyOpened = false
|
||||
|
||||
$: subGrids = Array.from({ length: gridItem.data.numberOfSubgrids }).map(
|
||||
(_, i) => `${gridItem.id}-${i}`
|
||||
)
|
||||
|
||||
function x(name: string) {
|
||||
if (name === 'Tabs') {
|
||||
return 'Tab'
|
||||
} else if (name === 'Horizontal Split Panes') {
|
||||
return 'Pane'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if $staticOutputs[gridItem.id] || gridItem.data.numberOfSubgrids > 1}
|
||||
<div class="flex flex-col mb-2">
|
||||
<div class="flex items-center justify-between p-1 border-t border-l border-b bg-gray-100">
|
||||
<div class="text-xs ml-1 bg-indigo-500 text-white px-2 py-0.5">
|
||||
{gridItem.id}
|
||||
</div>
|
||||
<div class="text-xs font-bold">
|
||||
{getComponentNameById(gridItem.id)}
|
||||
</div>
|
||||
</div>
|
||||
{#if $selectedComponent === gridItem.id}
|
||||
<div class="my-1">
|
||||
<ComponentOutputViewer componentId={gridItem.id} outputs={$staticOutputs[gridItem.id]} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{#each subGrids as subGridId, index}
|
||||
{#if subGrids.length > 1}
|
||||
<div class="ml-2 border-y border-l bg-gray-400 font-bold text-xs p-1 my-1">
|
||||
{x(name)}
|
||||
{index + 1}
|
||||
|
||||
{subGridId}
|
||||
</div>
|
||||
{/if}
|
||||
{#if $app.subgrids}
|
||||
{#each $app.subgrids[subGridId] as subGridItem}
|
||||
{#if subGridItem}
|
||||
<div class="ml-2 pl-2">
|
||||
<svelte:self gridItem={subGridItem} />
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -3,16 +3,19 @@
|
||||
import { X } from 'lucide-svelte'
|
||||
import { getContext } from 'svelte'
|
||||
import { flip } from 'svelte/animate'
|
||||
import { fade } from 'svelte/transition'
|
||||
import { fade, slide } from 'svelte/transition'
|
||||
import type { AppEditorContext } from '../../types'
|
||||
import { findGridItem } from '../appUtils'
|
||||
import { components } from '../component'
|
||||
import PanelSection from '../settingsPanel/common/PanelSection.svelte'
|
||||
import ComponentOutput from './ComponentOutput.svelte'
|
||||
import ComponentOutputViewer from './ComponentOutputViewer.svelte'
|
||||
|
||||
const { connectingInput, staticOutputs, worldStore, selectedComponent, app } =
|
||||
getContext<AppEditorContext>('AppEditorContext')
|
||||
|
||||
const manualyOpenedIds = new Set<string>()
|
||||
|
||||
function connectInput(componentId: string, path: string) {
|
||||
if ($connectingInput) {
|
||||
$connectingInput = {
|
||||
@@ -42,6 +45,7 @@
|
||||
return 'Table action'
|
||||
}
|
||||
}
|
||||
|
||||
$: panels = [['ctx', ['email', 'username', 'query', 'hash']] as [string, string[]]].concat(
|
||||
Object.entries($staticOutputs)
|
||||
)
|
||||
@@ -78,82 +82,9 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative p-2">
|
||||
{#each filteredPanels as [componentId, outputs] (componentId)}
|
||||
<div
|
||||
animate:flip={{ duration: 300 }}
|
||||
in:fade|local={{ duration: 100, delay: 50 }}
|
||||
out:fade|local={{ duration: 100 }}
|
||||
class="pb-2"
|
||||
>
|
||||
{#if outputs.length > 0 && $worldStore?.outputsById[componentId]}
|
||||
{@const name = getComponentNameById(componentId)}
|
||||
<div>
|
||||
<div
|
||||
class="flex {$connectingInput?.opened
|
||||
? 'bg-white z-50'
|
||||
: ''} flex-row justify-between w-full"
|
||||
>
|
||||
<button
|
||||
on:click|stopPropagation|preventDefault={$connectingInput.opened
|
||||
? undefined
|
||||
: () => ($selectedComponent = componentId)}
|
||||
class={classNames(
|
||||
'px-2 text-2xs py-0.5 border-t border-x font-bold rounded-t-sm w-fit',
|
||||
$selectedComponent === componentId
|
||||
? ' bg-indigo-500/90 text-white border-indigo-500/90'
|
||||
: 'bg-gray-100 text-gray-500 border-gray-200'
|
||||
)}
|
||||
>
|
||||
{componentId}
|
||||
</button>
|
||||
<span
|
||||
class={classNames(
|
||||
'px-1 text-2xs py-0.5 font-semibold rounded-t-sm w-fit',
|
||||
'bg-gray-700 text-white'
|
||||
)}
|
||||
>
|
||||
{name}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class={classNames(
|
||||
$connectingInput?.opened ? 'bg-white z-50' : '',
|
||||
`w-full py-2 grow border relative break-all `,
|
||||
$selectedComponent === componentId ? 'border border-indigo-500/90 ' : '',
|
||||
$connectingInput.hoveredComponent === componentId
|
||||
? 'outline outline-indigo-500/90'
|
||||
: ''
|
||||
)}
|
||||
>
|
||||
{#key $selectedComponent}
|
||||
{#key $connectingInput?.opened}
|
||||
<ComponentOutputViewer
|
||||
outputs={$connectingInput?.opened && $selectedComponent === componentId
|
||||
? name == 'Table'
|
||||
? ['search']
|
||||
: []
|
||||
: outputs}
|
||||
{componentId}
|
||||
on:select={({ detail }) => {
|
||||
connectInput(componentId, detail)
|
||||
}}
|
||||
/>
|
||||
{/key}
|
||||
{/key}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
in:fade|local={{ duration: 50, delay: 100 }}
|
||||
out:fade|local={{ duration: 50 }}
|
||||
class="absolute left-0 top-0 w-full text-sm text-gray-500 text-center py-4 px-2"
|
||||
>
|
||||
No outputs found
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
{#each $app.grid as gridItem}
|
||||
<ComponentOutput {gridItem} />
|
||||
{/each}
|
||||
</div>
|
||||
</PanelSection>
|
||||
|
||||
Reference in New Issue
Block a user