Skip to content
Twilight React Playground
ثيم رائدaren

registry

objectBeginnerserverbrowserlive demo

The shared name-to-component table the engine consults for a few swappable parts: the product card, the product gallery and home blocks.

import { registry } from '@salla.sa/twilight-theme-engine';

In plain words

Think of registry as an address book: a name on one side, a component on the other. When the engine needs "the product card", it looks up product:card and renders whatever is stored there. Store your own component under that name and every product grid uses it, without copying any engine page.

This only matters for the names the engine actually looks up, listed in the notes. Any other name changes nothing unless your own code renders it (with <Component name=…>).

Signature

const registry: ComponentRegistry

registry.register(name, component): void     // store; replaces and forgets any original
registry.override(name, component): void     // store, keeping the previous one as the original
registry.resolve(name): ComponentType | null
registry.getOriginal(name): ComponentType | null
registry.has(name): boolean
registry.list(): string[]
registry.listByPrefix(prefix): string[]
registry.remove(name): boolean
registry.clear(): void

Try it live

Registry calls on a playground key, and what ProductCard would do if the same calls were made on product:card.Try this: switch to "override only": the key resolves to MyCard, but getOriginal is null, so ProductCard keeps its default.
Storefront canvas · ar · RTL
Runs in the browser…
Controls
What a theme writes
import { registry } from '@salla.sa/twilight-theme-engine';
import { MyProductCard } from './components/MyProductCard';

// app/router.tsx: at module scope, before createRouter()
registry.register('product:card', MyProductCard);
registry.override('product:card', MyProductCard);

// Where the engine renders <ProductCard product={…} /> (grids, sliders, listings),
// MyProductCard receives the same props, but only after both calls.

Example

app/router.tsx
import { registry } from '@salla.sa/twilight-theme-engine';
import { createRouter } from '@salla.sa/twilight-theme-engine/tanstack';
import { MyProductCard } from './components/MyProductCard';
import { routeTree } from './routeTree.gen';

// Both calls: ProductCard only honours an override that has an original.
registry.register('product:card', MyProductCard);
registry.override('product:card', MyProductCard);

export function getRouter() {
  return createRouter(routeTree);
}

How it behaves

  • Names the engine resolves: product:card (every ProductCard), product:gallery (ProductGallery), account:layout-pending (the account layout while it loads) and home:<path>, tried as home:<path>:<view_style> first (home blocks, registered with registerHomeComponents() from /routes/home).

  • Register at module scope in app/router.tsx, before createRouter(). The registry is a module-level object: on the server one copy is shared by every request, so never register per request or per render.

  • ProductCard and ProductGallery look their key up once per mounted instance (useMemo with no dependencies); a registration made later reaches only instances mounted after it.

  • product:gallery needs no seed: ProductGallery renders whatever the key resolves to, unless that is ProductGallery itself.

Gotchas

  • product:card needs register and then override. ProductCard uses the key only when registry.getOriginal('product:card') is not null (src/components/product/ProductCard.tsx), and override on an empty key records no original. With override alone the default card keeps rendering, with no warning.

  • Names are colon-separated. header, footer, product.card or cart.item register without complaint and change nothing: the engine imports those parts directly.

  • You cannot wrap the default card. The engine never stores it under product:card, so useOriginalComponent('product:card') inside your override returns your own seed, and rendering it recurses until React gives up. Treat the override as a full replacement.

Related

Source and docs