UNPKG

@yamada-ui/rating

Version:

Yamada UI rating component

209 lines (207 loc) 5.53 kB
"use client" import { RatingGroup } from "./chunk-LHWQAME3.mjs"; import { getRoundedValue } from "./chunk-5OU2JQG4.mjs"; // src/use-rating.tsx import { formControlProperties, useFormControlProps } from "@yamada-ui/form-control"; import { useControllableState } from "@yamada-ui/use-controllable-state"; import { clampNumber, dataAttr, handlerAll, mergeRefs, runIfFunc, splitObject } from "@yamada-ui/utils"; import { useCallback, useId, useRef, useState } from "react"; import { jsx } from "react/jsx-runtime"; var useRating = ({ name, color, defaultValue = 0, emptyIcon, filledIcon, fractions = 1, highlightSelectedOnly = false, items = 5, value: valueProp, groupProps, inputProps, itemProps, onChange: onChangeProp, onHover, onMouseEnter: onMouseEnterProp, onMouseLeave: onMouseLeaveProp, onMouseMove: onMouseMoveProp, onTouchEnd: onTouchEndProp, onTouchStart: onTouchStartProp, ...props }) => { const uuid = useId(); const { id = uuid, ...rest } = useFormControlProps(props); const containerRef = useRef(null); const [value, setValue] = useControllableState({ defaultValue, value: valueProp, onChange: onChangeProp }); const [hoveredValue, setHoveredValue] = useState(-1); const [outside, setOutside] = useState(true); const [formControlProps, containerProps] = splitObject( rest, formControlProperties ); const { disabled, readOnly, ...omittedFormControlProps } = formControlProps; const resolvedFractions = Math.floor(fractions); const resolvedItems = Math.floor(items); const decimal = 1 / resolvedFractions; const roundedValue = getRoundedValue(value, decimal); const resolvedValue = hoveredValue !== -1 ? hoveredValue : roundedValue; name != null ? name : name = `rating-${id}`; const getHoveredValue = useCallback( (x) => { const { left, width } = containerRef.current.getBoundingClientRect(); const itemWidth = width / resolvedItems; const hoveredValue2 = (x - left) / itemWidth; const value2 = clampNumber( getRoundedValue(hoveredValue2 + decimal / 2, decimal), decimal, resolvedItems ); return value2; }, [decimal, resolvedItems] ); const onMouseEnter = useCallback(() => { if (!disabled && !readOnly) setOutside(false); }, [disabled, readOnly]); const onMouseLeave = useCallback(() => { if (disabled || readOnly) return; setHoveredValue(-1); setOutside(true); if (hoveredValue !== -1) onHover == null ? void 0 : onHover(-1); }, [disabled, hoveredValue, onHover, readOnly, setHoveredValue]); const onTouchStart = useCallback( (ev) => { ev.preventDefault(); const el = ev.touches[0]; if (!el) return; const value2 = getHoveredValue(el.clientX); setValue(value2); }, [getHoveredValue, setValue] ); const onTouchEnd = useCallback((ev) => { ev.preventDefault(); }, []); const onMouseMove = useCallback( (ev) => { if (disabled || readOnly) return; const roundedValue2 = getHoveredValue(ev.clientX); setHoveredValue(roundedValue2); if (roundedValue2 !== hoveredValue) onHover == null ? void 0 : onHover(roundedValue2); }, [disabled, getHoveredValue, hoveredValue, readOnly, onHover] ); const getContainerProps = useCallback( (props2 = {}, ref = null) => ({ ref: mergeRefs(ref, containerRef), "aria-label": `${value} Stars`, role: "radiogroup", ...omittedFormControlProps, ...containerProps, ...props2, id, onMouseEnter: handlerAll( onMouseEnter, props2.onMouseEnter, onMouseEnterProp ), onMouseLeave: handlerAll( onMouseLeave, props2.onMouseLeave, onMouseLeaveProp ), onMouseMove: handlerAll(onMouseMove, props2.onMouseMove, onMouseMoveProp), onTouchEnd: handlerAll(onTouchEnd, props2.onTouchEnd, onTouchEndProp), onTouchStart: handlerAll( onTouchStart, props2.onTouchStart, onTouchStartProp ) }), [ omittedFormControlProps, containerProps, id, value, onMouseEnter, onMouseEnterProp, onMouseLeave, onMouseLeaveProp, onMouseMove, onMouseMoveProp, onTouchEnd, onTouchEndProp, onTouchStart, onTouchStartProp ] ); const getGroupProps = useCallback( ({ value: value2, ...props2 }, ref = null) => { const isActive = !readOnly && Math.ceil(hoveredValue) === value2; return { ref, whileTap: !disabled && !readOnly ? { y: -4 } : void 0, ...props2, "data-active": dataAttr(isActive), tabIndex: -1 }; }, [disabled, hoveredValue, readOnly] ); const children = Array(resolvedItems).fill(0).map((_, index) => { const value2 = index + 1; return /* @__PURE__ */ jsx( RatingGroup, { color: runIfFunc(color, value2), items: index === 0 ? resolvedFractions + 1 : resolvedFractions, value: value2 }, value2 ); }); return { id, name, children, decimal, emptyIcon, filledIcon, highlightSelectedOnly, hoveredValue, outside, resolvedValue, roundedValue, setHoveredValue, setValue, value, formControlProps, getContainerProps, getGroupProps, groupProps, inputProps, itemProps }; }; export { useRating }; //# sourceMappingURL=chunk-PRD35X5H.mjs.map