import { html } from "lit"; import type { WebwriterWebsiteBuilder } from "../../webwriter-website-builder"; import { ComponentRegistry } from "../../components/registry"; import { SHOELACE_ICON_NAMES } from "../data/shoelaceIcons"; import { componentSyntaxHint, tileGlyph } from "../palette-helpers"; import { msg } from "@lit/localize"; // ─── Icon Dialog ────────────────────────────────────────────────────────────── export function renderIconDialog(host: WebwriterWebsiteBuilder) { const q = host.iconQuery.trim().toLowerCase(); const items = q ? SHOELACE_ICON_NAMES.filter((n) => n.toLowerCase().includes(q)) : SHOELACE_ICON_NAMES; return html`
{ const input = e.currentTarget as any; host.iconQuery = String(input.value ?? ""); host.iconScrollTop = 0; host.iconScroller?.scrollTo({ top: 0 }); host.requestUpdate(); }} @sl-clear=${() => (host.iconQuery = "")} > { host.iconDraftColor = String( e?.target?.value ?? e?.detail?.value ?? (e?.currentTarget as any)?.value ?? "", ); host.requestUpdate(); }} >
${renderIconVirtualGrid(host, items)}
`; } function renderIconVirtualGrid(host: WebwriterWebsiteBuilder, items: string[]) { const ICON_ROW_H = 60; const ICON_OVERSCAN = 3; const width = host.iconScroller?.clientWidth ?? 760; const minCol = 56; const cols = Math.max(1, Math.floor((width - 24) / (minCol + 6))); const totalRows = Math.ceil(items.length / cols); const spacerH = totalRows * ICON_ROW_H; let startRow = Math.floor(host.iconScrollTop / ICON_ROW_H) - ICON_OVERSCAN; startRow = Math.max(0, Math.min(startRow, totalRows - 1)); const endRow = Math.min( totalRows, Math.ceil((host.iconScrollTop + host.iconViewportH) / ICON_ROW_H) + ICON_OVERSCAN, ); const startIndex = startRow * cols; const endIndex = Math.min(items.length, endRow * cols); const slice = items.slice(startIndex, endIndex); const offsetY = startRow * ICON_ROW_H; return html`
${slice.map((name) => { const selected = name === host.iconDraftName; return html` `; })}
`; } // ─── All Components Dialog ──────────────────────────────────────────────────── export function renderAllComponentsDialog(host: WebwriterWebsiteBuilder) { const q = host.allComponentsQuery.trim().toLowerCase(); const allTypes = Object.keys(ComponentRegistry); const types = ( q ? allTypes.filter((t) => { const label = (ComponentRegistry[t]?.label() ?? t).toLowerCase(); return t.toLowerCase().includes(q) || label.includes(q); }) : allTypes ).sort((a, b) => { const la = (ComponentRegistry[a]?.label() ?? a).toLowerCase(); const lb = (ComponentRegistry[b]?.label() ?? b).toLowerCase(); return la.localeCompare(lb); }); return html` { const dlg = e.target as HTMLElement; queueMicrotask(() => { (dlg.querySelector("#ww-all-components-search") as any)?.focus?.(); }); }} @sl-after-hide=${() => { host.allComponentsDialogOpen = false; }} >
{ host.allComponentsQuery = String( e?.currentTarget?.value ?? e?.target?.value ?? e?.detail?.value ?? "", ); host.requestUpdate(); }} @sl-clear=${() => (host.allComponentsQuery = "")} style="flex:1;" >
${types.length} ${types.length === 1 ? msg("item") : msg("items")}
${types.map((type) => { const comp = ComponentRegistry[type]; const label = comp?.label?.() ?? type; const syntax = componentSyntaxHint(type); return html`
${tileGlyph(type)}
${label}
{ host.quickAdd(type); host.requestUpdate(); }} >${msg("Insert")}
${msg("Drag tiles from the palette, or insert here at default position.")}
${msg("Syntax (preview)")}
${syntax}
`; })}
(host.renderRoot.querySelector("#ww-all-components-dialog") as any)?.hide?.()} >${msg("Close")}
`; }