import React, { memo, useMemo, useRef, useState, } from '../../../lib/teact/teact'; import { requestMeasure, requestMutation } from '../../../lib/fasterdom/fasterdom'; import buildClassName from '../../../util/buildClassName'; import { formatInteger } from '../../../util/textFormat'; import useEffectOnce from '../../../hooks/useEffectOnce'; import useLastCallback from '../../../hooks/useLastCallback'; import useResizeObserver from '../../../hooks/useResizeObserver'; import AnimatedCounter from '../../common/AnimatedCounter'; import Icon from '../../common/icons/Icon'; import Sparkles from '../../common/Sparkles'; import styles from './StarSlider.module.scss'; type OwnProps = { maxValue: number; defaultValue: number; className?: string; onChange: (value: number) => void; }; const DEFAULT_POINTS = [50, 100, 500, 1000, 2000, 5000, 10000]; const StarSlider = ({ maxValue, defaultValue, className, onChange, }: OwnProps) => { // eslint-disable-next-line no-null/no-null const floatingBadgeRef = useRef(null); const points = useMemo(() => { const result = []; for (let i = 0; i < DEFAULT_POINTS.length; i++) { if (DEFAULT_POINTS[i] < maxValue) { result.push(DEFAULT_POINTS[i]); } if (DEFAULT_POINTS[i] >= maxValue) { result.push(maxValue); break; } } return result; }, [maxValue]); const [value, setValue] = useState(0); useEffectOnce(() => { setValue(getProgress(points, defaultValue)); }); const updateSafeBadgePosition = useLastCallback(() => { const badge = floatingBadgeRef.current; if (!badge) return; const parent = badge.parentElement!; requestMeasure(() => { const safeMinX = parent.offsetLeft + badge.offsetWidth / 2; const safeMaxX = parent.offsetLeft + parent.offsetWidth - badge.offsetWidth / 2; requestMutation(() => { parent.style.setProperty('--_min-x', `${safeMinX}px`); parent.style.setProperty('--_max-x', `${safeMaxX}px`); }); }); }); useResizeObserver(floatingBadgeRef, updateSafeBadgePosition); const handleChange = useLastCallback((event: React.ChangeEvent) => { const newValue = Number(event.currentTarget.value); setValue(newValue); onChange(getValue(points, newValue)); }); return (
); }; function getProgress(points: number[], value: number) { const pointIndex = points.findIndex((point) => value <= point); const prevPoint = points[pointIndex - 1] || 1; const nextPoint = points[pointIndex] || points[points.length - 1]; const progress = (value - prevPoint) / (nextPoint - prevPoint); return pointIndex + progress; } function getValue(points: number[], progress: number) { const pointIndex = Math.floor(progress); const prevPoint = points[pointIndex - 1] || 1; const nextPoint = points[pointIndex] || points[points.length - 1]; const value = prevPoint + (nextPoint - prevPoint) * (progress - pointIndex); return Math.round(value); } export default memo(StarSlider);