component ToggleCount { props { size = "default" color = "primary" variant = "segmented" class = "" name = "billing-cycle" value = "monthly" firstValue = "monthly" firstLabel = "Monthly" secondValue = "annual" secondLabel = "Annual" ariaLabel = "Billing frequency" items = [] currency = "$" suffix = "" firstValueKey = "monthly" secondValueKey = "annual" emptyValue = "—" align = "end" fullWidth = true disabled = false animate = true animationDuration = 450 animationSteps = 18 @event change = function @event toggle = function } state selectedValue = value functions { function isFirstSelected() { return selectedValue === firstValue } function isSecondSelected() { return selectedValue === secondValue } function displayValue(item) { if (isSecondSelected()) { return item[secondValueKey] !== undefined ? item[secondValueKey] : emptyValue } return item[firstValueKey] !== undefined ? item[firstValueKey] : emptyValue } function dispatchToggleEvent(sourceEvent, previousValue, root, customEvent) { root = sourceEvent.currentTarget.closest("[data-wrn-toggle-count]") if (!root) { return } customEvent = document.createEvent("CustomEvent") customEvent.initCustomEvent("change", true, false, { component: "ToggleCount", name: name, value: selectedValue, previousValue: previousValue, firstValue: firstValue, secondValue: secondValue }) root.dispatchEvent(customEvent) customEvent = document.createEvent("CustomEvent") customEvent.initCustomEvent("toggle", true, false, { component: "ToggleCount", name: name, value: selectedValue, previousValue: previousValue, firstValue: firstValue, secondValue: secondValue }) root.dispatchEvent(customEvent) } function selectValue(sourceEvent, nextValue, previousValue) { if (disabled || selectedValue === nextValue) { return } previousValue = selectedValue selectedValue = nextValue if ( animate && !window.matchMedia("(prefers-reduced-motion: reduce)").matches ) { animateDisplayedValues(sourceEvent, previousValue) } dispatchToggleEvent(sourceEvent, previousValue) } function animateDisplayedValues(sourceEvent, previousValue, root, nodes) { root = sourceEvent.currentTarget.closest("[data-wrn-toggle-count]") if (!root) { return } nodes = root.querySelectorAll("[data-toggle-count-value]") animateValueAt(nodes, 0, previousValue) } function animateValueAt(nodes, index, previousValue, node, fromValue, toValue) { if (index >= nodes.length) { return } node = nodes[index] fromValue = Number( previousValue === secondValue ? node.getAttribute("data-second-value") : node.getAttribute("data-first-value") ) toValue = Number( selectedValue === secondValue ? node.getAttribute("data-second-value") : node.getAttribute("data-first-value") ) if (!Number.isNaN(fromValue) && !Number.isNaN(toValue)) { animateValueFrame(node, fromValue, toValue, 0) } animateValueAt(nodes, index + 1, previousValue) } function animateValueFrame(node, fromValue, toValue, frame, totalFrames, nextValue) { totalFrames = Math.max(1, Number(animationSteps) || 1) if (frame >= totalFrames) { node.replaceChildren(String(toValue)) return } nextValue = Math.round( fromValue + (toValue - fromValue) * (frame / totalFrames) ) node.replaceChildren(String(nextValue)) setTimeout( animateValueFrame, Math.max(1, Number(animationDuration) / totalFrames), node, fromValue, toValue, frame + 1 ) } function toggleValue(sourceEvent) { selectValue( sourceEvent, isFirstSelected() ? secondValue : firstValue ) } } view {
{#if variant === "switch"} {firstLabel} {secondLabel} {:else}
{/if}
{#if items.length > 0}
{#each items as item}
{item.label || item.name} {#if currency}{currency}{/if} {displayValue(item)} {#if suffix}{suffix}{/if} {#if item.description}{item.description}{/if}
{/each}
{/if}
} }