mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-04-21 07:32:02 +00:00
slider refactored with liverefs
This commit is contained in:
parent
d0e8f8c0ab
commit
8412c22e64
2 changed files with 30 additions and 24 deletions
|
|
@ -7,9 +7,9 @@ const useLiveRef = require('stremio/common/useLiveRef');
|
||||||
const styles = require('./styles');
|
const styles = require('./styles');
|
||||||
|
|
||||||
const Slider = ({ className, value, minimumValue, maximumValue, onSlide, onComplete }) => {
|
const Slider = ({ className, value, minimumValue, maximumValue, onSlide, onComplete }) => {
|
||||||
minimumValue = minimumValue !== null && !isNaN(minimumValue) && isFinite(minimumValue) ? minimumValue : 0;
|
const minimumValueRef = useLiveRef(minimumValue !== null && !isNaN(minimumValue) ? minimumValue : 0, [minimumValue]);
|
||||||
maximumValue = maximumValue !== null && !isNaN(maximumValue) && isFinite(maximumValue) ? maximumValue : 100;
|
const maximumValueRef = useLiveRef(maximumValue !== null && !isNaN(maximumValue) ? maximumValue : 100, [maximumValue]);
|
||||||
value = value !== null && !isNaN(value) && value >= minimumValue && value <= maximumValue ? value : 0;
|
const valueRef = useLiveRef(value !== null && !isNaN(value) ? Math.min(maximumValueRef.current, Math.max(minimumValueRef.current, value)) : 0, [minimumValue, maximumValue, value]);
|
||||||
const onSlideRef = useLiveRef(onSlide, [onSlide]);
|
const onSlideRef = useLiveRef(onSlide, [onSlide]);
|
||||||
const onCompleteRef = useLiveRef(onComplete, [onComplete]);
|
const onCompleteRef = useLiveRef(onComplete, [onComplete]);
|
||||||
const sliderContainerRef = React.useRef(null);
|
const sliderContainerRef = React.useRef(null);
|
||||||
|
|
@ -20,11 +20,9 @@ const Slider = ({ className, value, minimumValue, maximumValue, onSlide, onCompl
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const minimumValue = parseInt(sliderContainerRef.current.getAttribute('aria-valuemin'));
|
|
||||||
const maximumValue = parseInt(sliderContainerRef.current.getAttribute('aria-valuemax'));
|
|
||||||
const { x: sliderX, width: sliderWidth } = sliderContainerRef.current.getBoundingClientRect();
|
const { x: sliderX, width: sliderWidth } = sliderContainerRef.current.getBoundingClientRect();
|
||||||
const thumbStart = Math.min(Math.max(mouseX - sliderX, 0), sliderWidth);
|
const thumbStart = Math.min(Math.max(mouseX - sliderX, 0), sliderWidth);
|
||||||
const value = (thumbStart / sliderWidth) * (maximumValue - minimumValue) + minimumValue;
|
const value = (thumbStart / sliderWidth) * (maximumValueRef.current - minimumValueRef.current) + minimumValueRef.current;
|
||||||
return value;
|
return value;
|
||||||
}, []);
|
}, []);
|
||||||
const retainThumb = React.useCallback(() => {
|
const retainThumb = React.useCallback(() => {
|
||||||
|
|
@ -42,17 +40,16 @@ const Slider = ({ className, value, minimumValue, maximumValue, onSlide, onCompl
|
||||||
const classIndex = classList.indexOf(styles['active-slider-within']);
|
const classIndex = classList.indexOf(styles['active-slider-within']);
|
||||||
if (classIndex !== -1) {
|
if (classIndex !== -1) {
|
||||||
classList.splice(classIndex, 1);
|
classList.splice(classIndex, 1);
|
||||||
|
document.documentElement.className = classnames(classList);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.documentElement.className = classnames(classList);
|
|
||||||
}, []);
|
}, []);
|
||||||
const onBlur = React.useCallback(() => {
|
const onBlur = React.useCallback(() => {
|
||||||
const value = parseInt(sliderContainerRef.current.getAttribute('aria-valuenow'));
|
|
||||||
if (typeof onSlideRef.current === 'function') {
|
if (typeof onSlideRef.current === 'function') {
|
||||||
onSlideRef.current(value);
|
onSlideRef.current(valueRef.current);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof onCompleteRef.current === 'function') {
|
if (typeof onCompleteRef.current === 'function') {
|
||||||
onCompleteRef.current(value);
|
onCompleteRef.current(valueRef.current);
|
||||||
}
|
}
|
||||||
|
|
||||||
releaseThumb();
|
releaseThumb();
|
||||||
|
|
@ -85,22 +82,19 @@ const Slider = ({ className, value, minimumValue, maximumValue, onSlide, onCompl
|
||||||
|
|
||||||
retainThumb();
|
retainThumb();
|
||||||
}, []);
|
}, []);
|
||||||
|
React.useLayoutEffect(() => {
|
||||||
React.useEffect(() => {
|
|
||||||
if (!routeFocused) {
|
if (!routeFocused) {
|
||||||
releaseThumb();
|
releaseThumb();
|
||||||
}
|
}
|
||||||
}, [routeFocused]);
|
}, [routeFocused]);
|
||||||
React.useEffect(() => {
|
React.useLayoutEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
releaseThumb();
|
releaseThumb();
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
const thumbPosition = React.useMemo(() => {
|
const thumbPosition = Math.max(0, Math.min(1, (valueRef.current - minimumValueRef.current) / (maximumValueRef.current - minimumValueRef.current)));
|
||||||
return Math.max(0, Math.min(1, (value - minimumValue) / (maximumValue - minimumValue)));
|
|
||||||
}, [value, minimumValue, maximumValue]);
|
|
||||||
return (
|
return (
|
||||||
<div ref={sliderContainerRef} className={classnames(className, styles['slider-container'])} aria-valuenow={value} aria-valuemin={minimumValue} aria-valuemax={maximumValue} onMouseDown={onMouseDown}>
|
<div ref={sliderContainerRef} className={classnames(className, styles['slider-container'])} onMouseDown={onMouseDown}>
|
||||||
<div className={styles['layer']}>
|
<div className={styles['layer']}>
|
||||||
<div className={styles['track']} />
|
<div className={styles['track']} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
@import (reference) '~stremio-colors/dist/less/stremio-colors.less';
|
||||||
|
|
||||||
html.active-slider-within {
|
html.active-slider-within {
|
||||||
cursor: grabbing;
|
cursor: grabbing;
|
||||||
|
|
||||||
|
|
@ -12,15 +14,25 @@ html.active-slider-within {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover, &:global(.active) {
|
||||||
|
.track-before {
|
||||||
|
background-color: @color-primary-light5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:global(.disabled) {
|
&:global(.disabled) {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
.track, .track-before {
|
.track {
|
||||||
background-color: var(--color-surfacedark);
|
background-color: @color-surface-dark5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-before {
|
||||||
|
background-color: @color-surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumb {
|
.thumb {
|
||||||
fill: var(--color-surfacedark);
|
fill: @color-surface;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,13 +52,13 @@ html.active-slider-within {
|
||||||
.track {
|
.track {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: var(--track-size, 0.5rem);
|
height: var(--track-size, 0.5rem);
|
||||||
background-color: var(--color-backgroundlighter);
|
background-color: @color-primary-dark3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.track-before {
|
.track-before {
|
||||||
flex: none;
|
flex: none;
|
||||||
height: var(--track-size, 0.5rem);
|
height: var(--track-size, 0.5rem);
|
||||||
background-color: var(--color-primary);
|
background-color: @color-primary-light3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumb {
|
.thumb {
|
||||||
|
|
@ -54,6 +66,6 @@ html.active-slider-within {
|
||||||
width: var(--thumb-size, 1.5rem);
|
width: var(--thumb-size, 1.5rem);
|
||||||
height: var(--thumb-size, 1.5rem);
|
height: var(--thumb-size, 1.5rem);
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
fill: var(--color-surfacelighter);
|
fill: @color-surface-light5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue