UNPKG

@create-figma-plugin/ui

Version:

Production-grade Preact components that replicate the Figma UI design

61 lines 3.06 kB
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