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.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263import type { Attachment } from 'svelte/attachments';
/** * Keeps a popover inside the box it must not leave: moved back across, in CSS * pixels (the canvas and a window's zoom scale it). Opened inside a window's * body (a chat's chips under its composer), which clips whatever sticks out, * it also gets no wider than the body and no taller than the room on the side * it opens to (`up` or down; a tooltip leaves `up` out and is only moved). Elsewhere the box is its window, or the board * when it is wider than that, so it never goes under the sidebar. */export function fit(pop: HTMLElement, up?: boolean) { const style = pop.style; style.transform = style.maxWidth = style.maxHeight = style.overflowY = ''; const body = pop.closest('.window > .body'); const rect = pop.getBoundingClientRect(); const win = pop.closest('.window:not(.auto-height)'); const wide = !win || rect.width > win.getBoundingClientRect().width - 16; const box = (body ?? (wide ? pop.closest('main') : win) ?? document.documentElement).getBoundingClientRect(); const scale = rect.width / pop.offsetWidth || 1; const width = body ? Math.min(rect.width, box.width - 16) : rect.width; const right = rect.left + width; const past = right > box.right - 8 ? box.right - 8 - right : rect.left < box.left + 8 ? box.left + 8 - rect.left : 0; if (past) style.transform = `translateX(${Math.round(past / scale)}px)`; if (!body || up === undefined) return; const room = (up ? rect.bottom - box.top - 8 : box.bottom - rect.top - 8) / scale; style.maxWidth = `${Math.floor(width / scale)}px`; style.maxHeight = `${Math.floor(Math.min(room, parseFloat(getComputedStyle(pop).maxHeight) || Infinity))}px`; style.overflowY = 'auto';}
/** `fit` once the popover is on the page and has its content. */export const fitted = (up: boolean): Attachment<HTMLElement> => (pop) => { queueMicrotask(() => pop.isConnected && fit(pop, up)); };
/** Closes a popover on a press outside it (`keep` says what counts as inside) or on Escape, taken so the chat under it keeps its own state. Returns the cleanup, for an $effect. */export function dismissal(keep: (target: Element) => boolean, close: () => void): () => void { const away = (event: PointerEvent) => event.target instanceof Element && !keep(event.target) && close(); const escape = (event: KeyboardEvent) => event.key === 'Escape' && (event.preventDefault(), close()); document.addEventListener('pointerdown', away, true); document.addEventListener('keydown', escape); return () => { document.removeEventListener('pointerdown', away, true); document.removeEventListener('keydown', escape); };}
/** * Remembers what has the focus now and returns a function that gives it back, * once whatever took it is gone and left it on the page: a popover closed by * Esc, a pick or its own button leaves the keyboard where it was. */export function keepFocus(): () => void { const before = document.activeElement; return () => queueMicrotask(() => { const now = document.activeElement; if (before instanceof HTMLElement && before.isConnected && (!now || now === document.body)) before.focus({ preventScroll: true }); });}