| 1 | import catalogue from "@/public/ratatui/catalogue.json"; |
| 2 | import { discoveryText, displayApi, normalizeSearch } from "./learning"; |
| 3 | |
| 4 | export interface CatalogueEntry { |
| 5 | name: string; |
| 6 | title: string; |
| 7 | family: string; |
| 8 | width: number; |
| 9 | height: number; |
| 10 | description: string; |
| 11 | api: string[]; |
| 12 | source: { file: string; function: string; line: number; url: string }; |
| 13 | previewPath: string; |
| 14 | } |
| 15 | |
| 16 | export interface Catalogue { |
| 17 | schemaVersion: number; |
| 18 | source: { revision: string; digest: string; repository: string; nativeRevision: string }; |
| 19 | profiles: { id: string; label: string }[]; |
| 20 | sizes: { id: string; label: string }[]; |
| 21 | families: { id: string; title: string; description: string; count: number }[]; |
| 22 | entries: CatalogueEntry[]; |
| 23 | } |
| 24 | |
| 25 | export interface EntryPreview { |
| 26 | name: string; |
| 27 | width: number; |
| 28 | height: number; |
| 29 | previews: Record<string, Record<string, string>>; |
| 30 | fixture: { code: string; imports: string; helpers?: { name: string; code: string; line: number }[]; source: unknown }; |
| 31 | } |
| 32 | |
| 33 | /** Bundled at build time: no filesystem or remote repository dependency in the Worker. */ |
| 34 | export function readCatalogue(): Catalogue { |
| 35 | return catalogue; |
| 36 | } |
| 37 | |
| 38 | export function searchEntries(entries: readonly CatalogueEntry[], query: string, family = "all") { |
| 39 | const terms = normalizeSearch(query).split(/\s+/).filter(Boolean); |
| 40 | return entries.filter((entry) => { |
| 41 | if (family !== "all" && entry.family !== family) return false; |
| 42 | const text = normalizeSearch([entry.name, entry.title, ...displayApi(entry), discoveryText(entry)].join(" ")); |
| 43 | return terms.every((term) => text.includes(term)); |
| 44 | }); |
| 45 | } |
| 46 | |
| 47 | export function previewAssetPath(entry: CatalogueEntry) { |
| 48 | if (!/^entries\/[a-z0-9_-]+\.json$/.test(entry.previewPath)) throw new Error("Invalid catalogue path"); |
| 49 | return `/ratatui/${entry.previewPath}`; |
| 50 | } |
| 51 | |
| 52 | export function motionId(entry: CatalogueEntry, profile: string) { |
| 53 | if (entry.name === "showcase-life" || ["whales", "whale-actions"].includes(entry.family)) return "whale"; |
| 54 | if (entry.family === "habitat") return "habitat"; |
| 55 | if (entry.family === "motion") return profile === "light-truecolor" ? "motion-light" : "motion"; |
| 56 | if (entry.family === "studio") return profile === "light-truecolor" ? "studio-light" : "studio"; |
| 57 | return null; |
| 58 | } |
| 59 |