168 lines
4.1 KiB
Text
168 lines
4.1 KiB
Text
// templui component slider - version: main installed by templui v0.71.0
|
|
package slider
|
|
|
|
import (
|
|
"fmt"
|
|
"git.jmbit.de/jmb/scanfile/server/web/templui/utils"
|
|
)
|
|
|
|
type Props struct {
|
|
ID string
|
|
Class string
|
|
Attributes templ.Attributes
|
|
}
|
|
|
|
type InputProps struct {
|
|
ID string
|
|
Class string
|
|
Attributes templ.Attributes
|
|
Name string
|
|
Min int
|
|
Max int
|
|
Step int
|
|
Value int
|
|
Disabled bool
|
|
}
|
|
|
|
type ValueProps struct {
|
|
ID string
|
|
Class string
|
|
Attributes templ.Attributes
|
|
For string // Corresponds to the ID of the Slider Input
|
|
}
|
|
|
|
templ Slider(props ...Props) {
|
|
@Script()
|
|
{{ var p Props }}
|
|
if len(props) > 0 {
|
|
{{ p = props[0] }}
|
|
}
|
|
<div
|
|
if p.ID != "" {
|
|
id={ p.ID }
|
|
}
|
|
class={ utils.TwMerge("w-full", p.Class) }
|
|
data-slider-wrapper
|
|
{ p.Attributes... }
|
|
>
|
|
{ children... }
|
|
</div>
|
|
}
|
|
|
|
templ Input(props ...InputProps) {
|
|
{{ var p InputProps }}
|
|
if len(props) > 0 {
|
|
{{ p = props[0] }}
|
|
}
|
|
if p.ID == "" {
|
|
{{ p.ID = utils.RandomID() }}
|
|
}
|
|
<input
|
|
type="range"
|
|
id={ p.ID }
|
|
data-slider-input
|
|
if p.Name != "" {
|
|
name={ p.Name }
|
|
}
|
|
if p.Value != 0 {
|
|
value={ fmt.Sprintf("%d", p.Value) }
|
|
}
|
|
if p.Min != 0 {
|
|
min={ fmt.Sprintf("%d", p.Min) }
|
|
}
|
|
if p.Max != 0 {
|
|
max={ fmt.Sprintf("%d", p.Max) }
|
|
}
|
|
if p.Step != 0 {
|
|
step={ fmt.Sprintf("%d", p.Step) }
|
|
}
|
|
class={
|
|
utils.TwMerge(
|
|
"w-full h-2 rounded-full bg-secondary appearance-none cursor-pointer",
|
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
"[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4",
|
|
"[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-primary",
|
|
"[&::-webkit-slider-thumb]:hover:bg-primary/90",
|
|
"[&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:border-0",
|
|
"[&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-primary",
|
|
"[&::-moz-range-thumb]:hover:bg-primary/90",
|
|
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
p.Class,
|
|
),
|
|
}
|
|
disabled?={ p.Disabled }
|
|
{ p.Attributes... }
|
|
/>
|
|
}
|
|
|
|
templ Value(props ...ValueProps) {
|
|
{{ var p ValueProps }}
|
|
if len(props) > 0 {
|
|
{{ p = props[0] }}
|
|
}
|
|
if p.For == "" {
|
|
<span class="text-xs text-destructive">Error: SliderValue missing 'For' attribute.</span>
|
|
}
|
|
<span
|
|
if p.ID != "" {
|
|
id={ p.ID }
|
|
}
|
|
data-slider-value
|
|
data-slider-value-for={ p.For }
|
|
class={ utils.TwMerge("text-sm text-muted-foreground", p.Class) }
|
|
{ p.Attributes... }
|
|
>
|
|
<!-- Initial value will be set by JS -->
|
|
</span>
|
|
}
|
|
|
|
var handle = templ.NewOnceHandle()
|
|
|
|
templ Script() {
|
|
@handle.Once() {
|
|
<script defer nonce={ templ.GetNonce(ctx) }>
|
|
(function() { // IIFE
|
|
function initSlider(sliderInput) {
|
|
if (sliderInput.hasAttribute('data-initialized')) return;
|
|
|
|
sliderInput.setAttribute('data-initialized', 'true');
|
|
|
|
const sliderId = sliderInput.id;
|
|
if (!sliderId) return;
|
|
|
|
const valueElements = document.querySelectorAll(`[data-slider-value][data-slider-value-for="${sliderId}"]`);
|
|
|
|
function updateValues() {
|
|
valueElements.forEach(el => {
|
|
el.textContent = sliderInput.value;
|
|
});
|
|
}
|
|
|
|
updateValues();
|
|
sliderInput.addEventListener('input', updateValues);
|
|
}
|
|
|
|
function initAllComponents(root = document) {
|
|
if (root instanceof Element && root.matches('input[type="range"][data-slider-input]')) {
|
|
initSlider(root);
|
|
}
|
|
for (const slider of root.querySelectorAll('input[type="range"][data-slider-input]:not([data-initialized])')) {
|
|
initSlider(slider);
|
|
}
|
|
}
|
|
|
|
const handleHtmxSwap = (event) => {
|
|
const target = event.detail.target || event.detail.elt;
|
|
if (target instanceof Element) {
|
|
requestAnimationFrame(() => initAllComponents(target));
|
|
}
|
|
};
|
|
|
|
initAllComponents();
|
|
document.addEventListener('DOMContentLoaded', () => initAllComponents());
|
|
document.body.addEventListener('htmx:afterSwap', handleHtmxSwap);
|
|
document.body.addEventListener('htmx:oobAfterSwap', handleHtmxSwap);
|
|
})(); // End of IIFE
|
|
</script>
|
|
}
|
|
}
|