UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

111 lines (110 loc) • 3.44 kB
"use client"; import { styles } from "./style.mjs"; import { memo, useState } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; import { cssVar, cx } from "antd-style"; import useMergeState from "use-merge-value"; import { Star } from "lucide-react"; //#region src/base-ui/Rate/Rate.tsx const clamp = (value, min, max) => Math.min(max, Math.max(min, value)); const formatValue = (value) => String(Math.round(value * 100) / 100); const Rate = memo(({ allowHalf = false, character, className, color = cssVar.colorWarning, count = 5, defaultValue = 0, disabled = false, gap, onChange, onKeyDown, onPointerLeave, readOnly = false, size = 20, style, value, ...rest }) => { const [mergedValue, setMergedValue] = useMergeState(defaultValue, { onChange, value }); const [hoverValue, setHoverValue] = useState(null); const interactive = !readOnly && !disabled; const step = allowHalf ? .5 : 1; const displayValue = clamp(hoverValue ?? mergedValue, 0, count); const label = `${formatValue(clamp(mergedValue, 0, count))} out of ${count}`; const icon = character ?? /* @__PURE__ */ jsx(Star, { fill: "currentColor", size }); const handleKeyDown = (event) => { onKeyDown?.(event); if (!interactive || event.defaultPrevented) return; const next = { ArrowDown: mergedValue - step, ArrowLeft: mergedValue - step, ArrowRight: mergedValue + step, ArrowUp: mergedValue + step, End: count, Home: 0 }[event.key]; if (next === void 0) return; event.preventDefault(); setMergedValue(clamp(Math.round(next / step) * step, 0, count)); }; const a11yProps = readOnly ? { "aria-label": label, "role": "img" } : { "aria-disabled": disabled || void 0, "aria-valuemax": count, "aria-valuemin": 0, "aria-valuenow": mergedValue, "aria-valuetext": label, "role": "slider", "tabIndex": disabled ? -1 : 0 }; return /* @__PURE__ */ jsx("div", { className: cx(styles.root, className), style: { gap: gap ?? size / 2, ...style }, onKeyDown: handleKeyDown, onPointerLeave: (event) => { onPointerLeave?.(event); setHoverValue(null); }, ...a11yProps, ...rest, children: Array.from({ length: count }, (_, index) => { const fill = clamp(displayValue - index, 0, 1); const targets = allowHalf ? [index + .5, index + 1] : [index + 1]; return /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: styles.star, "data-index": index, style: { fontSize: size, height: size }, children: [ /* @__PURE__ */ jsx("span", { className: cx(styles.icon, styles.empty), style: { minWidth: size }, children: icon }), /* @__PURE__ */ jsx("span", { className: styles.fill, style: { color, width: `${fill * 100}%` }, children: /* @__PURE__ */ jsx("span", { className: styles.icon, style: { minWidth: size }, children: icon }) }), interactive && targets.map((target) => /* @__PURE__ */ jsx("span", { className: styles.half, "data-half": target % 1 === 0 && allowHalf ? "end" : "start", "data-value": target, style: allowHalf ? void 0 : { width: "100%" }, onClick: () => setMergedValue(target), onPointerEnter: () => setHoverValue(target) }, target)) ] }, index); }) }); }); Rate.displayName = "Rate"; //#endregion export { Rate as default }; //# sourceMappingURL=Rate.mjs.map