@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
1 lines • 10.8 kB
Source Map (JSON)
{"version":3,"file":"use-saturation-slider.cjs","names":["useFieldProps","useI18n","useControllableState","usePanEvent","h","s","v","getRootProps: PropGetter","props","getInputProps: PropGetter<\"input\">","visuallyHiddenAttributes","mergeRefs","getTrackProps: PropGetter"],"sources":["../../../../src/components/saturation-slider/use-saturation-slider.ts"],"sourcesContent":["\"use client\"\n\nimport type { KeyboardEvent } from \"react\"\nimport type { HTMLProps, HTMLRefAttributes, PropGetter } from \"../../core\"\nimport type { Point } from \"../../utils\"\nimport type { FieldProps } from \"../field\"\nimport { useCallback } from \"react\"\nimport { useControllableState } from \"../../hooks/use-controllable-state\"\nimport { usePanEvent } from \"../../hooks/use-pan-event\"\nimport { useI18n } from \"../../providers/i18n-provider\"\nimport {\n clampNumber,\n cx,\n handlerAll,\n mergeRefs,\n roundNumberToStep,\n visuallyHiddenAttributes,\n} from \"../../utils\"\nimport { runKeyAction } from \"../../utils/dom\"\nimport { useFieldProps } from \"../field\"\n\nfunction clampValue(value: [number, number, number]) {\n return [\n clampNumber(value[0], 0, 360),\n clampNumber(value[1], 0, 1),\n clampNumber(value[2], 0, 1),\n ] as [number, number, number]\n}\n\nexport interface UseSaturationSliderProps\n extends Omit<HTMLProps, \"defaultValue\" | \"onChange\" | \"ref\">,\n HTMLRefAttributes<\"input\">,\n FieldProps {\n /**\n * The base `id` to use for the slider.\n */\n id?: string\n /**\n * The name attribute of the hidden `input` field.\n * This is particularly useful in forms.\n */\n name?: string\n /**\n * The initial value of the saturation slider.\n *\n * @default [0, 0, 1]\n */\n defaultValue?: [number, number, number]\n /**\n * This is used to format the value so that screen readers\n * can speak out a more human-friendly value.\n *\n * It is used to set the `aria-valuetext` property of the input.\n */\n getAriaValueText?: (value: [number, number, number]) => string | undefined\n /**\n * The step in which increments or decrements have to be made.\n *\n * @default 0.01\n */\n step?: number\n /**\n * The value of the saturation slider.\n */\n value?: [number, number, number]\n /**\n * Function called whenever the saturation slider value changes.\n */\n onChange?: (value: [number, number, number]) => void\n /**\n * Function called when the user is done selecting a new value.\n */\n onChangeEnd?: (value: [number, number, number]) => void\n /**\n * Function called when the user starts selecting a new value.\n */\n onChangeStart?: (value: [number, number, number]) => void\n}\n\nexport const useSaturationSlider = (props: UseSaturationSliderProps = {}) => {\n const {\n props: {\n id,\n ref,\n name,\n \"aria-labelledby\": ariaLabelledBy,\n \"aria-valuetext\": ariaValueText,\n defaultValue = [0, 0, 1],\n disabled,\n getAriaValueText,\n readOnly,\n required,\n step = 0.01,\n value: valueProp,\n onChange: onChangeProp,\n onChangeEnd,\n onChangeStart,\n ...rest\n },\n ariaProps,\n dataProps,\n eventProps,\n } = useFieldProps(props)\n const { t } = useI18n(\"saturationSlider\")\n const [value, setValue] = useControllableState({\n defaultValue,\n value: valueProp,\n onChange: onChangeProp,\n })\n const [h, s, v] = clampValue(value)\n const interactive = !(disabled || readOnly)\n const [_, getPanEventProps] = usePanEvent<HTMLDivElement>({\n onEnd: (_, point, rect) => {\n if (!interactive) return\n\n const panValue = getPanValue(point, rect)\n\n onChangeEnd?.(panValue)\n },\n onMove: (_, point, rect) => {\n if (!interactive) return\n\n const panValue = getPanValue(point, rect)\n\n setValue(panValue)\n },\n onStart: (_, point, rect) => {\n if (!interactive) return\n\n const panValue = getPanValue(point, rect)\n\n onChangeStart?.(value)\n setValue(panValue)\n },\n })\n\n const onChange = useCallback(\n ([h, s, v]: [number, number, number]) => {\n if (!interactive) return\n\n s = clampNumber(s, 0, 1)\n v = clampNumber(v, 0, 1)\n\n setValue([h, s, v])\n },\n [interactive, setValue],\n )\n\n const getPanValue = useCallback(\n (\n { x, y }: Point,\n { bottom, height, left, width }: DOMRect,\n ): [number, number, number] => {\n const diff = { x: x - left, y: bottom - y }\n const percent = { x: diff.x / width, y: diff.y / height }\n const clamp = {\n x: clampNumber(percent.x, 0, 1),\n y: clampNumber(percent.y, 0, 1),\n }\n const s = roundNumberToStep(clamp.x, 0, step)\n const v = roundNumberToStep(clamp.y, 0, step)\n\n return [h, parseFloat(s), parseFloat(v)]\n },\n [h, step],\n )\n\n const onKeyDown = useCallback(\n (ev: KeyboardEvent<HTMLDivElement>) => {\n runKeyAction(ev, {\n ArrowDown: () => onChange([h, s, v - step]),\n ArrowLeft: () => onChange([h, s - step, v]),\n ArrowRight: () => onChange([h, s + step, v]),\n ArrowUp: () => onChange([h, s, v + step]),\n })\n },\n [h, onChange, s, step, v],\n )\n\n const getRootProps: PropGetter = useCallback(\n (props = {}) => ({\n ...dataProps,\n ...rest,\n ...props,\n style: {\n ...rest.style,\n ...props.style,\n \"--x\": `${Math.abs(s * 100)}%`,\n \"--y\": `${Math.abs(100 - v * 100)}%`,\n backgroundColor: `hsl(${h}, 100%, 50%)`,\n backgroundImage:\n \"linear-gradient(0deg, #000, transparent), linear-gradient(90deg, #fff, transparent)\",\n },\n onBlur: handlerAll(props.onBlur, eventProps.onBlur),\n onFocus: handlerAll(props.onFocus, eventProps.onFocus),\n }),\n [dataProps, eventProps, h, rest, s, v],\n )\n\n const getInputProps: PropGetter<\"input\"> = useCallback(\n (props = {}) => ({\n ...visuallyHiddenAttributes,\n ...dataProps,\n ...ariaProps,\n id,\n type: \"hidden\",\n name,\n disabled,\n readOnly,\n required,\n value: [h, s, v].toString(),\n ...props,\n ref: mergeRefs(props.ref, ref),\n }),\n [\n ariaProps,\n dataProps,\n disabled,\n h,\n id,\n name,\n readOnly,\n ref,\n required,\n s,\n v,\n ],\n )\n\n const getTrackProps: PropGetter = useCallback(\n (props = {}) => getPanEventProps({ ...dataProps, ...props }),\n [dataProps, getPanEventProps],\n )\n\n const getThumbProps: PropGetter = useCallback(\n (props = {}) => ({\n ...dataProps,\n ...ariaProps,\n \"aria-label\": t(\"Saturation and brightness thumb\"),\n \"aria-roledescription\": \"2D slider\",\n \"aria-valuemax\": 100,\n \"aria-valuemin\": 0,\n \"aria-valuenow\": s * 100,\n \"aria-valuetext\":\n ariaValueText ??\n getAriaValueText?.(value) ??\n t(\"Saturation {saturation}%, Brightness {brightness}%\", {\n brightness: v * 100,\n saturation: s * 100,\n }),\n role: \"slider\",\n tabIndex: interactive ? 0 : -1,\n ...props,\n \"aria-labelledby\": cx(props[\"aria-labelledby\"], ariaLabelledBy),\n onKeyDown: handlerAll(props.onKeyDown, onKeyDown),\n }),\n [\n ariaLabelledBy,\n ariaProps,\n ariaValueText,\n dataProps,\n getAriaValueText,\n interactive,\n onKeyDown,\n s,\n t,\n v,\n value,\n ],\n )\n\n return {\n setValue,\n value,\n getInputProps,\n getRootProps,\n getThumbProps,\n getTrackProps,\n onChange,\n }\n}\n\nexport type UseSaturationSliderReturn = ReturnType<typeof useSaturationSlider>\n"],"mappings":"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"}