fix(site-builder): add Hero/CTA components to Layers virtual-rows registry
A grep across every component under src/components/ (not just the 12
files the original registry hardcoded) turns up three more leaf
components with the identical array-prop-as-content pattern: Hero
(HeroSimple.tsx), Call to Action (CallToAction.tsx) and CTA Section
(CTASection.tsx) all render a shared `ctas?: CtaButton[]` prop whose
items are `{ text, href, variant?, target? }`. Without this, a Hero's
CTA buttons still wouldn't appear in the Layers tree.
Verified displayName, prop name and label field against each
component's craft.props defaults and the shared CtaButton type in
sections/_cta-helpers.tsx -- all three matched exactly, no corrections
needed. A follow-up sweep for any further array-prop leaf components
found none: the only other array fields in the tree are nested one
level inside already-covered items (ContactFormField.options,
PricingPlan.features), not top-level component props.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -45,6 +45,35 @@ describe('deriveVirtualRows', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
test('Hero, Call to Action and CTA Section derive rows from their shared ctas prop', () => {
|
||||
const ctas = [
|
||||
{ text: 'Get Started', href: '#', variant: 'primary' },
|
||||
{ text: 'Learn More', href: '#learn', variant: 'outline' },
|
||||
];
|
||||
expect(deriveVirtualRows('Hero', { ctas })).toEqual([
|
||||
{ index: 0, label: 'Get Started' },
|
||||
{ index: 1, label: 'Learn More' },
|
||||
]);
|
||||
expect(deriveVirtualRows('Call to Action', { ctas })).toEqual([
|
||||
{ index: 0, label: 'Get Started' },
|
||||
{ index: 1, label: 'Learn More' },
|
||||
]);
|
||||
expect(deriveVirtualRows('CTA Section', { ctas })).toEqual([
|
||||
{ index: 0, label: 'Get Started' },
|
||||
{ index: 1, label: 'Learn More' },
|
||||
]);
|
||||
});
|
||||
|
||||
test('a CTA with no text falls back to "Button N"', () => {
|
||||
const rows = deriveVirtualRows('Hero', {
|
||||
ctas: [{ href: '#' }, { text: '', href: '#empty' }],
|
||||
});
|
||||
expect(rows).toEqual([
|
||||
{ index: 0, label: 'Button 1' },
|
||||
{ index: 1, label: 'Button 2' },
|
||||
]);
|
||||
});
|
||||
|
||||
test('every registry entry has a non-empty prop, label and fallback', () => {
|
||||
for (const [name, spec] of Object.entries(VIRTUAL_CHILD_PROPS)) {
|
||||
expect(spec.prop, `${name}.prop`).toBeTruthy();
|
||||
|
||||
@@ -38,7 +38,18 @@ export interface VirtualChildSpec {
|
||||
* - ContentSlider items are `{ heading, text, ... }`, not `{ title }` --
|
||||
* registry corrected from `title` to `heading`.
|
||||
* Every other entry (prop name and label field) matched the component as
|
||||
* originally drafted. */
|
||||
* originally drafted.
|
||||
*
|
||||
* Hero, Call to Action and CTA Section were added after a follow-up sweep
|
||||
* of every component under src/components/ for top-level array props (not
|
||||
* just the 12 files initially listed) turned up three more leaf components
|
||||
* with the identical pattern: all three render a `ctas?: CtaButton[]` prop
|
||||
* (see sections/_cta-helpers.tsx) whose items are `{ text, href, variant?,
|
||||
* target? }`, so `text` is the label field. Verified against each file's
|
||||
* `craft.displayName` and `craft.props.ctas` defaults. That sweep found no
|
||||
* further candidates -- the only other array fields in the tree are nested
|
||||
* one level down inside already-covered items (ContactFormField.options,
|
||||
* PricingPlan.features), not top-level component props. */
|
||||
export const VIRTUAL_CHILD_PROPS: Record<string, VirtualChildSpec> = {
|
||||
'Features Grid': { prop: 'features', label: 'title', fallback: 'Feature' },
|
||||
Tabs: { prop: 'tabs', label: 'label', fallback: 'Tab' },
|
||||
@@ -52,6 +63,9 @@ export const VIRTUAL_CHILD_PROPS: Record<string, VirtualChildSpec> = {
|
||||
'Social Links': { prop: 'links', label: 'platform', fallback: 'Link' },
|
||||
Navbar: { prop: 'links', label: 'text', fallback: 'Link' },
|
||||
'Contact Form': { prop: 'fields', label: 'label', fallback: 'Field' },
|
||||
Hero: { prop: 'ctas', label: 'text', fallback: 'Button' },
|
||||
'Call to Action': { prop: 'ctas', label: 'text', fallback: 'Button' },
|
||||
'CTA Section': { prop: 'ctas', label: 'text', fallback: 'Button' },
|
||||
};
|
||||
|
||||
const MAX_LABEL = 40;
|
||||
|
||||
Reference in New Issue
Block a user