semantic-ui-react-spinbutton
Version:
Spinbuttons for Semantic UI React
510 lines (429 loc) • 15.2 kB
JavaScript
import React, { useRef, useEffect, useState } from 'react';
import { Button, Input } from 'semantic-ui-react';
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArrayLimit(arr, i) {
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
if (_i == null) return;
var _arr = [];
var _n = true;
var _d = false;
var _s, _e;
try {
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
var classnames = {exports: {}};
/*!
Copyright (c) 2018 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/
(function (module) {
/* global define */
(function () {
var hasOwn = {}.hasOwnProperty;
function classNames() {
var classes = [];
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
if (!arg) continue;
var argType = typeof arg;
if (argType === 'string' || argType === 'number') {
classes.push(arg);
} else if (Array.isArray(arg)) {
if (arg.length) {
var inner = classNames.apply(null, arg);
if (inner) {
classes.push(inner);
}
}
} else if (argType === 'object') {
if (arg.toString === Object.prototype.toString) {
for (var key in arg) {
if (hasOwn.call(arg, key) && arg[key]) {
classes.push(key);
}
}
} else {
classes.push(arg.toString());
}
}
}
return classes.join(' ');
}
if (module.exports) {
classNames.default = classNames;
module.exports = classNames;
} else {
window.classNames = classNames;
}
}());
}(classnames));
var classNames = classnames.exports;
var styles$2 = {"spinbutton":"spinbutton-o3pfL","buttons":"buttons-gPhpG","vertical":"vertical-NPwPZ","horizontal":"horizontal-WCywh","up":"up-YCggi","down":"down-IqEiE","right":"right-iC8wb","bottom":"bottom-WQcEM","left":"left-Adm0Y","top":"top-PlmTf"};
var _excluded$2 = ["buttonPosition", "buttonOrientation", "buttonSize", "upIcon", "downIcon", "onUp", "onDown", "onWheel", "className", "disabled", "upDisabled", "downDisabled", "children"];
var Spinbutton = (function (_ref) {
var _ref$buttonPosition = _ref.buttonPosition,
buttonPosition = _ref$buttonPosition === void 0 ? 'wrapped' : _ref$buttonPosition,
_ref$buttonOrientatio = _ref.buttonOrientation,
buttonOrientation = _ref$buttonOrientatio === void 0 ? 'vertical' : _ref$buttonOrientatio,
buttonSize = _ref.buttonSize,
_ref$upIcon = _ref.upIcon,
upIcon = _ref$upIcon === void 0 ? 'caret up' : _ref$upIcon,
_ref$downIcon = _ref.downIcon,
downIcon = _ref$downIcon === void 0 ? 'caret down' : _ref$downIcon,
onUp = _ref.onUp,
onDown = _ref.onDown,
onWheel = _ref.onWheel,
className = _ref.className,
disabled = _ref.disabled,
upDisabled = _ref.upDisabled,
downDisabled = _ref.downDisabled,
children = _ref.children,
props = _objectWithoutProperties(_ref, _excluded$2);
var buttonUpRef = useRef();
var buttonDownRef = useRef();
var contentOrientation = buttonPosition === 'left' || buttonPosition === 'right' ? 'horizontal' : buttonPosition === 'top' || buttonPosition === 'bottom' ? 'vertical' : buttonOrientation;
var wrapperClassName = classNames(className, styles$2.spinbutton, styles$2[contentOrientation], _defineProperty({}, styles$2[buttonPosition], buttonPosition !== 'wrapped'));
var buttonsClassName = classNames(styles$2.buttons, styles$2[buttonOrientation]);
useEffect(function () {
if (onWheel === undefined) return;
buttonUpRef.current.ref.current.addEventListener('wheel', function (event) {
event.preventDefault();
});
buttonDownRef.current.ref.current.addEventListener('wheel', function (event) {
event.preventDefault();
});
}, []);
var ButtonUp = React.createElement(Button, {
type: "button",
className: styles$2.up,
size: buttonSize,
icon: upIcon,
onClick: onUp,
onWheel: onWheel,
ref: buttonUpRef,
disabled: upDisabled || disabled
});
var ButtonDown = React.createElement(Button, {
type: "button",
className: styles$2.down,
size: buttonSize,
icon: downIcon,
onClick: onDown,
onWheel: onWheel,
ref: buttonDownRef,
disabled: downDisabled || disabled
});
return React.createElement("div", _extends({}, props, {
className: wrapperClassName
}), buttonPosition === 'top' || buttonPosition === 'left' ? React.createElement(React.Fragment, null, React.createElement("div", {
className: buttonsClassName
}, ButtonUp, ButtonDown), children) : buttonPosition === 'right' || buttonPosition === 'bottom' ? React.createElement(React.Fragment, null, children, React.createElement("div", {
className: buttonsClassName
}, ButtonUp, ButtonDown)) : React.createElement(React.Fragment, null, ButtonUp, children, ButtonDown));
});
function useFirstMountState() {
var isFirst = useRef(true);
if (isFirst.current) {
isFirst.current = false;
return true;
}
return isFirst.current;
}
var useUpdateEffect = function (effect, deps) {
var isFirstMount = useFirstMountState();
useEffect(function () {
if (!isFirstMount) {
return effect();
}
}, deps);
};
var useUpdateEffect$1 = useUpdateEffect;
var styles$1 = {"inputspinner":"inputspinner-4RTkr","left":"left-loXxn","right":"right-q6Mll","top":"top-C4WrO","bottom":"bottom-7hKJ6"};
var _excluded$1 = ["name", "value", "buttonPosition", "buttonOrientation", "buttonSize", "upIcon", "downIcon", "onUp", "onDown", "onChange", "onInput", "onWheel", "onKeyDown", "formatter", "className", "disabled", "upDisabled", "downDisabled", "style"];
var InputSpinner = (function (_ref) {
var name = _ref.name,
_ref$value = _ref.value,
defaultValue = _ref$value === void 0 ? '' : _ref$value,
_ref$buttonPosition = _ref.buttonPosition,
buttonPosition = _ref$buttonPosition === void 0 ? 'right' : _ref$buttonPosition,
_ref$buttonOrientatio = _ref.buttonOrientation,
buttonOrientation = _ref$buttonOrientatio === void 0 ? 'vertical' : _ref$buttonOrientatio,
buttonSize = _ref.buttonSize,
upIcon = _ref.upIcon,
downIcon = _ref.downIcon,
onUp = _ref.onUp,
onDown = _ref.onDown,
onChange = _ref.onChange,
onInput = _ref.onInput,
onWheel = _ref.onWheel,
onKeyDown = _ref.onKeyDown,
formatter = _ref.formatter,
className = _ref.className,
disabled = _ref.disabled,
upDisabled = _ref.upDisabled,
downDisabled = _ref.downDisabled,
style = _ref.style,
props = _objectWithoutProperties(_ref, _excluded$1);
var inputRef = useRef();
var hiddenInputRef = useRef();
var _useState = useState(defaultValue),
_useState2 = _slicedToArray(_useState, 2),
value = _useState2[0],
setValue = _useState2[1];
var _useState3 = useState(false),
_useState4 = _slicedToArray(_useState3, 2),
isFocused = _useState4[0],
setFocused = _useState4[1];
var wrapperClassName = classNames(className, styles$1.inputspinner, _defineProperty({}, styles$1.top, buttonPosition === 'top' || buttonPosition === 'wrapped' && buttonOrientation === 'vertical'), _defineProperty({}, styles$1.left, buttonPosition === 'left' || buttonPosition === 'wrapped' && buttonOrientation === 'horizontal'), _defineProperty({}, styles$1.right, buttonPosition === 'right' || buttonPosition === 'wrapped' && buttonOrientation === 'horizontal'), _defineProperty({}, styles$1.bottom, buttonPosition === 'bottom' || buttonPosition === 'wrapped' && buttonOrientation === 'vertical'));
useEffect(function () {
var input = inputRef.current.inputRef.current;
input.addEventListener('wheel', function (event) {
event.preventDefault();
});
props.readOnly && input.addEventListener('keydown', function (event) {
event.preventDefault();
});
}, []);
useUpdateEffect$1(function () {
var event = new Event('input', {
bubbles: true
});
hiddenInputRef.current.dispatchEvent(event);
}, [value]);
function handleUp(event) {
var _onUp;
onUp && setValue((_onUp = onUp(value, event)) !== null && _onUp !== void 0 ? _onUp : value);
}
function handleDown(event) {
var _onDown;
onDown && setValue((_onDown = onDown(value, event)) !== null && _onDown !== void 0 ? _onDown : value);
}
function handleInput(event) {
setValue(event.target.value);
}
function handleHiddenInput(event) {
onInput && onInput(event);
if (onChange) {
event._reactName = 'onChange';
event.type = 'change';
onChange(event);
}
}
function handleWheel(event) {
if (onWheel) {
onWheel(event);
return;
}
event.deltaY < 0 ? handleUp(event) : handleDown(event);
}
function handleKey(event) {
if (onKeyDown) {
onKeyDown(event);
return;
}
if (!props.readOnly && isFocused && ['+', '-'].includes(event.key)) return;
switch (event.key) {
case 'ArrowUp':
case '+':
handleUp(event);
break;
case 'ArrowDown':
case '-':
handleDown(event);
break;
}
}
function handleFocus(event) {
setFocused(true);
}
function blurHandler(event) {
setFocused(false);
}
return React.createElement(Spinbutton, {
className: wrapperClassName,
buttonPosition: buttonPosition,
buttonOrientation: buttonOrientation,
buttonSize: buttonSize || props.size,
upIcon: upIcon,
downIcon: downIcon,
onUp: handleUp,
onDown: handleDown,
onWheel: handleWheel,
disabled: disabled,
upDisabled: upDisabled,
downDisabled: downDisabled,
style: style
}, React.createElement(Input, _extends({}, props, {
value: formatter && !isFocused && value !== '' ? formatter(value) : value,
onInput: handleInput,
onKeyDown: handleKey,
onWheel: handleWheel,
onFocus: handleFocus,
onBlur: blurHandler,
ref: inputRef,
disabled: disabled,
fluid: true
})), React.createElement("input", {
type: "hidden",
name: name,
value: value,
ref: hiddenInputRef,
onInput: handleHiddenInput
}));
});
var styles = {"numberinputspinner":"numberinputspinner-23Ef3"};
var _excluded = ["className", "min", "max", "step", "shiftStep", "ctrlStep", "altStep"];
var index = (function (_ref) {
var className = _ref.className,
min = _ref.min,
max = _ref.max,
_ref$step = _ref.step,
step = _ref$step === void 0 ? 1 : _ref$step,
shiftStep = _ref.shiftStep,
ctrlStep = _ref.ctrlStep,
altStep = _ref.altStep,
props = _objectWithoutProperties(_ref, _excluded);
var _useState = useState(false),
_useState2 = _slicedToArray(_useState, 2),
isMin = _useState2[0],
setMin = _useState2[1];
var _useState3 = useState(false),
_useState4 = _slicedToArray(_useState3, 2),
isMax = _useState4[0],
setMax = _useState4[1];
function setMinMax(value) {
setMin(min && value <= min);
setMax(max && value >= max);
}
useEffect(function () {
setMinMax(props.value);
}, []);
className = classNames(className, styles.numberinputspinner);
var numberFormatter = new Intl.NumberFormat([], {
useGrouping: false
}).format;
function getStepValue(event) {
if (shiftStep && event.shiftKey && !(event.ctrlKey || event.altKey)) {
return shiftStep;
} else if (ctrlStep && event.ctrlKey && !(event.shiftKey || event.altKey)) {
return ctrlStep;
} else if (altStep && event.altKey && !(event.shiftKey || event.ctrlKey)) {
return altStep;
} else {
return step;
}
}
function handleUp(value, event) {
var newValue = (Number(value) * 1000 + Number(getStepValue(event)) * 1000) / 1000 || 0;
setMinMax(newValue);
if (!isMax) {
return newValue;
}
}
function handleDown(value, event) {
var newValue = (Number(value) * 1000 - Number(getStepValue(event)) * 1000) / 1000 || 0;
setMinMax(newValue);
if (!isMin) {
return newValue;
}
}
return React.createElement(InputSpinner, _extends({}, props, {
className: className,
onUp: handleUp,
onDown: handleDown,
upDisabled: isMax,
downDisabled: isMin,
formatter: numberFormatter
}));
});
export { InputSpinner, index as NumberInputSpinner, Spinbutton };