{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "duck-slider",
"title": "Duck Slider",
"description": "The waterline: the filled track is water, the thumb floats on it, and letting go leaves a wake. A real input type=range, so arrows, PageUp/PageDown, Home/End, touch and RTL are the browser's job. curve=log owns the geometric mapping a font-size or zoom slider needs, and keeps aria-valuetext honest; label, valuePosition=row and action put the readout and a reset on the label row instead of above the track. Single value.",
"registryDependencies": [
"@duck/theme"
],
"files": [
{
"path": "registry/duck/ui/duck-slider.tsx",
"content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * DuckSlider — the waterline.\n *\n * The filled track is water, the thumb is the duck floating on it, and letting\n * go leaves a wake that spreads and dies. No foil here: an iridescent track\n * would be decoration pretending to be metaphor, and sliders come in sixes.\n *\n * It is a real , which is the whole point. Arrow keys,\n * PageUp/PageDown, Home/End, touch dragging without stealing the page scroll,\n * and RTL where Left increases — all of it is browser behaviour that a div\n * with role=\"slider\" would have to reimplement and would get wrong.\n *\n * Single value only. A two-thumb range needs a different control; this is not\n * that control pretending.\n */\n\nconst LOG_STEPS = 1000;\n\n/** How many decimals the grain has, so quantising cannot leak 0.30000000000004. */\nfunction decimalsOf(step: number) {\n const text = String(step);\n const dot = text.indexOf(\".\");\n return dot === -1 ? 0 : text.length - dot - 1;\n}\n\nexport interface DuckSliderProps\n extends Omit, \"type\" | \"value\" | \"defaultValue\"> {\n value?: number;\n defaultValue?: number;\n /**\n * Turns the raw number into something a screen reader can read out —\n * \"120 ms\", \"Large\". Without it the user hears a bare integer.\n */\n formatValue?: (value: number) => string;\n /** Show the formatted value. */\n showValue?: boolean;\n /**\n * Where that value goes. `above` is a line of its own over the track; `row`\n * puts it at the end of the label row, right-aligned in tabular mono, which is\n * what a control rail wants — a dragging slider never reflows the row it sits\n * in, and 40 of them stay a fixed height.\n */\n valuePosition?: \"above\" | \"row\";\n /**\n * The control's name, rendered as a real