<!--
    Component: Slider
    Single-value slider using bits-ui Slider primitive.
    Swiss design: 1px track, diamond thumb (rotate-45), brand accent.
-->
<script lang="ts">
import {
    type Orientation,
    Slider,
} from 'bits-ui';

interface Props {
    /**
     * Slider value
     * @default 0
     */
    value?: number;
    /**
     * Minimum value
     * @default 0
     */
    min?: number;
    /**
     * Maximum value
     * @default 100
     */
    max?: number;
    /**
     * Step increment
     * @default 1
     */
    step?: number;
    /**
     * Disabled state
     * @default false
     */
    disabled?: boolean;
    /**
     * Slider orientation
     * @default 'horizontal'
     */
    orientation?: Orientation;
    /**
     * Value formatter
     * @default (v) => v
     */
    format?: (v: number) => string | number;
    /**
     * Value change callback
     */
    onValueChange?: (v: number) => void;
    /**
     * CSS classes
     */
    class?: string;
}

let {
    value = $bindable(0),
    min = 0,
    max = 100,
    step = 1,
    disabled = false,
    orientation = 'horizontal',
    format = (v: number) => v,
    onValueChange,
    class: className,
}: Props = $props();

const isVertical = $derived(orientation === 'vertical');

const labelClasses = `font-mono text-2xs tabular-nums shrink-0
    text-subtle
    group-hover:text-neutral-700 dark:group-hover:text-neutral-300
    transition-colors`;

const thumbClasses = `block w-2.5 h-2.5 bg-brand
    rotate-45 shadow-rest
    hover:scale-125
    focus-visible:outline-none
    focus-visible:ring-2 focus-visible:ring-brand/20
    data-active:scale-90
    transition-transform duration-fast
    disabled:pointer-events-none disabled:opacity-50
    cursor-grab active:cursor-grabbing`;
</script>

{#if isVertical}
    <div class="inline-flex flex-col items-center gap-3 group h-full {className ?? ''}">
        <span class="{labelClasses} text-center">
            {format(value)}
        </span>

        <Slider.Root
            type="single"
            orientation="vertical"
            bind:value
            {min}
            {max}
            {step}
            {disabled}
            onValueChange={(v => onValueChange?.(v))}
            class="
                relative flex flex-col items-center select-none touch-none
                w-5 h-full grow cursor-row-resize
                disabled:opacity-50 disabled:cursor-not-allowed
            "
        >
            {#snippet children({ thumbItems })}
                <span
                    class="
                        bg-neutral-200 dark:bg-neutral-800
                        relative grow w-px overflow-visible
                        group-hover:bg-neutral-300 dark:group-hover:bg-neutral-700
                        transition-colors
                    "
                >
                    <Slider.Range class="absolute bg-brand w-full" />
                </span>

                {#each thumbItems as thumb (thumb)}
                    <Slider.Thumb
                        index={thumb.index}
                        class={thumbClasses}
                        aria-label="Value"
                    />
                {/each}
            {/snippet}
        </Slider.Root>
    </div>
{:else}
    <div class="flex items-center gap-4 group w-full {className ?? ''}">
        <Slider.Root
            type="single"
            orientation="horizontal"
            bind:value
            {min}
            {max}
            {step}
            {disabled}
            onValueChange={(v => onValueChange?.(v))}
            class="
                relative flex items-center select-none touch-none
                w-full h-5 cursor-col-resize
                disabled:opacity-50 disabled:cursor-not-allowed
            "
        >
            {#snippet children({ thumbItems })}
                <span
                    class="
                        bg-neutral-200 dark:bg-neutral-800
                        relative grow h-px overflow-visible
                        group-hover:bg-neutral-300 dark:group-hover:bg-neutral-700
                        transition-colors
                    "
                >
                    <Slider.Range class="absolute bg-brand h-full" />
                </span>

                {#each thumbItems as thumb (thumb)}
                    <Slider.Thumb
                        index={thumb.index}
                        class={thumbClasses}
                        aria-label="Value"
                    />
                {/each}
            {/snippet}
        </Slider.Root>

        <!-- Label: right of slider -->
        <span class="{labelClasses} w-12 text-right">
            {format(value)}
        </span>
    </div>
{/if}
