HomeComponentData and home block item types
Describes the home page blocks a merchant arranges, and the brand, feature, testimonial and slide items some blocks list.
import { HomeComponentData, HomeComponent, Brand, Feature, Testimonial, Slider, HomeComponentConfig } from '@salla.sa/twilight-theme-engine/types';In plain words
A store's home page is a list of blocks the merchant arranges in the Salla dashboard: a slider, a row of brands, a list of store features. HomeComponentData is one block: path says which block it is, and the block's own settings sit next to it.
Brand, Feature, Testimonial and Slider describe items inside some blocks, and HomeComponent the fields of a products block. Check each one against the live demo before relying on it: only some of them match what the API sends.
Signature
interface HomeComponentData {
path: string; // e.g. 'home.brands', 'store-features'
key?: string | number | null;
view_style?: string | null;
component?: JsonObject;
[key: string]: string | number | boolean | null | JsonObject | undefined;
}
interface HomeComponent { // the fields of a products block
title?: string; description?: string; background?: string;
products?: Product[]; display_all_url?: string;
}
interface Brand { id: number; name: string; logo: string; url: string }
interface Feature { icon: string; title: string; description?: string }
interface Testimonial { id: number; name: string; content: string; rating?: number; image?: string }
interface Slider { id: number; image: string; link?: string; title?: string; description?: string }
interface HomeComponentConfig { // not the type registerHomeComponentConfig takes
key: string; title?: string; path: string; position: number; data: JsonObject;
}Try it live
id and content never arrive, and the text, rating and image come as text, stars and avatar.Loading the home page blocks…
import type { Brand } from '@salla.sa/twilight-theme-engine/types';
// Registered as 'brands': the home loader strips "home." from the block path.
export function BrandsBlock({ data }: { data: { brands: Brand[]; [key: string]: unknown } }) {
return (
<ul className="brands-block">
{data.brands.map((brand) => (
// brand.id is a string path on the wire: fine as a key, never for math.
<li key={brand.id}>
<img src={brand.logo} alt={brand.name} width={160} height={120} />
</li>
))}
</ul>
);
}
Example
import type { Brand } from '@salla.sa/twilight-theme-engine/types';
import { Link } from '@salla.sa/twilight-theme-engine/components/common';
export interface BrandsBlockProps {
// Declare the block's own data: HomeComponentData's index signature rejects arrays.
data: { brands: Brand[]; title?: string; [key: string]: unknown };
}
export function BrandsBlock({ data }: BrandsBlockProps) {
if (!data.brands.length) return null;
return (
<section className="s-block container">
{data.title && <h2>{data.title}</h2>}
<div className="brands-grid">
{data.brands.map((brand) => (
<Link key={brand.id} to={brand.url}>
<img src={brand.logo} alt={brand.name} width={160} height={120} />
</Link>
))}
</div>
</section>
);
}
// app/router.tsx: the home loader strips "home." from paths, so 'home.brands' registers as 'brands'.
// registerHomeComponents({ ...DefaultHomeComponents, brands: BrandsBlock });
How it behaves
home.components()andhome.queries.components()(@salla.sa/twilight-theme-engine/api/home) returnHomeComponentData[]exactly as the API sends them. The engine home loader then removes the firsthome.from eachpath, andHomeComponentRendererlooks uphome:<path>:<view_style>, thenhome:<path>, in the component registry.The reference theme types its blocks the way the example does:
Brandstakes{ brands: Brand[]; title?: string; [key: string]: unknown }, andCustomTestimonialsdeclares its ownTestimonialIteminstead of usingTestimonial.In the engine,
StoreFeaturesreadsFeatureand the home loader and renderer readHomeComponentData. Nothing readsBrand,HomeComponent,Testimonial,Slideror thisHomeComponentConfig.
Gotchas
Two types are called
HomeComponentConfig. This one (key,path,position,data) is used by nothing.registerHomeComponentConfigtakes the one from@salla.sa/twilight-theme-engine/components/home(height,className,id,placeholder); passing this one fails with TS2559, "has no properties in common".interface MyBlock extends HomeComponentData { brands?: Brand[] }fails with TS2411: the index signature allowsJsonObjectvalues, not arrays. Declare the block's props yourself, with[key: string]: unknown, as the example does.pathfrom the API keeps thehome.prefix on theme blocks (home.brands), but the registry key ishome:brands. Registerbrands, nothome.brands.Two types are called
Brand. This one has a numericid; the brands API (brand.list(), andBrandfrom/routes/brands) uses the other, with a stringid,label,bannerand more. In the demo store'shome.brandsblock,idis a text path ending in/brand-729170207.TestimonialandSliderdo not match the demo store's blocks:home.custom-testimonialsitems are{ name, text, stars, avatar }, andhome.enhanced-sliderslides are{ image, title, description }, with noidorlink. Declare the shape you receive.The JSDoc on
Feature.descriptionsays it is mapped from the API fieldtextinsideStoreFeatures.tsx. There is no such mapping there, and the demo store already sendsdescription.
Related
Fetches the blocks the merchant arranged on the home page, in order, each with its own settings.
registerHomeComponentsTells the engine which component draws each home page block, by the block path the Salla API sends. Call it once at startup.
registerHomeComponentConfigSets the placeholder, reserved height, class and id HomeComponentRenderer uses around your own home blocks before they load.
HomeComponentRendererDraws one home page block from its API data: finds its registered component, wraps it in an error boundary, and defers it until visible.
StoreFeaturesA grid of the store's selling points, each an icon, a title and a line of text, such as fast shipping or secure payment.
BrandsThe A to Z brands directory: every brand logo, grouped by first letter, each linking to that brand's product list.