react-toggle-slider
Version:
A highly customizable React toggle slider component.
121 lines (120 loc) • 7.89 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import React, { useState } from 'react';
import interpolate from "color-interpolate";
function ToggleSliderHandle(props) {
return (React.createElement("div", { style: __assign({ width: props.size, height: props.size }, props) }));
}
function ToggleSliderBar(props) {
return (React.createElement("div", { style: props }));
}
function ToggleSlider(_a) {
var _b = _a.barBackgroundColor, barBackgroundColor = _b === void 0 ? "#dedede" : _b, _c = _a.barBackgroundColorActive, barBackgroundColorActive = _c === void 0 ? "#06b7e7" : _c, _d = _a.barBorderRadius, barBorderRadius = _d === void 0 ? 16 : _d, _e = _a.barHeight, barHeight = _e === void 0 ? 26 : _e, _f = _a.barWidth, barWidth = _f === void 0 ? 48 : _f, _g = _a.handleBackgroundColor, handleBackgroundColor = _g === void 0 ? "#ffffff" : _g, handleBackgroundColorActive = _a.handleBackgroundColorActive, _h = _a.handleBorderRadius, handleBorderRadius = _h === void 0 ? 16 : _h, _j = _a.handleSize, handleSize = _j === void 0 ? 18 : _j, _k = _a.padding, padding = _k === void 0 ? 5 : _k, _l = _a.transitionDuration, transitionDuration = _l === void 0 ? "100ms" : _l, barTransitionDuration = _a.barTransitionDuration, handleTransitionDuration = _a.handleTransitionDuration, _m = _a.onToggle, onToggle = _m === void 0 ? function () { return undefined; } : _m, handleRenderer = _a.handleRenderer, handleRendererActive = _a.handleRendererActive, barRenderer = _a.barRenderer, barRendererActive = _a.barRendererActive, flip = _a.flip, barStyles = _a.barStyles, barStylesActive = _a.barStylesActive, handleStyles = _a.handleStyles, handleStylesActive = _a.handleStylesActive, _o = _a.active, initialActive = _o === void 0 ? false : _o, _p = _a.draggable, draggable = _p === void 0 ? true : _p, _q = _a.barTransitionType, barTransitionType = _q === void 0 ? "fade" : _q;
var _r = useState(initialActive), active = _r[0], setActive = _r[1];
var _s = useState((active && !flip || !active && flip) ? 1 : 0), progress = _s[0], setProgressState = _s[1];
var _t = useState(active ? barBackgroundColorActive : barBackgroundColor), currentBarColor = _t[0], setCurrentBarColor = _t[1];
var _u = useState(false), dragging = _u[0], setDragging = _u[1];
function interpolateColors(start, end, pos) {
var colorMap = interpolate([start, end]);
return colorMap(pos);
}
function setProgress(p) {
var paddingLeft = Math.max(padding, Math.min(barWidth - padding - handleSize, p * barWidth - handleSize / 2));
var paddingProgress = (paddingLeft - padding) / (barWidth - padding * 2 - handleSize);
setProgressState(p);
if (barTransitionType === "fade") {
setCurrentBarColor(interpolateColors(barBackgroundColor, barBackgroundColorActive, paddingProgress));
}
}
var overlayStyles = {
boxSizing: "border-box",
width: "100%",
flex: "none",
};
barStyles = active ? __assign(__assign({}, barStyles), barStylesActive) : barStyles;
handleStyles = active ? __assign(__assign({}, handleStyles), handleStylesActive) : handleStyles;
var bar = barRenderer !== null && barRenderer !== void 0 ? barRenderer : React.createElement(ToggleSliderBar, __assign({ width: barWidth, height: barHeight, borderRadius: barBorderRadius, background: currentBarColor, transition: "all " + (dragging ? "0s" : (barTransitionDuration !== null && barTransitionDuration !== void 0 ? barTransitionDuration : transitionDuration)) }, barStyles));
var handle = handleRenderer !== null && handleRenderer !== void 0 ? handleRenderer : React.createElement(ToggleSliderHandle, __assign({ size: handleSize, borderRadius: handleBorderRadius, backgroundColor: active ?
(handleBackgroundColorActive !== null && handleBackgroundColorActive !== void 0 ? handleBackgroundColorActive : handleBackgroundColor) :
handleBackgroundColor, transition: "all " + (dragging ? "0s" : (handleTransitionDuration !== null && handleTransitionDuration !== void 0 ? handleTransitionDuration : transitionDuration)) }, handleStyles));
var barActive = barRendererActive !== null && barRendererActive !== void 0 ? barRendererActive : bar;
var handleActive = handleRendererActive !== null && handleRendererActive !== void 0 ? handleRendererActive : handle;
var _v = useState(false), down = _v[0], setDown = _v[1];
function onPointerDown(e) {
setDown(true);
}
function onPointerMove(e) {
if (!down || !draggable) {
return;
}
var localDragging = dragging;
if (!dragging) {
setDragging(true);
localDragging = true;
}
if (localDragging) {
var bounds = e.currentTarget.getBoundingClientRect();
var position = (e.clientX - bounds.left) / barWidth;
setProgress(position);
}
}
function onPointerUp() {
if (!down) {
return;
}
if (!dragging) {
onToggle(!active);
setProgress(active ? 0 : 1);
setActive(!active);
}
else {
var newActive = progress > 0.5;
onToggle(newActive);
setProgress(newActive ? 1 : 0);
setActive(newActive);
}
setDown(false);
setDragging(false);
}
return (React.createElement("div", { style: { display: "flex", flexFlow: "row nowrap", cursor: "pointer", width: barWidth, userSelect: "none" }, onPointerUp: onPointerUp, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerLeave: onPointerUp },
React.createElement("div", { style: __assign({ paddingTop: Math.max(handleSize - barHeight, 0) / 2 }, overlayStyles) }, active ? barActive : bar),
barTransitionType === "slide" ? (React.createElement("div", { style: __assign({ marginLeft: "-100%" }, overlayStyles) },
React.createElement("div", { style: {
borderRadius: barBorderRadius,
width: barWidth,
height: barHeight,
marginTop: Math.max(handleSize - barHeight, 0) / 2,
// boxSizing: "border-box",
overflow: "hidden",
} },
React.createElement("div", { style: {
transition: "all " + (dragging ? "0s" : transitionDuration),
backgroundColor: barBackgroundColorActive,
width: progress * barWidth,
height: barHeight,
} })))) : undefined,
React.createElement("div", { style: __assign({ marginLeft: "-100%" }, overlayStyles) },
React.createElement("div", { style: {
transition: "all " + (dragging ? "0s" : transitionDuration),
paddingTop: Math.max(barHeight - handleSize, 0) / 2,
paddingLeft: Math.max(padding, Math.min(barWidth - padding - handleSize, progress * barWidth - handleSize / 2)),
} }, active ? handleActive : handle))));
}
function useToggleSlider(props) {
var _a;
var _b = useState((_a = props === null || props === void 0 ? void 0 : props.active) !== null && _a !== void 0 ? _a : false), activeState = _b[0], setActiveState = _b[1];
function onToggle(value) {
setActiveState(value);
}
return [React.createElement(ToggleSlider, __assign({ onToggle: onToggle }, props)), activeState];
}
export { ToggleSlider, useToggleSlider };