release: WRNexusJS 0.5.0

This commit is contained in:
2026-07-29 12:51:10 +05:30
parent 76c768099d
commit 6afe32f63f
456 changed files with 40879 additions and 8850 deletions
+228 -11
View File
@@ -2,19 +2,236 @@ component ToggleCount {
props {
size = "default"
color = "primary"
label = "Toggle Count"
name = ""
value = ""
placeholder = ""
type = "text"
min = ""
max = ""
step = ""
disabled = false
required = false
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 {
<label class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--field wire-next--toggle-count {class}"><span>{label}</span><input {...attrs} type="{type}" name="{name}" value="{value}" placeholder="{placeholder}" min="{min}" max="{max}" step="{step}" disabled="{disabled}" required="{required}" /></label>
<section
{...attrs}
data-wrn-toggle-count
data-variant="{variant}"
data-value="{selectedValue}"
data-disabled="{disabled ? 'true' : 'false'}"
class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--toggle-count wire-next--toggle-count-{variant} {fullWidth ? 'wire-next--toggle-count-full' : ''} {disabled ? 'wire-next--disabled' : ''} {class}"
>
<input type="hidden" name="{name}" value="{selectedValue}" />
<div class="wire-next__toggle-count-control wire-next__toggle-count-control--{align}">
{#if variant === "switch"}
<span data-selected="{isFirstSelected() ? 'true' : 'false'}">{firstLabel}</span>
<button
type="button"
role="switch"
aria-label="{ariaLabel}"
aria-checked="{isSecondSelected() ? 'true' : 'false'}"
disabled="{disabled}"
@click="toggleValue(event)"
class="wire-next__toggle-count-switch"
>
<span aria-hidden="true"></span>
</button>
<span data-selected="{isSecondSelected() ? 'true' : 'false'}">{secondLabel}</span>
{:else}
<div class="wire-next__toggle-count-segmented" role="group" aria-label="{ariaLabel}">
<button
type="button"
aria-pressed="{isFirstSelected() ? 'true' : 'false'}"
disabled="{disabled}"
@click="selectValue(event, firstValue)"
>{firstLabel}</button>
<button
type="button"
aria-pressed="{isSecondSelected() ? 'true' : 'false'}"
disabled="{disabled}"
@click="selectValue(event, secondValue)"
>{secondLabel}</button>
</div>
{/if}
</div>
{#if items.length > 0}
<div class="wire-next__toggle-count-items">
{#each items as item}
<article>
<span>{item.label || item.name}</span>
<strong>
{#if currency}<small>{currency}</small>{/if}
<span
data-toggle-count-value
data-first-value="{item[firstValueKey]}"
data-second-value="{item[secondValueKey]}"
>{displayValue(item)}</span>
{#if suffix}<small>{suffix}</small>{/if}
</strong>
{#if item.description}<small>{item.description}</small>{/if}
</article>
{/each}
</div>
{/if}
</section>
}
}