Skip to content

Commit

Permalink
chore: use custom range slider
Browse files Browse the repository at this point in the history
  • Loading branch information
adityasingh-anyline committed Sep 8, 2024
1 parent 440d456 commit 53b00eb
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 25 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
"@grafana/runtime": "10.0.3",
"@grafana/schema": "10.0.3",
"@grafana/ui": "10.0.3",
"multi-range-slider-react": "^2.0.7",
"react": "18.2.0",
"react-dom": "18.2.0",
"tslib": "2.5.3"
Expand Down
96 changes: 96 additions & 0 deletions src/components/MultiRangeSlider/MultiRangeSlider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { ChangeEvent, FC, useCallback, useEffect, useState, useRef } from 'react';
import classnames from 'classnames';
import './multiRangeSlider.css';

interface MultiRangeSliderProps {
min: number;
max: number;
onChange: Function;
}

const MultiRangeSlider: FC<MultiRangeSliderProps> = ({ min, max, onChange }) => {
const [minVal, setMinVal] = useState(min);
const [maxVal, setMaxVal] = useState(max);
const minValRef = useRef<HTMLInputElement>(null);
const maxValRef = useRef<HTMLInputElement>(null);
const range = useRef<HTMLDivElement>(null);

// Convert to percentage
const getPercent = useCallback((value: number) => Math.round(((value - min) / (max - min)) * 100), [min, max]);

// Set width of the range to decrease from the left side
useEffect(() => {
if (maxValRef.current) {
const minPercent = getPercent(minVal);
const maxPercent = getPercent(+maxValRef.current.value);

if (range.current) {
range.current.style.left = `${minPercent}%`;
range.current.style.width = `${maxPercent - minPercent}%`;
}
}
}, [minVal, getPercent]);

// Set width of the range to decrease from the right side
useEffect(() => {
if (minValRef.current) {
const minPercent = getPercent(+minValRef.current.value);
const maxPercent = getPercent(maxVal);

if (range.current) {
range.current.style.width = `${maxPercent - minPercent}%`;
}
}
}, [maxVal, getPercent]);

// Get min and max values when their state changes
useEffect(() => {
onChange({ min: minVal, max: maxVal });
}, [minVal, maxVal, onChange]);

return (
<div className="mrs-container">
<input
type="range"
min={min}
max={max}
value={minVal}
ref={minValRef}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
const value = Math.min(+event.target.value, maxVal - 1);
setMinVal(value);
event.target.value = value.toString();
}}
className={classnames('thumb thumb--zindex-3', {
'thumb--zindex-5': minVal > max - 100,
})}
/>
<input
type="range"
min={min}
max={max}
value={maxVal}
ref={maxValRef}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
const value = Math.max(+event.target.value, minVal + 1);
setMaxVal(value);
event.target.value = value.toString();
}}
className="thumb thumb--zindex-4"
/>

<div className="slider">
<div className="slider__track"></div>
<div ref={range} className="slider__range"></div>
<div className="slider__left-value" style={{ left: `${getPercent(minVal)}%` }}>
{minVal}
</div>
<div className="slider__right-value" style={{ left: `${getPercent(maxVal)}%` }}>
{maxVal}
</div>
</div>
</div>
);
};

export default MultiRangeSlider;
98 changes: 98 additions & 0 deletions src/components/MultiRangeSlider/multiRangeSlider.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
.mrs-container {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}

.slider {
position: relative;
width: 100%;
}

.slider__track,
.slider__range,
.slider__left-value,
.slider__right-value {
position: absolute;
}

.slider__track,
.slider__range {
border-radius: 3px;
height: 5px;
}

.slider__track {
background-color: #ced4da;
width: 100%;
z-index: 1;
}

.slider__range {
background-color: rgba(59, 130, 246, 0.5);
z-index: 2;
}

.slider__left-value,
.slider__right-value {
color: #dee2e6;
font-size: 12px;
margin-top: 20px;
transform: translateX(-50%);
}

/* Removing the default appearance */
.thumb,
.thumb::-webkit-slider-thumb {
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
}

.thumb {
pointer-events: none;
position: absolute;
height: 0;
width: 100%;
outline: none;
}

.thumb--zindex-3 {
z-index: 3;
}

.thumb--zindex-4 {
z-index: 4;
}

.thumb--zindex-5 {
z-index: 5;
}

/* For Chrome browsers */
.thumb::-webkit-slider-thumb {
background-color: #f1f5f7;
border: none;
border-radius: 50%;
box-shadow: 0 0 1px 1px #ced4da;
cursor: pointer;
height: 18px;
width: 18px;
margin-top: 4px;
pointer-events: all;
position: relative;
}

/* For Firefox browsers */
.thumb::-moz-range-thumb {
background-color: #f1f5f7;
border: none;
border-radius: 50%;
box-shadow: 0 0 1px 1px #ced4da;
cursor: pointer;
height: 18px;
width: 18px;
margin-top: 4px;
pointer-events: all;
position: relative;
}
19 changes: 3 additions & 16 deletions src/components/SimplePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import React, { useEffect, useState, useCallback } from 'react';
import { PanelProps } from '@grafana/data';
import MultiRangeSlider from 'multi-range-slider-react';
import { getTemplateSrv, locationService } from '@grafana/runtime';
import { SimpleOptions } from '../types';
import findMinAndMaxValues from './utils/findMinAndMaxValues';
import { DEFAULT_MAX_THRESHOLD, DEFAULT_MIN_THRESHOLD } from './constants';

type RangeChangeEvent = {
minValue: number;
maxValue: number;
};
import MultiRangeSlider from './MultiRangeSlider/MultiRangeSlider';

interface Props extends PanelProps<SimpleOptions> {}

Expand Down Expand Up @@ -41,9 +36,7 @@ const SimplePanel: React.FC<Props> = ({ options }) => {
}, []);

const handleSliderInput = useCallback(
(e: RangeChangeEvent) => {
let { minValue, maxValue } = e;

(minValue: number, maxValue: number) => {
minValue = Math.max(minThreshold, Math.min(minValue, maxThreshold));
maxValue = Math.max(minValue, Math.min(maxValue, maxThreshold));

Expand Down Expand Up @@ -155,13 +148,7 @@ const SimplePanel: React.FC<Props> = ({ options }) => {
<MultiRangeSlider
min={minThreshold}
max={maxThreshold}
step={1}
ruler={false}
label={true}
preventWheel={false}
minValue={panelState.minValue}
maxValue={panelState.maxValue}
onInput={handleSliderInput}
onChange={({ min, max }: { min: number; max: number }) => handleSliderInput(min, max)}
/>
</div>
);
Expand Down
36 changes: 28 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7258,11 +7258,6 @@ [email protected], ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==

multi-range-slider-react@^2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/multi-range-slider-react/-/multi-range-slider-react-2.0.7.tgz#e028511c19142e1edf8b5f85f5c1ec35f21e8f9d"
integrity sha512-KRYUkatXxxYceL5ZT8xvetIN+4yTCdWszxRC6Y6Jkua+oRrWVkmBR6v3R03kosYg/QtcETBf2L1Jt+4U66DFbg==

murmurhash-js@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/murmurhash-js/-/murmurhash-js-1.0.0.tgz#b06278e21fc6c37fa5313732b0412bcb6ae15f51"
Expand Down Expand Up @@ -9124,7 +9119,16 @@ string-template@~0.2.1:
resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add"
integrity sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==

"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
Expand Down Expand Up @@ -9196,7 +9200,14 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"

"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
Expand Down Expand Up @@ -9976,7 +9987,7 @@ [email protected]:
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343"
integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==

"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
Expand All @@ -9994,6 +10005,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
Expand Down

0 comments on commit 53b00eb

Please sign in to comment.