"use client" import * as React from "react" import { Slider as SliderPrimitive } from "radix-ui" import { cn } from "../../lib/utils" import { Input } from "./input" /** * `RangeControl` is the replacement for `@wordpress/components`' `RangeControl` - * **2 imports across 2 files**, built on Radix's Slider. * * AN ADAPTER, NOT A RENAME, ON TWO COUNTS. * * `onChange` hands back the NUMBER, not an event. Both call sites pass `field.onChange` straight * from react-hook-form, which stores whatever it is given - an event object would be stored verbatim * and the field would look filled while holding nothing usable. * * A WORDPRESS RANGE IS NOT JUST A SLIDER. `withInputField` defaults to TRUE, so every one of these * already renders a number box beside the rail, and `allowReset` (on both `FhirRange` sliders) adds * a Reset button after it. Dropping either would be removing a control people use, not a restyle. * * `marks` reproduces WP's rule literally: a tick every `step` from `min` to `max`. At `FhirRange`'s * 0-100 step 1 that is 101 ticks, which is what ships today. * * Not reproduced: WP's floating value bubble while dragging. The number field carries the same value * permanently, and the bubble is the one piece that needs a second floating layer. * * `__nextHasNoMarginBottom` and `__next40pxDefaultSize` are deliberately not accepted - meaningless * outside WordPress. Call sites drop them. */ export interface RangeControlProps { label?: React.ReactNode help?: React.ReactNode /** WP treats `undefined` and `null` alike: nothing chosen yet. */ value?: number | null /** WP's contract: the NUMBER, or `undefined` when reset. */ onChange?: (value: number | undefined) => void min?: number max?: number step?: number disabled?: boolean /** Renders the Reset button WP puts after the number field. */ allowReset?: boolean /** A tick every `step` across the rail. */ marks?: boolean /** Fallback shown when `value` is absent. */ currentInput?: number /** Where the handle starts before anything is chosen. */ initialPosition?: number className?: string } function clamp(value: number, min: number, max: number) { return Math.min(max, Math.max(min, value)) } function RangeControl({ label, help, value, onChange, min = 0, max = 100, step = 1, disabled = false, allowReset = false, marks = false, currentInput, initialPosition, className, }: RangeControlProps) { // A generated id keeps the label a real `