Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f5e5caa
feat(registry): add texture mask PNGs for texture-mask-text component
vanceingalls May 6, 2026
a7a5161
feat(registry): add texture-mask-text CSS snippet
vanceingalls May 6, 2026
093e9fd
feat(registry): add registry-item.json for texture-mask-text
vanceingalls May 6, 2026
ad6e00c
feat(registry): add texture-mask-text demo composition
vanceingalls May 6, 2026
f48fea4
feat(registry): register texture-mask-text component in manifest
vanceingalls May 6, 2026
2c17c4f
style: format texture-mask-text files with oxfmt
vanceingalls May 6, 2026
00607f8
fix: set mask-image directly on texture classes instead of via CSS cu…
vanceingalls May 6, 2026
0cd9197
docs: add texture mask text catalog entry
vanceingalls May 6, 2026
028433a
test: lint texture mask text usage
vanceingalls May 6, 2026
0cf2569
fix: harden texture mask text docs and lint
vanceingalls May 6, 2026
f3173ce
fix: stabilize texture mask asset paths
vanceingalls May 6, 2026
ab11217
fix: address texture catalog review feedback
vanceingalls May 6, 2026
e1accf8
fix: harden texture mask text instructions
vanceingalls May 6, 2026
33f3974
docs: remove texture catalog intro copy
vanceingalls May 6, 2026
727cf8c
docs: use canonical texture preview URL
vanceingalls May 6, 2026
a2680c0
docs: use cdn texture mask assets
vanceingalls May 6, 2026
7d3c0f6
fix: escape catalog frontmatter safely
vanceingalls May 6, 2026
75a6bae
test: stabilize windows render cli test
vanceingalls May 6, 2026
7efdd17
test: pin texture catalog instructions
vanceingalls May 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
487 changes: 487 additions & 0 deletions docs/catalog/components/texture-mask-text.mdx

Large diffs are not rendered by default.

263 changes: 263 additions & 0 deletions docs/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,266 @@ a:not([class]) {
a:not([class]):hover {
opacity: 0.85;
}

/* Catalog texture examples */

.hf-texture-preview-panel {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
margin: 24px 0 40px;
}

.hf-texture-preview-card {
min-width: 0;
border: 1px solid rgba(127, 127, 127, 0.22);
border-radius: 8px;
padding: 16px;
background: #101010;
}

.hf-texture-preview-label {
margin-bottom: 12px;
color: rgba(255, 255, 255, 0.6);
font-size: 12px;
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.hf-texture-preview-shadow {
filter: drop-shadow(1px 2px 1px rgba(0, 0, 0, 0.48));
}

.hf-texture-preview-word {
color: #fff;
font-family: Impact, 'Arial Black', sans-serif;
font-size: 42px;
line-height: 0.9;
letter-spacing: 0;
text-align: center;
text-transform: uppercase;
white-space: nowrap;
-webkit-mask-image: var(--mask-url);
mask-image: var(--mask-url);
-webkit-mask-size: cover;
mask-size: cover;
-webkit-mask-position: center;
mask-position: center;
-webkit-mask-mode: luminance;
mask-mode: luminance;
}

.hf-texture-animate-demo {
border: 1px solid rgba(127, 127, 127, 0.22);
border-radius: 8px;
padding: 22px;
margin: 20px 0 24px;
background:
linear-gradient(90deg, rgba(255, 255, 255, 0.54) 1px, transparent 1px),
#f1f1f1;
background-size: 44px 100%;
}

.hf-texture-animate-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 18px;
}

.hf-texture-animate-label {
min-width: 0;
color: rgba(24, 24, 24, 0.62);
font-size: 13px;
line-height: 1.2;
}

.hf-texture-animate-class {
max-width: 62%;
padding: 2px 6px;
border: 1px solid rgba(24, 24, 24, 0.12);
border-radius: 6px;
background: rgba(255, 255, 255, 0.5);
color: rgba(24, 24, 24, 0.78);
font-size: 11px;
line-height: 1.3;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.hf-texture-animate-shadow {
filter: drop-shadow(1px 2px 1px rgba(0, 0, 0, 0.48));
}

.hf-texture-animate-word {
color: #181818;
font-family: Impact, 'Arial Black', sans-serif;
font-size: 92px;
line-height: 0.9;
letter-spacing: 0;
text-align: center;
text-transform: uppercase;
white-space: nowrap;
-webkit-mask-image: var(--mask-url);
mask-image: var(--mask-url);
-webkit-mask-size: 180% 180%;
mask-size: 180% 180%;
-webkit-mask-position: 0% 50%;
mask-position: 0% 50%;
-webkit-mask-mode: luminance;
mask-mode: luminance;
animation: hf-texture-mask-pan 2.1s ease-in-out infinite alternate;
}

@keyframes hf-texture-mask-pan {
from {
-webkit-mask-position: 0% 50%;
mask-position: 0% 50%;
}

to {
-webkit-mask-position: 100% 50%;
mask-position: 100% 50%;
}
}

.hf-texture-example-groups {
display: grid;
gap: 32px;
margin: 20px 0 40px;
}

.hf-texture-example-title {
margin: 0 0 10px;
font-size: 14px;
font-weight: 600;
}

.hf-texture-example-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
gap: 16px;
}

.hf-texture-example-card {
border: 1px solid rgba(127, 127, 127, 0.22);
border-radius: 8px;
padding: 20px;
background: #f1f1f1;
}

.hf-texture-example-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 14px;
}

.hf-texture-example-label {
min-width: 0;
color: rgba(24, 24, 24, 0.62);
font-size: 13px;
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.hf-texture-example-class {
max-width: 62%;
padding: 2px 6px;
border: 1px solid rgba(24, 24, 24, 0.12);
border-radius: 6px;
background: rgba(255, 255, 255, 0.5);
color: rgba(24, 24, 24, 0.78);
font-size: 11px;
line-height: 1.3;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.hf-texture-example-shadow {
filter: drop-shadow(1px 2px 1px rgba(0, 0, 0, 0.48));
}

.hf-texture-example-word {
color: #181818;
font-family: Impact, 'Arial Black', sans-serif;
font-size: 54px;
line-height: 0.9;
letter-spacing: 0;
text-align: center;
text-transform: uppercase;
white-space: nowrap;
-webkit-mask-image: var(--mask-url);
mask-image: var(--mask-url);
-webkit-mask-size: cover;
mask-size: cover;
-webkit-mask-position: center;
mask-position: center;
-webkit-mask-mode: luminance;
mask-mode: luminance;
}

.hf-texture-example-usage {
display: flex;
align-items: flex-start;
gap: 6px;
min-width: 0;
margin-top: 14px;
padding-top: 12px;
border-top: 1px solid rgba(24, 24, 24, 0.1);
color: rgba(24, 24, 24, 0.56);
font-size: 12px;
line-height: 1.3;
}

.hf-texture-example-usage code {
min-width: 0;
color: rgba(24, 24, 24, 0.82);
font-size: 11px;
line-height: 1.3;
white-space: normal;
overflow-wrap: anywhere;
}

@media (max-width: 860px) {
.hf-texture-preview-panel {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}

@media (max-width: 520px) {
.hf-texture-preview-panel {
grid-template-columns: 1fr;
}

.hf-texture-preview-word {
font-size: 40px;
}

.hf-texture-animate-meta {
align-items: flex-start;
flex-direction: column;
}

.hf-texture-animate-class {
max-width: 100%;
}

.hf-texture-animate-word {
font-size: 56px;
}
}

@media (prefers-reduced-motion: reduce) {
.hf-texture-animate-word {
animation: none;
}
}
3 changes: 2 additions & 1 deletion docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@
"pages": [
"catalog/components/grain-overlay",
"catalog/components/grid-pixelate-wipe",
"catalog/components/shimmer-sweep"
"catalog/components/shimmer-sweep",
"catalog/components/texture-mask-text"
]
},
{
Expand Down
14 changes: 14 additions & 0 deletions docs/public/catalog-index.json
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,20 @@
"href": "/catalog/blocks/swirl-vortex",
"preview": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/swirl-vortex.png"
},
{
"name": "texture-mask-text",
"type": "component",
"title": "Texture Mask Text",
"description": "CSS luminance masks that cut holes through letterforms - 66 pre-built texture masks from ambientCG PBR color maps",
"tags": [
"text",
"texture",
"mask",
"effect"
],
"href": "/catalog/components/texture-mask-text",
"preview": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/texture-mask-text.png"
},
{
"name": "thermal-distortion",
"type": "block",
Expand Down
10 changes: 8 additions & 2 deletions packages/cli/src/commands/add.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ const COMPONENT_ITEM: RegistryItem = {
target: "compositions/components/my-component/my-component.css",
type: "hyperframes:style",
},
{
path: "assets/mask.png",
target: "assets/my-component/mask.png",
type: "hyperframes:asset",
},
],
};

Expand Down Expand Up @@ -190,7 +195,7 @@ describe("runAdd (integration, mocked registry)", () => {
}
});

it("remaps component targets per hyperframes.json paths.components", async () => {
it("remaps component snippet/style targets while leaving asset targets stable", async () => {
const dir = tmp();
try {
const baseUrl = uniqueBase();
Expand All @@ -206,9 +211,10 @@ describe("runAdd (integration, mocked registry)", () => {
projectDir: dir,
skipClipboard: true,
});
expect(result.written.length).toBe(2);
expect(result.written.length).toBe(3);
expect(existsSync(join(dir, "src/fx/my-component/my-component.html"))).toBe(true);
expect(existsSync(join(dir, "src/fx/my-component/my-component.css"))).toBe(true);
expect(existsSync(join(dir, "assets/my-component/mask.png"))).toBe(true);
expect(result.snippet).toContain("src/fx/my-component/my-component.html");
} finally {
rmSync(dir, { recursive: true, force: true });
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/render.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ describe("renderLocal browser GPU config", () => {
browserGpuMode: "software",
resolved: true,
});
});
}, 15_000);

it("forwards browserGpuMode='auto' into producer config (probe-then-choose)", async () => {
const { renderLocal } = await import("./render.js");
Expand Down
Loading
Loading