| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import { SHARED_COMPONENT_DEFS, type SharedComponentDef } from "#shared/component-defs"; |
|
|
| export interface ComponentField { |
| name: string; |
| type: "string" | "boolean" | "select"; |
| default?: unknown; |
| options?: string[]; |
| label: string; |
| placeholder?: string; |
| } |
|
|
| export interface ComponentDef { |
| |
| name: string; |
| |
| tag: string; |
| |
| icon: string; |
| |
| label: string; |
| |
| description: string; |
| |
| kind: "wrapper" | "atomic"; |
| |
| fields: ComponentField[]; |
| |
| content?: string; |
| } |
|
|
| |
| interface UIMeta { |
| tag: string; |
| icon: string; |
| label: string; |
| description: string; |
| fieldMeta: Record<string, { label: string; placeholder?: string }>; |
| } |
|
|
| const UI_META: Record<string, UIMeta> = { |
| accordion: { |
| tag: "Accordion", icon: "▸", label: "Accordion", description: "Collapsible content section", |
| fieldMeta: { title: { label: "Title", placeholder: "Section title…" }, open: { label: "Open by default" } }, |
| }, |
| note: { |
| tag: "Note", icon: "ℹ", label: "Note / Callout", description: "Highlighted callout box", |
| fieldMeta: { title: { label: "Title", placeholder: "Optional title…" }, emoji: { label: "Emoji", placeholder: "e.g. 💡" }, variant: { label: "Variant" } }, |
| }, |
| quoteBlock: { |
| tag: "Quote", icon: "❝", label: "Quote block", description: "Quote with author attribution", |
| fieldMeta: { author: { label: "Author", placeholder: "Author name…" }, source: { label: "Source", placeholder: "Book, URL…" } }, |
| }, |
| wide: { |
| tag: "Wide", icon: "↔", label: "Wide", description: "Wider-than-column container", |
| fieldMeta: {}, |
| }, |
| fullWidth: { |
| tag: "FullWidth", icon: "⟷", label: "Full width", description: "Full-width container", |
| fieldMeta: {}, |
| }, |
| sidenote: { |
| tag: "Sidenote", icon: "¶", label: "Sidenote", description: "Margin note alongside content", |
| fieldMeta: {}, |
| }, |
| reference: { |
| tag: "Reference", icon: "🏷", label: "Reference / Figure", description: "Captioned figure with anchor ID", |
| fieldMeta: { id: { label: "ID", placeholder: "fig-1" }, caption: { label: "Caption", placeholder: "Figure caption…" } }, |
| }, |
| htmlEmbed: { |
| tag: "HtmlEmbed", icon: "📊", label: "HTML Embed", description: "Embed an external HTML visualization", |
| fieldMeta: { src: { label: "Source file", placeholder: "d3-chart.html" }, title: { label: "Title", placeholder: "Chart title…" }, desc: { label: "Description", placeholder: "Chart description…" }, wide: { label: "Wide" }, downloadable: { label: "Downloadable" }, height: { label: "Height (px)", placeholder: "400" } }, |
| }, |
| hfUser: { |
| tag: "HfUser", icon: "👤", label: "HF User card", description: "Hugging Face user profile card", |
| fieldMeta: { username: { label: "Username", placeholder: "username" }, name: { label: "Display name", placeholder: "Full Name" }, url: { label: "URL", placeholder: "https://huggingface.co/username" } }, |
| }, |
| iframe: { |
| tag: "Iframe", icon: "🔗", label: "Iframe", description: "Embed a remote URL (Space, widget, demo…)", |
| fieldMeta: { |
| src: { label: "URL", placeholder: "https://my-space.hf.space/" }, |
| title: { label: "Title", placeholder: "Embed title…" }, |
| desc: { label: "Description", placeholder: "Caption shown below…" }, |
| height: { label: "Height (px)", placeholder: "600" }, |
| wide: { label: "Wide" }, |
| }, |
| }, |
| rawHtml: { |
| tag: "RawHtml", icon: "</>", label: "Raw HTML", description: "Inject raw HTML content", |
| fieldMeta: { html: { label: "HTML", placeholder: "<div>…</div>" } }, |
| }, |
| mermaid: { |
| tag: "Mermaid", icon: "◈", label: "Mermaid diagram", description: "Flowchart, sequence, Gantt, etc.", |
| fieldMeta: { code: { label: "Code", placeholder: "graph LR\\n A --> B" } }, |
| }, |
| }; |
|
|
| function buildComponentDef(shared: SharedComponentDef): ComponentDef { |
| const ui = UI_META[shared.name]; |
| if (!ui) throw new Error(`Missing UI_META for component "${shared.name}"`); |
|
|
| return { |
| name: shared.name, |
| tag: ui.tag, |
| icon: ui.icon, |
| label: ui.label, |
| description: ui.description, |
| kind: shared.kind, |
| content: shared.content, |
| fields: shared.fields.map((f) => ({ |
| name: f.name, |
| type: f.type, |
| default: f.default, |
| options: f.options, |
| label: ui.fieldMeta[f.name]?.label ?? f.name, |
| placeholder: ui.fieldMeta[f.name]?.placeholder, |
| })), |
| }; |
| } |
|
|
| |
| |
| |
|
|
| export const COMPONENTS: ComponentDef[] = SHARED_COMPONENT_DEFS.map(buildComponentDef); |
|
|