UNPKG

11.3 kBJavaScriptView Raw
1"use strict";
2
3var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
5exports.__esModule = true;
6exports.valueToPercent = valueToPercent;
7exports.percentToValue = percentToValue;
8exports.roundValueToStep = roundValueToStep;
9exports.clampValue = clampValue;
10exports["default"] = exports.SliderFilledTrack = exports.SliderTrack = exports.SliderThumb = void 0;
11
12var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
13
14var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
15
16var _core = require("@emotion/core");
17
18var _react = require("react");
19
20var _Box = _interopRequireDefault(require("../Box"));
21
22var _styles = _interopRequireDefault(require("./styles"));
23
24var _PseudoBox = _interopRequireDefault(require("../PseudoBox"));
25
26var _utils = require("../utils");
27
28/**
29 * Slider Component
30 *
31 * The following code is a derivative of the amazing work done by the Material UI team.
32 * Original source: https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Slider/Slider.js
33 */
34
35/** @jsx jsx */
36function valueToPercent(value, min, max) {
37 return (value - min) * 100 / (max - min);
38}
39
40function percentToValue(percent, min, max) {
41 return (max - min) * percent + min;
42}
43
44function makeValuePrecise(value, step) {
45 var stepDecimalPart = step.toString().split(".")[1];
46 var stepPrecision = stepDecimalPart ? stepDecimalPart.length : 0;
47 return Number(value.toFixed(stepPrecision));
48}
49
50function roundValueToStep(value, step) {
51 return makeValuePrecise(Math.round(value / step) * step, step);
52}
53
54function clampValue(val, min, max) {
55 if (val > max) {
56 return max;
57 }
58
59 if (val < min) {
60 return min;
61 }
62
63 return val;
64} ////////////////////////////////////////////////////////////////
65
66
67var SliderThumb = (0, _react.forwardRef)(function (props, ref) {
68 var _useSliderContext = useSliderContext(),
69 thumbRef = _useSliderContext.thumbRef,
70 isDisabled = _useSliderContext.isDisabled,
71 onFocus = _useSliderContext.onFocus,
72 onKeyDown = _useSliderContext.onThumbKeyDown,
73 min = _useSliderContext.min,
74 max = _useSliderContext.max,
75 valueText = _useSliderContext.valueText,
76 orientation = _useSliderContext.orientation,
77 trackPercent = _useSliderContext.trackPercent,
78 size = _useSliderContext.size,
79 color = _useSliderContext.color,
80 value = _useSliderContext.value,
81 ariaLabelledBy = _useSliderContext.ariaLabelledBy;
82
83 var _useSliderStyle = (0, _styles["default"])({
84 trackPercent: trackPercent,
85 orientation: orientation,
86 size: size,
87 color: color
88 }),
89 thumbStyle = _useSliderStyle.thumbStyle;
90
91 var sliderThumbRef = (0, _utils.useForkRef)(thumbRef, ref);
92 return (0, _core.jsx)(_PseudoBox["default"], (0, _extends2["default"])({
93 "data-slider-thumb": "",
94 d: "flex",
95 alignItems: "center",
96 outline: "none",
97 justifyContent: "center",
98 onFocus: onFocus,
99 ref: sliderThumbRef,
100 role: "slider",
101 tabIndex: isDisabled ? undefined : 0,
102 "aria-disabled": isDisabled,
103 "aria-valuemin": min,
104 "aria-valuetext": valueText,
105 "aria-orientation": orientation,
106 "aria-valuenow": value,
107 "aria-valuemax": max,
108 "aria-labelledby": ariaLabelledBy,
109 onKeyDown: onKeyDown
110 }, thumbStyle, props));
111});
112exports.SliderThumb = SliderThumb;
113SliderThumb.displayName = "SliderThumb"; ////////////////////////////////////////////////////////////////
114
115var SliderTrack = function SliderTrack(props) {
116 var _useSliderContext2 = useSliderContext(),
117 trackRef = _useSliderContext2.trackRef,
118 isDisabled = _useSliderContext2.isDisabled,
119 context = (0, _objectWithoutPropertiesLoose2["default"])(_useSliderContext2, ["trackRef", "isDisabled"]);
120
121 var _useSliderStyle2 = (0, _styles["default"])(context),
122 trackStyle = _useSliderStyle2.trackStyle;
123
124 return (0, _core.jsx)(_Box["default"], (0, _extends2["default"])({
125 "data-slider-track": "",
126 "aria-disabled": isDisabled,
127 ref: trackRef
128 }, trackStyle, props));
129}; ////////////////////////////////////////////////////////////////
130
131
132exports.SliderTrack = SliderTrack;
133
134var SliderFilledTrack = function SliderFilledTrack(props) {
135 var _useSliderContext3 = useSliderContext(),
136 isDisabled = _useSliderContext3.isDisabled,
137 context = (0, _objectWithoutPropertiesLoose2["default"])(_useSliderContext3, ["isDisabled"]);
138
139 var _useSliderStyle3 = (0, _styles["default"])(context),
140 filledTrackStyle = _useSliderStyle3.filledTrackStyle;
141
142 return (0, _core.jsx)(_PseudoBox["default"], (0, _extends2["default"])({
143 "aria-disabled": isDisabled,
144 "data-slider-filled-track": ""
145 }, filledTrackStyle, props));
146}; ////////////////////////////////////////////////////////////////
147
148
149exports.SliderFilledTrack = SliderFilledTrack;
150var SliderContext = (0, _react.createContext)();
151
152var useSliderContext = function useSliderContext() {
153 return (0, _react.useContext)(SliderContext);
154};
155
156var Slider = (0, _react.forwardRef)(function (_ref, ref) {
157 var controlledValue = _ref.value,
158 defaultValue = _ref.defaultValue,
159 onChange = _ref.onChange,
160 onKeyDown = _ref.onKeyDown,
161 onFocus = _ref.onFocus,
162 _onBlur = _ref.onBlur,
163 onMouseDown = _ref.onMouseDown,
164 isDisabled = _ref.isDisabled,
165 _ref$max = _ref.max,
166 max = _ref$max === void 0 ? 100 : _ref$max,
167 _ref$min = _ref.min,
168 min = _ref$min === void 0 ? 0 : _ref$min,
169 _ref$step = _ref.step,
170 step = _ref$step === void 0 ? 1 : _ref$step,
171 ariaLabelledBy = _ref["aria-labelledby"],
172 ariaLabel = _ref["aria-label"],
173 ariaValueText = _ref["aria-valuetext"],
174 _ref$orientation = _ref.orientation,
175 orientation = _ref$orientation === void 0 ? "horizontal" : _ref$orientation,
176 getAriaValueText = _ref.getAriaValueText,
177 _ref$size = _ref.size,
178 size = _ref$size === void 0 ? "md" : _ref$size,
179 _ref$color = _ref.color,
180 color = _ref$color === void 0 ? "blue" : _ref$color,
181 name = _ref.name,
182 id = _ref.id,
183 children = _ref.children,
184 rest = (0, _objectWithoutPropertiesLoose2["default"])(_ref, ["value", "defaultValue", "onChange", "onKeyDown", "onFocus", "onBlur", "onMouseDown", "isDisabled", "max", "min", "step", "aria-labelledby", "aria-label", "aria-valuetext", "orientation", "getAriaValueText", "size", "color", "name", "id", "children"]);
185
186 var _useRef = (0, _react.useRef)(controlledValue != null),
187 isControlled = _useRef.current;
188
189 var _useState = (0, _react.useState)(defaultValue || 0),
190 value = _useState[0],
191 setValue = _useState[1];
192
193 var _value = isControlled ? controlledValue : value;
194
195 var actualValue = clampValue(_value, min, max);
196 var trackPercent = valueToPercent(actualValue, min, max);
197
198 var _useSliderStyle4 = (0, _styles["default"])({
199 trackPercent: trackPercent,
200 orientation: orientation,
201 size: size,
202 color: color
203 }),
204 rootStyle = _useSliderStyle4.rootStyle;
205
206 var trackRef = (0, _react.useRef)();
207 var thumbRef = (0, _react.useRef)();
208
209 var getNewValue = function getNewValue(event) {
210 if (trackRef.current) {
211 var _trackRef$current$get = trackRef.current.getBoundingClientRect(),
212 left = _trackRef$current$get.left,
213 width = _trackRef$current$get.width;
214
215 var _ref2 = event.touches ? event.touches[0] : event,
216 clientX = _ref2.clientX;
217
218 var diffX = clientX - left;
219 var percent = diffX / width;
220 var newValue = percentToValue(percent, min, max);
221
222 if (step) {
223 newValue = roundValueToStep(newValue, step);
224 }
225
226 newValue = clampValue(newValue, min, max);
227 return newValue;
228 }
229 };
230
231 var updateValue = (0, _react.useCallback)(function (newValue) {
232 if (!isControlled) {
233 setValue(newValue);
234 }
235
236 if (onChange) {
237 onChange(newValue);
238 }
239 }, [isControlled, onChange]);
240
241 var handleThumbKeyDown = function handleThumbKeyDown(event) {
242 var flag = false;
243 var newValue;
244 var tenSteps = (max - min) / 10;
245
246 switch (event.key) {
247 case "ArrowLeft":
248 case "ArrowDown":
249 newValue = actualValue - step;
250 flag = true;
251 break;
252
253 case "ArrowRight":
254 case "ArrowUp":
255 newValue = actualValue + step;
256 flag = true;
257 break;
258
259 case "PageDown":
260 newValue = actualValue - tenSteps;
261 flag = true;
262 break;
263
264 case "PageUp":
265 newValue = actualValue + tenSteps;
266 flag = true;
267 break;
268
269 case "Home":
270 newValue = min;
271 flag = true;
272 break;
273
274 case "End":
275 newValue = max;
276 flag = true;
277 break;
278
279 default:
280 return;
281 }
282
283 if (flag) {
284 event.preventDefault();
285 event.stopPropagation();
286 }
287
288 if (step) {
289 newValue = roundValueToStep(newValue, step);
290 }
291
292 newValue = clampValue(newValue, min, max);
293 updateValue(newValue);
294 onKeyDown && onKeyDown(event);
295 };
296
297 var handleMouseUp = function handleMouseUp() {
298 document.body.removeEventListener("mousemove", handleMouseMove);
299 document.body.removeEventListener("touchmove", handleMouseMove);
300 document.body.removeEventListener("mouseup", handleMouseUp);
301 document.body.removeEventListener("touchend", handleMouseUp);
302 }; // TODO: Optimize this mouseMove event
303
304
305 var handleMouseMove = function handleMouseMove(event) {
306 var newValue = getNewValue(event);
307 updateValue(newValue);
308 };
309
310 var handleMouseDown = function handleMouseDown(event) {
311 if (isDisabled) return;
312 onMouseDown && onMouseDown(event);
313 event.preventDefault();
314 var newValue = getNewValue(event);
315
316 if (newValue !== actualValue) {
317 updateValue(newValue);
318 }
319
320 document.body.addEventListener("mousemove", handleMouseMove);
321 document.body.addEventListener("touchmove", handleMouseMove);
322 document.body.addEventListener("mouseup", handleMouseUp);
323 document.body.addEventListener("touchend", handleMouseUp);
324 thumbRef.current && thumbRef.current.focus();
325 };
326
327 var valueText = getAriaValueText ? getAriaValueText(actualValue) : ariaValueText;
328 var context = {
329 trackRef: trackRef,
330 thumbRef: thumbRef,
331 onThumbKeyDown: handleThumbKeyDown,
332 onFocus: onFocus,
333 trackPercent: trackPercent,
334 ariaLabelledBy: ariaLabelledBy,
335 orientation: orientation,
336 isDisabled: isDisabled,
337 size: size,
338 color: color,
339 min: min,
340 max: max,
341 valueText: valueText,
342 value: actualValue
343 };
344 return (0, _core.jsx)(SliderContext.Provider, {
345 value: context
346 }, (0, _core.jsx)(_Box["default"], (0, _extends2["default"])({
347 role: "presentation",
348 tabIndex: "-1",
349 onMouseDown: handleMouseDown,
350 onTouchStart: handleMouseDown,
351 onMouseLeave: handleMouseUp,
352 onTouchEnd: handleMouseUp,
353 onBlur: function onBlur(event) {
354 handleMouseUp();
355 _onBlur && _onBlur(event);
356 },
357 py: 3,
358 "aria-disabled": isDisabled,
359 ref: ref,
360 css: {
361 touchAction: "none"
362 }
363 }, rootStyle, rest), children, (0, _core.jsx)("input", {
364 type: "hidden",
365 value: actualValue,
366 name: name,
367 id: id
368 })));
369});
370Slider.displayName = "Slider";
371var _default = Slider;
372exports["default"] = _default;
\No newline at end of file