@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
239 lines (238 loc) • 10.1 kB
JavaScript
"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