@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
111 lines (110 loc) • 3.44 kB
JavaScript
"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