Events
<dkl-price> is event-driven. It has no direct reference to the
volume picker — instead it listens for the picker’s tier-change
event and the theme’s variant-change events, and updates the price accordingly.
Listens for
Section titled “Listens for”discount-kit-live:volume-discount:tier-change
Section titled “discount-kit-live:volume-discount:tier-change”CustomEvent
Emitted by the volume picker. Matched by product id — a
selected tier shows the discounted price, a null tier reverts to base. Coupling is by
event name and product id only, with no import between the two components.
Honours the event’s updatesPrice flag: if the picker’s “Update price when a tier is
selected” setting is off, <dkl-price> ignores the tier for pricing (the event still
fires for other listeners).
It also reacts to the host theme’s variant-change events: on a variant change it updates the base price and re-applies the active tier, recomputing the discount off the new variant’s price (sale-priced variants included).
<dkl-price> emits a price-change event whenever its displayed price updates, plus
mount / unmount lifecycle events. All bubble, so you can listen on document.
Price change
Section titled “Price change”discount-kit-live:price:change
Section titled “discount-kit-live:price:change”CustomEvent
Fired whenever the displayed price changes — when a volume tier is selected or deselected, or
the variant changes. Not fired on initial mount (the server-rendered price is already in
the DOM), and deduped — a recompute that lands on the same price (e.g. switching to an
equally-priced variant) doesn’t fire. The detail carries resource with the previous and new
price, mirroring the tier event’s previousTier / currentTier:
resource: { widgetType: 'price' widgetId: string | null productId: number | null variantId: number | null previousPrice: PriceState | null // null on the first change after mount currentPrice: PriceState}
type PriceState = { priceCents: number // displayed price (discounted when a tier is active) compareAtCents: number | null // the struck-through "before" price, or null discounted: boolean // whether a volume tier is applied tier: VolumeDiscountTier | null // the active tier, or null}// VolumeDiscountTier: { index, quantity, discountAmount, discountType, unitPriceCents }A full example payload — selecting a tier that moves the price from £20.00 to £18.00:
// event.detail.resource on price:change{ widgetType: 'price', widgetId: 'a1b2c3d4', // the app block's id (null on a web component) productId: 7820000000001, variantId: 41200000000001, // the current variant — updates on a variant change previousPrice: { priceCents: 2000, compareAtCents: null, discounted: false, tier: null }, currentPrice: { priceCents: 1800, compareAtCents: 2000, // the original price, now struck through discounted: true, tier: { index: 1, quantity: 3, discountAmount: 10, discountType: 'percentage', unitPriceCents: 1800 } }}Lifecycle
Section titled “Lifecycle”The mount / unmount events fire as the instance’s behaviour attaches and tears down — handy
for wiring up (and cleaning up) custom integrations per instance. Both carry a
DklWidgetEventDetail resource.
discount-kit-live:widget:mount
Section titled “discount-kit-live:widget:mount”CustomEvent
Fired once the controller has attached its behaviour to the (already server-rendered)
element. resource: { widgetType, widgetId, productId?, variantId? } — productId and
variantId are included when known.
discount-kit-live:widget:unmount
Section titled “discount-kit-live:widget:unmount”CustomEvent
Fired when the instance tears down — e.g. the element is removed, or the theme editor
re-renders the section. Same resource shape. Use it to detach any listeners or observers
you set up on mount.
// event.detail.resource on widget:mount / widget:unmount{ widgetType: 'price', widgetId: 'a1b2c3d4', // the app block's id (null on a web component) productId: 7820000000001, variantId: 41200000000001}