Files
WRNexusJSDoc/app/pages/components/range-slider.wrn
T

106 lines
18 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
page RangeSlidercomponent {
seo {
title = "RangeSlider component"
description = "Theme-aware, responsive range slider component."
}
view {
<div class="docs-shell">
<SkipLink label="Skip to content" href="#main" class="docs-skip-link" />
<header class="topbar">
<a class="brand" href="/"><span>W</span> WRNexusJS</a>
<nav aria-label="Primary"><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="/components">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a></nav>
<div class="topbar-actions"><a class="preview-pill" href="/access">Private preview · v0.5.0</a><button data-wire-theme-toggle class="theme-button" aria-label="Toggle color theme" title="Toggle color theme">◐</button></div>
</header>
<div class="mobile-doc-nav"><details><summary>Browse documentation</summary><nav><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="/components">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a><a href="/tutorial">Tutorial</a><a href="/guides/project-structure">Guides</a><a href="/examples">Examples</a><a href="/search">Search</a></nav></details></div>
<main class="portal-main docs-layout component-detail-page"><article id="main" class="documentation prose standalone"><nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/">Home</a><span>/</span><a href="/components">Components</a><span>/</span><span aria-current="page">RangeSlider</span></nav><section class="doc-intro"><span class="eyebrow">forms component</span><h1>RangeSlider</h1><p>Theme-aware, responsive range slider component.</p><div class="doc-meta"><span>@wrnexus/ui 0.5.0</span><span>26 props</span><span>0 slots</span><span>4 events</span></div></section><section id="usage"><h2>Usage</h2><p>Components are auto-discovered. Use the component directly in any <code>.wrn</code> view:</p><pre data-language="wrn"><code>&lt;RangeSlider
size=&quot;default&quot;
color=&quot;primary&quot;
id=&quot;id&quot;
name=&quot;name&quot;
label=&quot;Range&quot;
/&gt;</code></pre><p>Legacy mount name: <code>data-component=&quot;RangeSlider&quot;</code>.</p></section><section id="props"><h2>Props and attributes</h2><div class="table-wrap"><table><thead><tr><th>Prop</th><th>Type</th><th>Requirement</th><th>Default</th></tr></thead><tbody><tr><td><code>size</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;default&quot;</code></td></tr><tr><td><code>color</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;primary&quot;</code></td></tr><tr><td><code>id</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;&quot;</code></td></tr><tr><td><code>name</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;&quot;</code></td></tr><tr><td><code>label</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;Range&quot;</code></td></tr><tr><td><code>hiddenLabel</code></td><td><code>boolean</code></td><td>Optional</td><td><code>false</code></td></tr><tr><td><code>placeholder</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;&quot;</code></td></tr><tr><td><code>variant</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;normal&quot;</code></td></tr><tr><td><code>icon</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;&quot;</code></td></tr><tr><td><code>iconPosition</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;start&quot;</code></td></tr><tr><td><code>value</code></td><td><code>number</code></td><td>Optional</td><td><code>50</code></td></tr><tr><td><code>min</code></td><td><code>number</code></td><td>Optional</td><td><code>0</code></td></tr><tr><td><code>max</code></td><td><code>number</code></td><td>Optional</td><td><code>100</code></td></tr><tr><td><code>step</code></td><td><code>number</code></td><td>Optional</td><td><code>1</code></td></tr><tr><td><code>showValue</code></td><td><code>boolean</code></td><td>Optional</td><td><code>true</code></td></tr><tr><td><code>showBounds</code></td><td><code>boolean</code></td><td>Optional</td><td><code>true</code></td></tr><tr><td><code>showSteps</code></td><td><code>boolean</code></td><td>Optional</td><td><code>false</code></td></tr><tr><td><code>marks</code></td><td><code>string</code></td><td>Optional</td><td><code>[]</code></td></tr><tr><td><code>helperText</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;&quot;</code></td></tr><tr><td><code>cornerHint</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;&quot;</code></td></tr><tr><td><code>error</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;&quot;</code></td></tr><tr><td><code>inline</code></td><td><code>boolean</code></td><td>Optional</td><td><code>false</code></td></tr><tr><td><code>readonly</code></td><td><code>boolean</code></td><td>Optional</td><td><code>false</code></td></tr><tr><td><code>disabled</code></td><td><code>boolean</code></td><td>Optional</td><td><code>false</code></td></tr><tr><td><code>required</code></td><td><code>boolean</code></td><td>Optional</td><td><code>false</code></td></tr><tr><td><code>class</code></td><td><code>string</code></td><td>Optional</td><td><code>&quot;&quot;</code></td></tr></tbody></table></div></section><section id="slots"><h2>Slots</h2><p>This component does not declare a slot.</p></section><section id="events"><h2>Events</h2><ul><li><code>input</code></li><li><code>change</code></li><li><code>focus</code></li><li><code>blur</code></li></ul></section><section id="source"><h2>Source contract</h2><p>Installed source: <code>components/RangeSlider.wrn</code></p><pre data-language="wrn"><code>component RangeSlider &#123;
props &#123;
@event input = function
@event change = function
@event focus = function
@event blur = function
size = &quot;default&quot;
color = &quot;primary&quot;
id = &quot;&quot;
name = &quot;&quot;
label = &quot;Range&quot;
hiddenLabel = false
placeholder = &quot;&quot;
variant = &quot;normal&quot;
icon = &quot;&quot;
iconPosition = &quot;start&quot;
value = 50
min = 0
max = 100
step = 1
showValue = true
showBounds = true
showSteps = false
marks = []
helperText = &quot;&quot;
cornerHint = &quot;&quot;
error = &quot;&quot;
inline = false
readonly = false
disabled = false
required = false
class = &quot;&quot;
&#125;
state currentValue = value
functions &#123;
function percent() &#123; if (Number(max) === Number(min)) &#123; return 0 &#125; return (Number(currentValue) - Number(min)) / (Number(max) - Number(min)) * 100 &#125;
function setValue(nextValue, sourceEvent, commit, detail, root, slider, input, output, progressValue) &#123; if (readonly || disabled) &#123; return &#125; currentValue = Number(nextValue); root = sourceEvent.currentTarget.closest(&quot;.wire-next--range-slider&quot;); if (root) &#123; slider = root.querySelector(&quot;[role=slider]&quot;); input = root.querySelector(&quot;input[name='&quot; + name + &quot;']&quot;); output = root.querySelector(&quot;output&quot;); progressValue = (currentValue - Number(min)) / (Number(max) - Number(min)) * 100; if (slider) &#123; slider.setAttribute(&quot;aria-valuenow&quot;, String(currentValue)); slider.style.setProperty(&quot;--wire-range-progress&quot;, progressValue + &quot;%&quot;) &#125; if (input) &#123; input.value = String(currentValue) &#125; if (output) &#123; output.textContent = String(currentValue) &#125; &#125; detail = &#123; value: currentValue, min: min, max: max, step: step, name: name, sourceEvent: sourceEvent &#125;; $emit(&quot;input&quot;, detail); if (commit) &#123; $emit(&quot;change&quot;, detail) &#125; &#125;
function valueFromPointer(sourceEvent, rect, ratio) &#123; rect = sourceEvent.currentTarget.getBoundingClientRect(); ratio = Math.max(0, Math.min(1, (sourceEvent.clientX - rect.left) / rect.width)); return Number(min) + ratio * (Number(max) - Number(min)) &#125;
function beginSlide(sourceEvent, rect, ratio, rawValue) &#123; if (readonly || disabled) &#123; return &#125; sourceEvent.currentTarget.setPointerCapture(sourceEvent.pointerId); rect = sourceEvent.currentTarget.getBoundingClientRect(); ratio = Math.max(0, Math.min(1, (sourceEvent.clientX - rect.left) / rect.width)); rawValue = Number(min) + ratio * (Number(max) - Number(min)); currentValue = Number(min) + Math.round((rawValue - Number(min)) / Number(step)) * Number(step); $emit(&quot;input&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;) &#125;
function moveSlide(sourceEvent, rect, ratio, rawValue) &#123; if (!sourceEvent.currentTarget.hasPointerCapture(sourceEvent.pointerId)) &#123; return &#125; rect = sourceEvent.currentTarget.getBoundingClientRect(); ratio = Math.max(0, Math.min(1, (sourceEvent.clientX - rect.left) / rect.width)); rawValue = Number(min) + ratio * (Number(max) - Number(min)); currentValue = Number(min) + Math.round((rawValue - Number(min)) / Number(step)) * Number(step); $emit(&quot;input&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;) &#125;
function endSlide(sourceEvent, rect, ratio, rawValue) &#123; rect = sourceEvent.currentTarget.getBoundingClientRect(); ratio = Math.max(0, Math.min(1, (sourceEvent.clientX - rect.left) / rect.width)); rawValue = Number(min) + ratio * (Number(max) - Number(min)); currentValue = Number(min) + Math.round((rawValue - Number(min)) / Number(step)) * Number(step); if (sourceEvent.currentTarget.hasPointerCapture(sourceEvent.pointerId)) &#123; sourceEvent.currentTarget.releasePointerCapture(sourceEvent.pointerId) &#125; $emit(&quot;change&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;) &#125;
function selectMark(sourceEvent, root, slider, input, output, nextValue, progressValue, detail) &#123; if (readonly || disabled) &#123; return &#125; root = sourceEvent.currentTarget.closest(&quot;.wire-next--range-slider&quot;); slider = root.querySelector(&quot;.wire-next__custom-slider&quot;); input = root.querySelector(&quot;.wire-next__range-value&quot;); output = root.querySelector(&quot;output&quot;); nextValue = Number(sourceEvent.currentTarget.dataset.value); currentValue = nextValue; progressValue = (nextValue - Number(min)) / (Number(max) - Number(min)) * 100; slider.setAttribute(&quot;aria-valuenow&quot;, String(nextValue)); slider.style.setProperty(&quot;--wire-range-progress&quot;, progressValue + &quot;%&quot;); input.setAttribute(&quot;value&quot;, String(nextValue)); output.replaceChildren(String(nextValue)); detail = &#123; value: nextValue, min: min, max: max, step: step, name: name, sourceEvent: sourceEvent &#125;; $emit(&quot;input&quot;, detail); $emit(&quot;change&quot;, detail) &#125;
function handleKey(sourceEvent) &#123; if (sourceEvent.key === &quot;ArrowRight&quot;) &#123; sourceEvent.preventDefault(); currentValue = Math.min(Number(max), Number(currentValue) + Number(step)); $emit(&quot;input&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;); $emit(&quot;change&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;) &#125; if (sourceEvent.key === &quot;ArrowLeft&quot;) &#123; sourceEvent.preventDefault(); currentValue = Math.max(Number(min), Number(currentValue) - Number(step)); $emit(&quot;input&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;); $emit(&quot;change&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;) &#125; if (sourceEvent.key === &quot;Home&quot;) &#123; sourceEvent.preventDefault(); currentValue = Number(min); $emit(&quot;change&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;) &#125; if (sourceEvent.key === &quot;End&quot;) &#123; sourceEvent.preventDefault(); currentValue = Number(max); $emit(&quot;change&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;) &#125; &#125;
function emitFocus(nameEvent, sourceEvent) &#123; $emit(nameEvent, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;) &#125;
function decreaseValue(sourceEvent) &#123; currentValue = Math.max(Number(min), Number(currentValue) - Number(step)); $emit(&quot;input&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;); $emit(&quot;change&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;) &#125;
function increaseValue(sourceEvent) &#123; currentValue = Math.min(Number(max), Number(currentValue) + Number(step)); $emit(&quot;input&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;); $emit(&quot;change&quot;, &#123; value: currentValue, name: name, sourceEvent: sourceEvent &#125;) &#125;
&#125;
view &#123;
&lt;div &#123;...attrs&#125; class=&quot;wire-next wire-next--color-&#123;color&#125; wire-next--size-&#123;size&#125; wire-next--field wire-next--range-slider &#123;class&#125;&quot; data-variant=&quot;&#123;variant&#125;&quot; data-inline=&quot;&#123;inline&#125;&quot; data-invalid=&quot;&#123;error ? 'true' : 'false'&#125;&quot;&gt;
&lt;div class=&quot;wire-next__field-heading&quot;&gt;
&lt;label class=&quot;&#123;hiddenLabel ? 'wire-next__sr-only' : ''&#125;&quot; for=&quot;&#123;id || name&#125;&quot;&gt;&#123;label&#125;&lt;/label&gt;&#123;#if cornerHint&#125;&lt;span class=&quot;wire-next__field-hint&quot;&gt;&#123;cornerHint&#125;&lt;/span&gt;&#123;/if&#125;&lt;/div&gt;
&lt;div class=&quot;wire-next__range-control&quot; data-variant=&quot;&#123;variant&#125;&quot; data-icon-position=&quot;&#123;iconPosition&#125;&quot; data-show-steps=&quot;&#123;showSteps&#125;&quot;&gt;
&#123;#if icon&#125;&lt;span class=&quot;&#123;icon&#125;&quot; aria-hidden=&quot;true&quot;&gt;
&lt;/span&gt;&#123;/if&#125;
&lt;button type=&quot;button&quot; class=&quot;wire-next__range-stepper&quot; aria-label=&quot;Decrease &#123;label&#125;&quot; disabled=&quot;&#123;disabled || readonly&#125;&quot; @click=&quot;decreaseValue(event)&quot;&gt;&lt;/button&gt;
&lt;div class=&quot;wire-next__range-track&quot;&gt;
&lt;input id=&quot;&#123;id || name&#125;&quot; class=&quot;wire-next__sr-only wire-next__range-value&quot; type=&quot;number&quot; name=&quot;&#123;name&#125;&quot; value=&quot;&#123;currentValue&#125;&quot; min=&quot;&#123;min&#125;&quot; max=&quot;&#123;max&#125;&quot; step=&quot;&#123;step&#125;&quot; required=&quot;&#123;required&#125;&quot; readonly /&gt;
&lt;div class=&quot;wire-next__custom-slider&quot; role=&quot;slider&quot; tabindex=&quot;&#123;disabled ? '-1' : '0'&#125;&quot; aria-label=&quot;&#123;hiddenLabel ? label : ''&#125;&quot; aria-valuemin=&quot;&#123;min&#125;&quot; aria-valuemax=&quot;&#123;max&#125;&quot; aria-valuenow=&quot;&#123;currentValue&#125;&quot; aria-disabled=&quot;&#123;disabled&#125;&quot; aria-readonly=&quot;&#123;readonly&#125;&quot; aria-invalid=&quot;&#123;error ? 'true' : 'false'&#125;&quot; style=&quot;--wire-range-progress: &#123;percent()&#125;%&quot; @pointerdown=&quot;beginSlide(event)&quot; @pointermove=&quot;moveSlide(event)&quot; @pointerup=&quot;endSlide(event)&quot; @pointercancel=&quot;endSlide(event)&quot; @keydown=&quot;handleKey(event)&quot; @focus=&quot;emitFocus('focus', event)&quot; @blur=&quot;emitFocus('blur', event)&quot;&gt;
&lt;span class=&quot;wire-next__slider-fill&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;wire-next__slider-thumb&quot;&gt;
&lt;/span&gt;
&#123;#if marks.length&#125;&lt;span class=&quot;wire-next__slider-marks&quot;&gt;&#123;#each marks as mark&#125;&lt;button type=&quot;button&quot; data-value=&quot;&#123;mark.value&#125;&quot; style=&quot;left: &#123;(Number(mark.value) - Number(min)) / (Number(max) - Number(min)) * 100&#125;%&quot; aria-label=&quot;&#123;mark.label&#125;&quot; @click=&quot;selectMark(event)&quot;&gt;
&lt;/button&gt;&#123;/each&#125;&lt;/span&gt;&#123;/if&#125;
&lt;/div&gt;
&#123;#if showBounds&#125;&lt;div class=&quot;wire-next__range-bounds&quot;&gt;
&lt;span&gt;&#123;min&#125;&lt;/span&gt;
&lt;span&gt;Step &#123;step&#125;&lt;/span&gt;
&lt;span&gt;&#123;max&#125;&lt;/span&gt;
&lt;/div&gt;&#123;/if&#125;
&lt;/div&gt;
&#123;#if showValue&#125;&lt;output for=&quot;&#123;id || name&#125;&quot;&gt;&#123;currentValue&#125;&lt;/output&gt;&#123;/if&#125;
&lt;button type=&quot;button&quot; class=&quot;wire-next__range-stepper&quot; aria-label=&quot;Increase &#123;label&#125;&quot; disabled=&quot;&#123;disabled || readonly&#125;&quot; @click=&quot;increaseValue(event)&quot;&gt;+&lt;/button&gt;
&lt;/div&gt;
&#123;#if helperText&#125;&lt;small class=&quot;wire-next__field-help&quot;&gt;&#123;helperText&#125;&lt;/small&gt;&#123;/if&#125;&lt;small class=&quot;wire-next__field-error&quot; data-error=&quot;&#123;name&#125;&quot;&gt;&#123;error&#125;&lt;/small&gt;
&lt;/div&gt;
&#125;
&#125;
</code></pre></section></article><aside class="on-this-page"><h2>On this page</h2><nav><a href="#usage">Usage</a><a href="#props">Props and attributes</a><a href="#slots">Slots</a><a href="#events">Events</a><a href="#source">Source contract</a></nav></aside></main>
<footer><div class="footer-brand"><span class="footer-mark" aria-hidden="true">W</span><p><strong>WRNexusJS 0.5.0</strong><span>Complete API documentation generated from installed package declarations.</span></p></div><nav aria-label="Footer"><a href="/packages">All packages</a><a href="/getting-started">Get started</a><a href="/security">Security</a><a href="/support">Support</a><a href="/llms.txt">AI guide</a></nav><p class="footer-meta">Private Developer Preview · Bun-native</p></footer>
<BackToTop />
</div>
}
}