@create-figma-plugin/ui
Version:
Production-grade Preact components that replicate the Figma UI design
61 lines • 3.06 kB
JavaScript
import { h } from 'preact';
import { useCallback, useEffect, useRef } from 'preact/hooks';
import { createClassName } from '../../utilities/create-class-name.js';
import { createComponent } from '../../utilities/create-component.js';
import { getCurrentFromRef } from '../../utilities/get-current-from-ref.js';
import { noop } from '../../utilities/no-op.js';
import styles from './range-slider.module.css';
const PROGRESS_TRACK_COLOR_VARIABLE_NAME = '--create-figma-plugin-range-slider-progress-track-color';
export const RangeSlider = createComponent(function ({ disabled = false, increment = 1, maximum, minimum, onInput = noop, onKeyDown = noop, onNumericValueInput = noop, onValueInput = noop, propagateEscapeKeyDown = true, value, ...rest }, ref) {
const inputElementRef = useRef(null);
if (minimum >= maximum) {
throw new Error('`minimum` must be less than `maximum`');
}
const handleInput = useCallback(function (event) {
onInput(event);
const value = event.currentTarget.value;
onValueInput(value);
const numericValue = parseFloat(value);
onNumericValueInput(numericValue);
}, [onInput, onNumericValueInput, onValueInput]);
const handleKeyDown = useCallback(function (event) {
onKeyDown(event);
if (event.key === 'Escape') {
if (propagateEscapeKeyDown === false) {
event.stopPropagation();
}
event.currentTarget.blur();
}
}, [onKeyDown, propagateEscapeKeyDown]);
const refCallback = useCallback(function (inputElement) {
inputElementRef.current = inputElement;
if (ref === null) {
return;
}
if (typeof ref === 'function') {
ref(inputElement);
return;
}
ref.current = inputElement;
}, [ref]);
const renderProgressTrack = useCallback(function (options) {
const { value, maximum } = options;
const inputElement = getCurrentFromRef(inputElementRef);
const inputElementWidth = inputElement.offsetWidth;
const sliderThumbElementWidth = inputElement.offsetHeight;
const percentage = value / maximum;
const px = `${percentage * (inputElementWidth - sliderThumbElementWidth) +
sliderThumbElementWidth / 2}px`;
inputElement.style.background = `linear-gradient(to right, var(${PROGRESS_TRACK_COLOR_VARIABLE_NAME}) ${px}, transparent ${px})`;
}, []);
useEffect(function () {
renderProgressTrack({ maximum, value: parseFloat(value) });
}, [maximum, renderProgressTrack, value]);
return (h("label", { class: createClassName([
styles.rangeSlider,
disabled === true ? styles.disabled : null
]) },
h("input", { ...rest, ref: refCallback, class: styles.input, disabled: disabled, max: maximum, min: minimum, onInput: handleInput, onKeyDown: handleKeyDown, step: increment, type: "range", value: value }),
h("div", { class: styles.box })));
});
//# sourceMappingURL=range-slider.js.map