UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

239 lines (238 loc) 10.1 kB
"use client"; import _extends from "@babel/runtime/helpers/esm/extends"; import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } import React, { useContext, useMemo, useCallback, useEffect, useRef } from 'react'; import { InputMasked, Button } from '../../../../components'; import SharedContext from '../../../../shared/Context'; import FieldBlockContext from '../../FieldBlock/FieldBlockContext'; import classnames from 'classnames'; import FieldBlock from '../../FieldBlock'; import { useFieldProps } from '../../hooks'; import { pickSpacingProps } from '../../../../components/flex/utils'; import { clamp } from '../../../../components/slider/SliderHelpers'; import DataContext from '../../DataContext/Context'; const defaultMinimum = Number.MIN_SAFE_INTEGER; const defaultMaximum = Number.MAX_SAFE_INTEGER; function NumberComponent(props) { var _props$width, _props$innerRef, _dataContext$props2, _sharedContext$transl, _sharedContext$transl2; const dataContext = useContext(DataContext); const fieldBlockContext = useContext(FieldBlockContext); const sharedContext = useContext(SharedContext); const { currency, currencyDisplay, percent, mask, step = 1, decimalLimit = 12, allowNegative = true, disallowLeadingZeroes = false, prefix: prefixProp, suffix: suffixProp, showStepControls } = props; const schema = useMemo(() => { var _props$schema, _props$minimum, _props$maximum; return (_props$schema = props.schema) !== null && _props$schema !== void 0 ? _props$schema : { type: 'number', minimum: (_props$minimum = props.minimum) !== null && _props$minimum !== void 0 ? _props$minimum : defaultMinimum, maximum: (_props$maximum = props.maximum) !== null && _props$maximum !== void 0 ? _props$maximum : defaultMaximum, exclusiveMinimum: props.exclusiveMinimum, exclusiveMaximum: props.exclusiveMaximum, multipleOf: props.multipleOf }; }, [props.schema, props.minimum, props.maximum, props.exclusiveMinimum, props.exclusiveMaximum, props.multipleOf]); const toInput = useCallback(external => { if (external === undefined) { return null; } return external; }, []); const fromInput = useCallback(({ value, numberValue }) => { if (value === '') { return props.emptyValue; } return numberValue; }, [props.emptyValue]); const ref = useRef(); const preparedProps = _objectSpread(_objectSpread({ valueType: 'number' }, props), {}, { schema, toInput, fromInput, width: (_props$width = props.width) !== null && _props$width !== void 0 ? _props$width : fieldBlockContext !== null && fieldBlockContext !== void 0 && fieldBlockContext.composition ? 'stretch' : 'medium', innerRef: (_props$innerRef = props.innerRef) !== null && _props$innerRef !== void 0 ? _props$innerRef : ref }); const { id, name, className, innerRef, inputClassName, autoComplete, placeholder, value, startWith = null, minimum = defaultMinimum, maximum = defaultMaximum, disabled, htmlAttributes, hasError, size, width, align, handleFocus, handleBlur, handleChange, setDisplayValue } = useFieldProps(preparedProps); useEffect(() => { var _innerRef$current; setDisplayValue((_innerRef$current = innerRef.current) === null || _innerRef$current === void 0 ? void 0 : _innerRef$current.value); }, [innerRef, setDisplayValue, value]); const { handleSubmit } = dataContext !== null && dataContext !== void 0 ? dataContext : {}; const onKeyDownHandler = useCallback(e => { var _dataContext$props; const { event } = e; if (dataContext !== null && dataContext !== void 0 && (_dataContext$props = dataContext.props) !== null && _dataContext$props !== void 0 && _dataContext$props.isolate && event.key === 'Enter') { var _event$preventDefault; handleSubmit(); (_event$preventDefault = event.preventDefault) === null || _event$preventDefault === void 0 ? void 0 : _event$preventDefault.call(event); } if (!showStepControls) { return; } let numberValue = null; switch (event.key) { case 'ArrowUp': numberValue = clamp((value !== null && value !== void 0 ? value : startWith) + step, minimum, maximum); break; case 'ArrowDown': numberValue = clamp((value !== null && value !== void 0 ? value : startWith) - step, minimum, maximum); break; } if (numberValue !== null) { event.persist(); event.preventDefault(); handleChange({ numberValue }); } }, [dataContext === null || dataContext === void 0 ? void 0 : (_dataContext$props2 = dataContext.props) === null || _dataContext$props2 === void 0 ? void 0 : _dataContext$props2.isolate, handleChange, handleSubmit, maximum, minimum, showStepControls, startWith, step, value]); const fieldBlockProps = _objectSpread({ forId: id, className: classnames("dnb-forms-field-number dnb-input__border--tokens", className), contentClassName: classnames('dnb-forms-field-number__contents', showStepControls && 'dnb-forms-field-number__contents--has-controls', hasError && 'dnb-input__status--error', disabled && 'dnb-input--disabled'), width: (width === 'stretch' || fieldBlockContext !== null && fieldBlockContext !== void 0 && fieldBlockContext.composition) && !showStepControls ? width : undefined, contentWidth: width !== false ? width : undefined }, pickSpacingProps(props)); const increaseClickHandler = useCallback(() => { handleChange({ numberValue: clamp((value !== null && value !== void 0 ? value : startWith) + step, minimum, maximum) }); }, [handleChange, maximum, minimum, startWith, step, value]); const increaseProps = showStepControls && { 'aria-hidden': true, className: 'dnb-button--control-after', variant: 'secondary', icon: 'add', size: size || 'small', tabIndex: -1, disabled: disabled || value >= maximum, onClick: increaseClickHandler, title: sharedContext === null || sharedContext === void 0 ? void 0 : (_sharedContext$transl = sharedContext.translation.Slider.addTitle) === null || _sharedContext$transl === void 0 ? void 0 : _sharedContext$transl.replace('%s', String(value + step)) }; const decreaseClickHandler = useCallback(() => { handleChange({ numberValue: clamp((value !== null && value !== void 0 ? value : startWith) - step, minimum, maximum) }); }, [handleChange, maximum, minimum, startWith, step, value]); const decreaseProps = showStepControls && _objectSpread(_objectSpread({}, increaseProps), {}, { className: 'dnb-button--control-before', icon: 'subtract', size: size || 'small', disabled: disabled || value <= minimum, onClick: decreaseClickHandler, title: sharedContext === null || sharedContext === void 0 ? void 0 : (_sharedContext$transl2 = sharedContext.translation.Slider.subtractTitle) === null || _sharedContext$transl2 === void 0 ? void 0 : _sharedContext$transl2.replace('%s', String(value - step)) }); const prefix = typeof prefixProp === 'function' ? prefixProp(value) : prefixProp; const suffix = typeof suffixProp === 'function' ? suffixProp(value) : suffixProp; const maskProps = useMemo(() => { const mask_options = { prefix, suffix, decimalLimit, allowNegative, disallowLeadingZeroes }; if (currency) { return { as_currency: currency, mask_options, currency_mask: { currencyDisplay, decimalLimit } }; } if (percent) { return { as_percent: percent, mask_options }; } return { as_number: true, mask, number_mask: _objectSpread({}, mask_options) }; }, [currency, currencyDisplay, decimalLimit, mask, percent, prefix, suffix, allowNegative, disallowLeadingZeroes]); const ariaParams = showStepControls && { role: 'spinbutton', 'aria-valuemin': String(minimum), 'aria-valuemax': String(maximum), 'aria-valuenow': String(value), 'aria-valuetext': String(value) }; const inputProps = _objectSpread(_objectSpread(_objectSpread({ id, name, inner_ref: innerRef, autoComplete, className: classnames(`dnb-forms-field-number__input dnb-input--${size}`, inputClassName), step: showStepControls ? step : undefined, placeholder, value, align: showStepControls ? 'center' : align, onKeyDown: onKeyDownHandler, onFocus: handleFocus, onBlur: handleBlur, onChange: handleChange, disabled, status: hasError ? 'error' : undefined, stretch: Boolean(width) }, maskProps), htmlAttributes), ariaParams); if (showStepControls) { return React.createElement(FieldBlock, _extends({}, fieldBlockProps, { asFieldset: false }), React.createElement("span", { className: "dnb-input__border dnb-input__border--root" }, React.createElement(Button, decreaseProps), React.createElement(InputMasked, inputProps), React.createElement(Button, increaseProps))); } return React.createElement(FieldBlock, _extends({}, fieldBlockProps, { asFieldset: false }), React.createElement(InputMasked, inputProps)); } NumberComponent._supportsSpacingProps = true; export default NumberComponent; //# sourceMappingURL=Number.js.map