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.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131<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 { canvasAbove, 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 }: { board: Board; tile: Tile; headed?: 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); a window off a canvas is carried there instead. */ const expanded = $derived(board.expanded === (tile.kind === 'leaf' ? tile.window : tile.id) && !board.expandedOver); /** The pane keys act on, ringed as a selected window is; one on a canvas is ringed by its node (nodes/SlotNode.svelte). */ const selected = $derived(board.selected === tile.id && !canvasAbove(board.root, tile.id));</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={board.picked.has(tile.id)} 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 && board.picked.has(tile.id)} class:selected={framed && selected} data-section={framed ? tile.id : undefined} style:--depth={framed ? outer() : undefined}> {#if framed} <SectionHead 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} data-pane={tile.id} /> {/if} {#if tile.kind === 'split'} <SplitView {board} split={tile} /> {:else} <TabsView {board} tabs={tile} /> {/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; } /* Selected, as a window is (WindowSlot.svelte): its name in the accent and a faint ring, calmer than a pick's. */ .section.selected > :global(.section-head) { color: var(--accent); } .section.selected:not(.picked)::after { position: absolute; inset: 0; border-radius: inherit; box-shadow: 0 0 0 1px color-mix(in oklab, var(--accent) 35%, transparent); content: ''; pointer-events: none; } .canvas-tile.nested.selected:not(.picked) { box-shadow: 0 0 0 1px color-mix(in oklab, var(--accent) 35%, transparent); } :global([data-theme='dark']) .section.selected::after, :global([data-theme='dark']) .canvas-tile.nested.selected:not(.picked) { box-shadow: 0 0 0 1px color-mix(in oklab, var(--accent) 55%, transparent); } /* Picked to make a section of: a ring in the gap around it, where nothing inside can cover it. */ .canvas-tile.picked, .section.picked { box-shadow: 0 0 0 2px var(--accent); } .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>