@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
244 lines (240 loc) • 8.15 kB
JavaScript
"use client";
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
const require_context = require('../../utils/context.cjs');
const require_dom = require('../../utils/dom.cjs');
const require_ref = require('../../utils/ref.cjs');
const require_utils_index = require('../../utils/index.cjs');
const require_hooks_use_controllable_state_index = require('../../hooks/use-controllable-state/index.cjs');
const require_use_field_props = require('../field/use-field-props.cjs');
let react = require("react");
react = require_rolldown_runtime.__toESM(react);
//#region src/components/rating/use-rating.tsx
const getRoundedValue = (value, to) => {
const rounded = Math.round(value / to) * to;
const precision = `${to}`.split(".")[1]?.length || 0;
return Number(rounded.toFixed(precision));
};
const [RatingContext, useRatingContext] = require_context.createContext({ name: "RatingContext" });
const useRating = (props = {}) => {
const uuid = (0, react.useId)();
const { props: { id = uuid, name = uuid, count: countProp = 5, defaultValue = 0, disabled, fractions: fractionsProp = 1, highlightSelectedOnly = false, readOnly, required, value: valueProp, onChange: onChangeProp, onHover,...rest }, ariaProps, dataProps, eventProps } = require_use_field_props.useFieldProps({
...props,
notSupportReadOnly: true
});
const rootRef = (0, react.useRef)(null);
const [value, setValue] = require_hooks_use_controllable_state_index.useControllableState({
defaultValue,
value: valueProp,
onChange: onChangeProp
});
const [hoveredValue, setHoveredValue] = (0, react.useState)(-1);
const outsideRef = (0, react.useRef)(true);
const fractions = Math.floor(fractionsProp);
const count = Math.floor(countProp);
const decimal = 1 / fractions;
const roundedValue = (0, react.useMemo)(() => getRoundedValue(value, decimal), [decimal, value]);
const interactive = !(readOnly || disabled);
const displayValue = hoveredValue !== -1 ? hoveredValue : roundedValue;
const getHoveredValue = (0, react.useCallback)((x) => {
if (!rootRef.current) return -1;
const { left, width } = rootRef.current.getBoundingClientRect();
const itemWidth = width / count;
return (0, require_utils_index.utils_exports.clampNumber)(getRoundedValue((x - left) / itemWidth + decimal / 2, decimal), decimal, count);
}, [count, decimal]);
const onMouseEnter = (0, react.useCallback)(() => {
if (interactive) outsideRef.current = false;
}, [interactive]);
const onMouseLeave = (0, react.useCallback)(() => {
if (!interactive) return;
setHoveredValue(-1);
outsideRef.current = true;
if (hoveredValue !== -1) onHover?.(-1);
}, [
hoveredValue,
onHover,
interactive,
setHoveredValue
]);
const onMouseMove = (0, react.useCallback)((ev) => {
if (disabled || readOnly) return;
const roundedValue$1 = getHoveredValue(ev.clientX);
setHoveredValue(roundedValue$1);
if (roundedValue$1 !== hoveredValue) onHover?.(roundedValue$1);
}, [
disabled,
getHoveredValue,
hoveredValue,
readOnly,
onHover
]);
const onTouchStart = (0, react.useCallback)((ev) => {
ev.preventDefault();
const el = ev.touches[0];
if (!el) return;
setValue(getHoveredValue(el.clientX));
}, [getHoveredValue, setValue]);
const onTouchEnd = (0, react.useCallback)((ev) => {
ev.preventDefault();
}, []);
return {
id,
name,
count,
decimal,
disabled,
displayValue,
fractions,
highlightSelectedOnly,
hoveredValue,
interactive,
outsideRef,
readOnly,
required,
roundedValue,
setHoveredValue,
setValue,
value,
ariaProps,
dataProps,
eventProps,
getRootProps: (0, react.useCallback)(({ ref,...props$1 } = {}) => ({
...dataProps,
...eventProps,
...ariaProps,
id,
"aria-label": `${value} Stars`,
"aria-readonly": (0, require_utils_index.utils_exports.ariaAttr)(readOnly),
role: "radiogroup",
...rest,
...props$1,
ref: require_ref.mergeRefs(ref, rest.ref, rootRef),
onMouseEnter: (0, require_utils_index.utils_exports.handlerAll)(props$1.onMouseEnter, rest.onMouseEnter, onMouseEnter),
onMouseLeave: (0, require_utils_index.utils_exports.handlerAll)(props$1.onMouseLeave, rest.onMouseLeave, onMouseLeave),
onMouseMove: (0, require_utils_index.utils_exports.handlerAll)(props$1.onMouseMove, rest.onMouseMove, onMouseMove),
onTouchEnd: (0, require_utils_index.utils_exports.handlerAll)(props$1.onTouchEnd, rest.onTouchEnd, onTouchEnd),
onTouchStart: (0, require_utils_index.utils_exports.handlerAll)(props$1.onTouchStart, rest.onTouchStart, onTouchStart)
}), [
ariaProps,
dataProps,
eventProps,
id,
onMouseEnter,
onMouseLeave,
onMouseMove,
onTouchEnd,
onTouchStart,
readOnly,
rest,
value
])
};
};
const useRatingItem = ({ groupValue, index,...rest }) => {
const { id: rootId, name, decimal, disabled, displayValue, highlightSelectedOnly, interactive, outsideRef, readOnly, required, roundedValue, setHoveredValue, setValue, ariaProps, dataProps, eventProps } = useRatingContext();
const fractionValue = decimal * (groupValue === 1 ? index : index + 1);
const value = (0, react.useMemo)(() => getRoundedValue(groupValue - 1 + fractionValue, decimal), [
decimal,
fractionValue,
groupValue
]);
const active = value === displayValue;
const checked = value === roundedValue;
const filled = highlightSelectedOnly ? value === displayValue : value <= displayValue;
const id = `${rootId}-${groupValue}-${value}`;
const onBlur = (0, react.useCallback)(() => {
if (outsideRef.current) setHoveredValue(-1);
}, [outsideRef, setHoveredValue]);
const onInputChange = (0, react.useCallback)((ev) => {
if (!interactive) return;
setHoveredValue(parseFloat(ev.target.value));
}, [interactive, setHoveredValue]);
const onChange = (0, react.useCallback)((value$1) => {
if (!interactive) return;
setValue(value$1);
}, [interactive, setValue]);
const onMouseDown = (0, react.useCallback)(() => {
onChange(value);
}, [onChange, value]);
const onTouchStart = (0, react.useCallback)(() => {
onChange(value);
}, [onChange, value]);
const onKeyDown = (0, react.useCallback)((ev) => {
require_dom.runKeyAction(ev, { Space: () => onChange(value) });
}, [onChange, value]);
const getLabelProps = (0, react.useCallback)(({ style,...props } = {}) => ({
...dataProps,
...ariaProps,
htmlFor: id,
"data-active": (0, require_utils_index.utils_exports.dataAttr)(active),
"data-filled": (0, require_utils_index.utils_exports.dataAttr)(filled),
...rest,
...props,
style: {
...style,
zIndex: fractionValue !== 1 ? active ? 1 : -1 : void 0
},
onMouseDown: (0, require_utils_index.utils_exports.handlerAll)(props.onMouseDown, onMouseDown),
onTouchStart: (0, require_utils_index.utils_exports.handlerAll)(props.onTouchStart, onTouchStart)
}), [
active,
ariaProps,
dataProps,
filled,
fractionValue,
id,
onMouseDown,
onTouchStart,
rest
]);
return {
active,
checked,
filled,
fractionValue,
groupValue,
value,
getInputProps: (0, react.useCallback)((props = {}) => ({
...dataProps,
...eventProps,
...ariaProps,
id,
type: "radio",
name,
style: require_dom.visuallyHiddenAttributes.style,
"aria-label": value.toString(),
"data-active": (0, require_utils_index.utils_exports.dataAttr)(active),
"data-checked": (0, require_utils_index.utils_exports.dataAttr)(checked),
checked,
disabled,
readOnly,
required,
value,
...props,
onBlur: (0, require_utils_index.utils_exports.handlerAll)(onBlur, props.onBlur),
onChange: (0, require_utils_index.utils_exports.handlerAll)(props.onChange, onInputChange),
onKeyDown: (0, require_utils_index.utils_exports.handlerAll)(props.onKeyDown, onKeyDown)
}), [
id,
name,
value,
active,
checked,
dataProps,
eventProps,
ariaProps,
disabled,
readOnly,
required,
onBlur,
onInputChange,
onKeyDown
]),
getLabelProps
};
};
//#endregion
exports.RatingContext = RatingContext;
exports.useRating = useRating;
exports.useRatingContext = useRatingContext;
exports.useRatingItem = useRatingItem;
//# sourceMappingURL=use-rating.cjs.map