Skip to main content

cv-customizer

The root component that orchestrates the entire product customizer. It creates a ChamevoCanvas and ChamevoJS instance, wires events to the Stencil Store, and manages the responsive layout.

Properties

PropertyAttributeTypeDefaultDescription
optionsoptionsstring | Partial<ChamevoOptions>'{}'Customizer configuration. JSON string (HTML) or object (JS).
colorSchemecolor-scheme'light' | 'dark''light'Color theme. Toggles .cv-dark class.
uiStyleui-style'default' | 'rounded' | 'sharp''default'Shape preset.
moduleDisplaymodule-display'sidebar' | 'dialog''sidebar'How module panels are displayed.
shadowshadow'none' | 'sm' | 'md' | 'lg''none'Box shadow on container.
proxyFileServerproxy-file-serverstring''CORS proxy URL.

Events

Evente.detailDescription
cvReady{ chamevo, canvas }Customizer initialized.
cvProductCreate{ product }Product loaded.
cvProductChange{ product }Product changed.
cvViewSelect{ view, index }View switched.
cvElementSelect{ element }Element selected/deselected.
cvPriceChange{ price, singleProductPrice, pricingRulesPrice }Price changed.

Methods

MethodReturnsDescription
loadProduct(product, options?)Promise<void>Load a CVProduct or legacy CVView[]. Pass { replaceInitialElements: true } to preserve user-added elements across the load; when omitted it falls back to mainOptions.replaceInitialElements.
selectView(index)Promise<void>Switch to a view by index.
getProduct()Promise<CVProduct | null>Get current product.
getOrder()Promise<object>Get product + fonts + colors. Also clears hasUnsavedChanges, so the unsavedProductAlert beforeunload prompt won't fire on the navigation that follows (every consumer that reads the order is about to persist it). To peek without that side effect, snapshot hasUnsavedChanges first.
getElements(viewIndex?, type?)Promise<object[]>Get elements.
markSaved()Promise<void>Mark the current state as saved — clears hasUnsavedChanges so the unsavedProductAlert beforeunload prompt won't fire on the next navigation. Call before an external flow (e.g. lightbox add-to-cart) initiates navigation that is the user's save action.
undo()Promise<void>Undo.
redo()Promise<void>Redo.
reset()Promise<void>Clear all views.
setProducts(catalog)Promise<void>Set product catalog.
setGraphics(catalog)Promise<void>Set graphics catalog.
registerModule(moduleId, target)Promise<() => void>Mount a module into an external DOM element. Returns cleanup function.

Slots

SlotPosition
toolbar-topAbove the canvas
sidebarLeft of the canvas
panelRight of the canvas
toolbar-bottomBelow the canvas

CSS Custom Properties

PropertyDefaultDescription
All --cv-* tokensSee ThemingCascade into all child components.

Responsive Layout

Container WidthBehavior
< 580pxBottom tab bar + dialog panels
580-1024pxDialog panels
> 1024pxSidebar panels

Layout size is exposed via the data-layout-size attribute (sm, md, lg) for CSS overrides.

Custom Modules

Add custom web components as mainbar modules by passing CustomModule descriptors in mainBarModules:

customizer.options = {
mainBarModules: [
'text',
'images',
{ id: 'quote', element: 'my-quote-picker', icon: 'sparkle', label: 'Quote' },
],
};

See Custom Modules for full details.

Distributed Modules (registerModule)

Mount any module into an external DOM element:

// Mount the text module into an external container
const cleanup = await customizer.registerModule('text', '#external-panel');

// Unmount when done
cleanup();

Works with both built-in module IDs ('text', 'images', 'designs', etc.) and custom module IDs defined in mainBarModules.