mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 07:19:52 +00:00
feat(studio): full Blocks panel — browse, search, add, drag-and-drop registry items
Adds a Blocks tab to the Studio left sidebar with the full 78-item registry
catalog (58 blocks + 20 components). Users can browse by category, search by
title/description, preview CDN-hosted poster thumbnails with video-on-hover,
and install items on-demand with one click or drag-to-timeline.
Core changes:
- BlockCategory type + resolveBlockCategory() for 7 categories (Captions, VFX,
Transitions, Effects, Social, Data, Scenes)
- Registry API routes: GET /api/registry/blocks (catalog) + POST install
- StudioApiAdapter extended with listRegistryCatalog + installRegistryBlock
- Vite adapter reads from disk; CLI adapter fetches from GitHub (24h cache)
- BlockParam interface + params on 6 blocks for future parameter controls
Studio UI:
- 4th sidebar tab "Blocks" with responsive grid, category pills, search bar
- BlockCard: CDN poster thumbnail, video autoplay on hover, duration + WebGL badges
- On-demand install: blocks append as sub-compositions on timeline; components
overlay at start=0 spanning full duration with transparent background patching
- TIMELINE_BLOCK_MIME drag-and-drop to timeline
- BlockParamsPanel (Phase 3 scaffold) auto-opens for parameterized blocks
Registry manifests:
- All 58 blocks backfilled with preview: { video, poster } CDN URLs
- All 20 components normalized to object format + poster URLs added
- 6 blocks annotated with params (Liquid Glass/Background, Portal, Chart,
Logo Outro, Magnetic)
- flowchart-vertical preview generated and uploaded to CDN
This commit is contained in:
@@ -10,12 +10,17 @@ export type {
|
||||
ComponentItem,
|
||||
RegistryManifestEntry,
|
||||
RegistryManifest,
|
||||
BlockCategory,
|
||||
BlockCategoryMeta,
|
||||
BlockParam,
|
||||
} from "./types.js";
|
||||
|
||||
export {
|
||||
ITEM_TYPES,
|
||||
FILE_TYPES,
|
||||
ITEM_TYPE_DIRS,
|
||||
BLOCK_CATEGORIES,
|
||||
resolveBlockCategory,
|
||||
isExampleItem,
|
||||
isBlockItem,
|
||||
isComponentItem,
|
||||
|
||||
@@ -77,6 +77,17 @@ export interface ExampleItem extends RegistryItemBase {
|
||||
duration: number;
|
||||
}
|
||||
|
||||
export interface BlockParam {
|
||||
key: string;
|
||||
label: string;
|
||||
type: "color" | "text" | "number" | "select";
|
||||
default: string;
|
||||
options?: { label: string; value: string }[];
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
}
|
||||
|
||||
/** Sub-composition block — installed by `hyperframes add <name>`. */
|
||||
export interface BlockItem extends RegistryItemBase {
|
||||
type: "hyperframes:block";
|
||||
@@ -84,6 +95,8 @@ export interface BlockItem extends RegistryItemBase {
|
||||
dimensions: RegistryItemDimensions;
|
||||
/** Duration in seconds (required for blocks). */
|
||||
duration: number;
|
||||
/** Customizable parameters with CSS variable mapping. */
|
||||
params?: BlockParam[];
|
||||
}
|
||||
|
||||
/** Effect / snippet — merged into an existing composition. */
|
||||
@@ -159,6 +172,45 @@ const _fileTypesExhaustive: _AssertFileTypesExhaustive = true;
|
||||
void _itemTypesExhaustive;
|
||||
void _fileTypesExhaustive;
|
||||
|
||||
// ── Block categories ───────────────────────────────────────────────────────
|
||||
|
||||
export type BlockCategory =
|
||||
| "vfx"
|
||||
| "transitions"
|
||||
| "social"
|
||||
| "data"
|
||||
| "scenes"
|
||||
| "captions"
|
||||
| "effects";
|
||||
|
||||
export interface BlockCategoryMeta {
|
||||
id: BlockCategory;
|
||||
label: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export const BLOCK_CATEGORIES: BlockCategoryMeta[] = [
|
||||
{ id: "captions", label: "Captions", color: "cyan" },
|
||||
{ id: "vfx", label: "VFX", color: "purple" },
|
||||
{ id: "transitions", label: "Transitions", color: "blue" },
|
||||
{ id: "effects", label: "Effects", color: "rose" },
|
||||
{ id: "social", label: "Social", color: "pink" },
|
||||
{ id: "data", label: "Data", color: "green" },
|
||||
{ id: "scenes", label: "Scenes", color: "amber" },
|
||||
];
|
||||
|
||||
export function resolveBlockCategory(tags: string[] | undefined): BlockCategory {
|
||||
if (!tags || tags.length === 0) return "scenes";
|
||||
const set = new Set(tags);
|
||||
if (set.has("captions") || set.has("caption-style")) return "captions";
|
||||
if (set.has("transition")) return "transitions";
|
||||
if (set.has("social") || set.has("overlay")) return "social";
|
||||
if (set.has("data") || set.has("chart") || set.has("map")) return "data";
|
||||
if (set.has("html-in-canvas") || set.has("webgl") || set.has("shader")) return "vfx";
|
||||
if (set.has("effect") || set.has("grain") || set.has("vignette")) return "effects";
|
||||
return "scenes";
|
||||
}
|
||||
|
||||
// ── Type guards ─────────────────────────────────────────────────────────────
|
||||
|
||||
export function isExampleItem(item: RegistryItem): item is ExampleItem {
|
||||
|
||||
Reference in New Issue
Block a user