aboutsummaryrefslogtreecommitdiff
path: root/packages/components/src/components/Slider/Slider.tsx
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2025-02-25 01:03:25 -0500
committerbobzel <zzzman@gmail.com>2025-02-25 01:03:25 -0500
commit515707c4561eb526426b8fa07dd50bd499fb91cc (patch)
treef4cbc69387da19add6dbc88acecbcdbdca575039 /packages/components/src/components/Slider/Slider.tsx
parent30b07ed24fbe5e6d49741bc63031807408cd4a0c (diff)
added a hideUI option to hide buttons. fixed a mess of runtime warnings mostly related to how scss files can be included in each other
Diffstat (limited to 'packages/components/src/components/Slider/Slider.tsx')
-rw-r--r--packages/components/src/components/Slider/Slider.tsx338
1 files changed, 174 insertions, 164 deletions
diff --git a/packages/components/src/components/Slider/Slider.tsx b/packages/components/src/components/Slider/Slider.tsx
index 3ca51efed..f6f53799c 100644
--- a/packages/components/src/components/Slider/Slider.tsx
+++ b/packages/components/src/components/Slider/Slider.tsx
@@ -1,178 +1,188 @@
-import React, { useEffect, useRef, useState } from 'react'
-import { Colors, getFontSize, getHeight, IGlobalProps, Size , getFormLabelSize, isDark, INumberProps } from '../../global'
-import './Slider.scss'
+import React, { useState } from 'react';
+import { Colors, getFontSize, getHeight, Size, getFormLabelSize, isDark, INumberProps } from '../../global';
+import './Slider.scss';
export interface ISliderProps extends INumberProps {
- multithumb: boolean
- autorangeMinVal?: number // minimimum value that min can have when autoranging
- autorangeMinSize?: number // minimum difference between min and max when autoranging
- autorange?: number // automatically adjust min/max to be +/- autorange/2 around the current value when the thumb is 15% from the min/max, or when the multithumbs are within 20% of the range and the range is bigger than autorange
- endNumber?: number
- setEndNumber?: (newVal: number) => void
- setFinalNumber?: (newVal: number) => void
- setFinalEndNumber?: (newVal: number) => void
- decimals?: number;
- step?: number
- minDiff?: number
+ multithumb: boolean;
+ autorangeMinVal?: number; // minimimum value that min can have when autoranging
+ autorangeMinSize?: number; // minimum difference between min and max when autoranging
+ autorange?: number; // automatically adjust min/max to be +/- autorange/2 around the current value when the thumb is 15% from the min/max, or when the multithumbs are within 20% of the range and the range is bigger than autorange
+ endNumber?: number;
+ setEndNumber?: (newVal: number) => void;
+ setFinalNumber?: (newVal: number) => void;
+ setFinalEndNumber?: (newVal: number) => void;
+ decimals?: number;
+ step?: number;
+ minDiff?: number;
}
-let lastVal = 0; // bcz: WHY do I have to do this?? the pointerdown event locks in the value of 'valLoc' when it's created so need some other way to get the current value to that old handler...
+let lastVal = 0; // bcz: WHY do I have to do this?? the pointerdown event locks in the value of 'valLoc' when it's created so need some other way to get the current value to that old handler...
let lastEndVal = 0;
export const Slider = (props: ISliderProps) => {
- const [width, setWidth] = useState<number>(100);
- const [valLoc, setNumberLoc] = useState<number>(props.number??(props.min + (props.max-props.min)/2));
- const [endNumberLoc, setEndNumberLoc] = useState<number>(props.endNumber??(props.min + 2*(props.max-props.min)/3));
- const [min, setMin] = useState<number>(props.min);
- const [max, setMax] = useState<number>(props.max);
- const {
- formLabel,
- formLabelPlacement,
- multithumb,
- autorange,
- autorangeMinVal,
- autorangeMinSize,
- decimals,
- step = 1,
- number = valLoc,
- endNumber = endNumberLoc,
- minDiff = (max-min)/20,
- size = Size.SMALL,
- height,
- unit,
- onPointerDown,
- setNumber,
- setEndNumber,
- setFinalNumber,
- setFinalEndNumber,
- color = Colors.MEDIUM_BLUE,
- fillWidth
- } = props
+ const [width, setWidth] = useState<number>(100);
+ const [valLoc, setNumberLoc] = useState<number>(props.number ?? props.min + (props.max - props.min) / 2);
+ const [endNumberLoc, setEndNumberLoc] = useState<number>(props.endNumber ?? props.min + (2 * (props.max - props.min)) / 3);
+ const [min, setMin] = useState<number>(props.min);
+ const [max, setMax] = useState<number>(props.max);
+ const {
+ formLabel,
+ formLabelPlacement,
+ multithumb,
+ autorange,
+ autorangeMinVal,
+ autorangeMinSize,
+ decimals,
+ step = 1,
+ number = valLoc,
+ endNumber = endNumberLoc,
+ minDiff = (max - min) / 20,
+ size = Size.SMALL,
+ height,
+ unit,
+ onPointerDown,
+ setNumber,
+ setEndNumber,
+ setFinalNumber,
+ setFinalEndNumber,
+ color = Colors.MEDIUM_BLUE,
+ fillWidth,
+ } = props;
- const toDecimal = (num:number) => decimals !== undefined ? Math.round(num*Math.pow(10,decimals))/Math.pow(10,decimals): num;
+ const toDecimal = (num: number) => (decimals !== undefined ? Math.round(num * Math.pow(10, decimals)) / Math.pow(10, decimals) : num);
- const getLeftPos = (locVal: number) => {
- const dragger = getHeight(height,size)
- return (((locVal-min)/ (max-min)) * (width-dragger))
- }
+ const getLeftPos = (locVal: number) => {
+ const dragger = getHeight(+(height || 0), size);
+ return ((locVal - min) / (max - min)) * (width - dragger);
+ };
- const getValueLabel = (locVal: number): JSX.Element => {
- return (<div className="rs-label-container"
- style={{
- left: `${getLeftPos(locVal)}px`,
- background: color,
- color: isDark(color) ? Colors.LIGHT_GRAY : Colors.DARK_GRAY,
- fontSize: getFontSize(size),
- height: getHeight(height, size),
- width: getHeight(height, size),
- top: 0
- }}
- >
- <span className="rs-label">
- {toDecimal(locVal)}
- </span>
- </div>)
- }
- const checkAutorange = () => {
- if (autorange) {
- const minval = multithumb ? Math.min(lastVal, lastEndVal) : lastVal;
- const maxval = multithumb ? Math.max(lastVal, lastEndVal) : lastVal;
- const autosize = Math.max(autorangeMinSize??0,(autorange ?? (maxval-minval)))/2;
- if ((Math.abs((minval - min)/(max-min)) < .15) || (Math.abs((max - maxval)/(max-min)) < .15) ||
- (multithumb && maxval - minval < (max-min)/5 && autosize < max-min)
- ) {
- const newminval = autorangeMinVal !== undefined && minval-autosize < autorangeMinVal? autorangeMinVal : minval-autosize;
- setMin(newminval)
- setMax(newminval !== minval ? Math.max(maxval + autosize, newminval +autosize): maxval+autosize )
- }
- }
- }
+ const getValueLabel = (locVal: number): JSX.Element => {
+ return (
+ <div
+ className="rs-label-container"
+ style={{
+ left: `${getLeftPos(locVal)}px`,
+ background: color,
+ color: isDark(color) ? Colors.LIGHT_GRAY : Colors.DARK_GRAY,
+ fontSize: getFontSize(size),
+ height: getHeight(+(height || 0), size),
+ width: getHeight(+(height || 0), size),
+ top: 0,
+ }}>
+ <span className="rs-label">{toDecimal(locVal)}</span>
+ </div>
+ );
+ };
+ const checkAutorange = () => {
+ if (autorange) {
+ const minval = multithumb ? Math.min(lastVal, lastEndVal) : lastVal;
+ const maxval = multithumb ? Math.max(lastVal, lastEndVal) : lastVal;
+ const autosize = Math.max(autorangeMinSize ?? 0, autorange ?? maxval - minval) / 2;
+ if (Math.abs((minval - min) / (max - min)) < 0.15 || Math.abs((max - maxval) / (max - min)) < 0.15 || (multithumb && maxval - minval < (max - min) / 5 && autosize < max - min)) {
+ const newminval = autorangeMinVal !== undefined && minval - autosize < autorangeMinVal ? autorangeMinVal : minval - autosize;
+ setMin(newminval);
+ setMax(newminval !== minval ? Math.max(maxval + autosize, newminval + autosize) : maxval + autosize);
+ }
+ }
+ };
- const valSlider = (which: string, val:number, onchange: (val:number) => void, setFinal: () => void) => {
- const valPointerup = (e:PointerEvent) => {
- document.removeEventListener('pointerup', valPointerup, true)
- setFinal();
- checkAutorange();
- }
- return (<div key={which} className={`range-slider ${size}`}>
- {getValueLabel(val)}
- <input
- className={`rs-range ${size}`}
- type="range"
- color={color}
- min={min}
- max={max}
- step={step}
- value={val}
- onPointerDown={e => document.addEventListener('pointerup', valPointerup, true)}
- onChange={e => {
- onchange(+e.target.value);
- e.stopPropagation();
- }}
- />
- </div>);
- }
- const onchange = (val:number) => {
- if (autorangeMinVal && val < autorangeMinVal) val = autorangeMinVal;
- setNumber?.(lastVal = Math.min(multithumb ? endNumber - (minDiff??0):Number.MAX_VALUE, val))
- setNumberLoc(lastVal = Math.min(multithumb ? endNumber - (minDiff??0):Number.MAX_VALUE, val))
- }
- const onendchange = (val:number) => {
- setEndNumber?.(lastEndVal = Math.max(number + (minDiff??0), val))
- setEndNumberLoc(lastEndVal = Math.max(number + (minDiff??0), val))
- }
- const Slider:(JSX.Element|null)[] = [
- !multithumb ? (null) : valSlider("end", endNumberLoc,onendchange, () => setFinalEndNumber?.(lastEndVal)),
- valSlider("start", valLoc, onchange, () => setFinalNumber?.(lastVal))
- ];
+ const valSlider = (which: string, val: number, onchange: (val: number) => void, setFinal: () => void) => {
+ const valPointerup = () => {
+ document.removeEventListener('pointerup', valPointerup, true);
+ setFinal();
+ checkAutorange();
+ };
+ return (
+ <div key={which} className={`range-slider ${size}`}>
+ {getValueLabel(val)}
+ <input
+ className={`rs-range ${size}`}
+ type="range"
+ color={color}
+ min={min}
+ max={max}
+ step={step}
+ value={val}
+ onPointerDown={() => document.addEventListener('pointerup', valPointerup, true)}
+ onChange={e => {
+ onchange(+e.target.value);
+ e.stopPropagation();
+ }}
+ />
+ </div>
+ );
+ };
+ const onchange = (val: number) => {
+ // eslint-disable-next-line no-param-reassign
+ if (autorangeMinVal && val < autorangeMinVal) val = autorangeMinVal;
+ setNumber?.((lastVal = Math.min(multithumb ? endNumber - (minDiff ?? 0) : Number.MAX_VALUE, val)));
+ setNumberLoc((lastVal = Math.min(multithumb ? endNumber - (minDiff ?? 0) : Number.MAX_VALUE, val)));
+ };
+ const onendchange = (val: number) => {
+ setEndNumber?.((lastEndVal = Math.max(number + (minDiff ?? 0), val)));
+ setEndNumberLoc((lastEndVal = Math.max(number + (minDiff ?? 0), val)));
+ };
+ const Slider: (JSX.Element | null)[] = [!multithumb ? null : valSlider('end', endNumberLoc, onendchange, () => setFinalEndNumber?.(lastEndVal)), valSlider('start', valLoc, onchange, () => setFinalNumber?.(lastVal))];
- const slider: JSX.Element = (
- <div className={`slider-wrapper`}
- onPointerEnter={e => {
- lastVal = valLoc;
- lastEndVal = endNumberLoc;
- }}
- style={{
- padding: `5px 0px ${getHeight(height, size)}px 0px`,
- width: fillWidth ? '100%' : 'fit-content'
- }}>
- <div className="slider-container"
- ref={r => {
- r && new ResizeObserver(() => setWidth(+(r?.clientWidth??100))).observe(r);
- setWidth(+(r?.clientWidth??100));
- }}
- style={{height: getHeight(height, size)}}
- onPointerDown={onPointerDown}
- >
- {Slider}
- <div className="selected-range" style={{
- height: getHeight(height, size) / 10,
- background: multithumb ? Colors.LIGHT_GRAY : color
-
- }}/>
- <div className="range" style={{
- height: getHeight(height, size) / 10,
- width: getLeftPos(endNumber) - getLeftPos(number),
- left: getLeftPos(number) + getHeight(height, size),
- display: multithumb ? undefined: 'none',
- background: color,
- }}/>
- <div className="box-minmax" style={{ fontSize: getFontSize(size), color }}>
- <span>{toDecimal(min)}{unit}</span>
- <span>{toDecimal(max)}{unit}</span>
+ const slider: JSX.Element = (
+ <div
+ className={`slider-wrapper`}
+ onPointerEnter={() => {
+ lastVal = valLoc;
+ lastEndVal = endNumberLoc;
+ }}
+ style={{
+ padding: `5px 0px ${getHeight(+(height || 0), size)}px 0px`,
+ width: fillWidth ? '100%' : 'fit-content',
+ }}>
+ <div
+ className="slider-container"
+ ref={r => {
+ r && new ResizeObserver(() => setWidth(+(r?.clientWidth ?? 100))).observe(r);
+ setWidth(+(r?.clientWidth ?? 100));
+ }}
+ style={{ height: getHeight(+(height || 0), size) }}
+ onPointerDown={onPointerDown}>
+ {Slider}
+ <div
+ className="selected-range"
+ style={{
+ height: getHeight(+(height || 0), size) / 10,
+ background: multithumb ? Colors.LIGHT_GRAY : color,
+ }}
+ />
+ <div
+ className="range"
+ style={{
+ height: getHeight(+(height || 0), size) / 10,
+ width: getLeftPos(endNumber) - getLeftPos(number),
+ left: getLeftPos(number) + getHeight(+(height || 0), size),
+ display: multithumb ? undefined : 'none',
+ background: color,
+ }}
+ />
+ <div className="box-minmax" style={{ fontSize: getFontSize(size), color }}>
+ <span>
+ {toDecimal(min)}
+ {unit}
+ </span>
+ <span>
+ {toDecimal(max)}
+ {unit}
+ </span>
+ </div>
+ </div>
</div>
- </div>
- </div>
- )
-
- return (
- formLabel ?
- <div className={`form-wrapper ${formLabelPlacement}`}>
- <div className={'formLabel'} style={{fontSize: getFormLabelSize(size)}}>{formLabel}</div>
- {slider}
- </div>
- :
- slider
-)
-}
+ );
+ return formLabel ? (
+ <div className={`form-wrapper ${formLabelPlacement}`}>
+ <div className={'formLabel'} style={{ fontSize: getFormLabelSize(size) }}>
+ {formLabel}
+ </div>
+ {slider}
+ </div>
+ ) : (
+ slider
+ );
+};