@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
211 lines (207 loc) • 5.19 kB
JavaScript
"use client";
import { runKeyAction, visuallyHiddenAttributes } from "../../utils/dom.js";
import { mergeRefs } from "../../utils/ref.js";
import { utils_exports } from "../../utils/index.js";
import { useControllableState } from "../../hooks/use-controllable-state/index.js";
import { usePanEvent } from "../../hooks/use-pan-event/index.js";
import { useI18n } from "../../providers/i18n-provider/i18n-provider.js";
import { useFieldProps } from "../field/use-field-props.js";
import { useCallback } from "react";
//#region src/components/saturation-slider/use-saturation-slider.ts
function clampValue(value) {
return [
(0, utils_exports.clampNumber)(value[0], 0, 360),
(0, utils_exports.clampNumber)(value[1], 0, 1),
(0, utils_exports.clampNumber)(value[2], 0, 1)
];
}
const useSaturationSlider = (props = {}) => {
const { props: { id, ref, name, "aria-labelledby": ariaLabelledBy, "aria-valuetext": ariaValueText, defaultValue = [
0,
0,
1
], disabled, getAriaValueText, readOnly, required, step = .01, value: valueProp, onChange: onChangeProp, onChangeEnd, onChangeStart,...rest }, ariaProps, dataProps, eventProps } = useFieldProps(props);
const { t } = useI18n("saturationSlider");
const [value, setValue] = useControllableState({
defaultValue,
value: valueProp,
onChange: onChangeProp
});
const [h, s, v] = clampValue(value);
const interactive = !(disabled || readOnly);
const [_, getPanEventProps] = usePanEvent({
onEnd: (_$1, point, rect) => {
if (!interactive) return;
const panValue = getPanValue(point, rect);
onChangeEnd?.(panValue);
},
onMove: (_$1, point, rect) => {
if (!interactive) return;
setValue(getPanValue(point, rect));
},
onStart: (_$1, point, rect) => {
if (!interactive) return;
const panValue = getPanValue(point, rect);
onChangeStart?.(value);
setValue(panValue);
}
});
const onChange = useCallback(([h$1, s$1, v$1]) => {
if (!interactive) return;
s$1 = (0, utils_exports.clampNumber)(s$1, 0, 1);
v$1 = (0, utils_exports.clampNumber)(v$1, 0, 1);
setValue([
h$1,
s$1,
v$1
]);
}, [interactive, setValue]);
const getPanValue = useCallback(({ x, y }, { bottom, height, left, width }) => {
const diff = {
x: x - left,
y: bottom - y
};
const percent = {
x: diff.x / width,
y: diff.y / height
};
const clamp = {
x: (0, utils_exports.clampNumber)(percent.x, 0, 1),
y: (0, utils_exports.clampNumber)(percent.y, 0, 1)
};
const s$1 = (0, utils_exports.roundNumberToStep)(clamp.x, 0, step);
const v$1 = (0, utils_exports.roundNumberToStep)(clamp.y, 0, step);
return [
h,
parseFloat(s$1),
parseFloat(v$1)
];
}, [h, step]);
const onKeyDown = useCallback((ev) => {
runKeyAction(ev, {
ArrowDown: () => onChange([
h,
s,
v - step
]),
ArrowLeft: () => onChange([
h,
s - step,
v
]),
ArrowRight: () => onChange([
h,
s + step,
v
]),
ArrowUp: () => onChange([
h,
s,
v + step
])
});
}, [
h,
onChange,
s,
step,
v
]);
const getRootProps = useCallback((props$1 = {}) => ({
...dataProps,
...rest,
...props$1,
style: {
...rest.style,
...props$1.style,
"--x": `${Math.abs(s * 100)}%`,
"--y": `${Math.abs(100 - v * 100)}%`,
backgroundColor: `hsl(${h}, 100%, 50%)`,
backgroundImage: "linear-gradient(0deg, #000, transparent), linear-gradient(90deg, #fff, transparent)"
},
onBlur: (0, utils_exports.handlerAll)(props$1.onBlur, eventProps.onBlur),
onFocus: (0, utils_exports.handlerAll)(props$1.onFocus, eventProps.onFocus)
}), [
dataProps,
eventProps,
h,
rest,
s,
v
]);
const getInputProps = useCallback((props$1 = {}) => ({
...visuallyHiddenAttributes,
...dataProps,
...ariaProps,
id,
type: "hidden",
name,
disabled,
readOnly,
required,
value: [
h,
s,
v
].toString(),
...props$1,
ref: mergeRefs(props$1.ref, ref)
}), [
ariaProps,
dataProps,
disabled,
h,
id,
name,
readOnly,
ref,
required,
s,
v
]);
const getTrackProps = useCallback((props$1 = {}) => getPanEventProps({
...dataProps,
...props$1
}), [dataProps, getPanEventProps]);
return {
setValue,
value,
getInputProps,
getRootProps,
getThumbProps: useCallback((props$1 = {}) => ({
...dataProps,
...ariaProps,
"aria-label": t("Saturation and brightness thumb"),
"aria-roledescription": "2D slider",
"aria-valuemax": 100,
"aria-valuemin": 0,
"aria-valuenow": s * 100,
"aria-valuetext": ariaValueText ?? getAriaValueText?.(value) ?? t("Saturation {saturation}%, Brightness {brightness}%", {
brightness: v * 100,
saturation: s * 100
}),
role: "slider",
tabIndex: interactive ? 0 : -1,
...props$1,
"aria-labelledby": (0, utils_exports.cx)(props$1["aria-labelledby"], ariaLabelledBy),
onKeyDown: (0, utils_exports.handlerAll)(props$1.onKeyDown, onKeyDown)
}), [
ariaLabelledBy,
ariaProps,
ariaValueText,
dataProps,
getAriaValueText,
interactive,
onKeyDown,
s,
t,
v,
value
]),
getTrackProps,
onChange
};
};
//#endregion
export { useSaturationSlider };
//# sourceMappingURL=use-saturation-slider.js.map