Files
windmill/frontend/src/lib/components/apps/editor/SubGridEditor.svelte
2023-10-21 22:50:19 +02:00

179 lines
4.6 KiB
Svelte

<script lang="ts">
import { push } from '$lib/history'
import { classNames } from '$lib/utils'
import { createEventDispatcher, getContext, onDestroy } from 'svelte'
import { twMerge } from 'tailwind-merge'
import { columnConfiguration, isFixed, toggleFixed } from '../gridUtils'
import Grid from '../svelte-grid/Grid.svelte'
import type { AppEditorContext, AppViewerContext, GridItem } from '../types'
import { expandGriditem, findGridItem, selectId } from './appUtils'
import Component from './component/Component.svelte'
import ComponentWrapper from './component/ComponentWrapper.svelte'
import GridViewer from './GridViewer.svelte'
export let containerHeight: number | undefined = undefined
export let containerWidth: number | undefined = undefined
let classes = ''
export { classes as class }
export let style = ''
export let noPadding = false
export let noYPadding = false
export let subGridId: string
export let visible: boolean = true
export let id: string
export let shouldHighlight: boolean = true
const dispatch = createEventDispatcher()
const {
app,
connectingInput,
selectedComponent,
focusedGrid,
mode,
parentWidth,
breakpoint,
allIdsInPath
} = getContext<AppViewerContext>('AppViewerContext')
const editorContext = getContext<AppEditorContext>('AppEditorContext')
let isActive = false
let sber = editorContext?.componentActive?.subscribe((x) => (isActive = x))
onDestroy(() => {
sber?.()
})
$: highlight = id === $focusedGrid?.parentComponentId && shouldHighlight
const onpointerdown = (e) => {
dispatch('focus')
}
function selectComponent(e: PointerEvent, id: string) {
if (!$connectingInput.opened) {
selectId(e, id, selectedComponent, $app)
}
}
function lock(dataItem: GridItem) {
let fComponent = findGridItem($app, dataItem.id)
if (fComponent) {
fComponent = toggleFixed(fComponent)
}
$app = $app
}
let container: HTMLElement | undefined = undefined
</script>
<div
class="translate-x-0 translate-y-0 w-full subgrid {visible
? 'visible'
: 'invisible h-0 overflow-hidden'}"
bind:this={container}
on:pointerdown={onpointerdown}
>
<div
class={twMerge(
$allIdsInPath.includes(id) ? 'overflow-visible' : 'overflow-auto',
noYPadding ? '' : 'py-2',
classes ?? '',
noPadding ? 'px-0' : 'px-2'
)}
style="{containerHeight ? `height: ${containerHeight - 2}px;` : ''} {style ?? ''}"
>
{#if $mode !== 'preview'}
<div
class={highlight
? `animate-border border-dashed border-2 min-h-full ${
isActive && !$selectedComponent?.includes(id)
? 'border-orange-600'
: 'border-gray-600'
}`
: ''}
>
<Grid
allIdsInPath={$allIdsInPath}
items={$app.subgrids?.[subGridId] ?? []}
on:redraw={(e) => {
push(editorContext?.history, $app)
if ($app.subgrids) {
$app.subgrids[subGridId] = e.detail
}
}}
selectedIds={$selectedComponent}
let:dataItem
rowHeight={36}
cols={columnConfiguration}
fastStart={true}
gap={[4, 2]}
scroller={container}
parentWidth={$parentWidth - 17}
{containerWidth}
>
<ComponentWrapper
id={dataItem.id}
type={dataItem.data.type}
class={classNames(
'h-full w-full center-center',
$selectedComponent?.includes(dataItem.id) ? 'active-grid-item' : '',
'top-0'
)}
>
<Component
render={visible}
component={dataItem.data}
selected={Boolean($selectedComponent?.includes(dataItem.id))}
locked={isFixed(dataItem)}
on:lock={() => lock(dataItem)}
on:expand={() => {
const parentGridItem = findGridItem($app, id)
if (!parentGridItem) {
return
}
$selectedComponent = [dataItem.id]
push(editorContext?.history, $app)
expandGriditem(
$app.subgrids?.[subGridId] ?? [],
dataItem.id,
$breakpoint,
parentGridItem
)
$app = $app
}}
/>
</ComponentWrapper>
</Grid>
</div>
{:else}
<GridViewer
allIdsInPath={$allIdsInPath}
items={$app.subgrids?.[subGridId] ?? []}
let:dataItem
rowHeight={36}
cols={columnConfiguration}
gap={[4, 2]}
parentWidth={$parentWidth - 17}
{containerWidth}
>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
on:pointerdown|stopPropagation={(e) => selectComponent(e, dataItem.id)}
class={classNames('h-full w-full center-center', 'top-0')}
>
<Component
render={visible}
component={dataItem.data}
selected={Boolean($selectedComponent?.includes(dataItem.id))}
locked={isFixed(dataItem)}
/>
</div>
</GridViewer>
{/if}
</div>
</div>