Something went wrong. Try again.
small gleam coding and persistent agent daemon with a detachable cli and a canvas ui forked from okami.mom/albedo
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113<script module lang="ts"> /** How many sections hold this one: each sits a step deeper than the one round it. */ export const DEPTH = Symbol('section depth');</script>
<script lang="ts"> import { getContext, setContext } from 'svelte'; import type { Board } from '../board.svelte'; import Canvas from '../Canvas.svelte'; import SectionHead from './SectionHead.svelte'; import SplitView from './SplitView.svelte'; import TabsView from './TabsView.svelte'; import { canvasOf, type Tile } from './tree'; import WindowSlot from './WindowSlot.svelte';
// One tile of a board's layout, whatever its kind. A named split // or tabs is a section, framed with a header of its own unless what holds // it shows the name already (`headed`): a group on a canvas, a tab. The // frame is there, unseen, for every split and tabs, so naming one never // rebuilds the windows in it. let { board, tile, headed = true, over = false }: { board: Board; tile: Tile; headed?: boolean; over?: boolean } = $props();
const framed = $derived(headed && tile.kind !== 'leaf' && tile.kind !== 'canvas' && !!tile.name); const outer = getContext<(() => number) | undefined>(DEPTH) ?? (() => 0); setContext(DEPTH, () => outer() + (framed ? 1 : 0)); /** Filling the board where it is, over the rest (BoardView.svelte); one on a canvas is carried there instead (`away`). */ const expanded = $derived(board.expanded === (tile.kind === 'leaf' ? tile.window : tile.id) && !board.expandedOver); const away = $derived(!over && board.expandedOver && board.expanded === tile.id); /** A canvas sitting on a canvas is ringed by its node (nodes/SlotNode.svelte); a framed section here is ringed by its own tray. */ const onCanvas = $derived(tile.kind === 'canvas' && !!canvasOf(board.root, tile.id)); const selected = $derived(board.selected === tile.id && !onCanvas); const picked = $derived(board.picked.has(tile.id) && !onCanvas);</script>
{#if tile.kind === 'leaf'} <div class="leaf" class:expanded data-tile={tile.id}><WindowSlot {board} window={tile.window} /></div>{:else if tile.kind === 'canvas'} <div class="canvas-tile" class:nested={tile.id !== board.root.id} class:expanded class:picked class:selected data-tile={tile.id}><Canvas {board} canvas={tile} /></div>{:else} <div class="section" class:framed class:tray={framed} class:nested={framed && outer() > 0} class:expanded={framed && expanded} class:picked={framed && picked} class:selected={framed && selected} data-section={framed ? tile.id : undefined} style:--depth={framed ? outer() : undefined}> {#if framed} <SectionHead pane={tile.id} name={tile.name ?? ''} placeholder="section" bind:renaming={() => board.naming === tile.id, (on) => (board.naming = on ? tile.id : null)} onrename={(name) => board.rename(tile.id, name)} onungroup={() => board.ungroup(tile.id)} expanded={board.expanded === tile.id} onexpand={() => board.toggleExpanded(tile.id)} data-dock-tile={tile.id} /> {/if} {#if !away} {#if tile.kind === 'split'} <SplitView {board} split={tile} /> {:else} <TabsView {board} tabs={tile} /> {/if} {/if} </div>{/if}
<style> .leaf, .canvas-tile, .framed { position: relative; flex: 1; /* Fills its host whatever its display: a flex parent's main axis still goes by flex. */ width: 100%; height: 100%; min-width: 0; min-height: 0; } .leaf { display: flex; } .canvas-tile { overflow: hidden; } /* Inside the layout a canvas is a tile like the others, so two side by side read as two. */ .canvas-tile.nested { background: var(--rail); border-radius: 14px; box-shadow: 0 0 0 1px color-mix(in oklab, var(--text) 7%, transparent); } .canvas-tile.nested :global(.svelte-flow) { background: transparent; } .section { display: contents; } /* As a group on a canvas is framed (nodes/SlotNode.svelte). */ .section.framed { display: flex; flex-direction: column; padding: 0 6px 6px; }
.framed > :global(.section-head) { margin: 0 -6px; } /* Out of the layout's flow and over all of the board, the rest held as it was behind it. */ .expanded { position: fixed; top: var(--board-top); left: var(--board-left); z-index: 1; width: var(--board-width); height: var(--board-height); visibility: visible; } /* A tab's window keeps its tab's square corners only while it sits in the tabs. */ .leaf.expanded > :global(.window-slot .window) { border-radius: 14px; box-shadow: var(--shadow); } .leaf.expanded > :global(.window-slot .window > header) { border-radius: 14px 14px 0 0; }</style>