{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "use-slider-with-input",
  "title": "Use slider with input",
  "description": "The use-slider-with-input hook used by ndekoui components.",
  "dependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/ndeko/hooks/use-slider-with-input.ts",
      "content": "'use client';\n\nimport { useCallback, useState, type ChangeEvent } from 'react';\n\nexport type SliderWithInputOptions = {\n  minValue?: number;\n  maxValue?: number;\n  initialValue?: number[];\n  defaultValue?: number[];\n};\n\ntype SliderValue = number | readonly number[];\n\nconst DECIMAL_DRAFT = /^-?\\d*\\.?\\d*$/;\n\nfunction valuesOf(value: SliderValue) {\n  if (typeof value === 'number') {\n    return [value];\n  }\n  return [...value];\n}\n\nfunction textsOf(values: readonly number[]) {\n  return values.map(String);\n}\n\nfunction replaceAt<Item>(items: readonly Item[], index: number, item: Item) {\n  const nextItems = [...items];\n  nextItems[index] = item;\n  return nextItems;\n}\n\nfunction isEmptyDraft(rawValue: string) {\n  const isBlank = rawValue === '';\n  const isLoneMinus = rawValue === '-';\n  return isBlank || isLoneMinus;\n}\n\nfunction numberOf(rawValue: string) {\n  if (isEmptyDraft(rawValue)) {\n    return 0;\n  }\n  return parseFloat(rawValue);\n}\n\nfunction clamp(value: number, min: number, max: number) {\n  const atLeastMin = Math.max(min, value);\n  return Math.min(max, atLeastMin);\n}\n\nfunction keepBetweenNeighbours(\n  value: number,\n  index: number,\n  values: readonly number[]\n) {\n  const lowerNeighbour = values[index - 1];\n  const upperNeighbour = values[index + 1];\n  let allowedValue = value;\n  if (lowerNeighbour !== undefined) {\n    allowedValue = Math.max(allowedValue, lowerNeighbour);\n  }\n  if (upperNeighbour !== undefined) {\n    allowedValue = Math.min(allowedValue, upperNeighbour);\n  }\n  return allowedValue;\n}\n\nexport function useSliderWithInput({\n  minValue = 0,\n  maxValue = 100,\n  initialValue = [minValue],\n  defaultValue = [minValue],\n}: SliderWithInputOptions) {\n  const [sliderValue, setSliderValue] = useState(initialValue);\n  const [inputValues, setInputValues] = useState(() => textsOf(initialValue));\n\n  const hasSameLength = sliderValue.length === defaultValue.length;\n  const isAtDefault = sliderValue.every(\n    (value, index) => value === defaultValue[index]\n  );\n  const showReset = hasSameLength && !isAtDefault;\n\n  const validateAndUpdateValue = useCallback(\n    (rawValue: string, index: number) => {\n      const typedValue = numberOf(rawValue);\n\n      if (Number.isNaN(typedValue)) {\n        const currentText = String(sliderValue[index]);\n        const restoredTexts = replaceAt(inputValues, index, currentText);\n        setInputValues(restoredTexts);\n        return;\n      }\n\n      const valueInRange = clamp(typedValue, minValue, maxValue);\n      const allowedValue = keepBetweenNeighbours(\n        valueInRange,\n        index,\n        sliderValue\n      );\n      const allowedText = String(allowedValue);\n      const nextValues = replaceAt(sliderValue, index, allowedValue);\n      const nextTexts = replaceAt(inputValues, index, allowedText);\n      setSliderValue(nextValues);\n      setInputValues(nextTexts);\n    },\n    [sliderValue, inputValues, minValue, maxValue]\n  );\n\n  const handleInputChange = useCallback(\n    (event: ChangeEvent<HTMLInputElement>, index: number) => {\n      const draft = event.currentTarget.value;\n      const isDecimalDraft = DECIMAL_DRAFT.test(draft);\n      if (!isDecimalDraft) {\n        return;\n      }\n      const nextTexts = replaceAt(inputValues, index, draft);\n      setInputValues(nextTexts);\n    },\n    [inputValues]\n  );\n\n  const handleSliderChange = useCallback((value: SliderValue) => {\n    const nextValues = valuesOf(value);\n    const nextTexts = textsOf(nextValues);\n    setSliderValue(nextValues);\n    setInputValues(nextTexts);\n  }, []);\n\n  const resetToDefault = useCallback(() => {\n    const defaultTexts = textsOf(defaultValue);\n    setSliderValue(defaultValue);\n    setInputValues(defaultTexts);\n  }, [defaultValue]);\n\n  return {\n    sliderValue,\n    inputValues,\n    validateAndUpdateValue,\n    handleInputChange,\n    handleSliderChange,\n    resetToDefault,\n    showReset,\n  };\n}\n",
      "type": "registry:hook"
    }
  ],
  "categories": [
    "hooks"
  ],
  "type": "registry:hook"
}