From 590c192498ed738941380da7b3a2f6211966ba94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Mon, 28 Sep 2026 22:03:59 +0000 Subject: [PATCH] feat(catalog): add 3D objects, cursors, snow, starfield and paper transitions (#4349) * feat(catalog): shelve 3D objects and cursors in their own catalog sections Carries the generator grouping rules from #4310 and #4308. * feat(registry): add a starfield ambient overlay From #4313. * feat(registry): add a falling snow ambient overlay From #4331. * feat(registry): add a torn-paper-rip transition From #4321. * feat(registry): add a paper-collage-reveal transition From #4322. * feat(registry): add a curtain-reveal transition From #4323. * feat(registry): add 3D objects: product turntable, glass hero, exploded stack, extruded logo From #4310. * feat(registry): add eight cursor animations and the dart cursor From #4308. * fix(catalog): find items by everyday editor words and accept a bare search word From #4311. * chore(registry): remove the simulated-cursor component The Cursors section's new pointer animations replace it (from #4308). * fix(registry): take cursor-zoom-follow's screenshot from runtime variables only The declared default is empty, so page markup never becomes an image URL. Clears the code-scanning alert raised on #4308. * docs(cli): show a catalog search example that finds items "smoke" matches nothing in the catalog; "crossfade" finds fade-through. * chore(ci): allow the simulated-cursor removal in the deletion guard * fix(ci): skip tracked files missing from disk in the player CDN pin check Catalog regeneration removes a deleted item's pages before the publish PR untracks them, so the check crashed on every catalog deletion PR. * chore(cli): drop comments that narrate catalog search history * fix(registry): drag-drop keeps the family arrow and shows the drop slot only while hovering * fix(registry): agent cursor labels its steps in an accent tag, no glow or sparkles, in 4.8 s * fix(registry): annotate cursor draws a tapered marker stroke and clears the circled value * fix(registry): show real file thumbnails and end the context menu demo sooner * fix(registry): give marquee select real photos, a Finder-blue marquee and a tighter loop * fix(registry): centre the text-select toolbar on the selection and tighten its timing * fix(registry): selection cursors default to the macOS system blue * style(registry): format the agent and annotate cursor sources * fix(registry): dart-cursor stops covering the choice it makes and shows the export finishing * fix(registry): frame the product turntable fully and light it with two studio softboxes * fix(registry): touch-indicator taps like a real phone and the post it taps gets liked * fix(registry): press-ripple confirms with a check and small click rings at the cursor * fix(registry): exploded stack separates at once and marks each layer in blue as it is labelled * fix(registry): extruded logo settles facing the camera, set in Geist Bold with a neutral rim * fix(registry): magnetic cursor docks its toolbar on the selection and ends after the press * style(registry): format the exploded stack source * fix(registry): glyph trail becomes a tutorial cursor path with numbered steps on a settings screen * fix(registry): make glass-hero a clear lens that shows the headline through it * fix(registry): snow reads as real snowfall with bokeh flakes over a winter title card * fix(registry): oversized cursor is a 3.5x arrow that clicks a real editor toggle on * fix(registry): starfield reads as a drifting night sky over a real title card * style(registry): format the glass hero source * fix(registry): make the paper tear show a white fibrous edge and lift the torn sheet away * fix(registry): curtain reveal draws velvet folds that gather onto a title card * fix(registry): make every zoom-follow click change the screen and read at zoom * fix(registry): paper collage pieces stay opaque, tear with deckled grain and lift away on an arc * refactor(registry): drop dead code and correct stale comments in reworked items * fix(registry): agent cursor scrubs cleanly, docs match press-ripple, fictional demo names * docs(registry): catalog notes say oversized-cursor exits and how it differs from press-ripple * docs(registry): plain lowercase comments in oversized-cursor and touch-indicator * docs(registry): oversized-cursor names CLICK_AT as the click cue --- docs/catalog-gallery.css | 3 +- packages/cli/src/commands/catalog.test.ts | 22 + packages/cli/src/commands/catalog.ts | 12 +- packages/cli/src/registry/localSearch.test.ts | 55 + .../blocks/exploded-stack/exploded-stack.html | 409 +++++++ .../blocks/exploded-stack/registry-item.json | 29 + .../assets/fonts/Geist-Bold.typeface.json | 557 +++++++++ .../extruded-logo/assets/fonts/Geist-OFL.txt | 92 ++ .../blocks/extruded-logo/extruded-logo.html | 331 ++++++ .../blocks/extruded-logo/registry-item.json | 30 + registry/blocks/glass-hero/glass-hero.html | 281 +++++ registry/blocks/glass-hero/registry-item.json | 20 + .../product-turntable/product-turntable.html | 363 ++++++ .../product-turntable/registry-item.json | 20 + registry/blocks/snow/demo.html | 166 +++ registry/blocks/snow/registry-item.json | 60 + registry/blocks/snow/snow.html | 204 ++++ registry/blocks/starfield/demo.html | 118 ++ registry/blocks/starfield/registry-item.json | 75 ++ registry/blocks/starfield/starfield.html | 187 +++ .../transitions-dissolve/registry-item.json | 2 +- registry/components/CATALOG.md | 10 +- .../components/agent-cursor/agent-cursor.html | 398 +++++++ registry/components/agent-cursor/demo.html | 253 ++++ .../agent-cursor/registry-item.json | 55 + .../before-after-wipe/registry-item.json | 12 +- .../components/count-up/registry-item.json | 4 +- .../cursor-annotate/cursor-annotate.html | 494 ++++++++ registry/components/cursor-annotate/demo.html | 176 +++ .../cursor-annotate/registry-item.json | 87 ++ .../cursor-context-menu.html | 562 +++++++++ .../components/cursor-context-menu/demo.html | 69 ++ .../cursor-context-menu/registry-item.json | 52 + .../cursor-drag-drop/cursor-drag-drop.html | 464 ++++++++ .../components/cursor-drag-drop/demo.html | 64 + .../cursor-drag-drop/registry-item.json | 49 + .../components/cursor-glyph-trail/README.md | 35 +- .../cursor-glyph-trail.html | 989 ++++++++++------ .../components/cursor-glyph-trail/demo.html | 18 +- .../cursor-glyph-trail/registry-item.json | 36 +- .../cursor-marquee-select.html | 1048 +++++++++++++++++ .../cursor-marquee-select/demo.html | 64 + .../cursor-marquee-select/registry-item.json | 76 ++ .../cursor-text-select.html | 440 +++++++ .../components/cursor-text-select/demo.html | 69 ++ .../cursor-text-select/registry-item.json | 52 + .../cursor-zoom-follow.html | 720 +++++++++++ .../components/cursor-zoom-follow/demo.html | 75 ++ .../cursor-zoom-follow/registry-item.json | 128 ++ .../curtain-reveal/curtain-reveal.html | 377 ++++++ registry/components/curtain-reveal/demo.html | 106 ++ .../curtain-reveal/registry-item.json | 55 + .../components/dart-cursor/dart-cursor.html | 357 ++++++ registry/components/dart-cursor/demo.html | 326 +++++ .../components/dart-cursor/registry-item.json | 115 ++ .../fade-through/registry-item.json | 2 +- registry/components/magnetic-cursor/demo.html | 124 ++ .../magnetic-cursor/magnetic-cursor.html | 427 +++++++ .../magnetic-cursor/registry-item.json | 51 + .../components/oversized-cursor/README.md | 12 +- .../components/oversized-cursor/demo.html | 298 ++++- .../oversized-cursor/oversized-cursor.html | 168 ++- .../oversized-cursor/registry-item.json | 4 +- .../components/paper-collage-reveal/demo.html | 197 ++++ .../paper-collage-reveal.html | 441 +++++++ .../paper-collage-reveal/registry-item.json | 53 + registry/components/press-ripple/README.md | 54 +- registry/components/press-ripple/demo.html | 19 +- .../components/press-ripple/press-ripple.html | 225 ++-- .../press-ripple/registry-item.json | 18 +- .../components/simulated-cursor/demo.html | 237 ---- .../simulated-cursor/registry-item.json | 80 -- .../simulated-cursor/simulated-cursor.html | 141 --- registry/components/torn-paper-rip/demo.html | 250 ++++ .../torn-paper-rip/registry-item.json | 53 + .../torn-paper-rip/torn-paper-rip.html | 412 +++++++ registry/components/touch-indicator/demo.html | 371 ++++-- .../touch-indicator/registry-item.json | 4 +- .../touch-indicator/touch-indicator.html | 206 +--- registry/registry.json | 4 - scripts/check-no-main-deletions.mjs | 6 + scripts/generate-catalog-pages.test.ts | 57 + scripts/generate-catalog-pages.ts | 39 +- scripts/player-cdn-pin.test.ts | 31 +- scripts/sync-docs-catalog.mjs | 9 +- 85 files changed, 13451 insertions(+), 1413 deletions(-) create mode 100644 registry/blocks/exploded-stack/exploded-stack.html create mode 100644 registry/blocks/exploded-stack/registry-item.json create mode 100644 registry/blocks/extruded-logo/assets/fonts/Geist-Bold.typeface.json create mode 100644 registry/blocks/extruded-logo/assets/fonts/Geist-OFL.txt create mode 100644 registry/blocks/extruded-logo/extruded-logo.html create mode 100644 registry/blocks/extruded-logo/registry-item.json create mode 100644 registry/blocks/glass-hero/glass-hero.html create mode 100644 registry/blocks/glass-hero/registry-item.json create mode 100644 registry/blocks/product-turntable/product-turntable.html create mode 100644 registry/blocks/product-turntable/registry-item.json create mode 100644 registry/blocks/snow/demo.html create mode 100644 registry/blocks/snow/registry-item.json create mode 100644 registry/blocks/snow/snow.html create mode 100644 registry/blocks/starfield/demo.html create mode 100644 registry/blocks/starfield/registry-item.json create mode 100644 registry/blocks/starfield/starfield.html create mode 100644 registry/components/agent-cursor/agent-cursor.html create mode 100644 registry/components/agent-cursor/demo.html create mode 100644 registry/components/agent-cursor/registry-item.json create mode 100644 registry/components/cursor-annotate/cursor-annotate.html create mode 100644 registry/components/cursor-annotate/demo.html create mode 100644 registry/components/cursor-annotate/registry-item.json create mode 100644 registry/components/cursor-context-menu/cursor-context-menu.html create mode 100644 registry/components/cursor-context-menu/demo.html create mode 100644 registry/components/cursor-context-menu/registry-item.json create mode 100644 registry/components/cursor-drag-drop/cursor-drag-drop.html create mode 100644 registry/components/cursor-drag-drop/demo.html create mode 100644 registry/components/cursor-drag-drop/registry-item.json create mode 100644 registry/components/cursor-marquee-select/cursor-marquee-select.html create mode 100644 registry/components/cursor-marquee-select/demo.html create mode 100644 registry/components/cursor-marquee-select/registry-item.json create mode 100644 registry/components/cursor-text-select/cursor-text-select.html create mode 100644 registry/components/cursor-text-select/demo.html create mode 100644 registry/components/cursor-text-select/registry-item.json create mode 100644 registry/components/cursor-zoom-follow/cursor-zoom-follow.html create mode 100644 registry/components/cursor-zoom-follow/demo.html create mode 100644 registry/components/cursor-zoom-follow/registry-item.json create mode 100644 registry/components/curtain-reveal/curtain-reveal.html create mode 100644 registry/components/curtain-reveal/demo.html create mode 100644 registry/components/curtain-reveal/registry-item.json create mode 100644 registry/components/dart-cursor/dart-cursor.html create mode 100644 registry/components/dart-cursor/demo.html create mode 100644 registry/components/dart-cursor/registry-item.json create mode 100644 registry/components/magnetic-cursor/demo.html create mode 100644 registry/components/magnetic-cursor/magnetic-cursor.html create mode 100644 registry/components/magnetic-cursor/registry-item.json create mode 100644 registry/components/paper-collage-reveal/demo.html create mode 100644 registry/components/paper-collage-reveal/paper-collage-reveal.html create mode 100644 registry/components/paper-collage-reveal/registry-item.json delete mode 100644 registry/components/simulated-cursor/demo.html delete mode 100644 registry/components/simulated-cursor/registry-item.json delete mode 100644 registry/components/simulated-cursor/simulated-cursor.html create mode 100644 registry/components/torn-paper-rip/demo.html create mode 100644 registry/components/torn-paper-rip/registry-item.json create mode 100644 registry/components/torn-paper-rip/torn-paper-rip.html diff --git a/docs/catalog-gallery.css b/docs/catalog-gallery.css index e72bbd70c7..88caaa424b 100644 --- a/docs/catalog-gallery.css +++ b/docs/catalog-gallery.css @@ -52,13 +52,14 @@ #navigation-items li[data-group-tag] { --catalog-desc:""; } #navigation-items li[data-group-tag]::after { content:var(--catalog-desc); display:block; padding:0 12px 8px 40px; font-size:11px; line-height:1.5; color:var(--hf-text-secondary); } -#navigation-items li[data-title="3D motion"][data-group-tag] { --catalog-desc:"Three.js scenes: orbiting cards, particle fields, and depth-lit product shots."; } +#navigation-items li[data-title="3D"][data-group-tag] { --catalog-desc:"Three.js scenes and objects: camera moves, product turntables, glass, exploded layers."; } #navigation-items li[data-title="Carousels"][data-group-tag] { --catalog-desc:"Image cards that circle, orbit, or sweep a path across the frame."; } #navigation-items li[data-title="Text & captions"][data-group-tag] { --catalog-desc:"Word-by-word caption reveals, highlights, and kinetic type."; } #navigation-items li[data-title="Code"][data-group-tag] { --catalog-desc:"Code snippets that type, diff, highlight, and morph on screen."; } #navigation-items li[data-title="Transitions"][data-group-tag] { --catalog-desc:"Cuts between shots: zooms, warps, glitches, light leaks."; } #navigation-items li[data-title="Data & charts"][data-group-tag] { --catalog-desc:"Bar, line, and progress charts that animate their own data in."; } #navigation-items li[data-title="Scenes & demos"][data-group-tag] { --catalog-desc:"Full scenes: app showcases, chat exchanges, product demos."; } +#navigation-items li[data-title="Cursors"][data-group-tag] { --catalog-desc:"Pointers that glide, click, drag, select, and steer the eye across a UI."; } #navigation-items li[data-title="Motion & effects"][data-group-tag] { --catalog-desc:"General-purpose motion: hovers, pops, blurs, grids, paths."; } #navigation-items li[data-title="Surfaces"][data-group-tag] { --catalog-desc:"Background textures and screen treatments: grain, halftone, glass."; } #navigation-items li[data-title="Blocks"][data-group-tag] { --catalog-desc:"Flowcharts, sketched frames, speech bubbles, and outro cards."; } diff --git a/packages/cli/src/commands/catalog.test.ts b/packages/cli/src/commands/catalog.test.ts index 03b43fd972..2b4d1708ca 100644 --- a/packages/cli/src/commands/catalog.test.ts +++ b/packages/cli/src/commands/catalog.test.ts @@ -376,6 +376,28 @@ describe("catalog --json meaning search", () => { expect(envelope.shown).toBe(1); }); + it("treats a stray positional the same as --query, rather than dropping it", async () => { + state.modelStatus = "declined"; + state.ranking = null; + state.registry = [block("fade-through", ["transition"]), block("count-up", ["number"])]; + + const envelope = await runEnvelope({ words: "transition" }); + + expect(envelope.tier).toBe("words"); + expect(envelope.shown).toBe(1); + }); + + it("prefers an explicit --query over a positional", async () => { + state.modelStatus = "declined"; + state.ranking = null; + state.registry = [block("fade-through", ["transition"]), block("count-up", ["number"])]; + + const envelope = await runEnvelope({ query: "number", words: "transition" }); + + expect(envelope.shown).toBe(1); + expect(envelope.report_gap).toContain("number"); + }); + it("carries an on-device runtime failure into the JSON envelope", async () => { state.rankingError = new Error("model could not load"); diff --git a/packages/cli/src/commands/catalog.ts b/packages/cli/src/commands/catalog.ts index 4b7fd8a8c2..7e5ff21652 100644 --- a/packages/cli/src/commands/catalog.ts +++ b/packages/cli/src/commands/catalog.ts @@ -7,6 +7,7 @@ export const examples: Example[] = [ ["Filter by tag", "hyperframes catalog --type block --tag social"], ["Machine-readable JSON", "hyperframes catalog --json"], ["Interactive picker (install on select)", "hyperframes catalog --human-friendly"], + ["Search (positional, same as --query)", 'hyperframes catalog "crossfade"'], ]; import * as clack from "@clack/prompts"; @@ -162,6 +163,11 @@ export default defineCommand({ description: "Browse and install blocks and components from the registry", }, args: { + words: { + type: "positional", + description: "Search words, same as --query (e.g. `catalog crossfade`)", + required: false, + }, type: { type: "string", description: 'Filter by type: "block" or "component"', @@ -181,7 +187,8 @@ export default defineCommand({ query: { type: "string", description: - "Search by meaning when the on-device model is on, otherwise by name, title, description and tags", + "Search by meaning when the on-device model is on, otherwise by name, title, description and tags. " + + "A bare positional word works the same way (e.g. `catalog crossfade`).", }, yes: { type: "boolean", @@ -235,7 +242,8 @@ export default defineCommand({ ? items.filter((item) => item.tags?.some((t) => t.toLowerCase() === tagFilter)) : items; - const query = typeof args.query === "string" ? args.query.trim() : ""; + const query = + (typeof args.query === "string" ? args.query.trim() : "") || args.words?.trim() || ""; // Collected rather than only printed, so --json can carry the same reasons // the terminal shows. A machine that asked for a tier deserves to be told // it did not run. diff --git a/packages/cli/src/registry/localSearch.test.ts b/packages/cli/src/registry/localSearch.test.ts index 8d31029c01..1dce7a77d2 100644 --- a/packages/cli/src/registry/localSearch.test.ts +++ b/packages/cli/src/registry/localSearch.test.ts @@ -1,3 +1,6 @@ +import { readFileSync, readdirSync } from "node:fs"; +import { dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; import { describe, expect, it } from "vitest"; import { hasNoSearchableTokens, rankByWords, searchByWords, tokenize } from "./localSearch.js"; @@ -233,3 +236,55 @@ describe("the two spellings of a compound word find the same items", () => { expect(searchByWords("typewriter", typing, fieldsOf)[0]?.name).toBe("typewriter"); }); }); + +// ── Catalog vocabulary regression, against the real registry ──────────────── +// A gap here is a tag gap, not a ranker gap: fix it in a registry-item.json. + +describe("editor vocabulary finds the real catalog items that already do it", () => { + const registryDir = resolve(dirname(fileURLToPath(import.meta.url)), "../../../../registry"); + + interface RealItem { + name: string; + title: string; + description: string; + tags: string[]; + } + + function loadRealCatalog(): RealItem[] { + const items: RealItem[] = []; + for (const type of ["blocks", "components"]) { + const typeDir = join(registryDir, type); + for (const entry of readdirSync(typeDir, { withFileTypes: true })) { + if (!entry.isDirectory()) continue; + const name = entry.name; + const manifestPath = join(typeDir, name, "registry-item.json"); + const manifest = JSON.parse(readFileSync(manifestPath, "utf8")) as Partial; + items.push({ + name: manifest.name ?? name, + title: manifest.title ?? "", + description: manifest.description ?? "", + tags: manifest.tags ?? [], + }); + } + } + return items; + } + + const realItems = loadRealCatalog(); + // Mirrors how catalog.ts:609-612 splits an item's text for the word tier. + const realFieldsOf = (item: RealItem) => ({ + strong: `${item.name} ${item.title}`, + weak: `${item.description} ${item.tags.join(" ")}`, + }); + + it.each([ + ["crossfade", "fade-through"], + ["crossfade", "transitions-dissolve"], + ["cross dissolve", "transitions-dissolve"], + ["countdown timer", "count-up"], + ["split screen comparison", "comparison-split"], + ])("ranks %s -> %s in the top 3", (query, expectedName) => { + const ranked = searchByWords(query, realItems, realFieldsOf).slice(0, 3); + expect(ranked.map((item) => item.name)).toContain(expectedName); + }); +}); diff --git a/registry/blocks/exploded-stack/exploded-stack.html b/registry/blocks/exploded-stack/exploded-stack.html new file mode 100644 index 0000000000..ecec9314f9 --- /dev/null +++ b/registry/blocks/exploded-stack/exploded-stack.html @@ -0,0 +1,409 @@ + + + + + + + Exploded Stack + + + + +
+ + +
+
+
+ + + + + + diff --git a/registry/blocks/exploded-stack/registry-item.json b/registry/blocks/exploded-stack/registry-item.json new file mode 100644 index 0000000000..9c26cb60eb --- /dev/null +++ b/registry/blocks/exploded-stack/registry-item.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "exploded-stack", + "type": "hyperframes:block", + "title": "Exploded Stack", + "description": "Isometric layer plates explode apart with a label beside each layer, hold, then collapse back into one stack. Built for architecture and system diagrams.", + "tags": [ + "3d-object", + "three-js", + "webgl", + "isometric", + "exploded-view", + "layers", + "diagram", + "architecture" + ], + "dimensions": { + "width": 1920, + "height": 1080 + }, + "duration": 5, + "files": [ + { + "path": "exploded-stack.html", + "target": "compositions/exploded-stack.html", + "type": "hyperframes:composition" + } + ] +} diff --git a/registry/blocks/extruded-logo/assets/fonts/Geist-Bold.typeface.json b/registry/blocks/extruded-logo/assets/fonts/Geist-Bold.typeface.json new file mode 100644 index 0000000000..6bbc973bc4 --- /dev/null +++ b/registry/blocks/extruded-logo/assets/fonts/Geist-Bold.typeface.json @@ -0,0 +1,557 @@ +{ + "glyphs": { + " ": { "ha": 317, "x_min": 0, "x_max": 0, "o": "" }, + "!": { + "ha": 357, + "x_min": 65, + "x_max": 292, + "o": "m 111 315 q 96 429 104 362 q 82 565 88 496 q 76 689 76 633 l 76 986 l 286 986 l 286 689 q 281 565 286 633 q 267 429 275 496 q 253 315 260 362 m 65 0 l 65 212 l 292 212 l 292 0" + }, + "\"": { + "ha": 542, + "x_min": 58, + "x_max": 483, + "o": "m 88 599 l 58 869 l 58 986 l 224 986 l 214 599 m 328 599 l 318 986 l 483 986 l 483 869 l 454 599" + }, + "#": { + "ha": 818, + "x_min": 4, + "x_max": 810, + "o": "m 403 0 l 554 986 l 744 986 l 593 0 m 4 226 l 28 393 l 758 393 l 735 226 m 69 0 l 222 986 l 412 986 l 260 0 m 57 585 l 81 750 l 810 750 l 786 585" + }, + "$": { + "ha": 931, + "x_min": 72, + "x_max": 858, + "o": "m 415 -125 l 415 1111 l 529 1111 l 529 -125 m 485 -15 q 270 27 360 -15 q 130 146 181 69 q 72 324 79 222 l 281 335 q 314 238 289 278 q 381 177 339 197 q 488 157 424 157 q 575 169 539 157 q 630 206 611 181 q 649 268 649 231 q 633 327 649 301 q 570 374 617 353 q 433 415 524 396 q 235 478 310 443 q 126 568 160 514 q 92 704 92 622 q 135 856 92 790 q 259 958 178 921 q 453 994 340 994 q 656 953 572 994 q 785 838 739 911 q 843 667 832 764 l 636 658 q 608 744 631 707 q 545 803 585 782 q 450 824 506 824 q 340 792 381 824 q 300 711 300 761 q 317 651 300 675 q 378 609 335 626 q 500 575 422 592 q 713 507 635 549 q 825 408 792 465 q 858 278 858 351 q 812 122 858 188 q 683 20 767 56 q 485 -15 599 -15" + }, + "%": { + "ha": 1146, + "x_min": 51, + "x_max": 1096, + "o": "m 282 508 q 117 569 182 508 q 51 753 51 629 q 117 938 51 878 q 282 997 182 997 q 447 938 382 997 q 511 753 511 878 q 447 569 511 629 q 282 508 382 508 m 282 614 q 349 649 326 614 q 371 753 371 683 q 349 857 371 822 q 282 892 326 892 q 216 857 239 892 q 193 753 193 822 q 216 649 193 683 q 282 614 239 614 m 865 -11 q 700 49 765 -11 q 635 233 635 110 q 700 418 635 358 q 865 478 765 478 q 1031 418 965 478 q 1096 233 1096 358 q 1031 49 1096 110 q 865 -11 965 -11 m 865 94 q 932 129 910 94 q 954 233 954 164 q 932 338 954 303 q 865 372 910 372 q 799 338 822 372 q 776 233 776 303 q 799 129 776 164 q 865 94 822 94 m 182 0 l 838 986 l 965 986 l 310 0" + }, + "&": { + "ha": 985, + "x_min": 50, + "x_max": 964, + "o": "m 403 -22 q 140 47 231 -22 q 50 243 50 115 q 70 357 50 307 q 136 451 90 407 q 256 540 182 496 q 201 609 224 575 q 165 678 178 643 q 153 757 153 714 q 230 940 153 872 q 451 1008 307 1008 q 617 978 550 1008 q 717 894 683 947 q 750 772 750 840 q 698 624 750 685 q 538 503 646 564 l 693 308 q 729 456 728 360 l 940 435 q 906 282 935 356 q 829 156 876 208 l 964 0 l 718 0 l 682 43 q 565 -4 638 14 q 403 -22 492 -22 m 419 158 q 497 168 465 158 q 546 192 528 178 l 365 414 q 290 346 314 381 q 267 267 267 311 q 306 188 267 218 q 419 158 346 158 m 431 625 q 491 666 468 646 q 525 707 514 686 q 536 754 536 728 q 515 810 536 790 q 456 831 493 831 q 391 808 414 831 q 368 749 368 786 q 374 710 368 729 q 394 671 379 692 q 431 625 408 650" + }, + "'": { + "ha": 282, + "x_min": 58, + "x_max": 224, + "o": "m 79 599 l 58 869 l 58 986 l 224 986 l 224 869 l 203 599" + }, + "(": { + "ha": 449, + "x_min": 58, + "x_max": 432, + "o": "m 246 -153 q 58 444 58 143 q 246 1042 58 747 l 432 1042 q 264 444 264 743 q 306 147 264 296 q 432 -153 349 -3" + }, + ")": { + "ha": 449, + "x_min": 17, + "x_max": 390, + "o": "m 201 -153 l 17 -153 q 143 147 101 -3 q 185 444 185 296 q 17 1042 185 743 l 201 1042 q 390 444 390 747 q 201 -153 390 143" + }, + "*": { + "ha": 586, + "x_min": 51, + "x_max": 535, + "o": "m 222 504 l 114 567 l 193 688 l 51 685 l 51 824 l 193 822 l 114 943 l 222 1004 l 293 879 l 365 1004 l 474 943 l 393 822 l 535 824 l 535 685 l 393 688 l 474 567 l 365 504 l 293 631" + }, + "+": { + "ha": 792, + "x_min": 56, + "x_max": 736, + "o": "m 311 58 l 311 739 l 481 739 l 481 58 m 56 314 l 56 482 l 736 482 l 736 314" + }, + ",": { + "ha": 328, + "x_min": 51, + "x_max": 278, + "o": "m 67 -219 l 142 0 l 51 0 l 51 212 l 278 212 l 278 22 l 181 -219" + }, + "-": { "ha": 579, "x_min": 51, "x_max": 528, "o": "m 51 319 l 51 490 l 528 490 l 528 319" }, + ".": { "ha": 328, "x_min": 51, "x_max": 278, "o": "m 51 0 l 51 212 l 278 212 l 278 0" }, + "/": { + "ha": 725, + "x_min": 44, + "x_max": 661, + "o": "m 44 -153 l 456 1042 l 661 1042 l 250 -153" + }, + "0": { + "ha": 971, + "x_min": 65, + "x_max": 906, + "o": "m 486 -22 q 261 40 356 -22 q 116 217 167 101 q 65 492 65 332 q 117 767 65 651 q 262 946 168 883 q 486 1008 356 1008 q 709 946 615 1008 q 854 767 803 883 q 906 492 906 651 q 855 218 906 333 q 710 40 804 103 q 486 -22 615 -22 m 486 156 q 635 240 583 156 q 688 492 688 325 q 665 679 688 604 q 597 792 642 754 q 486 831 551 831 q 374 792 419 831 q 306 679 329 754 q 283 492 283 604 q 335 240 283 325 q 486 156 388 156" + }, + "1": { + "ha": 624, + "x_min": 53, + "x_max": 478, + "o": "m 267 0 l 267 649 l 53 649 l 53 803 l 138 803 q 237 820 199 803 q 292 877 275 838 q 310 986 310 917 l 478 986 l 478 0" + }, + "2": { + "ha": 907, + "x_min": 81, + "x_max": 828, + "o": "m 81 0 q 115 219 81 126 q 226 386 149 312 q 431 526 303 460 q 538 588 499 561 q 594 643 578 615 q 611 708 611 671 q 595 772 611 744 q 549 815 579 799 q 472 831 518 831 q 353 787 397 831 q 299 660 310 743 l 82 672 q 197 919 96 829 q 469 1008 297 1008 q 663 971 583 1008 q 785 867 743 933 q 828 711 828 800 q 802 581 828 633 q 719 483 776 528 q 569 389 662 439 q 393 272 450 325 q 332 178 336 218 l 828 178 l 828 0" + }, + "3": { + "ha": 903, + "x_min": 61, + "x_max": 842, + "o": "m 450 -22 q 167 62 267 -22 q 61 289 68 146 l 276 297 q 328 190 283 224 q 450 156 374 156 q 539 170 500 156 q 601 215 578 185 q 624 292 624 246 q 575 398 624 362 q 443 433 526 433 l 356 433 l 356 590 l 443 590 q 549 617 507 590 q 592 710 592 644 q 557 798 592 765 q 447 831 522 831 q 335 800 372 831 q 289 721 297 769 l 76 732 q 187 933 90 857 q 447 1008 283 1008 q 644 975 564 1008 q 767 879 725 942 q 808 732 808 817 q 751 588 808 644 q 585 510 693 531 l 585 533 q 775 449 708 515 q 842 276 842 382 q 793 116 842 183 q 657 13 744 49 q 450 -22 569 -22" + }, + "4": { + "ha": 911, + "x_min": 33, + "x_max": 850, + "o": "m 524 0 l 524 188 l 33 188 l 33 356 l 483 986 l 735 986 l 735 365 l 850 365 l 850 188 l 735 188 l 735 0 m 257 365 l 524 365 l 524 726" + }, + "5": { + "ha": 932, + "x_min": 78, + "x_max": 854, + "o": "m 464 -22 q 260 14 343 -22 q 131 117 176 50 q 78 272 85 183 l 292 282 q 348 187 304 218 q 464 156 392 156 q 591 201 544 156 q 638 328 638 247 q 616 419 638 381 q 556 481 594 458 q 462 503 517 503 q 360 476 403 503 q 300 410 317 450 l 89 410 l 157 986 l 786 986 l 786 808 l 336 808 l 300 521 l 276 542 q 335 603 300 578 q 418 644 371 629 q 522 658 465 658 q 699 615 625 658 q 814 497 774 572 q 854 328 854 422 q 806 142 854 221 q 669 20 757 62 q 464 -22 582 -22" + }, + "6": { + "ha": 918, + "x_min": 78, + "x_max": 839, + "o": "m 461 -22 q 249 32 335 -22 q 121 188 164 86 q 78 435 78 290 q 103 663 78 558 q 178 845 128 768 q 308 965 229 922 q 494 1008 388 1008 q 723 939 639 1008 q 835 750 807 869 l 639 736 q 590 808 622 782 q 494 835 558 835 q 342 750 397 835 q 279 489 286 665 l 250 494 q 299 569 265 535 q 384 626 332 604 q 506 647 436 647 q 681 607 606 647 q 798 494 757 567 q 839 325 839 422 q 792 137 839 214 q 660 19 744 60 q 461 -22 575 -22 m 460 146 q 583 194 536 146 q 629 322 629 242 q 609 414 629 375 q 552 475 589 453 q 467 497 515 497 q 375 475 415 497 q 312 414 335 453 q 290 322 290 375 q 311 231 290 271 q 370 168 332 190 q 460 146 408 146" + }, + "7": { + "ha": 756, + "x_min": 28, + "x_max": 756, + "o": "m 228 0 q 267 296 228 153 q 376 568 306 439 q 542 808 447 697 l 28 808 l 28 986 l 756 986 l 756 821 q 583 581 653 704 q 477 317 512 458 q 442 0 442 175" + }, + "8": { + "ha": 928, + "x_min": 50, + "x_max": 878, + "o": "m 464 -22 q 244 10 338 -22 q 101 108 151 43 q 50 268 50 174 q 119 451 50 379 q 304 542 189 522 l 307 514 q 154 590 211 532 q 97 738 97 649 q 140 879 97 818 q 265 974 183 940 q 464 1008 346 1008 q 662 974 581 1008 q 787 879 744 940 q 829 738 829 818 q 773 591 829 649 q 619 514 717 533 l 622 542 q 808 450 739 521 q 878 268 878 379 q 827 108 878 174 q 683 10 776 43 q 464 -22 590 -22 m 464 156 q 606 194 553 156 q 660 300 660 232 q 609 409 660 368 q 464 450 558 450 q 318 409 369 450 q 267 300 267 368 q 321 194 267 232 q 464 156 375 156 m 464 599 q 574 627 535 599 q 614 715 614 656 q 576 800 614 768 q 464 832 538 832 q 351 800 390 832 q 312 715 312 768 q 353 627 312 656 q 464 599 393 599" + }, + "9": { + "ha": 924, + "x_min": 78, + "x_max": 846, + "o": "m 436 -22 q 215 41 300 -22 q 94 222 131 104 l 297 235 q 347 173 312 194 q 436 151 382 151 q 590 228 540 151 q 639 482 639 304 l 667 469 q 565 358 629 396 q 406 321 500 321 q 235 362 308 321 q 119 478 161 403 q 78 651 78 553 q 124 841 78 761 q 253 965 169 921 q 447 1008 336 1008 q 670 952 582 1008 q 802 789 758 896 q 846 528 846 682 q 821 297 846 399 q 747 124 796 194 q 620 15 697 53 q 436 -22 543 -22 m 451 472 q 542 494 504 472 q 601 557 581 517 q 622 654 622 597 q 602 752 622 710 q 544 817 582 794 q 454 840 507 840 q 367 817 404 840 q 309 753 329 794 q 289 656 289 711 q 310 558 289 599 q 367 495 331 518 q 451 472 403 472" + }, + ":": { + "ha": 432, + "x_min": 103, + "x_max": 329, + "o": "m 103 0 l 103 212 l 329 212 l 329 0 m 103 494 l 103 707 l 329 707 l 329 494" + }, + ";": { + "ha": 432, + "x_min": 103, + "x_max": 329, + "o": "m 103 494 l 103 707 l 329 707 l 329 494 m 118 -219 l 193 0 l 103 0 l 103 212 l 329 212 l 329 22 l 232 -219" + }, + "<": { + "ha": 764, + "x_min": 56, + "x_max": 694, + "o": "m 694 31 l 56 301 l 56 510 l 694 781 l 694 600 l 140 367 l 140 444 l 694 211" + }, + "=": { + "ha": 767, + "x_min": 56, + "x_max": 711, + "o": "m 56 482 l 56 651 l 711 651 l 711 482 m 56 162 l 56 331 l 711 331 l 711 162" + }, + ">": { + "ha": 764, + "x_min": 69, + "x_max": 708, + "o": "m 69 31 l 69 211 l 624 444 l 624 367 l 69 600 l 69 781 l 708 510 l 708 301" + }, + "?": { + "ha": 821, + "x_min": 51, + "x_max": 771, + "o": "m 301 311 q 333 483 301 424 q 438 578 364 542 q 515 624 489 604 q 549 667 540 644 q 557 719 557 689 q 523 803 557 771 q 426 836 489 836 q 316 798 356 836 q 268 685 276 760 l 51 696 q 106 857 60 786 q 232 968 151 928 q 426 1008 312 1008 q 615 971 539 1008 q 731 868 692 933 q 771 719 771 803 q 753 618 771 660 q 699 543 736 576 q 599 475 661 510 q 528 411 549 444 q 508 311 508 378 m 289 0 l 289 212 l 515 212 l 515 0" + }, + "@": { + "ha": 1336, + "x_min": 58, + "x_max": 1278, + "o": "m 946 -101 q 780 -151 862 -135 q 608 -168 697 -168 q 312 -108 435 -168 q 124 66 189 -49 q 58 342 58 181 q 106 604 58 486 q 240 808 153 722 q 447 940 326 894 q 714 986 567 986 q 1010 925 883 986 q 1208 753 1138 864 q 1278 494 1278 643 q 1240 290 1278 376 q 1137 156 1203 203 q 983 108 1071 108 q 855 151 903 108 q 801 264 807 194 l 838 269 q 788 185 825 224 q 701 124 750 146 q 600 101 651 101 q 464 133 521 101 q 378 224 407 165 q 349 361 349 282 q 385 534 349 458 q 485 654 421 610 q 635 699 550 699 q 768 662 712 699 q 835 569 824 626 l 807 568 l 817 689 l 974 689 l 949 415 q 943 349 946 383 q 940 292 940 314 q 958 248 940 264 q 1006 232 975 232 q 1109 297 1071 232 q 1147 478 1147 361 q 1098 692 1147 606 q 951 821 1049 778 q 707 864 854 864 q 497 827 592 864 q 333 722 403 790 q 227 560 264 654 q 190 350 190 465 q 240 137 190 225 q 383 1 289 49 q 612 -46 478 -46 q 768 -32 696 -46 q 914 14 840 -18 m 643 239 q 723 264 690 239 q 773 331 756 289 q 790 422 790 372 q 778 495 790 464 q 739 544 765 526 q 671 561 712 561 q 594 537 626 561 q 545 470 562 512 q 528 375 528 428 q 556 276 528 314 q 643 239 583 239" + }, + "A": { + "ha": 1014, + "x_min": 26, + "x_max": 988, + "o": "m 26 0 l 382 986 l 632 986 l 988 0 l 768 0 l 696 210 l 317 210 l 244 0 m 376 383 l 638 383 l 507 764" + }, + "B": { + "ha": 976, + "x_min": 103, + "x_max": 906, + "o": "m 103 0 l 103 986 l 486 986 q 767 922 669 986 q 864 718 864 857 q 839 612 864 657 q 766 540 814 567 q 650 508 718 514 l 650 511 q 840 440 774 503 q 906 272 906 376 q 809 67 906 135 q 533 0 712 0 m 314 172 l 524 172 q 647 203 600 172 q 693 297 693 235 q 647 392 693 360 q 524 425 600 425 l 314 425 m 314 578 l 481 578 q 605 608 558 578 q 651 696 651 639 q 606 785 651 757 q 481 814 561 814 l 314 814" + }, + "C": { + "ha": 1019, + "x_min": 58, + "x_max": 968, + "o": "m 521 -22 q 281 39 386 -22 q 117 215 176 100 q 58 492 58 331 q 115 765 58 649 q 278 944 172 881 q 525 1008 383 1008 q 826 913 718 1008 q 964 642 933 818 l 744 633 q 672 778 728 726 q 525 831 617 831 q 390 789 446 831 q 306 671 335 747 q 276 492 276 594 q 306 312 276 388 q 392 196 336 236 q 524 156 447 156 q 678 212 624 156 q 747 368 733 268 l 968 360 q 892 154 949 239 q 742 24 835 69 q 521 -22 650 -22" + }, + "D": { + "ha": 1000, + "x_min": 103, + "x_max": 942, + "o": "m 103 0 l 103 986 l 443 986 q 812 858 683 986 q 942 492 942 729 q 815 128 942 256 q 451 0 688 0 m 314 178 l 443 178 q 655 255 586 178 q 724 493 724 332 q 655 731 724 654 q 443 808 586 808 l 314 808" + }, + "E": { + "ha": 864, + "x_min": 103, + "x_max": 800, + "o": "m 103 0 l 103 986 l 789 986 l 789 808 l 314 808 l 314 582 l 772 582 l 772 407 l 314 407 l 314 178 l 800 178 l 800 0" + }, + "F": { + "ha": 839, + "x_min": 103, + "x_max": 783, + "o": "m 103 0 l 103 986 l 783 986 l 783 808 l 197 808 l 314 929 l 314 478 l 197 569 l 758 569 l 758 394 l 197 394 l 314 486 l 314 0" + }, + "G": { + "ha": 1025, + "x_min": 58, + "x_max": 960, + "o": "m 514 -22 q 269 43 371 -22 q 113 224 168 108 q 58 492 58 340 q 114 757 58 640 q 274 941 169 874 q 526 1008 379 1008 q 742 966 654 1008 q 883 846 831 924 q 957 662 936 768 l 739 653 q 674 783 724 735 q 528 831 625 831 q 387 786 443 831 q 303 665 331 742 q 276 492 276 589 q 303 317 276 393 q 387 199 331 242 q 532 156 443 156 q 645 182 597 156 q 720 254 693 208 q 753 358 747 300 l 528 358 l 528 512 l 960 512 l 960 0 l 829 0 l 818 211 l 843 200 q 782 85 829 135 q 666 6 735 35 q 514 -22 597 -22" + }, + "H": { + "ha": 1001, + "x_min": 103, + "x_max": 899, + "o": "m 103 0 l 103 986 l 314 986 l 314 518 l 221 585 l 782 585 l 688 518 l 688 986 l 899 986 l 899 0 l 688 0 l 688 474 l 782 407 l 221 407 l 314 474 l 314 0" + }, + "I": { "ha": 417, "x_min": 103, "x_max": 314, "o": "m 103 0 l 103 986 l 314 986 l 314 0" }, + "J": { + "ha": 871, + "x_min": 68, + "x_max": 789, + "o": "m 429 -22 q 234 26 314 -22 q 112 159 154 75 q 68 351 69 243 l 281 361 q 321 206 282 256 q 429 156 360 156 q 539 204 500 156 q 578 354 578 253 l 578 986 l 789 986 l 789 354 q 744 154 789 239 q 618 24 699 69 q 429 -22 538 -22" + }, + "K": { + "ha": 957, + "x_min": 103, + "x_max": 940, + "o": "m 103 0 l 103 986 l 314 986 l 314 556 l 672 986 l 918 986 l 556 551 l 940 0 l 700 0 l 417 410 l 314 290 l 314 0" + }, + "L": { + "ha": 818, + "x_min": 103, + "x_max": 768, + "o": "m 103 0 l 103 986 l 314 986 l 314 57 l 197 178 l 768 178 l 768 0" + }, + "M": { + "ha": 1271, + "x_min": 103, + "x_max": 1168, + "o": "m 103 0 l 103 986 l 385 986 l 636 268 l 886 986 l 1168 986 l 1168 0 l 957 0 l 957 639 l 725 3 l 544 3 l 314 639 l 314 0" + }, + "N": { + "ha": 1042, + "x_min": 103, + "x_max": 939, + "o": "m 103 0 l 103 986 l 336 986 l 728 306 l 728 986 l 939 986 l 939 0 l 703 0 l 314 657 l 314 0" + }, + "O": { + "ha": 1078, + "x_min": 58, + "x_max": 1019, + "o": "m 539 -22 q 281 40 389 -22 q 116 218 174 103 q 58 492 58 333 q 116 766 58 650 q 281 945 174 882 q 539 1008 389 1008 q 797 945 689 1008 q 962 766 904 882 q 1019 492 1019 650 q 962 218 1019 333 q 797 40 904 103 q 539 -22 689 -22 m 538 156 q 680 195 621 156 q 770 310 739 235 q 801 492 801 385 q 770 674 801 599 q 680 790 739 750 q 538 831 621 831 q 397 790 456 831 q 308 674 339 750 q 276 492 276 599 q 308 310 276 385 q 398 195 339 235 q 538 156 457 156" + }, + "P": { + "ha": 933, + "x_min": 103, + "x_max": 876, + "o": "m 103 0 l 103 986 l 497 986 q 776 900 675 986 q 876 664 876 814 q 831 492 876 565 q 701 380 786 419 q 497 340 615 340 l 314 340 l 314 0 m 314 518 l 485 518 q 614 555 568 518 q 660 664 660 592 q 615 772 660 735 q 485 808 569 808 l 314 808" + }, + "Q": { + "ha": 1068, + "x_min": 58, + "x_max": 1010, + "o": "m 788 -86 l 711 10 q 634 -14 679 -6 q 535 -22 589 -22 q 282 44 389 -22 q 117 226 175 110 q 58 492 58 342 q 113 756 58 639 q 274 940 168 872 q 535 1008 381 1008 q 795 940 689 1008 q 956 756 901 872 q 1010 492 1010 639 q 963 250 1010 354 q 831 76 917 146 l 961 -86 m 535 156 q 568 158 553 156 q 597 165 583 160 l 460 333 l 635 333 l 707 238 q 770 338 749 276 q 792 492 792 400 q 765 659 792 582 q 681 783 738 736 q 535 831 624 831 q 388 783 444 831 q 303 659 331 736 q 276 492 276 582 q 303 326 276 403 q 388 202 331 249 q 535 156 446 156" + }, + "R": { + "ha": 968, + "x_min": 103, + "x_max": 899, + "o": "m 103 0 l 103 986 l 535 986 q 723 950 643 986 q 846 848 803 914 q 889 692 889 782 q 860 571 889 624 q 783 485 832 518 q 669 443 733 451 l 665 456 q 815 413 764 456 q 874 283 867 371 l 899 0 l 683 0 l 665 250 q 630 334 661 307 q 524 361 599 361 l 314 361 l 314 0 m 314 538 l 511 538 q 630 573 588 538 q 672 674 672 608 q 629 774 672 740 q 504 808 586 808 l 314 808" + }, + "S": { + "ha": 946, + "x_min": 72, + "x_max": 874, + "o": "m 493 -22 q 274 21 365 -22 q 131 142 182 64 q 72 325 79 219 l 285 335 q 319 235 293 276 q 388 174 344 194 q 496 153 432 153 q 585 165 549 153 q 642 203 622 178 q 661 267 661 229 q 644 327 661 301 q 581 374 628 353 q 442 417 533 396 q 238 482 315 446 q 126 573 161 518 q 92 711 92 628 q 135 867 92 800 q 262 971 179 933 q 461 1008 346 1008 q 668 965 583 1008 q 801 847 753 922 q 858 675 849 772 l 647 664 q 619 753 643 715 q 556 812 596 792 q 458 833 515 833 q 345 801 386 833 q 304 718 304 769 q 323 658 304 682 q 385 615 342 633 q 510 581 429 597 q 727 510 647 553 q 840 410 807 468 q 874 276 874 351 q 827 117 874 185 q 695 14 781 50 q 493 -22 610 -22" + }, + "T": { + "ha": 832, + "x_min": 15, + "x_max": 818, + "o": "m 310 0 l 310 808 l 15 808 l 15 986 l 818 986 l 818 808 l 522 808 l 522 0" + }, + "U": { + "ha": 976, + "x_min": 82, + "x_max": 894, + "o": "m 489 -22 q 273 24 364 -22 q 132 155 182 69 q 82 356 82 240 l 82 988 l 293 988 l 293 356 q 344 208 293 260 q 489 156 394 156 q 633 208 583 156 q 683 356 683 260 l 683 988 l 894 988 l 894 356 q 845 155 894 240 q 704 24 796 69 q 489 -22 612 -22" + }, + "V": { + "ha": 1014, + "x_min": 26, + "x_max": 988, + "o": "m 382 0 l 26 986 l 244 986 l 507 238 l 769 986 l 988 986 l 631 0" + }, + "W": { + "ha": 1410, + "x_min": 51, + "x_max": 1358, + "o": "m 318 0 l 51 986 l 272 986 l 442 292 l 612 986 l 797 986 l 969 292 l 1138 986 l 1358 986 l 1093 0 l 865 0 l 704 631 l 543 0" + }, + "X": { + "ha": 956, + "x_min": 17, + "x_max": 939, + "o": "m 17 0 l 351 494 l 19 986 l 264 986 l 479 654 l 689 986 l 935 986 l 603 497 l 939 0 l 693 0 l 476 338 l 262 0" + }, + "Y": { + "ha": 876, + "x_min": -10, + "x_max": 886, + "o": "m 333 0 l 333 383 l -10 986 l 224 986 l 439 589 l 653 986 l 886 986 l 544 383 l 544 0" + }, + "Z": { + "ha": 825, + "x_min": 38, + "x_max": 788, + "o": "m 38 0 l 38 172 l 507 808 l 60 808 l 60 986 l 769 986 l 769 814 l 290 178 l 788 178 l 788 0" + }, + "[": { + "ha": 542, + "x_min": 103, + "x_max": 525, + "o": "m 525 -153 l 103 -153 l 103 1042 l 525 1042 l 525 878 l 303 878 l 303 11 l 525 11" + }, + "\\": { + "ha": 696, + "x_min": 39, + "x_max": 657, + "o": "m 657 -153 l 450 -153 l 39 1042 l 244 1042" + }, + "]": { + "ha": 542, + "x_min": 17, + "x_max": 439, + "o": "m 17 -153 l 17 11 l 239 11 l 239 878 l 17 878 l 17 1042 l 439 1042 l 439 -153" + }, + "^": { + "ha": 640, + "x_min": 56, + "x_max": 585, + "o": "m 56 532 l 222 935 l 418 935 l 585 532 l 435 532 l 300 849 l 340 849 l 207 532" + }, + "_": { "ha": 779, "x_min": 51, "x_max": 728, "o": "m 51 -168 l 51 0 l 728 0 l 728 -168" }, + "`": { "ha": 386, "x_min": 51, "x_max": 335, "o": "m 176 831 l 51 1035 l 253 1035 l 335 831" }, + "a": { + "ha": 825, + "x_min": 51, + "x_max": 807, + "o": "m 312 -17 q 124 37 197 -17 q 51 186 51 90 q 113 338 51 285 q 296 417 175 392 l 536 464 q 503 573 536 536 q 410 610 471 610 q 317 583 350 610 q 274 503 283 556 l 64 512 q 174 698 85 635 q 410 761 264 761 q 660 682 576 761 q 744 450 744 603 l 744 196 q 755 153 744 164 q 786 143 765 143 l 807 143 l 807 0 q 776 -6 797 -3 q 733 -8 754 -8 q 651 7 689 -8 q 589 59 612 22 q 565 164 565 96 l 583 150 q 534 62 569 100 q 442 4 499 25 q 312 -17 386 -17 m 362 126 q 453 147 414 126 q 514 206 492 167 q 536 297 536 244 l 536 333 l 367 297 q 291 265 317 288 q 265 206 265 242 q 290 147 265 168 q 362 126 315 126" + }, + "b": { + "ha": 881, + "x_min": 92, + "x_max": 829, + "o": "m 519 -17 q 384 17 442 -17 q 294 110 326 50 l 290 0 l 92 0 l 92 986 l 300 986 l 300 639 q 386 726 329 690 q 519 761 443 761 q 683 713 614 761 q 791 578 753 665 q 829 372 829 490 q 791 167 829 254 q 683 31 753 79 q 519 -17 614 -17 m 461 143 q 573 203 531 143 q 615 372 615 264 q 574 541 615 481 q 462 601 532 601 q 374 574 411 601 q 319 496 338 547 q 300 372 300 444 q 319 250 300 301 q 374 171 338 199 q 461 143 411 143" + }, + "c": { + "ha": 831, + "x_min": 51, + "x_max": 793, + "o": "m 429 -17 q 231 31 315 -17 q 99 167 146 79 q 51 372 51 254 q 99 577 51 490 q 231 712 146 664 q 429 761 315 761 q 606 726 528 761 q 733 626 685 692 q 793 469 782 561 l 578 460 q 528 565 568 529 q 429 600 489 600 q 308 540 351 600 q 265 372 265 481 q 308 203 265 264 q 429 143 351 143 q 529 180 489 143 q 578 292 569 217 l 793 283 q 735 124 783 192 q 609 20 688 57 q 429 -17 531 -17" + }, + "d": { + "ha": 881, + "x_min": 51, + "x_max": 789, + "o": "m 357 -17 q 194 31 262 -17 q 88 166 125 79 q 51 372 51 253 q 89 578 51 492 q 195 713 126 665 q 357 761 264 761 q 494 728 436 761 q 581 639 551 696 l 581 986 l 789 986 l 789 0 l 590 0 l 586 110 q 495 17 556 50 q 357 -17 435 -17 m 425 143 q 510 169 475 143 q 562 247 544 196 q 581 372 581 297 q 562 499 581 449 q 510 576 544 550 q 425 601 475 601 q 308 540 351 601 q 265 372 265 478 q 309 206 265 268 q 425 143 353 143" + }, + "e": { + "ha": 840, + "x_min": 51, + "x_max": 790, + "o": "m 426 -17 q 228 31 312 -17 q 98 167 144 79 q 51 372 51 254 q 98 577 51 490 q 228 712 144 664 q 425 761 311 761 q 618 712 536 761 q 745 574 700 664 q 790 358 790 483 l 790 317 l 267 317 q 315 185 271 228 q 431 142 358 142 q 519 164 483 142 q 569 232 554 186 l 779 219 q 656 46 750 108 q 426 -17 561 -17 m 267 444 l 576 444 q 531 567 572 526 q 425 607 490 607 q 317 565 360 607 q 267 444 275 522" + }, + "f": { + "ha": 621, + "x_min": 64, + "x_max": 576, + "o": "m 172 0 l 172 754 q 232 926 172 865 q 418 986 292 986 l 576 986 l 576 831 l 462 831 q 400 809 419 831 q 381 744 381 788 l 381 0 m 64 561 l 64 717 l 565 717 l 565 561" + }, + "g": { + "ha": 881, + "x_min": 51, + "x_max": 789, + "o": "m 425 -225 q 247 -199 318 -225 q 133 -125 175 -172 q 74 -17 90 -78 l 288 -1 q 330 -58 299 -38 q 425 -79 361 -79 q 540 -44 500 -79 q 579 69 579 -8 l 579 149 q 494 66 553 97 q 364 35 436 35 q 201 80 272 35 q 91 206 131 125 q 51 397 51 288 q 91 586 51 504 q 201 715 131 668 q 361 761 271 761 q 499 725 443 761 q 585 629 556 689 l 585 744 l 789 744 l 789 74 q 743 -92 789 -26 q 615 -192 697 -158 q 425 -225 533 -225 m 424 189 q 538 244 496 189 q 581 399 581 300 q 562 511 581 464 q 508 583 543 558 q 424 608 472 608 q 307 551 349 608 q 265 399 265 494 q 308 245 265 301 q 424 189 351 189" + }, + "h": { + "ha": 849, + "x_min": 92, + "x_max": 757, + "o": "m 92 0 l 92 986 l 300 986 l 300 571 l 272 571 q 316 678 283 636 q 398 740 349 719 q 506 761 447 761 q 644 725 589 761 q 728 625 700 689 q 757 479 757 561 l 757 0 l 549 0 l 549 429 q 523 554 549 512 q 436 596 497 596 q 336 553 372 596 q 300 424 300 510 l 300 0" + }, + "i": { + "ha": 390, + "x_min": 88, + "x_max": 303, + "o": "m 92 0 l 92 744 l 300 744 l 300 0 m 88 836 l 88 1003 l 303 1003 l 303 836" + }, + "j": { + "ha": 460, + "x_min": -4, + "x_max": 372, + "o": "m -4 -208 l -4 -53 l 78 -53 q 140 -36 119 -53 q 160 31 160 -19 l 160 744 l 369 744 l 369 25 q 313 -154 369 -100 q 121 -208 257 -208 m 157 836 l 157 1003 l 372 1003 l 372 836" + }, + "k": { + "ha": 899, + "x_min": 92, + "x_max": 835, + "o": "m 92 0 l 92 986 l 300 986 l 300 439 l 576 744 l 826 744 l 538 438 l 835 0 l 607 0 l 403 319 l 300 210 l 300 0" + }, + "l": { + "ha": 435, + "x_min": 92, + "x_max": 410, + "o": "m 286 0 q 143 46 194 0 q 92 194 92 92 l 92 986 l 300 986 l 300 217 q 315 169 300 183 q 360 156 331 156 l 410 156 l 410 0" + }, + "m": { + "ha": 1250, + "x_min": 92, + "x_max": 1158, + "o": "m 92 0 l 92 744 l 279 744 l 286 565 l 267 574 q 313 675 282 633 q 389 739 344 717 q 486 761 433 761 q 637 707 579 761 q 711 561 694 653 l 685 560 q 728 670 697 625 q 806 738 760 715 q 908 761 851 761 q 1042 729 986 761 q 1128 634 1097 697 q 1158 479 1158 571 l 1158 0 l 950 0 l 950 421 q 924 552 950 508 q 838 596 897 596 q 774 575 800 596 q 733 515 747 554 q 718 418 718 475 l 718 0 l 531 0 l 531 418 q 506 550 531 504 q 419 596 481 596 q 355 575 382 596 q 314 514 328 554 q 300 418 300 474 l 300 0" + }, + "n": { + "ha": 849, + "x_min": 92, + "x_max": 757, + "o": "m 92 0 l 92 744 l 279 744 l 288 526 l 261 533 q 306 667 272 617 q 392 739 340 717 q 504 761 443 761 q 641 726 585 761 q 727 628 697 692 q 757 479 757 565 l 757 0 l 549 0 l 549 410 q 539 511 549 469 q 504 574 529 553 q 435 596 479 596 q 335 548 369 596 q 300 410 300 500 l 300 0" + }, + "o": { + "ha": 858, + "x_min": 51, + "x_max": 807, + "o": "m 429 -17 q 231 31 315 -17 q 99 167 146 79 q 51 372 51 254 q 99 577 51 490 q 231 712 146 664 q 429 761 315 761 q 628 712 543 761 q 760 577 712 664 q 807 372 807 490 q 760 167 807 254 q 628 31 712 79 q 429 -17 543 -17 m 429 143 q 550 203 507 143 q 593 372 593 264 q 550 541 593 481 q 429 601 507 601 q 308 541 351 601 q 265 372 265 481 q 308 203 265 264 q 429 143 351 143" + }, + "p": { + "ha": 881, + "x_min": 92, + "x_max": 829, + "o": "m 92 -208 l 92 744 l 292 744 l 296 588 l 279 594 q 369 718 307 675 q 515 761 432 761 q 689 710 619 761 q 794 570 758 658 q 829 372 829 482 q 794 175 829 264 q 688 35 758 86 q 514 -17 618 -17 q 412 3 460 -17 q 331 60 365 24 q 282 146 297 96 l 300 157 l 300 -208 m 457 143 q 573 204 531 143 q 615 372 615 265 q 573 540 615 479 q 457 601 531 601 q 373 576 408 601 q 319 499 338 550 q 300 372 300 447 q 319 246 300 297 q 373 169 338 194 q 457 143 408 143" + }, + "q": { + "ha": 881, + "x_min": 51, + "x_max": 789, + "o": "m 789 -208 l 581 -208 l 581 157 l 599 146 q 549 60 583 96 q 468 3 515 24 q 367 -17 421 -17 q 192 35 262 -17 q 87 175 122 86 q 51 372 51 264 q 87 570 51 482 q 192 710 122 658 q 365 761 261 761 q 512 718 450 761 q 601 594 575 675 l 585 588 l 589 744 l 789 744 m 424 143 q 508 169 474 143 q 562 246 543 194 q 581 372 581 297 q 562 499 581 447 q 508 576 543 550 q 424 601 472 601 q 308 540 350 601 q 265 372 265 479 q 308 204 265 265 q 424 143 350 143" + }, + "r": { + "ha": 590, + "x_min": 92, + "x_max": 539, + "o": "m 92 0 l 92 744 l 289 744 l 296 528 l 281 532 q 344 694 299 644 q 471 744 390 744 l 539 744 l 539 572 l 471 572 q 375 557 412 572 q 319 508 338 542 q 300 418 300 475 l 300 0" + }, + "s": { + "ha": 793, + "x_min": 51, + "x_max": 743, + "o": "m 410 -17 q 217 16 294 -17 q 98 105 139 49 q 51 235 57 161 l 262 242 q 307 160 272 189 q 410 131 342 131 q 497 149 465 131 q 528 204 528 167 q 517 244 528 228 q 473 272 506 260 q 376 293 440 283 q 192 342 258 314 q 97 414 125 369 q 69 522 69 458 q 152 695 69 629 q 400 761 235 761 q 577 728 506 761 q 688 637 649 694 q 738 506 728 579 l 528 497 q 506 559 524 533 q 462 599 489 585 q 399 614 436 614 q 313 591 343 614 q 283 531 283 568 q 297 485 283 503 q 340 457 310 468 q 422 439 371 446 q 612 392 542 422 q 712 318 682 362 q 743 208 743 274 q 701 86 743 136 q 585 10 660 36 q 410 -17 511 -17" + }, + "t": { + "ha": 618, + "x_min": 57, + "x_max": 581, + "o": "m 400 0 q 231 53 285 0 q 176 224 176 107 l 176 919 l 385 919 l 385 249 q 408 175 385 194 q 476 156 431 156 l 581 156 l 581 0 m 57 589 l 57 744 l 581 744 l 581 589" + }, + "u": { + "ha": 843, + "x_min": 92, + "x_max": 753, + "o": "m 336 -17 q 156 58 221 -17 q 92 265 92 132 l 92 744 l 300 744 l 300 314 q 326 188 300 228 q 410 149 353 149 q 509 192 474 149 q 544 324 544 236 l 544 744 l 753 744 l 753 0 l 562 0 l 557 214 l 583 208 q 504 40 567 97 q 336 -17 442 -17" + }, + "v": { + "ha": 846, + "x_min": 29, + "x_max": 817, + "o": "m 301 0 l 29 744 l 247 744 l 424 210 l 599 744 l 817 744 l 543 0" + }, + "w": { + "ha": 1179, + "x_min": 29, + "x_max": 1150, + "o": "m 250 0 l 29 744 l 239 744 l 367 240 l 504 744 l 674 744 l 811 240 l 940 744 l 1150 744 l 929 0 l 726 0 l 589 465 l 451 0" + }, + "x": { + "ha": 903, + "x_min": 64, + "x_max": 839, + "o": "m 64 0 l 329 378 l 71 744 l 292 744 l 451 506 l 606 744 l 832 744 l 575 376 l 839 0 l 618 0 l 454 253 l 289 0" + }, + "y": { + "ha": 814, + "x_min": 29, + "x_max": 785, + "o": "m 153 -208 l 153 -53 l 251 -53 q 305 -42 288 -53 q 332 -6 322 -32 l 347 38 l 290 38 l 29 744 l 242 744 l 412 232 l 572 744 l 785 744 l 499 -71 q 426 -176 474 -144 q 294 -208 379 -208" + }, + "z": { + "ha": 826, + "x_min": 78, + "x_max": 749, + "o": "m 78 0 l 78 164 l 488 589 l 94 589 l 94 744 l 738 744 l 738 581 l 321 156 l 749 156 l 749 0" + }, + "{": { + "ha": 567, + "x_min": 58, + "x_max": 550, + "o": "m 462 -174 q 257 -100 331 -174 q 183 89 183 -26 l 183 204 q 170 296 183 262 q 129 344 157 329 q 58 358 101 358 l 58 522 q 129 536 101 522 q 170 584 157 550 q 183 676 183 618 l 183 792 q 257 980 183 907 q 462 1053 331 1053 l 550 1053 l 550 874 q 422 850 462 878 q 382 758 382 822 l 382 662 q 334 508 382 564 q 222 444 286 453 l 222 436 q 335 373 288 429 q 382 218 382 317 l 382 121 q 422 27 382 57 q 550 0 462 -3 l 550 -174" + }, + "|": { + "ha": 408, + "x_min": 103, + "x_max": 306, + "o": "m 103 -153 l 103 1042 l 306 1042 l 306 -153" + }, + "}": { + "ha": 567, + "x_min": 17, + "x_max": 508, + "o": "m 104 -174 l 17 -174 l 17 0 q 144 27 104 -3 q 183 121 183 57 l 183 218 q 231 373 183 317 q 344 436 279 429 l 344 444 q 232 508 281 453 q 183 662 183 564 l 183 758 q 144 850 183 822 q 17 874 104 878 l 17 1053 l 104 1053 q 310 980 238 1053 q 382 792 382 907 l 382 676 q 395 584 382 618 q 436 536 408 550 q 508 522 464 522 l 508 358 q 436 344 464 358 q 395 296 408 329 q 382 204 382 262 l 382 89 q 310 -100 382 -26 q 104 -174 238 -174" + }, + "~": { + "ha": 726, + "x_min": 56, + "x_max": 671, + "o": "m 478 333 q 404 348 435 333 q 340 399 374 362 q 305 435 318 424 q 283 451 292 447 q 261 454 274 454 q 219 426 233 454 q 204 340 204 397 l 56 340 q 108 524 56 457 q 250 592 160 592 q 326 575 294 592 q 389 524 357 558 q 433 481 418 490 q 467 471 447 471 q 509 499 496 471 q 522 585 522 528 l 671 585 q 619 401 671 468 q 478 333 567 333" + } + }, + "familyName": "Geist Bold", + "ascender": 1396, + "descender": -410, + "underlinePosition": -100, + "underlineThickness": 50, + "boundingBox": { "xMin": -200, "xMax": 2338, "yMin": -253, "yMax": 958 }, + "resolution": 1000, + "original_font_information": { + "copyright": "Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font.git)", + "licence_url": "https://openfontlicense.org" + }, + "cssFontWeight": "bold", + "cssFontStyle": "normal" +} diff --git a/registry/blocks/extruded-logo/assets/fonts/Geist-OFL.txt b/registry/blocks/extruded-logo/assets/fonts/Geist-OFL.txt new file mode 100644 index 0000000000..8d003fec6b --- /dev/null +++ b/registry/blocks/extruded-logo/assets/fonts/Geist-OFL.txt @@ -0,0 +1,92 @@ +Copyright (c) 2023 Vercel, in collaboration with basement.studio + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION AND CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/registry/blocks/extruded-logo/extruded-logo.html b/registry/blocks/extruded-logo/extruded-logo.html new file mode 100644 index 0000000000..4f96cf9607 --- /dev/null +++ b/registry/blocks/extruded-logo/extruded-logo.html @@ -0,0 +1,331 @@ + + + + + + + Extruded Logo + + + + +
+ +
+
+ + + + + + diff --git a/registry/blocks/extruded-logo/registry-item.json b/registry/blocks/extruded-logo/registry-item.json new file mode 100644 index 0000000000..01313093aa --- /dev/null +++ b/registry/blocks/extruded-logo/registry-item.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "extruded-logo", + "type": "hyperframes:block", + "title": "Extruded Logo", + "description": "Beveled 3D letters flip up one by one, the word swings so light runs across the bevels, then settles for a readable hold. Chrome, gold or matte.", + "tags": ["3d-object", "three-js", "webgl", "logo", "text", "extruded", "title-card"], + "dimensions": { + "width": 1920, + "height": 1080 + }, + "duration": 5, + "files": [ + { + "path": "extruded-logo.html", + "target": "compositions/extruded-logo.html", + "type": "hyperframes:composition" + }, + { + "path": "assets/fonts/Geist-Bold.typeface.json", + "target": "compositions/assets/fonts/Geist-Bold.typeface.json", + "type": "hyperframes:asset" + }, + { + "path": "assets/fonts/Geist-OFL.txt", + "target": "compositions/assets/fonts/Geist-OFL.txt", + "type": "hyperframes:asset" + } + ] +} diff --git a/registry/blocks/glass-hero/glass-hero.html b/registry/blocks/glass-hero/glass-hero.html new file mode 100644 index 0000000000..7cdf186b47 --- /dev/null +++ b/registry/blocks/glass-hero/glass-hero.html @@ -0,0 +1,281 @@ + + + + + + + Glass Hero + + + + +
+ +
+
+ + + + + + diff --git a/registry/blocks/glass-hero/registry-item.json b/registry/blocks/glass-hero/registry-item.json new file mode 100644 index 0000000000..7419419535 --- /dev/null +++ b/registry/blocks/glass-hero/registry-item.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "glass-hero", + "type": "hyperframes:block", + "title": "Glass Hero", + "description": "A solid glass object rises in front of a giant headline and keeps turning, so the type bends and splits into colour through it.", + "tags": ["3d-object", "three-js", "webgl", "glass", "refraction", "hero", "title-card"], + "dimensions": { + "width": 1920, + "height": 1080 + }, + "duration": 5, + "files": [ + { + "path": "glass-hero.html", + "target": "compositions/glass-hero.html", + "type": "hyperframes:composition" + } + ] +} diff --git a/registry/blocks/product-turntable/product-turntable.html b/registry/blocks/product-turntable/product-turntable.html new file mode 100644 index 0000000000..cc3f717cbf --- /dev/null +++ b/registry/blocks/product-turntable/product-turntable.html @@ -0,0 +1,363 @@ + + + + + + + Product Turntable + + + + +
+ +
+
+ + + + + + diff --git a/registry/blocks/product-turntable/registry-item.json b/registry/blocks/product-turntable/registry-item.json new file mode 100644 index 0000000000..7197766519 --- /dev/null +++ b/registry/blocks/product-turntable/registry-item.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "product-turntable", + "type": "hyperframes:block", + "title": "Product Turntable", + "description": "A product turns a full revolution on a studio plinth in a seamless loop. Drop in a GLB or glTF model, or keep the built-in drink can with your own label.", + "tags": ["3d-object", "three-js", "webgl", "product", "turntable", "glb", "loop"], + "dimensions": { + "width": 1920, + "height": 1080 + }, + "duration": 6, + "files": [ + { + "path": "product-turntable.html", + "target": "compositions/product-turntable.html", + "type": "hyperframes:composition" + } + ] +} diff --git a/registry/blocks/snow/demo.html b/registry/blocks/snow/demo.html new file mode 100644 index 0000000000..398e595381 --- /dev/null +++ b/registry/blocks/snow/demo.html @@ -0,0 +1,166 @@ + + + + + + + + +
+
+ +
+

Winter release

+

Offline sync, shared folders and a faster search.

+
+
+
+
+ + + + diff --git a/registry/blocks/snow/registry-item.json b/registry/blocks/snow/registry-item.json new file mode 100644 index 0000000000..2a2e1475ff --- /dev/null +++ b/registry/blocks/snow/registry-item.json @@ -0,0 +1,60 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "snow", + "type": "hyperframes:block", + "title": "Snow", + "description": "Seek-safe falling-snow overlay: sparse or dense flakes drift down with size, speed and opacity correlated per flake for depth, radial-masked so the frame center stays clear", + "tags": [ + "snow", + "snowfall", + "winter", + "weather", + "overlay", + "ambient", + "particles", + "media-treatment-overlay", + "loopable" + ], + "dimensions": { + "width": 1920, + "height": 1080 + }, + "duration": 6, + "variables": [ + { + "id": "density", + "type": "enum", + "role": "style", + "label": "Density", + "description": "Flake count across the frame.", + "default": "sparse", + "options": [ + { "value": "sparse", "label": "Sparse" }, + { "value": "dense", "label": "Dense" } + ] + }, + { + "id": "speed", + "type": "enum", + "role": "style", + "label": "Fall speed", + "description": "How fast flakes fall and sway.", + "default": "calm", + "options": [ + { "value": "calm", "label": "Calm" }, + { "value": "gust", "label": "Gust" } + ] + } + ], + "files": [ + { + "path": "snow.html", + "target": "compositions/snow.html", + "type": "hyperframes:composition" + } + ], + "preview": { + "poster": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/snow.png", + "video": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/snow.mp4" + } +} diff --git a/registry/blocks/snow/snow.html b/registry/blocks/snow/snow.html new file mode 100644 index 0000000000..7de7bf0d92 --- /dev/null +++ b/registry/blocks/snow/snow.html @@ -0,0 +1,204 @@ + + + + + + + + + +
+ +
+ + + + diff --git a/registry/blocks/starfield/demo.html b/registry/blocks/starfield/demo.html new file mode 100644 index 0000000000..d234ddc89f --- /dev/null +++ b/registry/blocks/starfield/demo.html @@ -0,0 +1,118 @@ + + + + + + + + +
+
+
+

Northstar

+

Offline maps for the backcountry

+ +
+
+
+ + + + diff --git a/registry/blocks/starfield/registry-item.json b/registry/blocks/starfield/registry-item.json new file mode 100644 index 0000000000..1e382a96c9 --- /dev/null +++ b/registry/blocks/starfield/registry-item.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "starfield", + "type": "hyperframes:block", + "title": "Starfield", + "description": "Seek-safe night-sky overlay: sparse or dense stars in three size tiers that twinkle and drift in two parallax layers, radial-masked to keep the frame center clear", + "tags": [ + "starfield", + "night-sky", + "stars", + "twinkle", + "sky", + "weather", + "overlay", + "ambient", + "particles", + "media-treatment-overlay", + "loopable" + ], + "dimensions": { + "width": 1920, + "height": 1080 + }, + "duration": 6, + "variables": [ + { + "id": "density", + "type": "enum", + "role": "style", + "label": "Density", + "description": "Star count across the frame.", + "default": "sparse", + "options": [ + { "value": "sparse", "label": "Sparse" }, + { "value": "dense", "label": "Dense" } + ] + }, + { + "id": "tone", + "type": "enum", + "role": "style", + "label": "Tone", + "description": "Star color mix.", + "default": "warm", + "options": [ + { "value": "warm", "label": "Warm (white + yellow)" }, + { "value": "cool", "label": "Cool (white + blue)" }, + { "value": "white", "label": "White only" } + ] + }, + { + "id": "speed", + "type": "enum", + "role": "style", + "label": "Twinkle speed", + "description": "How fast stars pulse.", + "default": "slow", + "options": [ + { "value": "slow", "label": "Slow" }, + { "value": "fast", "label": "Fast" } + ] + } + ], + "files": [ + { + "path": "starfield.html", + "target": "compositions/starfield.html", + "type": "hyperframes:composition" + } + ], + "preview": { + "poster": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/starfield.png", + "video": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/starfield.mp4" + } +} diff --git a/registry/blocks/starfield/starfield.html b/registry/blocks/starfield/starfield.html new file mode 100644 index 0000000000..11ed70fb7d --- /dev/null +++ b/registry/blocks/starfield/starfield.html @@ -0,0 +1,187 @@ + + + + + + + + + +
+ +
+ + + + diff --git a/registry/blocks/transitions-dissolve/registry-item.json b/registry/blocks/transitions-dissolve/registry-item.json index 9b529eff69..508c6c1870 100644 --- a/registry/blocks/transitions-dissolve/registry-item.json +++ b/registry/blocks/transitions-dissolve/registry-item.json @@ -4,7 +4,7 @@ "type": "hyperframes:block", "title": "Dissolve Transitions", "description": "Showcase of dissolve and fade transitions", - "tags": ["transition", "showcase"], + "tags": ["transition", "showcase", "crossfade"], "dimensions": { "width": 1920, "height": 1080 diff --git a/registry/components/CATALOG.md b/registry/components/CATALOG.md index 88d048eec0..0bf8845aa8 100644 --- a/registry/components/CATALOG.md +++ b/registry/components/CATALOG.md @@ -45,20 +45,20 @@ variables: prefix (string, default "Ship"): fixed text before the slot. options ### oversized-cursor group: Product demo. -what: A deliberately oversized macOS-style pointer enters off-screen, glides to a target, clicks to visibly ignite it, then accelerates back off-screen. +what: The look-here pointer: the macOS arrow at 3.5x its normal size enters from the frame edge, lands its tip on one control, clicks it on, settles just below it so the result stays in view, then exits off-screen. use_when: The scene needs a personified "someone clicks the thing and it works" beat with theatrical scale. -avoid_when: The click target is your own slotted UI or the pressed state must persist; use press-ripple, which presses a slot and holds it. +avoid_when: A normal-size cursor should press your own slotted button and confirm it; use press-ripple. pairs_with: browser-device-stage, cut-the-curve. variables: cursor_variant (enum light or dark, default light): pointer body tone. target_x (number percent, default 55) and target_y (number percent, default 55): tip landing point. click_label (string, default "Generate"): label on the clicked pill. exit (enum none, fade, up, default none): fade and up also depart the ignited target. ### press-ripple group: Product demo. -what: A cursor decel-arrives from off-stage, lands slightly off-center on a caller-positioned target, compresses with it in lockstep, releases with ink ripple rings, and holds the pressed state. +what: A cursor decel-arrives from off-stage, lands slightly off-center on a caller-positioned target, compresses with it in lockstep, releases with two small click rings at the tip while the label swaps to a check, then exits while the confirmed state holds. use_when: The payoff beat: the user presses the button and the film rests on that satisfied pressed state. -avoid_when: The cursor itself is the star or must leave after the click; use oversized-cursor for the enter-click-exit arc. +avoid_when: The pointer itself should be the look-here star at theatrical scale; use oversized-cursor. pairs_with: browser-device-stage, cta-close. -variables: label (string, default "Get started"): text in the default pill; ignored when the target slot is replaced. target_x (number percent, default 50) and target_y (number percent, default 50): zone center. press_at (number seconds, default 1.4): press cue. cursor (enum light or dark, default light): pointer tone. accent (enum green, blue, violet, default green): ripple ink and pressed fill. exit (enum none, fade, up, default none). +variables: label (string, default "Get started"): text in the default pill; ignored when the target slot is replaced. target_x (number percent, default 50) and target_y (number percent, default 50): zone center. done_label (string, default "Saved"): label after the press. press_at (number seconds, default 0.9): press cue. cursor (enum light or dark, default light): pointer tone. accent (enum green, blue, violet, default green): click rings and the confirmation check. exit (enum none, fade, up, default none). ### browser-device-stage diff --git a/registry/components/agent-cursor/agent-cursor.html b/registry/components/agent-cursor/agent-cursor.html new file mode 100644 index 0000000000..42aaa54ab8 --- /dev/null +++ b/registry/components/agent-cursor/agent-cursor.html @@ -0,0 +1,398 @@ + + + + + + Agent Cursor + + + + + diff --git a/registry/components/agent-cursor/demo.html b/registry/components/agent-cursor/demo.html new file mode 100644 index 0000000000..1d1bd9239e --- /dev/null +++ b/registry/components/agent-cursor/demo.html @@ -0,0 +1,253 @@ + + + + + + + Agent Cursor, Demo + + + + +
+
+
+
Workspace
+ + + + + +
+ +
+

Projects

+
+
Spring campaign
+
Edited 2 hours ago by Priya
+
In review
+
+
+
Onboarding emails
+
Edited yesterday by Marco
+
Draft
+
+
+
Pricing page refresh
+
Edited Monday by Lena
+
Shipped
+
+
+ +
+

Settings

+
+
Automatic backups
+
Off. Your workspace is not backed up.
+
+
+
+
Version history
+
Keep every change for 30 days
+
+
+
+
Export workspace
+
Download everything as a zip
+
Export
+
+
+
+ +
+
+ + + + diff --git a/registry/components/agent-cursor/registry-item.json b/registry/components/agent-cursor/registry-item.json new file mode 100644 index 0000000000..4be5dbfd2f --- /dev/null +++ b/registry/components/agent-cursor/registry-item.json @@ -0,0 +1,55 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "agent-cursor", + "type": "hyperframes:component", + "title": "Agent Cursor", + "description": "An AI agent operating a UI: a cursor with an accent name label that types out each step, clicks each target with a small ring, and ends on a check.", + "tags": ["cursor", "motion-primitive", "agent", "ai", "status", "click"], + "files": [ + { + "path": "agent-cursor.html", + "target": "compositions/components/agent-cursor.html", + "type": "hyperframes:snippet" + } + ], + "jobs": ["demonstrate"], + "family": "pointers", + "profile": "interaction", + "syncPoints": [ + { "id": "first-click", "phase": "in", "offset": 2.0 }, + { "id": "second-click", "phase": "in", "offset": 3.35 }, + { "id": "done", "phase": "in", "offset": 3.65 } + ], + "variables": [ + { + "id": "agent_name", + "type": "string", + "role": "content", + "label": "Agent name", + "default": "Agent" + }, + { + "id": "steps", + "type": "string", + "role": "content", + "label": "Status steps", + "description": "Comma-separated: a reading line, one line per target, then a done line.", + "default": "Reading the page,Opening Settings,Turning on backups,Done" + }, + { + "id": "targets", + "type": "string", + "role": "layout", + "label": "Click targets", + "description": "Semicolon-separated x,y points in percent of the frame.", + "default": "25,47;76,30" + }, + { + "id": "accent", + "type": "color", + "role": "style", + "label": "Accent", + "default": "#0a84ff" + } + ] +} diff --git a/registry/components/before-after-wipe/registry-item.json b/registry/components/before-after-wipe/registry-item.json index 9daf70acdd..299d0fe4e3 100644 --- a/registry/components/before-after-wipe/registry-item.json +++ b/registry/components/before-after-wipe/registry-item.json @@ -4,7 +4,17 @@ "type": "hyperframes:component", "title": "Before After Wipe", "description": "Two full-bleed content slots compare before and after states as a persistent divider wipes the after layer over the before layer and rests at a configurable split. Callers fill the named before/after slot panels; token-styled defaults render when a slot is left empty.", - "tags": ["prop", "ui-props", "compare", "holdable", "before-after", "wipe", "slots"], + "tags": [ + "prop", + "ui-props", + "compare", + "comparison", + "split-screen", + "holdable", + "before-after", + "wipe", + "slots" + ], "jobs": ["compare"], "family": "ui-props", "profile": "holdable", diff --git a/registry/components/count-up/registry-item.json b/registry/components/count-up/registry-item.json index fc8c948971..e1f271c1ec 100644 --- a/registry/components/count-up/registry-item.json +++ b/registry/components/count-up/registry-item.json @@ -3,8 +3,8 @@ "name": "count-up", "type": "hyperframes:component", "title": "Count Up", - "description": "A token-native stat counter that eases between values and lands with a restrained scale pulse.", - "tags": ["motion-primitive", "proof", "stats", "counter", "number", "deterministic"], + "description": "A token-native stat counter that eases between values, counting up or down, and lands with a restrained scale pulse.", + "tags": ["motion-primitive", "proof", "stats", "counter", "number", "countdown", "deterministic"], "jobs": ["prove"], "family": "proof-stats", "profile": "count", diff --git a/registry/components/cursor-annotate/cursor-annotate.html b/registry/components/cursor-annotate/cursor-annotate.html new file mode 100644 index 0000000000..bd22c13a3c --- /dev/null +++ b/registry/components/cursor-annotate/cursor-annotate.html @@ -0,0 +1,494 @@ + + + + + + Annotate Cursor + + + + + diff --git a/registry/components/cursor-annotate/demo.html b/registry/components/cursor-annotate/demo.html new file mode 100644 index 0000000000..e9ea1e9470 --- /dev/null +++ b/registry/components/cursor-annotate/demo.html @@ -0,0 +1,176 @@ + + + + + + + Annotate Cursor, Demo + + + + +
+
+
Weekly signups
+
12,480
+
+38% this quarter
+
+
+
+
+
+
+
+
+
+
+
+
+184%
+
W1
+
W2
+
W3
+
W4
+
Launch
+
W6
+
W7
+
W8
+
+ +
+
+ + + + diff --git a/registry/components/cursor-annotate/registry-item.json b/registry/components/cursor-annotate/registry-item.json new file mode 100644 index 0000000000..b732ddc876 --- /dev/null +++ b/registry/components/cursor-annotate/registry-item.json @@ -0,0 +1,87 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "cursor-annotate", + "type": "hyperframes:component", + "title": "Annotate Cursor", + "description": "A marker pen glides onto the frame and hand-draws a loose loop, an underline, or an arrow around a region, the ink laid exactly under its nib, then lifts and leaves.", + "tags": ["cursor", "motion-primitive", "pen", "annotation", "draw-on", "highlight"], + "files": [ + { + "path": "cursor-annotate.html", + "target": "compositions/components/cursor-annotate.html", + "type": "hyperframes:snippet" + } + ], + "jobs": ["demonstrate"], + "family": "pointers", + "profile": "interaction", + "syncPoints": [ + { "id": "ink-down", "phase": "in", "offset": 0.7 }, + { "id": "ink-done", "phase": "in", "offset": 1.8 } + ], + "variables": [ + { + "id": "shape", + "type": "enum", + "role": "style", + "label": "Mark", + "default": "circle", + "options": [ + { "value": "circle", "label": "Loose loop" }, + { "value": "underline", "label": "Underline" }, + { "value": "arrow", "label": "Arrow" } + ] + }, + { + "id": "color", + "type": "color", + "role": "style", + "label": "Ink", + "default": "#f43f5e" + }, + { + "id": "target_x", + "type": "number", + "role": "layout", + "label": "Region left", + "default": 40, + "min": 0, + "max": 95, + "step": 1, + "unit": "%" + }, + { + "id": "target_y", + "type": "number", + "role": "layout", + "label": "Region top", + "default": 38, + "min": 0, + "max": 95, + "step": 1, + "unit": "%" + }, + { + "id": "target_w", + "type": "number", + "role": "layout", + "label": "Region width", + "default": 20, + "min": 2, + "max": 90, + "step": 1, + "unit": "%" + }, + { + "id": "target_h", + "type": "number", + "role": "layout", + "label": "Region height", + "default": 16, + "min": 2, + "max": 90, + "step": 1, + "unit": "%" + } + ] +} diff --git a/registry/components/cursor-context-menu/cursor-context-menu.html b/registry/components/cursor-context-menu/cursor-context-menu.html new file mode 100644 index 0000000000..85890ef901 --- /dev/null +++ b/registry/components/cursor-context-menu/cursor-context-menu.html @@ -0,0 +1,562 @@ + + + + + + Context Menu Cursor + + + + + diff --git a/registry/components/cursor-context-menu/demo.html b/registry/components/cursor-context-menu/demo.html new file mode 100644 index 0000000000..9dd7e21456 --- /dev/null +++ b/registry/components/cursor-context-menu/demo.html @@ -0,0 +1,69 @@ + + + + + + + Context Menu Cursor, Demo + + + + +
+
+
+
+ + + + diff --git a/registry/components/cursor-context-menu/registry-item.json b/registry/components/cursor-context-menu/registry-item.json new file mode 100644 index 0000000000..824c9d6b1e --- /dev/null +++ b/registry/components/cursor-context-menu/registry-item.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "cursor-context-menu", + "type": "hyperframes:component", + "title": "Context Menu Cursor", + "description": "A cursor right-clicks a file, a context menu blooms from its tip, the hover highlight tracks the item under it, and the chosen action plays out: duplicate, rename, move to trash, or a confirmation toast.", + "tags": ["cursor", "motion-primitive", "menu", "right-click", "desktop", "files"], + "files": [ + { + "path": "cursor-context-menu.html", + "target": "compositions/components/cursor-context-menu.html", + "type": "hyperframes:snippet" + } + ], + "jobs": ["demonstrate"], + "family": "pointers", + "profile": "interaction", + "syncPoints": [ + { "id": "right-click", "phase": "in", "offset": 0.7 }, + { "id": "menu-pick", "phase": "in", "offset": 1.85 } + ], + "variables": [ + { + "id": "items", + "type": "string", + "role": "content", + "label": "Menu items", + "default": "Open,Rename,Duplicate,Share,Move to Trash" + }, + { + "id": "pick", + "type": "number", + "role": "content", + "label": "Chosen item (0 = first)", + "default": 2, + "min": 0, + "max": 9, + "step": 1 + }, + { + "id": "tone", + "type": "enum", + "role": "style", + "label": "Tone", + "default": "light", + "options": [ + { "value": "light", "label": "Light" }, + { "value": "dark", "label": "Dark" } + ] + } + ] +} diff --git a/registry/components/cursor-drag-drop/cursor-drag-drop.html b/registry/components/cursor-drag-drop/cursor-drag-drop.html new file mode 100644 index 0000000000..72d57b85f8 --- /dev/null +++ b/registry/components/cursor-drag-drop/cursor-drag-drop.html @@ -0,0 +1,464 @@ + + + + + + Drag and Drop Cursor + + + + + diff --git a/registry/components/cursor-drag-drop/demo.html b/registry/components/cursor-drag-drop/demo.html new file mode 100644 index 0000000000..dd2d809c01 --- /dev/null +++ b/registry/components/cursor-drag-drop/demo.html @@ -0,0 +1,64 @@ + + + + + + + Drag and Drop Cursor, Demo + + + + +
+
+
+ + + + diff --git a/registry/components/cursor-drag-drop/registry-item.json b/registry/components/cursor-drag-drop/registry-item.json new file mode 100644 index 0000000000..74a6555ca7 --- /dev/null +++ b/registry/components/cursor-drag-drop/registry-item.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "cursor-drag-drop", + "type": "hyperframes:component", + "title": "Drag and Drop Cursor", + "description": "A cursor grabs a task card, lifts and tilts it into its motion, carries it in lockstep to an empty column, drops it with a small settle, and the list closes the gap behind it.", + "tags": ["cursor", "motion-primitive", "drag", "drop", "kanban", "product-demo"], + "files": [ + { + "path": "cursor-drag-drop.html", + "target": "compositions/components/cursor-drag-drop.html", + "type": "hyperframes:snippet" + } + ], + "jobs": ["demonstrate"], + "family": "pointers", + "profile": "interaction", + "syncPoints": [ + { "id": "grab", "phase": "in", "offset": 0.7 }, + { "id": "drop", "phase": "in", "offset": 2 } + ], + "variables": [ + { + "id": "card_label", + "type": "string", + "role": "content", + "label": "Dragged card", + "default": "Fix checkout validation" + }, + { + "id": "accent", + "type": "color", + "role": "style", + "label": "Accent", + "default": "#0a84ff" + }, + { + "id": "tone", + "type": "enum", + "role": "style", + "label": "Board tone", + "default": "light", + "options": [ + { "value": "light", "label": "Light" }, + { "value": "dark", "label": "Dark" } + ] + } + ] +} diff --git a/registry/components/cursor-glyph-trail/README.md b/registry/components/cursor-glyph-trail/README.md index a29e1add5c..4ec539b8b6 100644 --- a/registry/components/cursor-glyph-trail/README.md +++ b/registry/components/cursor-glyph-trail/README.md @@ -1,23 +1,23 @@ # cursor-glyph-trail -An actor (default: a cursor dot) travels an authored path and deposits small dithered glyphs at its past positions. Each glyph pops in where the actor passed and decays in place; stamps land at fixed arc-length spacing along the path, so the per-second stamp rate scales with the actor's velocity. The jh3yy stamp-and-decay register: the trail is the residue of the motion, fully dissolved before the hold. +A tutorial cursor path. On a Settings screen the arrow clicks through three steps: turn on the email digest, pick Weekly, save. Each move leaves a dotted trail spaced evenly by distance (not by time), each click leaves a numbered step marker, and a step's trail fades as the next move begins, so a viewer can follow the path without the screen filling with noise. The markers stay, so the last frame reads as the recap. -4s authored, elastic HOLD, exit `none` by default. +3.5s authored, elastic HOLD, exit `none` by default. ## Variables -| id | type | default | notes | -| --------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------- | -| `glyphs` | string | `░▒▓+·×` | Stamp charset; one glyph per stamp is chosen by a fixed-seed LCG. | -| `density` | enum | `med` | Arc-length spacing between stamps: `low` (4.6), `med` (2.9), `high` (1.8) percent units. | -| `path` | enum | `sweep` | `sweep` is an S-curve lower-left to upper-right; `arc` rises over the top; `zigzag` cuts three straight legs. | -| `fade` | number | `0.8` | Per-stamp decay window in seconds, clamped 0.3 to 1.5; per stamp varied 0.75x to 1.25x. | -| `accent` | enum | `green` | Trail and actor color: green rides `--brand`, blue rides `--accent`, violet rides `--accent-2`. | -| `exit` | enum | `none` | `none` holds until the cut; `fade` departs opacity-only; `up` rises out. | +| id | type | default | notes | +| --------- | ------ | ------- | ------------------------------------------------------------------------------------------------ | +| `glyphs` | string | `""` | Deprecated and ignored; still accepted so existing mounts keep working. | +| `density` | enum | `med` | Spacing between trail dots: `low` (30), `med` (21), `high` (15) px at 1920 wide. | +| `path` | enum | `sweep` | How each move bends: `sweep` a gentle curve, `arc` a deeper one, `zigzag` a straight line. | +| `fade` | number | `0.5` | Seconds a step trail takes to fade once the next move begins, clamped 0.3 to 1.5. | +| `accent` | enum | `green` | Trail and marker color: green rides `--brand`, blue rides `--accent`, violet rides `--accent-2`. | +| `exit` | enum | `none` | `none` holds until the cut; `fade` departs opacity-only; `up` rises out. | ## Actor slot -The actor is a slot. Place an inert template anywhere in the HOST page (templates never render, and the runtime wipes the host clip's own children on mount, so the slot lives at document level): +The arrow can be replaced. Place an inert template anywhere in the HOST page (templates never render, and the runtime wipes the host clip's own children on mount, so the slot lives at document level); its content is centred on the click point: ```html ``` -With no slot, the primitive renders a token cursor dot (accent core, hairline ring, contract tokens only). +With no slot, the component draws the family arrow (64 px at 1920 wide). ## Mount @@ -34,9 +34,9 @@ With no slot, the primitive renders a token cursor dot (accent core, hairline ri class="clip" data-composition-id="cursor-glyph-trail" data-composition-src="./cursor-glyph-trail.html" - data-variable-values='{"path":"zigzag","density":"high","accent":"blue"}' + data-variable-values='{"path":"sweep","density":"med","accent":"green"}' data-start="0" - data-duration="4" + data-duration="3.5" data-track-index="0" > ``` @@ -45,7 +45,6 @@ Elastic root: no `data-width`/`data-height`; it fills whatever box the host clip ## Notes -- Deterministic: the stamp table (positions, times, glyph choices, jitter, sizes, peaks, decay multipliers) is built once at mount from fixed LCG seed `0x67117a11`. Stamps carry no tweens: each stamp's opacity is recomputed on every timeline update as a pure function `f(tl.time() - t_i)` of its table row (two sequential tweens on one property render in direction-dependent order under GSAP seeks), and the actor position is recomputed from `tl.time()` the same way, so eventful seeks (`suppressEvents=false`, the engine's render path) land identical frames in any order and either direction. -- Density law: stamps land at fixed arc-length spacing, so faster travel deposits more stamps per second; the shared ease (power2-style inOut) makes the trail thin at the ends and dense through the middle. -- Every stamp's decay completes inside IN by construction (`IN = travel + pop + fade * 1.25 + margin`), so the HOLD is truly still: the actor rests at the path end and the field is empty. -- The travel ease is one shared function used by both the stamp-table sampler and the per-update actor position, so stamps always sit exactly on the actor's past path. +- Seek-safe: every frame is `render(t)`. The trail at time t is the part of each move's curve the cursor has covered by t, so seeking in any order lands the same frame. +- Dots are a round-capped zero-length dash pattern along the covered part of the curve, which is what spaces them by distance. +- Shorter durations compress every beat evenly. diff --git a/registry/components/cursor-glyph-trail/cursor-glyph-trail.html b/registry/components/cursor-glyph-trail/cursor-glyph-trail.html index 76d342a385..7806315c08 100644 --- a/registry/components/cursor-glyph-trail/cursor-glyph-trail.html +++ b/registry/components/cursor-glyph-trail/cursor-glyph-trail.html @@ -1,75 +1,30 @@ @@ -78,313 +33,619 @@ diff --git a/registry/components/cursor-glyph-trail/demo.html b/registry/components/cursor-glyph-trail/demo.html index dfd1c32a0f..3001edcf1b 100644 --- a/registry/components/cursor-glyph-trail/demo.html +++ b/registry/components/cursor-glyph-trail/demo.html @@ -1,8 +1,8 @@ @@ -21,7 +21,7 @@ width: 1920px; height: 1080px; overflow: hidden; - background: var(--bg, #eef0f3); + background: #f4f4f5; } #root { @@ -30,7 +30,7 @@ --muted: #5b6472; --surface: #ffffff; --border: #d3d8e0; - --brand: #3f3f46; + --brand: #0a84ff; --accent: #3f3f46; --accent-2: #3f3f46; --font-display: "Inter", system-ui, sans-serif; @@ -39,7 +39,7 @@ width: 1920px; height: 1080px; overflow: hidden; - background: radial-gradient(ellipse at 50% 42%, #f7f8fa 0%, var(--bg, #eef0f3) 72%); + background: #f4f4f5; } .mount-bleed { @@ -59,7 +59,7 @@ data-start="0" data-width="1920" data-height="1080" - data-duration="4" + data-duration="3.5" data-fps="30" >
+ + + + + Marquee Select Cursor + + + + + diff --git a/registry/components/cursor-marquee-select/demo.html b/registry/components/cursor-marquee-select/demo.html new file mode 100644 index 0000000000..6f8a6ee260 --- /dev/null +++ b/registry/components/cursor-marquee-select/demo.html @@ -0,0 +1,64 @@ + + + + + + + Marquee Select Cursor, Demo + + + + +
+
+
+ + + + diff --git a/registry/components/cursor-marquee-select/registry-item.json b/registry/components/cursor-marquee-select/registry-item.json new file mode 100644 index 0000000000..d844e728eb --- /dev/null +++ b/registry/components/cursor-marquee-select/registry-item.json @@ -0,0 +1,76 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "cursor-marquee-select", + "type": "hyperframes:component", + "title": "Marquee Select Cursor", + "description": "A cursor drags a selection rectangle across a photo grid; each tile rings and pops a check the frame the rectangle touches it, while a pill counts the selection up.", + "tags": ["cursor", "motion-primitive", "select", "marquee", "grid", "product-demo"], + "files": [ + { + "path": "cursor-marquee-select.html", + "target": "compositions/components/cursor-marquee-select.html", + "type": "hyperframes:snippet" + } + ], + "jobs": ["demonstrate"], + "family": "pointers", + "profile": "interaction", + "syncPoints": [ + { "id": "press", "phase": "in", "offset": 0.62 }, + { "id": "release", "phase": "in", "offset": 2.1 } + ], + "variables": [ + { "id": "accent", "type": "color", "role": "style", "label": "Accent", "default": "#0a84ff" }, + { + "id": "start_x", + "type": "number", + "role": "layout", + "label": "Drag start X", + "default": 20.5, + "min": 0, + "max": 100, + "step": 0.5, + "unit": "%" + }, + { + "id": "start_y", + "type": "number", + "role": "layout", + "label": "Drag start Y", + "default": 25.5, + "min": 0, + "max": 100, + "step": 0.5, + "unit": "%" + }, + { + "id": "end_x", + "type": "number", + "role": "layout", + "label": "Drag end X", + "default": 57, + "min": 0, + "max": 100, + "step": 0.5, + "unit": "%" + }, + { + "id": "end_y", + "type": "number", + "role": "layout", + "label": "Drag end Y", + "default": 52, + "min": 0, + "max": 100, + "step": 0.5, + "unit": "%" + }, + { + "id": "pill_label", + "type": "string", + "role": "content", + "label": "Pill label", + "default": "selected" + } + ] +} diff --git a/registry/components/cursor-text-select/cursor-text-select.html b/registry/components/cursor-text-select/cursor-text-select.html new file mode 100644 index 0000000000..842c9e99ba --- /dev/null +++ b/registry/components/cursor-text-select/cursor-text-select.html @@ -0,0 +1,440 @@ + + + + + + Text Select Cursor + + + + + diff --git a/registry/components/cursor-text-select/demo.html b/registry/components/cursor-text-select/demo.html new file mode 100644 index 0000000000..1bfb798620 --- /dev/null +++ b/registry/components/cursor-text-select/demo.html @@ -0,0 +1,69 @@ + + + + + + + Text Select Cursor, Demo + + + + +
+
+
+
+ + + + diff --git a/registry/components/cursor-text-select/registry-item.json b/registry/components/cursor-text-select/registry-item.json new file mode 100644 index 0000000000..23fdffdb26 --- /dev/null +++ b/registry/components/cursor-text-select/registry-item.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "cursor-text-select", + "type": "hyperframes:component", + "title": "Text Select Cursor", + "description": "An arrow turns into an I-beam over a document, drags a selection across a phrase character by character, raises a format toolbar, turns back into an arrow and clicks Bold.", + "tags": ["cursor", "motion-primitive", "text", "selection", "editor", "toolbar"], + "files": [ + { + "path": "cursor-text-select.html", + "target": "compositions/components/cursor-text-select.html", + "type": "hyperframes:snippet" + } + ], + "jobs": ["demonstrate"], + "family": "pointers", + "profile": "interaction", + "syncPoints": [ + { "id": "selection-released", "phase": "in", "offset": 1.65 }, + { "id": "bold-click", "phase": "in", "offset": 2.7 } + ], + "variables": [ + { + "id": "title", + "type": "string", + "role": "content", + "label": "Heading", + "default": "Spring release notes" + }, + { + "id": "text", + "type": "string", + "role": "content", + "label": "Paragraph", + "default": "Our spring release ships on Thursday. Teams can now share a live review link, collect time-stamped comments, and approve the final cut without leaving the editor. Early customers cut their review rounds in half." + }, + { + "id": "phrase", + "type": "string", + "role": "content", + "label": "Phrase to select", + "default": "approve the final cut" + }, + { + "id": "accent", + "type": "color", + "role": "style", + "label": "Accent", + "default": "#0a84ff" + } + ] +} diff --git a/registry/components/cursor-zoom-follow/cursor-zoom-follow.html b/registry/components/cursor-zoom-follow/cursor-zoom-follow.html new file mode 100644 index 0000000000..9011340321 --- /dev/null +++ b/registry/components/cursor-zoom-follow/cursor-zoom-follow.html @@ -0,0 +1,720 @@ + + + + + + Zoom Follow Cursor + + + + + diff --git a/registry/components/cursor-zoom-follow/demo.html b/registry/components/cursor-zoom-follow/demo.html new file mode 100644 index 0000000000..f3a21f0dd7 --- /dev/null +++ b/registry/components/cursor-zoom-follow/demo.html @@ -0,0 +1,75 @@ + + + + + + + Zoom Follow Cursor, Demo + + + + +
+
+
+ + + + diff --git a/registry/components/cursor-zoom-follow/registry-item.json b/registry/components/cursor-zoom-follow/registry-item.json new file mode 100644 index 0000000000..1327605406 --- /dev/null +++ b/registry/components/cursor-zoom-follow/registry-item.json @@ -0,0 +1,128 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "cursor-zoom-follow", + "type": "hyperframes:component", + "title": "Zoom Follow Cursor", + "description": "Screen-recording auto-zoom: the camera pushes in toward each upcoming click, trails the cursor on a smooth spring, marks every click with a press and a ring, then eases back out to the full screen as the cursor leaves.", + "tags": ["cursor", "camera", "zoom", "screen-recording", "click", "product-demo"], + "files": [ + { + "path": "cursor-zoom-follow.html", + "target": "compositions/components/cursor-zoom-follow.html", + "type": "hyperframes:snippet" + } + ], + "jobs": ["demonstrate"], + "family": "pointers", + "profile": "camera", + "syncPoints": [ + { + "id": "click-1", + "phase": "hold", + "offset": 0.95 + }, + { + "id": "click-2", + "phase": "hold", + "offset": 2.55 + }, + { + "id": "click-3", + "phase": "hold", + "offset": 3.65 + } + ], + "variables": [ + { + "id": "image", + "type": "image", + "role": "content", + "label": "Screenshot", + "description": "Your own screen capture. Leave empty for the built-in dashboard.", + "default": "" + }, + { + "id": "zoom", + "type": "number", + "role": "style", + "label": "Zoom", + "default": 1.8, + "min": 1.2, + "max": 2.6, + "step": 0.1 + }, + { + "id": "click1_x", + "type": "number", + "role": "layout", + "label": "Click 1 X", + "default": 68.5, + "min": 0, + "max": 100, + "step": 0.5, + "unit": "%" + }, + { + "id": "click1_y", + "type": "number", + "role": "layout", + "label": "Click 1 Y", + "default": 7.5, + "min": 0, + "max": 100, + "step": 0.5, + "unit": "%" + }, + { + "id": "click2_x", + "type": "number", + "role": "layout", + "label": "Click 2 X", + "default": 50, + "min": 0, + "max": 100, + "step": 0.5, + "unit": "%" + }, + { + "id": "click2_y", + "type": "number", + "role": "layout", + "label": "Click 2 Y", + "default": 48.5, + "min": 0, + "max": 100, + "step": 0.5, + "unit": "%" + }, + { + "id": "click3_x", + "type": "number", + "role": "layout", + "label": "Click 3 X", + "default": 90.5, + "min": 0, + "max": 100, + "step": 0.5, + "unit": "%" + }, + { + "id": "click3_y", + "type": "number", + "role": "layout", + "label": "Click 3 Y", + "default": 7.5, + "min": 0, + "max": 100, + "step": 0.5, + "unit": "%" + }, + { + "id": "accent", + "type": "color", + "role": "style", + "label": "Ripple", + "default": "#0a84ff" + } + ] +} diff --git a/registry/components/curtain-reveal/curtain-reveal.html b/registry/components/curtain-reveal/curtain-reveal.html new file mode 100644 index 0000000000..e1c364479f --- /dev/null +++ b/registry/components/curtain-reveal/curtain-reveal.html @@ -0,0 +1,377 @@ + + + + + + Curtain Reveal + + + + + diff --git a/registry/components/curtain-reveal/demo.html b/registry/components/curtain-reveal/demo.html new file mode 100644 index 0000000000..55788ab77b --- /dev/null +++ b/registry/components/curtain-reveal/demo.html @@ -0,0 +1,106 @@ + + + + + + + Curtain Reveal Demo + + + + + +
+
+
+ + + + + diff --git a/registry/components/curtain-reveal/registry-item.json b/registry/components/curtain-reveal/registry-item.json new file mode 100644 index 0000000000..83e9bb8d14 --- /dev/null +++ b/registry/components/curtain-reveal/registry-item.json @@ -0,0 +1,55 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "curtain-reveal", + "type": "hyperframes:component", + "title": "Curtain Reveal", + "description": "Two pleated stage curtains gather outward from center, the way real velvet bunches at the tieback, revealing the stage underneath. A static pelmet frames the top; a soft spotlight can bloom in as they part.", + "tags": ["curtain", "stage reveal", "transition", "motion-primitive"], + "files": [ + { + "path": "curtain-reveal.html", + "target": "compositions/components/curtain-reveal.html", + "type": "hyperframes:snippet" + } + ], + "variables": [ + { + "id": "tone", + "type": "enum", + "role": "style", + "label": "Curtain tone", + "description": "Curtain color.", + "default": "burgundy", + "options": [ + { "value": "red", "label": "Red" }, + { "value": "burgundy", "label": "Burgundy" }, + { "value": "navy", "label": "Navy" }, + { "value": "forest", "label": "Forest" } + ] + }, + { + "id": "pelmet", + "type": "enum", + "role": "style", + "label": "Pelmet", + "description": "Static valance framing the top of the stage.", + "default": "on", + "options": [ + { "value": "on", "label": "On" }, + { "value": "off", "label": "Off" } + ] + }, + { + "id": "spotlight", + "type": "enum", + "role": "style", + "label": "Spotlight", + "description": "Soft glow blooming over the stage as the curtains part.", + "default": "on", + "options": [ + { "value": "on", "label": "On" }, + { "value": "off", "label": "Off" } + ] + } + ] +} diff --git a/registry/components/dart-cursor/dart-cursor.html b/registry/components/dart-cursor/dart-cursor.html new file mode 100644 index 0000000000..979655bbb9 --- /dev/null +++ b/registry/components/dart-cursor/dart-cursor.html @@ -0,0 +1,357 @@ + + + + + + Dart Cursor + + + + + diff --git a/registry/components/dart-cursor/demo.html b/registry/components/dart-cursor/demo.html new file mode 100644 index 0000000000..a5060a4011 --- /dev/null +++ b/registry/components/dart-cursor/demo.html @@ -0,0 +1,326 @@ + + + + + + + Dart Cursor, Demo + + + + +
+
+
Export
+
+ +
0:42
+
+
product-tour.mp4
+
42 seconds, 30 fps, stereo audio
+ +
Resolution
+
+
+
720p
+
1080p
+
4K
+
+ +
Format
+
+
+
MP4
+
MOV
+
GIF
+
+ +
Cancel
+
+ Export video + Exporting… +
+ + Exported +
+
+ +
+
+ + + + diff --git a/registry/components/dart-cursor/registry-item.json b/registry/components/dart-cursor/registry-item.json new file mode 100644 index 0000000000..aaeb62beb5 --- /dev/null +++ b/registry/components/dart-cursor/registry-item.json @@ -0,0 +1,115 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "dart-cursor", + "type": "hyperframes:component", + "title": "Dart Cursor", + "description": "A bold outlined arrowhead that dives in from camera depth, flies nose-first with motion blur along its path, squashes on two clicks, and whips out of frame.", + "tags": ["cursor", "motion-primitive", "pointer", "click", "motion-blur", "depth"], + "files": [ + { + "path": "dart-cursor.html", + "target": "compositions/components/dart-cursor.html", + "type": "hyperframes:snippet" + } + ], + "jobs": ["demonstrate"], + "family": "pointers", + "profile": "interaction", + "syncPoints": [ + { "id": "first-click", "phase": "in", "offset": 0.7 }, + { "id": "second-click", "phase": "in", "offset": 1.7 } + ], + "variables": [ + { + "id": "tone", + "type": "enum", + "role": "style", + "label": "Tone", + "default": "dark", + "options": [ + { "value": "dark", "label": "Dark body, white outline" }, + { "value": "light", "label": "Light body, dark outline" } + ] + }, + { + "id": "target_x", + "type": "number", + "role": "layout", + "label": "First click X", + "default": 34, + "min": 5, + "max": 95, + "step": 1, + "unit": "%" + }, + { + "id": "target_y", + "type": "number", + "role": "layout", + "label": "First click Y", + "default": 58, + "min": 5, + "max": 95, + "step": 1, + "unit": "%" + }, + { + "id": "target2_x", + "type": "number", + "role": "layout", + "label": "Second click X", + "default": 64, + "min": 5, + "max": 95, + "step": 1, + "unit": "%" + }, + { + "id": "target2_y", + "type": "number", + "role": "layout", + "label": "Second click Y", + "default": 46, + "min": 5, + "max": 95, + "step": 1, + "unit": "%" + }, + { + "id": "enter_from", + "type": "enum", + "role": "timing", + "label": "Enter from", + "default": "right", + "options": [ + { "value": "right", "label": "Right" }, + { "value": "left", "label": "Left" }, + { "value": "top", "label": "Top" }, + { "value": "bottom", "label": "Bottom" } + ] + }, + { + "id": "exit_to", + "type": "enum", + "role": "timing", + "label": "Exit to", + "default": "right", + "options": [ + { "value": "right", "label": "Right" }, + { "value": "left", "label": "Left" }, + { "value": "top", "label": "Top" }, + { "value": "bottom", "label": "Bottom" } + ] + }, + { + "id": "blur", + "type": "number", + "role": "style", + "label": "Motion blur", + "default": 1, + "min": 0, + "max": 1.5, + "step": 0.1 + } + ] +} diff --git a/registry/components/fade-through/registry-item.json b/registry/components/fade-through/registry-item.json index 57b71aedd4..e0cfcd3355 100644 --- a/registry/components/fade-through/registry-item.json +++ b/registry/components/fade-through/registry-item.json @@ -4,7 +4,7 @@ "type": "hyperframes:component", "title": "Fade Through", "description": "A calm transition primitive that fades one layer out, passes through a wash, and reveals the next layer", - "tags": ["motion-primitive", "transition", "fade", "scene"], + "tags": ["motion-primitive", "transition", "fade", "crossfade", "scene"], "files": [ { "path": "fade-through.html", diff --git a/registry/components/magnetic-cursor/demo.html b/registry/components/magnetic-cursor/demo.html new file mode 100644 index 0000000000..6bbc196d39 --- /dev/null +++ b/registry/components/magnetic-cursor/demo.html @@ -0,0 +1,124 @@ + + + + + + + Magnetic Cursor, Demo + + + + +
+
+

Launch notes, week 38

+

+ The new onboarding flow ships to everyone on Thursday, and the old setup wizard stays + behind a flag for one more week. Before your first support shift, please read the + rollout checklist + and flag anything that still reads unclear. +

+

Open questions go in the team thread, not in comments here.

+
+ +
+
+ + + + diff --git a/registry/components/magnetic-cursor/magnetic-cursor.html b/registry/components/magnetic-cursor/magnetic-cursor.html new file mode 100644 index 0000000000..9917ee637c --- /dev/null +++ b/registry/components/magnetic-cursor/magnetic-cursor.html @@ -0,0 +1,427 @@ + + + + + + Magnetic Cursor + + + + + diff --git a/registry/components/magnetic-cursor/registry-item.json b/registry/components/magnetic-cursor/registry-item.json new file mode 100644 index 0000000000..2ef9148b05 --- /dev/null +++ b/registry/components/magnetic-cursor/registry-item.json @@ -0,0 +1,51 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "magnetic-cursor", + "type": "hyperframes:component", + "title": "Magnetic Cursor", + "description": "A soft dot pointer glides across an editor toolbar, is pulled into each button and morphs into its rounded hover plate while the icon leans toward it, presses one, and leaves as a dot.", + "tags": ["cursor", "motion-primitive", "pointer", "hover", "morph", "toolbar"], + "files": [ + { + "path": "magnetic-cursor.html", + "target": "compositions/components/magnetic-cursor.html", + "type": "hyperframes:snippet" + } + ], + "jobs": ["demonstrate"], + "family": "pointers", + "profile": "interaction", + "syncPoints": [{ "id": "press", "phase": "hold", "offset": 1.91 }], + "variables": [ + { "id": "accent", "type": "color", "role": "style", "label": "Accent", "default": "#3b82f6" }, + { + "id": "tone", + "type": "enum", + "role": "style", + "label": "Tone", + "default": "light", + "options": [ + { "value": "light", "label": "Light toolbar" }, + { "value": "dark", "label": "Dark toolbar" } + ] + }, + { + "id": "visits", + "type": "string", + "role": "content", + "label": "Buttons visited", + "description": "Comma-separated indexes 0-5: bold, italic, underline, link, list, image.", + "default": "0,3" + }, + { + "id": "press", + "type": "number", + "role": "timing", + "label": "Pressed visit", + "default": 2, + "min": 1, + "max": 3, + "step": 1 + } + ] +} diff --git a/registry/components/oversized-cursor/README.md b/registry/components/oversized-cursor/README.md index 6456b1223a..46a9674a26 100644 --- a/registry/components/oversized-cursor/README.md +++ b/registry/components/oversized-cursor/README.md @@ -1,8 +1,8 @@ # oversized-cursor -An actor primitive: a deliberately oversized macOS-style pointer enters from off-screen, glides in one continuous vector to a caller-positioned target, taps it (the click visibly ignites the target), drifts aside during the dwell, then accelerates off-screen. One mechanic: a pointer-driven click that visibly causes something. +The look-here pointer for a video: the family macOS arrow at 3.5x its normal size (224px box at 1920 wide) enters from off-screen, lands its tip on a caller-positioned control, clicks it (the control switches on in the accent blue with a check), settles just below it so the result stays in view, then accelerates off-screen. -4.2s authored, elastic HOLD; the cursor's own physical off-screen exit always plays (it is the mechanic). +2.6s authored, elastic HOLD; the cursor's own physical off-screen exit always plays (it is the mechanic). ## Variables @@ -11,7 +11,7 @@ An actor primitive: a deliberately oversized macOS-style pointer enters from off | `cursor_variant` | enum | `light` | `light` (white body) or `dark` (near-black body); pick per scene contrast. | | `target_x` | number (%) | `55` | Tip landing point, percent of the host box (15 to 85). | | `target_y` | number (%) | `55` | Tip landing point, percent of the host box (15 to 85). | -| `click_label` | string | `Generate` | Label on the clicked target pill. | +| `click_label` | string | `Generate` | Label on the clicked control. It gains a check when switched on, so a noun or state reads best. | | `exit` | enum | `none` | `none` leaves the ignited target on screen until the cut; `fade`/`up` also depart the whole stage (target included) during the OUT window. | ## Mount @@ -23,7 +23,7 @@ An actor primitive: a deliberately oversized macOS-style pointer enters from off data-composition-src="./oversized-cursor.html" data-variable-values='{"target_x":62,"target_y":48,"click_label":"Render"}' data-start="0" - data-duration="4.2" + data-duration="2.6" data-track-index="0" >
``` @@ -32,5 +32,5 @@ Elastic root: no `data-width`/`data-height`; it fills whatever box the host clip ## Notes -- Invariants: cursor size floor 7cqw; motion on transforms only (never left/top); ripple and click pivot anchor to the arrow tip at (21%, 14%) of the cursor box. -- Sync point: the click lands at the end of the entry glide (a fixed offset into IN, never inside the elastic HOLD); route a soft UI click SFX there in the mix stage. +- Invariants: cursor box 11.67cqw (3.5x the family's 64u arrow); motion on transforms only (never left/top); the click pivots on the arrow tip at (5/24, 3/24) of the cursor box. +- Sync point: the click lands at 0.7s (0.5s glide plus 0.2s aim, a fixed offset into IN, never inside the elastic HOLD); route a soft UI click SFX there in the mix stage. diff --git a/registry/components/oversized-cursor/demo.html b/registry/components/oversized-cursor/demo.html index 96edf3dcaa..2ac36bdf4c 100644 --- a/registry/components/oversized-cursor/demo.html +++ b/registry/components/oversized-cursor/demo.html @@ -2,11 +2,9 @@ @@ -34,22 +32,217 @@ width: 1920px; height: 1080px; overflow: hidden; - background: var(--bg, #05070c); - font-family: var(--font-body, Inter, system-ui, sans-serif); + background: #111318; + font-family: Inter, system-ui, sans-serif; + -webkit-font-smoothing: antialiased; } .demo-frame { position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 1280px; - height: 720px; - border-radius: 24px; - border: 1px solid var(--border, rgba(148, 163, 184, 0.25)); - background: var(--surface, #0b0f16); - box-shadow: 0 40px 120px rgba(2, 6, 23, 0.55); + left: 280px; + top: 150px; + width: 1360px; + height: 780px; + border-radius: 14px; + background: #ffffff; + box-shadow: + 0 0 0 1px rgba(255, 255, 255, 0.06), + 0 2px 6px rgba(0, 0, 0, 0.3), + 0 30px 80px rgba(0, 0, 0, 0.45); overflow: hidden; + color: #1c1c1e; + } + .app-titlebar { + display: flex; + align-items: center; + gap: 9px; + height: 52px; + padding: 0 20px; + border-bottom: 1px solid rgba(0, 0, 0, 0.08); + background: #f6f6f7; + } + .app-titlebar i { + width: 13px; + height: 13px; + border-radius: 50%; + background: #ff5f57; + } + .app-titlebar i:nth-child(2) { + background: #febc2e; + } + .app-titlebar i:nth-child(3) { + background: #28c840; + } + .app-titlebar span { + flex: 1; + margin-right: 57px; + text-align: center; + font-size: 15px; + font-weight: 600; + color: #6e6e73; + } + .app-body { + display: flex; + height: 728px; + } + .app-side { + width: 300px; + padding: 22px 14px; + border-right: 1px solid rgba(0, 0, 0, 0.08); + background: #fafafa; + } + .app-side h4 { + margin: 0 10px 12px; + font-size: 13px; + font-weight: 600; + letter-spacing: 0.04em; + text-transform: uppercase; + color: #8e8e93; + } + .app-post { + padding: 12px 12px; + border-radius: 9px; + font-size: 17px; + font-weight: 500; + line-height: 1.3; + } + .app-post small { + display: block; + margin-top: 3px; + font-size: 14px; + font-weight: 400; + color: #8e8e93; + } + .app-post.is-open { + background: rgba(10, 132, 255, 0.1); + } + .app-main { + position: relative; + flex: 1; + } + .app-toolbar { + position: relative; + display: flex; + align-items: center; + height: 72px; + padding: 0 36px; + border-bottom: 1px solid rgba(0, 0, 0, 0.08); + font-size: 16px; + color: #8e8e93; + } + .app-toolbar b { + margin-left: 8px; + font-weight: 500; + color: #1c1c1e; + } + /* Ends left of the Comments toggle, which the cursor mount draws. */ + .app-actions { + position: absolute; + right: 220px; + top: 50%; + display: flex; + align-items: center; + gap: 14px; + transform: translateY(-50%); + } + .app-chip { + display: flex; + align-items: center; + gap: 8px; + height: 34px; + padding: 0 14px; + border-radius: 17px; + font-size: 15px; + font-weight: 500; + white-space: nowrap; + background: #f2f2f3; + color: #6e6e73; + } + .app-chip::before { + content: ""; + width: 8px; + height: 8px; + border-radius: 50%; + background: #aeaeb2; + } + .app-ghost { + height: 42px; + padding: 0 18px; + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 10px; + font-size: 19px; + font-weight: 600; + line-height: 40px; + color: #1c1c1e; + } + .app-doc { + max-width: 680px; + margin: 52px 0 0 84px; + } + .app-doc h1 { + margin: 0; + font-size: 44px; + font-weight: 700; + letter-spacing: -0.02em; + line-height: 1.15; + } + .app-meta { + margin: 14px 0 30px; + font-size: 16px; + color: #8e8e93; + } + .app-doc p { + margin: 0 0 20px; + font-size: 20px; + line-height: 1.6; + color: #3a3a3c; + } + .app-doc mark { + border-radius: 3px; + background: rgba(255, 204, 0, 0); + color: inherit; + } + .app-comment { + position: absolute; + left: 785px; + top: 372px; + width: 236px; + padding: 14px 16px; + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 12px; + background: #ffffff; + box-shadow: + 0 1px 2px rgba(0, 0, 0, 0.06), + 0 8px 24px rgba(0, 0, 0, 0.08); + font-size: 16px; + line-height: 1.45; + color: #3a3a3c; + opacity: 0; + } + .app-comment b { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 6px; + font-size: 15px; + font-weight: 600; + color: #1c1c1e; + } + .app-comment b i { + width: 24px; + height: 24px; + border-radius: 50%; + background: #ff9f0a; + font-size: 11px; + font-style: normal; + line-height: 24px; + text-align: center; + color: #ffffff; + } + .app-comment small { + font-size: 14px; + font-weight: 400; + color: #8e8e93; } @@ -60,41 +253,84 @@ data-start="0" data-width="1920" data-height="1080" - data-duration="4.2" + data-duration="2.6" >
+ > +
Field Notes
+
+ +
+
+ Posts /Offline mode, one year in +
+ Draft + Preview +
+
+
+

Offline mode, one year in

+
Priya Raman · 6 min read
+

+ A year ago we shipped offline mode to every workspace. Since then, 38% of edits have + happened on a plane, a train, or a flaky café connection. +

+

+ Most of that traffic lands in the first ten minutes after a device reconnects, so + this post walks through how + the sync queue drains without locking the editor. +

+
+
+ SKSam Kim 2h + Could this be a diagram? The drain order is the whole point. +
+
+
+
diff --git a/registry/components/oversized-cursor/oversized-cursor.html b/registry/components/oversized-cursor/oversized-cursor.html index c55b0e51e1..fd943663fe 100644 --- a/registry/components/oversized-cursor/oversized-cursor.html +++ b/registry/components/oversized-cursor/oversized-cursor.html @@ -2,15 +2,10 @@ -
+
- - +
+ + +
``` ## Variables -| id | type | default | notes | -| -------- | ------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| label | string | "Get started" | Text in the default pill. Ignored when the slot is replaced. | -| target_x | number | 50 | Zone center, percent of host width (8 to 92). | -| target_y | number | 50 | Zone center, percent of host height (8 to 92). | -| press_at | number | 1.4 | Seconds from mount start when the compression begins. Clamped so the press tail (release, ripple, cursor exit, ~1.05s) and any exit stay inside the clip duration. | -| cursor | enum | light | light (white pointer, dark stroke) or dark (inverse). | -| accent | enum | green | green maps to --brand, blue to --accent, violet to --accent-2. Colors the ripple ink and the pressed fill. | -| exit | enum | none | none holds the pressed state (frame roots own transitions); fade or up add a 0.45s departure. | +| id | type | default | notes | +| ---------- | ------ | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| label | string | "Get started" | Text in the default pill. Ignored when the slot is replaced. | +| done_label | string | "Saved" | Text beside the check once the default pill is pressed. Keep it no wider than `label`; the pill keeps the label's width. | +| target_x | number | 50 | Zone center, percent of host width (8 to 92). | +| target_y | number | 50 | Zone center, percent of host height (8 to 92). | +| press_at | number | 0.9 | Seconds from mount start when the compression begins. Clamped so the press tail (release, rings, cursor exit, 0.8s) and any exit stay inside the clip duration. | +| cursor | enum | light | light (white pointer, dark stroke) or dark (inverse). | +| accent | enum | green | green maps to --brand, blue to --accent, violet to --accent-2. Colors the click rings and the confirmation check. | +| exit | enum | none | none holds the pressed state (frame roots own transitions); fade or up add a 0.45s departure. | ## Target slot The element marked `data-slot="target"` is the press surface. Its default child is a token-styled pill (`--surface` body, `--border` edge, `--font-body` at -weight 600) carrying `label`. Replace the slot's children in your installed copy +weight 600) carrying `label`, and a check plus `done_label` layered over it. +The pill keeps its fill when pressed; only the label changes. Replace the slot's children in your installed copy to press anything else: an icon button, a card, a toggle. The slot wrapper flips `data-state="idle"` to `data-state="pressed"` at the @@ -54,17 +56,19 @@ key its own pressed look off that attribute, mirroring the default rule: ## Choreography - 0.00s: target settles in (fade + short rise, power3.out). -- press_at - 0.94s: cursor departs off-stage bottom-right, decelerating the - whole way, tip landing slightly below-right of the zone center (human aim). +- press_at - 0.6s: cursor departs off-stage bottom-right (0.45s, power3.out), + tip landing slightly below-right of the zone center (human aim), then a + 0.15s dwell. - press_at: target and cursor compress to 0.93 in lockstep (cursor scales about its tip). -- press_at + 0.12s: pressed state lands; release springs back (back.out) while - two thick ink rings (accent mixed toward `--fg` for contrast) ripple out from - under the slot, 0.11s apart. -- press_at + 0.5s: the cursor exits off-stage bottom-right (power2.in, +- press_at + 0.12s: pressed state lands; release springs back (back.out). Two + 2px accent rings grow from the cursor tip, 16px to 72px radius at 1920 wide + (320ms, power2.out), the second 60ms behind at 60% opacity. The label swaps + to a check plus `done_label` (scale 0.3 to 1, blur 3px to 0, 300ms). +- press_at + 0.4s: the cursor exits off-stage bottom-right (0.4s, power2.in, accelerating away), clearing the label before the hold begins. -- HOLD: dead still on the pressed state, elastic with the clip duration; the - pressed control and the ripple aftermath carry the frame, cursor gone. +- HOLD: dead still on the confirmed state, elastic with the clip duration, + cursor gone. Sync point `press` fires the moment compression starts; align SFX or a downstream reveal to it. diff --git a/registry/components/press-ripple/demo.html b/registry/components/press-ripple/demo.html index 8d33add162..642ab65aea 100644 --- a/registry/components/press-ripple/demo.html +++ b/registry/components/press-ripple/demo.html @@ -2,9 +2,8 @@ @@ -23,22 +22,22 @@ width: 1920px; height: 1080px; overflow: hidden; - background: var(--bg, #f4f6f9); + background: var(--bg, #f4f4f5); } #root { - --bg: #f4f6f9; + --bg: #f4f4f5; --fg: #14161b; --surface: #ffffff; --border: #dfe4ec; - --brand: #1d4ed8; + --brand: #0a84ff; --accent: #0284c7; --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace; position: relative; width: 1920px; height: 1080px; overflow: hidden; - background: radial-gradient(ellipse at 50% 40%, #ffffff 0%, var(--bg, #f4f6f9) 70%); + background: var(--bg); } .mount-stage { @@ -58,7 +57,7 @@ data-start="0" data-width="1920" data-height="1080" - data-duration="3" + data-duration="2.4" data-fps="30" >
@@ -54,7 +57,7 @@