UNPKG

11.6 kBJavaScriptView Raw
1"use strict";
2
3exports.__esModule = true;
4exports.default = void 0;
5
6var _classnames = _interopRequireDefault(require("classnames"));
7
8var _propTypes = _interopRequireDefault(require("prop-types"));
9
10var _react = _interopRequireWildcard(require("react"));
11
12var _uncontrollable = require("uncontrollable");
13
14var _Button = _interopRequireDefault(require("./Button"));
15
16var _Icon = require("./Icon");
17
18var _Localization = require("./Localization");
19
20var _NumberInput = _interopRequireDefault(require("./NumberInput"));
21
22var _Widget = _interopRequireDefault(require("./Widget"));
23
24var _WidgetPicker = _interopRequireDefault(require("./WidgetPicker"));
25
26var CustomPropTypes = _interopRequireWildcard(require("./PropTypes"));
27
28var _useFocusManager = _interopRequireDefault(require("./useFocusManager"));
29
30var _WidgetHelpers = require("./WidgetHelpers");
31
32var _useEventCallback = _interopRequireDefault(require("@restart/hooks/useEventCallback"));
33
34const _excluded = ["className", "containerClassName", "disabled", "readOnly", "value", "min", "max", "incrementIcon", "decrementIcon", "placeholder", "autoFocus", "tabIndex", "parse", "name", "onChange", "messages", "format", "onKeyDown", "onKeyPress", "onKeyUp", "inputProps", "precision", "step"];
35
36function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
37
38function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
39
40function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
41
42function _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); }
43
44function _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; }
45
46// my tests in ie11/chrome/FF indicate that keyDown repeats
47// at about 35ms+/- 5ms after an initial 500ms delay. callback fires on the leading edge
48function createInterval(callback) {
49 let fn;
50 let id;
51
52 const cancel = () => clearTimeout(id);
53
54 id = window.setTimeout(fn = () => {
55 id = window.setTimeout(fn, 35);
56 callback(); //fire after everything in case the user cancels on the first call
57 }, 500);
58 return cancel;
59}
60
61function clamp(value, min, max) {
62 max = max == null ? Infinity : max;
63 min = min == null ? -Infinity : min;
64 if (value == null || value === '') return null;
65 return Math.max(Math.min(typeof value == 'string' ? parseInt(value) : value, max), min);
66}
67
68const propTypes = {
69 /**
70 * @example ['valuePicker', [ [1, null] ]]
71 */
72 value: _propTypes.default.number,
73
74 /**
75 * @example ['onChangePicker', [ [1, null] ]]
76 */
77 onChange: _propTypes.default.func,
78
79 /**
80 * The minimum number that the NumberPicker value.
81 * @example ['prop', ['min', 0]]
82 */
83 min: _propTypes.default.number,
84
85 /**
86 * The maximum number that the NumberPicker value.
87 *
88 * @example ['prop', ['max', 0]]
89 */
90 max: _propTypes.default.number,
91
92 /**
93 * Amount to increase or decrease value when using the spinner buttons.
94 *
95 * @example ['prop', ['step', 5]]
96 */
97 step: _propTypes.default.number,
98
99 /**
100 * Specify how precise the `value` should be when typing, incrementing, or decrementing the value.
101 * When empty, precision is parsed from the current `format` and culture.
102 */
103 precision: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.oneOf(['auto'])]),
104
105 /**
106 * A format string used to display the number value. Localizer dependent, read about [localization](localization) for more info.
107 *
108 * @example ['prop', { max: 1, min: -1 , defaultValue: 0.2585, format: "{ style: 'percent' }" }]
109 */
110 format: _propTypes.default.any,
111 parse: _propTypes.default.func,
112 incrementIcon: _propTypes.default.node,
113 decrementIcon: _propTypes.default.node,
114
115 /** @ignore */
116 tabIndex: _propTypes.default.any,
117 name: _propTypes.default.string,
118 placeholder: _propTypes.default.string,
119 onKeyDown: _propTypes.default.func,
120 onKeyPress: _propTypes.default.func,
121 onKeyUp: _propTypes.default.func,
122 autoFocus: _propTypes.default.bool,
123
124 /**
125 * @example ['disabled', ['1']]
126 */
127 disabled: CustomPropTypes.disabled,
128
129 /**
130 * @example ['readOnly', ['1.5']]
131 */
132 readOnly: CustomPropTypes.disabled,
133
134 /** Adds a css class to the input container element. */
135 containerClassName: _propTypes.default.string,
136 inputProps: _propTypes.default.object,
137 messages: _propTypes.default.shape({
138 increment: _propTypes.default.string,
139 decrement: _propTypes.default.string
140 }),
141
142 /** @ignore */
143 localizer: _propTypes.default.object
144};
145const defaultProps = {
146 incrementIcon: _Icon.caretUp,
147 decrementIcon: _Icon.caretDown,
148 min: -Infinity,
149 max: Infinity,
150 step: 1,
151 precision: 'auto'
152};
153
154/**
155 * ---
156 * localized: true
157 * shortcuts:
158 * - { key: down arrow, label: decrement value }
159 * - { key: up arrow, label: increment value }
160 * - { key: home, label: set value to minimum value, if finite }
161 * - { key: end, label: set value to maximum value, if finite }
162 * ---
163 *
164 * @public
165 */
166function NumberPicker(uncontrolledProps) {
167 const _useUncontrolled = (0, _uncontrollable.useUncontrolled)(uncontrolledProps, {
168 value: 'onChange'
169 }),
170 {
171 className,
172 containerClassName,
173 disabled,
174 readOnly,
175 value,
176 min,
177 max,
178 incrementIcon,
179 decrementIcon,
180 placeholder,
181 autoFocus,
182 tabIndex,
183 parse,
184 name,
185 onChange,
186 messages,
187 format,
188 onKeyDown,
189 onKeyPress,
190 onKeyUp,
191 inputProps,
192 precision,
193 step: pStep
194 } = _useUncontrolled,
195 elementProps = _objectWithoutPropertiesLoose(_useUncontrolled, _excluded);
196
197 const localizer = (0, _Localization.useLocalizer)(messages, {
198 number: format
199 });
200 const ref = (0, _react.useRef)(null);
201 const inputRef = (0, _react.useRef)(null);
202 const repeaterRef = (0, _react.useRef)(null);
203 const [focusEvents, focused] = (0, _useFocusManager.default)(ref, uncontrolledProps, {
204 willHandle(focused) {
205 if (focused) focus();
206 }
207
208 });
209 const handleMouseDown = (0, _useEventCallback.default)((direction, event) => {
210 if (event) event.persist();
211 let method = direction === 'UP' ? increment : decrement;
212 let value = method(event),
213 atTop = direction === 'UP' && value === max,
214 atBottom = direction === 'DOWN' && value === min;
215 if (atTop || atBottom) handleMouseUp();else if (!repeaterRef.current) {
216 repeaterRef.current = createInterval(() => {
217 handleMouseDown(direction, event);
218 });
219 }
220 });
221 const handleMouseUp = (0, _useEventCallback.default)(() => {
222 if (!repeaterRef.current) return;
223 repeaterRef.current();
224 repeaterRef.current = null;
225 });
226 const handleKeyDown = (0, _useEventCallback.default)(event => {
227 if (readOnly) return;
228 let key = event.key;
229 (0, _WidgetHelpers.notify)(onKeyDown, [event]);
230 if (event.defaultPrevented) return;
231 if (key === 'End' && isFinite(max)) handleChange(max, event);else if (key === 'Home' && isFinite(min)) handleChange(min, event);else if (key === 'ArrowDown') {
232 event.preventDefault();
233 decrement(event);
234 } else if (key === 'ArrowUp') {
235 event.preventDefault();
236 increment(event);
237 }
238 });
239
240 const handleChange = (rawValue, originalEvent = null) => {
241 let nextValue = clamp(rawValue, min, max);
242 if (value !== nextValue) (0, _WidgetHelpers.notify)(onChange, [nextValue, {
243 rawValue,
244 originalEvent,
245 lastValue: value
246 }]);
247 };
248
249 function focus() {
250 var _inputRef$current;
251
252 (_inputRef$current = inputRef.current) == null ? void 0 : _inputRef$current.focus();
253 }
254
255 function increment(event) {
256 return step(pStep, event);
257 }
258
259 function decrement(event) {
260 return step(-pStep, event);
261 }
262
263 function step(amount, event) {
264 const nextValue = (value || 0) + amount;
265 let p = precision === 'auto' ? Math.max(getPrecision(value || 0), getPrecision(amount)) : precision;
266 handleChange(p != null ? parseFloat(nextValue.toFixed(p)) : nextValue, event);
267 return nextValue;
268 }
269
270 const clampedValue = clamp(value, min, max);
271 return /*#__PURE__*/_react.default.createElement(_Widget.default, _extends({}, elementProps, {
272 focused: focused,
273 disabled: disabled,
274 readOnly: readOnly,
275 onKeyDown: handleKeyDown
276 }, focusEvents, {
277 ref: ref,
278 className: (0, _classnames.default)(className, 'rw-number-picker')
279 }), /*#__PURE__*/_react.default.createElement(_WidgetPicker.default, {
280 className: containerClassName
281 }, /*#__PURE__*/_react.default.createElement(_NumberInput.default, _extends({}, inputProps, {
282 role: "spinbutton",
283 tabIndex: tabIndex,
284 value: clampedValue,
285 placeholder: placeholder,
286 autoFocus: autoFocus,
287 editing: focused,
288 localizer: localizer,
289 parse: parse,
290 name: name,
291 min: min,
292 max: max,
293 disabled: disabled,
294 readOnly: readOnly,
295 onChange: handleChange,
296 onKeyPress: onKeyPress,
297 onKeyUp: onKeyUp,
298 innerRef: inputRef
299 })), /*#__PURE__*/_react.default.createElement("span", {
300 className: "rw-input-addon rw-number-picker-spinners"
301 }, /*#__PURE__*/_react.default.createElement(_Button.default, {
302 icon: incrementIcon,
303 className: "rw-picker-btn",
304 disabled: clampedValue === max || disabled || readOnly,
305 label: localizer.messages.increment({
306 value: clampedValue,
307 min,
308 max
309 }),
310 onMouseUp: () => handleMouseUp(),
311 onMouseDown: e => handleMouseDown('UP', e),
312 onMouseLeave: () => handleMouseUp()
313 }), /*#__PURE__*/_react.default.createElement(_Button.default, {
314 icon: decrementIcon,
315 className: "rw-picker-btn",
316 disabled: clampedValue === min || disabled || readOnly,
317 label: localizer.messages.decrement({
318 value: clampedValue,
319 min,
320 max
321 }),
322 onMouseUp: () => handleMouseUp(),
323 onMouseDown: e => handleMouseDown('DOWN', e),
324 onMouseLeave: () => handleMouseUp()
325 }))));
326}
327
328;
329NumberPicker.propTypes = propTypes;
330NumberPicker.defaultProps = defaultProps;
331var _default = NumberPicker;
332exports.default = _default;
333
334function getPrecision(a) {
335 if (!isFinite(a)) return 0;
336 let e = 1;
337 let p = 0;
338
339 while (Math.round(a * e) / e !== a) {
340 e *= 10;
341 p++;
342 }
343
344 return p;
345}
\No newline at end of file