Created
April 19, 2023 13:55
-
-
Save fabiospampinato/36bdf44dca584df2b155ce5603489a53 to your computer and use it in GitHub Desktop.
Some code that will probably look pretty weird to you
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* IMPORT */ | |
import './styles.scss'; | |
import _ from '_'; | |
import {$, $$} from 'voby'; | |
import {If} from '~/components'; | |
import {useActiving, useDragger} from '~/hooks'; | |
import type {Props} from './types'; | |
/* MAIN */ | |
const RangeSlider = ( { disabled, grow, min, max, start = min, end = max, name, step, tooltip = true, value, onChange }: Props ): JSX.Element => { | |
const ref = $<HTMLDivElement>(); | |
const handleMinRef = $<HTMLDivElement>(); | |
const handleMaxRef = $<HTMLDivElement>(); | |
const handleMinActiving = useActiving ( handleMinRef ); | |
const handleMaxActiving = useActiving ( handleMaxRef ); | |
const clampMin = ( valueMin: number ) => _.clamp ( _.round ( valueMin, $$(step) ), $$(min), valueMax () ); | |
const clampMax = ( valueMax: number ) => _.clamp ( _.round ( valueMax, $$(step) ), valueMin (), $$(max) ); | |
const valueMin = () => $$(value)[0]; | |
const valueMax = () => $$(value)[1]; | |
const valueMinClamped = () => clampMin ( valueMin () ); | |
const valueMaxClamped = () => clampMax ( valueMax () ); | |
const onChangeMin = ( valueMin: number ) => onChange?.([ clampMin ( valueMin ), valueMax () ]); | |
const onChangeMax = ( valueMax: number ) => onChange?.([ valueMin (), clampMax ( valueMax ) ]); | |
const decrementMin = () => onChangeMin ( valueMin () - $$(step) ); | |
const incrementMin = () => onChangeMin ( valueMin () + $$(step) ); | |
const decrementMinFast = () => onChangeMin ( valueMin () - ( $$(step) * 5 ) ); | |
const incrementMinFast = () => onChangeMin ( valueMin () + ( $$(step) * 5 ) ); | |
const decrementMax = () => onChangeMax ( valueMax () - $$(step) ); | |
const incrementMax = () => onChangeMax ( valueMax () + $$(step) ); | |
const decrementMaxFast = () => onChangeMax ( valueMax () - ( $$(step) * 5 ) ); | |
const incrementMaxFast = () => onChangeMax ( valueMax () + ( $$(step) * 5 ) ); | |
const input = () => `${valueMinClamped ()},${valueMaxClamped ()}`; | |
const onInput = ( input: string ) => onChange?.([ clampMin ( Number ( input.split ( ',' )[0] ) ), clampMax ( Number ( input.split ( ',' )[1] ) ) ]); | |
const highlightLeft = () => `${( valueMin () - $$(start) ) * 100 / ( $$(end) - $$(start) )}%`; | |
const highlightRight = () => `${( $$(end) - valueMax () ) * 100 / ( $$(end) - $$(start) )}%`; | |
const handleMinLeft = highlightLeft; | |
const handleMaxLeft = () => `${( valueMax () - $$(start) ) * 100 / ( $$(end) - $$(start) )}%`; | |
useDragger ( ref, { | |
onUpdate: ({ constrainedPercentageX }) => { | |
const value = ( constrainedPercentageX * ( $$(end) - $$(start) ) ) + $$(start); | |
if ( handleMinActiving () ) { | |
onChangeMin ( value ); | |
} | |
if ( handleMaxActiving () ) { | |
onChangeMax ( value ); | |
} | |
} | |
}); | |
return ( | |
<div use:ui="range-slider" ref={ref} class={{ disabled, grow }} disabled={disabled}> | |
<input use:ui="range-slider-input" use:controlled={[input, onInput]} type="text" name={name} value={input} /> | |
<div use:ui="range-slider-track" /> | |
<div use:ui="range-slider-highlight" style={{ left: highlightLeft, right: highlightRight }} /> | |
<div use:ui="range-slider-side-min" use:shortcuts={{ 'Left': decrementMin, 'Down': decrementMin, 'Right': incrementMin, 'Up': incrementMin, 'Shift+Left': decrementMinFast, 'Shift+Down': decrementMinFast, 'Shift+Right': incrementMinFast, 'Shift+Up': incrementMinFast }} tabIndex> | |
<div use:ui="range-slider-handle" ref={handleMinRef} style={{ left: handleMinLeft }} /> | |
<div use:ui="range-slider-handle-halo" style={{ left: handleMinLeft }} /> | |
<If when={tooltip}> | |
<div use:ui="range-slider-tooltip" style={{ left: handleMinLeft }}> | |
{valueMinClamped} | |
</div> | |
</If> | |
</div> | |
<div use:ui="range-slider-side-max" use:shortcuts={{ 'Left': decrementMax, 'Down': decrementMax, 'Right': incrementMax, 'Up': incrementMax, 'Shift+Left': decrementMaxFast, 'Shift+Down': decrementMaxFast, 'Shift+Right': incrementMaxFast, 'Shift+Up': incrementMaxFast }} tabIndex> | |
<div use:ui="range-slider-handle" ref={handleMaxRef} style={{ left: handleMaxLeft }} /> | |
<div use:ui="range-slider-handle-halo" style={{ left: handleMaxLeft }} /> | |
<If when={tooltip}> | |
<div use:ui="range-slider-tooltip" style={{ left: handleMaxLeft }}> | |
{valueMaxClamped} | |
</div> | |
</If> | |
</div> | |
</div> | |
); | |
}; | |
/* EXPORT */ | |
export default RangeSlider; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment