{"version":3,"file":"slider.cjs","names":[],"sources":["../../src/core/slider.ts"],"sourcesContent":["import { clamp as clampRange } from '@vielzeug/arsenal/math';\nimport type { Readable } from '@vielzeug/ripple';\n\nimport { toFiniteNumberOr, toPositiveStep } from './numbers';\n\n// ── Slider control ────────────────────────────────────────────────────────────\n\nexport type SliderControlOptions = {\n  disabled?: Readable<boolean | undefined>;\n  max?: Readable<number | string | undefined>;\n  min?: Readable<number | string | undefined>;\n  readonly?: Readable<boolean | undefined>;\n  step?: Readable<number | string | undefined>;\n};\n\nexport type SliderControl = {\n  clamp: (value: number) => number;\n  fromClientX: (clientX: number, rect: { left: number; width: number }) => number;\n  /**\n   * Handles keyboard navigation for a slider input.\n   * When the slider is disabled or readonly, the event is ignored and `false` is returned.\n   * @returns `true` when the event was handled and `onCommit` was called, `false` otherwise.\n   */\n  handleKeydown: (event: KeyboardEvent, currentValue: number, onCommit: (value: number) => void) => boolean;\n  max: () => number;\n  min: () => number;\n  nextFromKey: (key: string, current: number) => number | null;\n  snap: (value: number) => number;\n  toPercent: (value: number) => number;\n};\n\nexport const createSliderControl = (options: SliderControlOptions): SliderControl => {\n  const min = (): number => toFiniteNumberOr(options.min?.value, 0);\n  const max = (): number => toFiniteNumberOr(options.max?.value, 100);\n  const step = (): number => toPositiveStep(options.step?.value, 1);\n\n  const clamp = (value: number): number => {\n    const minValue = min();\n    const maxValue = max();\n\n    return clampRange(toFiniteNumberOr(value, minValue), minValue, maxValue);\n  };\n\n  const snap = (value: number): number => {\n    const minValue = min();\n\n    return clamp(Math.round(toFiniteNumberOr(value, minValue) / step()) * step());\n  };\n\n  const toPercent = (value: number): number => {\n    const minValue = min();\n    const maxValue = max();\n    const normalized = toFiniteNumberOr(value, minValue);\n\n    if (maxValue <= minValue) return 0;\n\n    return ((normalized - minValue) / (maxValue - minValue)) * 100;\n  };\n\n  const fromClientX = (clientX: number, rect: { left: number; width: number }): number => {\n    if (rect.width <= 0) return snap(min());\n\n    const pct = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\n    const minValue = min();\n    const maxValue = max();\n\n    return snap(minValue + pct * (maxValue - minValue));\n  };\n\n  const nextFromKey = (key: string, current: number): number | null => {\n    const normalized = toFiniteNumberOr(current, min());\n\n    if (key === 'ArrowRight' || key === 'ArrowUp') return clamp(normalized + step());\n\n    if (key === 'ArrowLeft' || key === 'ArrowDown') return clamp(normalized - step());\n\n    if (key === 'Home') return min();\n\n    if (key === 'End') return max();\n\n    return null;\n  };\n\n  const handleKeydown = (event: KeyboardEvent, currentValue: number, onCommit: (value: number) => void): boolean => {\n    if (options.disabled?.value || options.readonly?.value) return false;\n\n    const next = nextFromKey(event.key, currentValue);\n\n    if (next === null) return false;\n\n    event.preventDefault();\n    onCommit(next);\n\n    return true;\n  };\n\n  return { clamp, fromClientX, handleKeydown, max, min, nextFromKey, snap, toPercent };\n};\n"],"mappings":"yEA+BA,IAAa,EAAuB,GAAiD,CACnF,IAAM,MAAoB,EAAA,iBAAiB,EAAQ,KAAK,MAAO,CAAC,EAC1D,MAAoB,EAAA,iBAAiB,EAAQ,KAAK,MAAO,GAAG,EAC5D,MAAqB,EAAA,eAAe,EAAQ,MAAM,MAAO,CAAC,EAE1D,EAAS,GAA0B,CACvC,IAAM,EAAW,EAAI,EACf,EAAW,EAAI,EAErB,OAAA,EAAO,EAAA,MAAA,CAAW,EAAA,iBAAiB,EAAO,CAAQ,EAAG,EAAU,CAAQ,CACzE,EAEM,EAAQ,GAA0B,CACtC,IAAM,EAAW,EAAI,EAErB,OAAO,EAAM,KAAK,MAAM,EAAA,iBAAiB,EAAO,CAAQ,EAAI,EAAK,CAAC,EAAI,EAAK,CAAC,CAC9E,EAEM,EAAa,GAA0B,CAC3C,IAAM,EAAW,EAAI,EACf,EAAW,EAAI,EACf,EAAa,EAAA,iBAAiB,EAAO,CAAQ,EAInD,OAFI,GAAY,EAAiB,GAExB,EAAa,IAAa,EAAW,GAAa,GAC7D,EAEM,GAAe,EAAiB,IAAkD,CACtF,GAAI,EAAK,OAAS,EAAG,OAAO,EAAK,EAAI,CAAC,EAEtC,IAAM,EAAM,KAAK,IAAI,EAAG,KAAK,IAAI,GAAI,EAAU,EAAK,MAAQ,EAAK,KAAK,CAAC,EACjE,EAAW,EAAI,EACf,EAAW,EAAI,EAErB,OAAO,EAAK,EAAW,GAAO,EAAW,EAAS,CACpD,EAEM,GAAe,EAAa,IAAmC,CACnE,IAAM,EAAa,EAAA,iBAAiB,EAAS,EAAI,CAAC,EAUlD,OARI,IAAQ,cAAgB,IAAQ,UAAkB,EAAM,EAAa,EAAK,CAAC,EAE3E,IAAQ,aAAe,IAAQ,YAAoB,EAAM,EAAa,EAAK,CAAC,EAE5E,IAAQ,OAAe,EAAI,EAE3B,IAAQ,MAAc,EAAI,EAEvB,IACT,EAeA,MAAO,CAAE,QAAO,cAAa,eAbN,EAAsB,EAAsB,IAA+C,CAChH,GAAI,EAAQ,UAAU,OAAS,EAAQ,UAAU,MAAO,MAAO,GAE/D,IAAM,EAAO,EAAY,EAAM,IAAK,CAAY,EAOhD,OALI,IAAS,OAEb,EAAM,eAAe,EACrB,EAAS,CAAI,EAEN,GACT,EAE4C,MAAK,MAAK,cAAa,OAAM,WAAU,CACrF"}