@grafana/ui
Version:
Grafana Components Library
154 lines (151 loc) • 4.8 kB
JavaScript
import { jsxs, jsx } from 'react/jsx-runtime';
import { cx } from '@emotion/css';
import { Global } from '@emotion/react';
import SliderComponent from '@rc-component/slider';
import { useState, useEffect, useCallback } from 'react';
import { usePrevious } from 'react-use';
import { t } from '@grafana/i18n';
import { useStyles2 } from '../../themes/ThemeContext.mjs';
import { Input } from '../Input/Input.mjs';
import { getStyles } from './styles.mjs';
;
function stripAndParseNumber(raw) {
const str = raw.replace(/^0+/, "");
let decimal = false;
let numericBody = "";
for (let i = 0; i < str.length; i += 1) {
const char = str.charAt(i);
if (/\d/.test(char)) {
numericBody += char;
}
if (char === "." && !decimal) {
decimal = true;
numericBody += ".";
}
if (char === "-" && numericBody.length === 0) {
numericBody = "-";
}
}
const value = Number(numericBody);
return value;
}
function roundFloatingPointError(n) {
return parseFloat(n.toPrecision(12));
}
function clampToAllowedValue(min, max, step, n) {
if (Number.isNaN(n)) {
return min;
}
if (n > max) {
return max;
}
if (n < min) {
return min;
}
const closestStep = roundFloatingPointError(Math.round((n - min) / step) * step + min);
return Math.min(max, Math.max(min, closestStep));
}
const Slider = ({
min,
max,
onChange,
onAfterChange,
orientation = "horizontal",
reverse,
step = 1,
value,
ariaLabelForHandle,
marks,
included,
inputId,
showInput = true
}) => {
const isHorizontal = orientation === "horizontal";
const styles = useStyles2(getStyles, isHorizontal, Boolean(marks));
const SliderWithTooltip = SliderComponent;
const [inputValue, setInputValue] = useState((value != null ? value : min).toString());
const numericValue = clampToAllowedValue(min, max, step, stripAndParseNumber(inputValue));
const previousValue = usePrevious(value);
const externalValueChanged = value !== previousValue && value !== numericValue;
useEffect(() => {
if (externalValueChanged && value !== void 0) {
setInputValue(String(value));
}
}, [externalValueChanged, value]);
const dragHandleAriaLabel = ariaLabelForHandle != null ? ariaLabelForHandle : t("grafana-ui.slider.drag-handle-aria-label", "Use arrow keys to change the value");
const onSliderChange = useCallback(
(v) => {
const num = typeof v === "number" ? v : v[0];
setInputValue(num.toString());
onChange == null ? void 0 : onChange(num);
},
[onChange]
);
const handleChangeComplete = useCallback(
(v) => {
const num = typeof v === "number" ? v : v[0];
onAfterChange == null ? void 0 : onAfterChange(num);
},
[onAfterChange]
);
const onTextInputChange = useCallback(
(e) => {
const raw = e.target.value;
setInputValue(raw === "0-" ? "-" : raw);
const parsed = stripAndParseNumber(raw);
if (onChange && !Number.isNaN(parsed)) {
onChange(clampToAllowedValue(min, max, step, parsed));
}
},
[onChange, min, max, step]
);
const onTextInputBlur = useCallback(
(e) => {
const parsed = clampToAllowedValue(min, max, step, stripAndParseNumber(e.target.value));
setInputValue(parsed.toString());
onChange == null ? void 0 : onChange(parsed);
onAfterChange == null ? void 0 : onAfterChange(parsed);
},
[min, max, step, onChange, onAfterChange]
);
const sliderInputClassNames = !isHorizontal ? [styles.sliderInputVertical] : [];
const sliderInputFieldClassNames = !isHorizontal ? [styles.sliderInputFieldVertical] : [];
return /* @__PURE__ */ jsxs("div", { className: cx(styles.container, styles.slider), children: [
/* @__PURE__ */ jsx(Global, { styles: styles.tooltip }),
/* @__PURE__ */ jsxs("div", { className: cx(styles.sliderInput, ...sliderInputClassNames), children: [
/* @__PURE__ */ jsx(
SliderWithTooltip,
{
min,
max,
step: step != null ? step : 0.1,
value: numericValue,
onChange: onSliderChange,
onChangeComplete: handleChangeComplete,
vertical: !isHorizontal,
reverse,
ariaLabelForHandle: dragHandleAriaLabel,
marks,
included
}
),
showInput && /* @__PURE__ */ jsx(
Input,
{
type: "text",
width: 7.5,
className: cx(styles.sliderInputField, ...sliderInputFieldClassNames),
value: inputValue,
onChange: onTextInputChange,
onBlur: onTextInputBlur,
min,
max,
id: inputId
}
)
] })
] });
};
Slider.displayName = "Slider";
export { Slider };
//# sourceMappingURL=Slider.mjs.map