phx-react
Version:
PHX REACT
64 lines • 3.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PHXMiniProgressBar = void 0;
const tslib_1 = require("tslib");
const react_1 = tslib_1.__importStar(require("react"));
const easeOutExpo = (t) => (t === 1 ? 1 : 1 - Math.pow(2, -10 * t));
const PHXMiniProgressBar = ({ percent, isCompleted, className }) => {
const barRef = (0, react_1.useRef)(null);
const rafRef = (0, react_1.useRef)(null);
const startTimeRef = (0, react_1.useRef)(null);
const startValueRef = (0, react_1.useRef)(0);
(0, react_1.useEffect)(() => {
if (percent == null) {
if (barRef.current) {
barRef.current.style.transform = 'translateX(-100%)';
}
startValueRef.current = 0;
return;
}
const target = Math.max(0, Math.min(100, Number(percent)));
const duration = 1200;
startValueRef.current = startValueRef.current || 0;
const animate = (now) => {
if (!startTimeRef.current)
startTimeRef.current = now;
const elapsed = now - startTimeRef.current;
const progress = Math.min(elapsed / duration, 1);
const eased = easeOutExpo(progress);
const current = startValueRef.current + (target - startValueRef.current) * eased;
if (barRef.current) {
barRef.current.style.transform = `translateX(${current - 100}%)`;
}
if (progress < 1) {
rafRef.current = requestAnimationFrame(animate);
}
else {
if (barRef.current) {
barRef.current.style.transform = `translateX(${target - 100}%)`;
}
startValueRef.current = target;
startTimeRef.current = null;
}
};
rafRef.current = requestAnimationFrame(animate);
return () => {
if (rafRef.current)
cancelAnimationFrame(rafRef.current);
rafRef.current = null;
};
}, [percent]);
const displayPercent = percent == null ? '--' : `${Math.round(Number(percent))}%`;
return (react_1.default.createElement("div", { className: 'flex justify-start items-center pr-4' },
react_1.default.createElement("div", { className: 'flex items-center gap-3' },
react_1.default.createElement("div", { className: `flex-1 w-[91px] ${className}` },
react_1.default.createElement("div", { className: 'h-2 bg-gray-200 rounded-full overflow-hidden relative' },
react_1.default.createElement("div", { ref: barRef, className: `absolute inset-y-0 left-0 ${isCompleted ? 'bg-green-600' : 'bg-gray-900'} transition-colors duration-300`, style: {
transform: 'translateX(-100%)',
width: '100%',
} }))),
react_1.default.createElement("span", { className: 'text-sm font-medium text-left text-gray-500 w-[32px] tabular-nums' }, displayPercent))));
};
exports.PHXMiniProgressBar = PHXMiniProgressBar;
exports.default = exports.PHXMiniProgressBar;
//# sourceMappingURL=MiniProgressBar.js.map