{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "slider",
  "type": "registry:ui",
  "title": "Slider",
  "description": "Slider control for Tile UI.",
  "devDependencies": [
    "sass"
  ],
  "registryDependencies": [
    "@tile-ui/core",
    "@tile-ui/styles"
  ],
  "files": [
    {
      "path": "packages/react/src/components/slider/slider.tsx",
      "type": "registry:ui",
      "target": "components/ui/slider/slider.tsx",
      "content": "import React, { createContext, useContext, useState } from 'react';\nimport { clampSliderValue, getSliderOffsetStyle, getSliderPercent, sliderStyleKeys } from '../lib/core';\nimport type { SliderBaseProps } from '../lib/core';\nimport styles from './slider.module.scss';\n\ninterface SliderContextValue {\n\tvalue: number;\n\tmin: number;\n\tmax: number;\n\tstep: number;\n\torientation: 'horizontal' | 'vertical';\n\tdisabled: boolean;\n\tsetValue: (value: number) => void;\n}\n\nconst SliderContext = createContext<SliderContextValue | null>(null);\n\nfunction useSliderContext(): SliderContextValue {\n\tconst context = useContext(SliderContext);\n\tif (!context) {\n\t\tthrow new Error('Slider sub-components must be used within <Slider>.');\n\t}\n\treturn context;\n}\n\nexport interface SliderProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'value' | 'defaultValue'>, SliderBaseProps {}\n\nconst Slider = React.forwardRef<HTMLDivElement, SliderProps>(\n\t({ className = '', value, defaultValue = 0, min = 0, max = 100, step = 1, orientation = 'horizontal', disabled = false, onValueChange, children, ...props }, ref) => {\n\t\tconst [internalValue, setInternalValue] = useState(defaultValue);\n\t\tconst currentValue = value !== undefined ? value : internalValue;\n\t\tconst clampedValue = clampSliderValue(currentValue, min, max);\n\n\t\tfunction setValue(next: number) {\n\t\t\tif (disabled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst clamped = clampSliderValue(next, min, max);\n\t\t\tconst stepped = clampSliderValue(min + Math.round((clamped - min) / step) * step, min, max);\n\t\t\tif (value === undefined) {\n\t\t\t\tsetInternalValue(stepped);\n\t\t\t}\n\t\t\tonValueChange?.(stepped);\n\t\t}\n\n\t\tfunction updateFromEvent(event: React.PointerEvent<HTMLDivElement>, element: HTMLElement) {\n\t\t\tconst rect = element.getBoundingClientRect();\n\t\t\tlet next: number;\n\t\t\tif (orientation === 'vertical') {\n\t\t\t\tnext = min + ((event.clientY - rect.top) / rect.height) * (max - min);\n\t\t\t} else {\n\t\t\t\tnext = min + ((event.clientX - rect.left) / rect.width) * (max - min);\n\t\t\t}\n\t\t\tsetValue(next);\n\t\t}\n\n\t\tfunction handlePointerDown(event: React.PointerEvent<HTMLDivElement>) {\n\t\t\tif (disabled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tevent.currentTarget.setPointerCapture(event.pointerId);\n\t\t\tupdateFromEvent(event, event.currentTarget);\n\t\t}\n\n\t\tfunction handlePointerMove(event: React.PointerEvent<HTMLDivElement>) {\n\t\t\tif (disabled || !event.currentTarget.hasPointerCapture(event.pointerId)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tupdateFromEvent(event, event.currentTarget);\n\t\t}\n\n\t\treturn (\n\t\t\t<SliderContext.Provider value={{ value: clampedValue, min, max, step, orientation, disabled, setValue }}>\n\t\t\t\t<div\n\t\t\t\t\t{...props}\n\t\t\t\t\tref={ref}\n\t\t\t\t\tdata-orientation={orientation}\n\t\t\t\t\tdata-disabled={disabled}\n\t\t\t\t\tclassName={`${styles[sliderStyleKeys.root]} ${className}`}\n\t\t\t\t\tonPointerDown={handlePointerDown}\n\t\t\t\t\tonPointerMove={handlePointerMove}>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</SliderContext.Provider>\n\t\t);\n\t},\n);\nSlider.displayName = 'Slider';\n\nexport interface SliderTrackProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst SliderTrack = React.forwardRef<HTMLDivElement, SliderTrackProps>(({ className = '', ...props }, ref) => {\n\tconst context = useSliderContext();\n\n\treturn <div ref={ref} data-orientation={context.orientation} className={`${styles[sliderStyleKeys.track]} ${className}`} {...props} />;\n});\nSliderTrack.displayName = 'SliderTrack';\n\nexport interface SliderRangeProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst SliderRange = React.forwardRef<HTMLDivElement, SliderRangeProps>(({ className = '', ...props }, ref) => {\n\tconst context = useSliderContext();\n\tconst percent = getSliderPercent(context.value, context.min, context.max);\n\tconst style = context.orientation === 'vertical' ? { height: `${percent}%` } : { width: `${percent}%` };\n\n\treturn <div ref={ref} data-orientation={context.orientation} className={`${styles[sliderStyleKeys.range]} ${className}`} style={style} {...props} />;\n});\nSliderRange.displayName = 'SliderRange';\n\nexport interface SliderThumbProps extends React.HTMLAttributes<HTMLSpanElement> {}\n\nconst SliderThumb = React.forwardRef<HTMLSpanElement, SliderThumbProps>(({ className = '', onKeyDown, ...props }, ref) => {\n\tconst context = useSliderContext();\n\tconst offsetStyle = getSliderOffsetStyle(context.value, context.min, context.max, context.orientation);\n\n\tfunction handleKeyDown(event: React.KeyboardEvent<HTMLSpanElement>) {\n\t\tonKeyDown?.(event);\n\n\t\tif (event.key === 'Home') {\n\t\t\tcontext.setValue(context.min);\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.key === 'End') {\n\t\t\tcontext.setValue(context.max);\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tconst delta =\n\t\t\tcontext.orientation === 'horizontal'\n\t\t\t\t? event.key === 'ArrowRight'\n\t\t\t\t\t? 1\n\t\t\t\t\t: event.key === 'ArrowLeft'\n\t\t\t\t\t\t? -1\n\t\t\t\t\t\t: 0\n\t\t\t\t: event.key === 'ArrowDown'\n\t\t\t\t\t? 1\n\t\t\t\t\t: event.key === 'ArrowUp'\n\t\t\t\t\t\t? -1\n\t\t\t\t\t\t: 0;\n\n\t\tif (delta !== 0) {\n\t\t\tcontext.setValue(context.value + delta * context.step);\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\treturn (\n\t\t<span\n\t\t\t{...props}\n\t\t\tref={ref}\n\t\t\trole=\"slider\"\n\t\t\ttabIndex={context.disabled ? -1 : 0}\n\t\t\taria-disabled={context.disabled}\n\t\t\taria-valuemin={context.min}\n\t\t\taria-valuemax={context.max}\n\t\t\taria-valuenow={context.value}\n\t\t\taria-orientation={context.orientation}\n\t\t\tdata-orientation={context.orientation}\n\t\t\tclassName={`${styles[sliderStyleKeys.thumb]} ${className}`}\n\t\t\tstyle={offsetStyle}\n\t\t\tonKeyDown={handleKeyDown}\n\t\t/>\n\t);\n});\nSliderThumb.displayName = 'SliderThumb';\n\nexport { Slider, SliderTrack, SliderRange, SliderThumb };\nexport default Slider;\n"
    },
    {
      "path": "packages/styles/scss/components/slider.module.scss",
      "type": "registry:file",
      "target": "components/ui/slider/slider.module.scss",
      "content": "@use '../../../styles/variables/colors' as *;\n\n.root {\n\tposition: relative;\n\tdisplay: flex;\n\twidth: 100%;\n\talign-items: center;\n\ttouch-action: none;\n\tuser-select: none;\n\tpadding: var(--tile-slider-padding, 0);\n\tborder-radius: var(--tile-slider-radius, 0);\n\tbackground-color: var(--tile-slider-background, transparent);\n\tbox-shadow: var(--tile-slider-shadow, none);\n\n\t&[data-orientation='vertical'] {\n\t\twidth: auto;\n\t\theight: 100%;\n\t\tmin-height: 11rem;\n\t\tflex-direction: column;\n\t}\n\n\t&[data-disabled='true'] {\n\t\topacity: 0.5;\n\t}\n}\n\n.track {\n\tposition: relative;\n\tflex-grow: 1;\n\toverflow: hidden;\n\tborder-radius: var(--tile-slider-track-radius, #{$radius-full});\n\tbackground-color: var(--tile-slider-track-background, #{$muted});\n\n\t[data-orientation='horizontal'] & {\n\t\theight: var(--tile-slider-track-size, 0.375rem);\n\t\twidth: 100%;\n\t}\n\n\t[data-orientation='vertical'] & {\n\t\theight: 100%;\n\t\twidth: var(--tile-slider-track-size, 0.375rem);\n\t}\n}\n\n.range {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tbackground-color: var(--tile-slider-range-background, #{$primary});\n\tborder-radius: var(--tile-slider-range-radius, 0);\n\tbox-shadow: var(--tile-slider-range-shadow, none);\n\n\t[data-orientation='horizontal'] & {\n\t\theight: 100%;\n\t}\n\n\t[data-orientation='vertical'] & {\n\t\twidth: 100%;\n\t}\n}\n\n.thumb {\n\tposition: absolute;\n\tdisplay: block;\n\twidth: var(--tile-slider-thumb-width, 1rem);\n\theight: var(--tile-slider-thumb-height, 1rem);\n\tborder: var(--tile-slider-thumb-border-width, 1px) solid var(--tile-slider-thumb-border, #{$primary});\n\tborder-radius: var(--tile-slider-thumb-radius, #{$radius-full});\n\tbackground-color: var(--tile-slider-thumb-background, #{$background});\n\tbox-shadow: var(--tile-slider-thumb-shadow, #{$shadow-sm});\n\ttransition: box-shadow $transition-fast;\n\toutline: none;\n\tcursor: grab;\n\n\t&:active {\n\t\tcursor: grabbing;\n\t}\n\n\t&:focus-visible {\n\t\tbox-shadow: var(--tile-slider-thumb-focus-shadow, 0 0 0 1px $ring, 0 0 0 4px color-mix(in srgb, $ring 50%, transparent));\n\t}\n\n\t[data-orientation='horizontal'] & {\n\t\ttop: 50%;\n\t\ttransform: translate(-50%, -50%);\n\t}\n\n\t[data-orientation='vertical'] & {\n\t\tleft: 50%;\n\t\ttransform: translate(-50%, -50%);\n\t}\n}\n"
    },
    {
      "path": "packages/react/src/components/slider/index.ts",
      "type": "registry:ui",
      "target": "components/ui/slider/index.ts",
      "content": "export { Slider, SliderTrack, SliderRange, SliderThumb, type SliderProps, type SliderTrackProps, type SliderRangeProps, type SliderThumbProps } from './slider';\n"
    }
  ]
}
