@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
333 lines (332 loc) • 13.3 kB
JavaScript
"use strict";
"use client";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.COPY_TOOLTIP_TIMEOUT = void 0;
var _react = _interopRequireWildcard(require("react"));
var _useMountEffect = _interopRequireDefault(require("../../shared/helpers/useMountEffect.js"));
var _useIsomorphicLayoutEffect = require("../../shared/helpers/useIsomorphicLayoutEffect.js");
var _clsx = _interopRequireDefault(require("clsx"));
var _withComponentMarkers = _interopRequireDefault(require("../../shared/helpers/withComponentMarkers.js"));
var _Context = _interopRequireDefault(require("../../shared/Context.js"));
var _useId = _interopRequireDefault(require("../../shared/helpers/useId.js"));
var _componentHelper = require("../../shared/component-helper.js");
var _helpers = require("../../shared/helpers.js");
var _SpacingUtils = require("../space/SpacingUtils.js");
var _SkeletonHelper = require("../skeleton/SkeletonHelper.js");
var _Tooltip = _interopRequireWildcard(require("../tooltip/Tooltip.js"));
var _index = require("./utils/index.js");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const COPY_TOOLTIP_TIMEOUT = exports.COPY_TOOLTIP_TIMEOUT = 3000;
const numberFormatDefaultProps = {
id: null,
value: null,
locale: null,
prefix: null,
suffix: null,
currency: null,
currencyDisplay: null,
currencyPosition: null,
compact: null,
monospace: false,
options: null,
decimals: null,
selectAll: true,
alwaysSelectAll: false,
copySelection: true,
cleanCopyValue: false,
rounding: null,
clean: null,
srLabel: null,
element: 'span',
tooltip: null,
skeleton: null,
className: null,
children: null
};
let hasiOSFix = false;
function runFix(comp, className) {
if (typeof comp === 'function') {
comp = comp();
}
if (_react.default.isValidElement(comp)) {
const elemProps = comp.props;
return _react.default.createElement(comp.type, {
...elemProps,
className: (0, _clsx.default)(elemProps.className, className)
});
}
return (0, _jsxRuntime.jsx)("span", {
className: className,
children: comp
});
}
function NumberFormat(ownProps) {
var _context$getTranslati3;
const context = (0, _react.useContext)(_Context.default);
const propsWithDefaults = {
...numberFormatDefaultProps,
...(0, _componentHelper.removeUndefinedProps)({
...ownProps
})
};
const propsWithDefaultsRef = (0, _react.useRef)(propsWithDefaults);
propsWithDefaultsRef.current = propsWithDefaults;
const elRef = (0, _react.useRef)(null);
const selectionRef = (0, _react.useRef)(null);
const generatedId = (0, _useId.default)(propsWithDefaults.id);
const copyTooltipTimeoutRef = (0, _react.useRef)(null);
const outsideClickRef = (0, _react.useRef)(null);
const cleanedValueRef = (0, _react.useRef)(undefined);
const [selected, setSelected] = (0, _react.useState)(false);
const [hover, setHover] = (0, _react.useState)(false);
const [copyTooltipActive, setCopyTooltipActive] = (0, _react.useState)(false);
const [copyTooltipText, setCopyTooltipText] = (0, _react.useState)(null);
const needsFocusRef = (0, _react.useRef)(false);
(0, _useMountEffect.default)(() => {
if (_helpers.IS_IOS && !hasiOSFix) {
hasiOSFix = true;
(0, _index.runIOSSelectionFix)();
}
return () => {
var _outsideClickRef$curr;
(_outsideClickRef$curr = outsideClickRef.current) === null || _outsideClickRef$curr === void 0 || _outsideClickRef$curr.remove();
if (copyTooltipTimeoutRef.current) {
clearTimeout(copyTooltipTimeoutRef.current);
}
};
});
const clearCopyTooltipTimeout = (0, _react.useCallback)(() => {
if (copyTooltipTimeoutRef.current) {
clearTimeout(copyTooltipTimeoutRef.current);
copyTooltipTimeoutRef.current = null;
}
}, []);
const onBlurHandler = (0, _react.useCallback)(() => {
setSelected(false);
}, []);
const doSelectAll = (0, _react.useCallback)(() => {
try {
const elem = selectionRef.current || elRef.current;
if (elem) {
const selection = window.getSelection();
const range = document.createRange();
range.selectNodeContents(elem);
selection.removeAllRanges();
selection.addRange(range);
}
} catch (e) {
(0, _componentHelper.warn)(e);
}
}, []);
const setFocus = (0, _react.useCallback)(() => {
if ((0, _componentHelper.isTouchDevice)()) {
return;
}
needsFocusRef.current = true;
setSelected(true);
}, []);
(0, _useIsomorphicLayoutEffect.useIsomorphicLayoutEffect)(() => {
if (selected && needsFocusRef.current) {
var _selectionRef$current;
needsFocusRef.current = false;
(_selectionRef$current = selectionRef.current) === null || _selectionRef$current === void 0 || _selectionRef$current.focus({
preventScroll: true
});
doSelectAll();
if (!propsWithDefaults.copySelection) {
outsideClickRef.current = (0, _componentHelper.detectOutsideClick)(elRef.current, onBlurHandler);
}
}
}, [selected, doSelectAll, onBlurHandler, propsWithDefaults.copySelection]);
const showCopyTooltip = (0, _react.useCallback)(message => {
var _context$getTranslati;
const translations = (_context$getTranslati = context.getTranslation) === null || _context$getTranslati === void 0 || (_context$getTranslati = _context$getTranslati.call(context, propsWithDefaultsRef.current)) === null || _context$getTranslati === void 0 ? void 0 : _context$getTranslati.NumberFormat;
const label = message || (translations === null || translations === void 0 ? void 0 : translations.clipboardCopy);
if (!label) {
return;
}
clearCopyTooltipTimeout();
setCopyTooltipActive(true);
setCopyTooltipText(label);
copyTooltipTimeoutRef.current = setTimeout(() => {
setCopyTooltipActive(false);
}, COPY_TOOLTIP_TIMEOUT);
}, [context, clearCopyTooltipTimeout]);
const shortcutHandler = (0, _react.useCallback)(() => {
var _context$getTranslati2;
const label = (_context$getTranslati2 = context.getTranslation) === null || _context$getTranslati2 === void 0 || (_context$getTranslati2 = _context$getTranslati2.call(context, propsWithDefaultsRef.current)) === null || _context$getTranslati2 === void 0 || (_context$getTranslati2 = _context$getTranslati2.NumberFormat) === null || _context$getTranslati2 === void 0 ? void 0 : _context$getTranslati2.clipboardCopy;
showCopyTooltip(label);
}, [context, showCopyTooltip]);
const onContextMenuHandler = (0, _react.useCallback)(() => {
if (!(0, _helpers.hasSelectedText)()) {
setFocus();
}
}, [setFocus]);
const onClickHandler = (0, _react.useCallback)(() => {
if ((propsWithDefaults.selectAll || propsWithDefaults.alwaysSelectAll) && !(0, _helpers.hasSelectedText)()) {
setFocus();
}
}, [propsWithDefaults.selectAll, propsWithDefaults.alwaysSelectAll, setFocus]);
const onMouseEnter = (0, _react.useCallback)(() => {
setHover(true);
}, []);
const onMouseLeave = (0, _react.useCallback)(() => {
setHover(false);
}, []);
const translations = (_context$getTranslati3 = context.getTranslation) === null || _context$getTranslati3 === void 0 || (_context$getTranslati3 = _context$getTranslati3.call(context, propsWithDefaults)) === null || _context$getTranslati3 === void 0 ? void 0 : _context$getTranslati3.NumberFormat;
const props = (0, _componentHelper.extendExistingPropsWithContext)(propsWithDefaults, numberFormatDefaultProps, translations, context === null || context === void 0 ? void 0 : context.NumberFormat);
const {
id,
value: _value,
prefix,
suffix,
children,
currency,
currencyDisplay,
currencyPosition,
compact,
monospace,
tooltip,
skeleton,
options,
locale,
decimals,
rounding,
signDisplay,
clean,
selectAll: selectAllProp,
copySelection,
cleanCopyValue,
srLabel,
element,
className,
alwaysSelectAll,
__format,
..._rest
} = props;
let rest = _rest;
let value = _value !== null && _value !== void 0 ? _value : null;
if (value === null && children !== null) {
value = children;
}
let usedCurrencyPosition = currencyPosition;
if (currencyDisplay === 'code' && !usedCurrencyPosition) {
usedCurrencyPosition = 'before';
}
const formatOptions = {
locale,
currency,
currencyDisplay,
currencyPosition: usedCurrencyPosition,
compact,
decimals,
rounding,
signDisplay,
options,
clean: clean,
cleanCopyValue: cleanCopyValue,
returnAria: true,
invalidAriaText: locale && locale !== context.locale ? null : translations === null || translations === void 0 ? void 0 : translations.notAvailable
};
const useCtx = (0, _componentHelper.extendDeep)({
locale: null,
currency: null
}, context);
if (useCtx) {
if (useCtx.locale && !locale) {
formatOptions.locale = useCtx.locale;
}
if (useCtx.currency && currency === true) {
formatOptions.options = formatOptions.options ? {
...formatOptions.options
} : {};
formatOptions.options.currency = useCtx.currency;
}
}
const formatter = __format !== null && __format !== void 0 ? __format : currency === true || typeof currency === 'string' ? _index.formatCurrency : _index.formatNumber;
const result = formatter(value, formatOptions);
const {
cleanedValue,
locale: lang
} = result;
let {
aria
} = result;
let display = result.number;
cleanedValueRef.current = cleanedValue;
if (prefix) {
display = (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [runFix(prefix, 'dnb-number-format__prefix'), " ", display]
});
aria = String(`${(0, _componentHelper.convertJsxToString)(runFix(prefix, 'dnb-number-format__prefix'))} ${aria}`);
}
if (suffix) {
const suffixElement = runFix(suffix, 'dnb-number-format__suffix');
const suffixStartsWithSlash = typeof suffix === 'string' && suffix.startsWith('/');
const suffixSpace = suffixStartsWithSlash ? '' : ' ';
display = (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [display, suffixSpace, suffixElement]
});
aria = `${aria}${suffixSpace}${(0, _componentHelper.convertJsxToString)(suffixElement)}`;
}
if (tooltip) {
rest = (0, _Tooltip.injectTooltipSemantic)(rest);
}
const attributes = (0, _SpacingUtils.applySpacing)(ownProps, {
lang,
ref: elRef,
className: (0, _clsx.default)('dnb-number-format', className, (currency === true || typeof currency === 'string') && 'dnb-number-format--currency', selectAllProp && 'dnb-number-format--select-all', selected && 'dnb-number-format--selected', monospace && 'dnb-number-format--monospace'),
onMouseEnter,
onMouseLeave,
...rest
});
const displayParams = {};
if (selectAllProp || copySelection) {
displayParams.onClick = onClickHandler;
displayParams.onContextMenu = onContextMenuHandler;
}
(0, _componentHelper.validateDOMAttributes)(ownProps, attributes);
(0, _SkeletonHelper.skeletonDOMAttributes)(attributes, skeleton, context);
const Element = element;
return (0, _jsxRuntime.jsxs)(Element, {
...attributes,
children: [(0, _jsxRuntime.jsx)("span", {
className: (0, _clsx.default)('dnb-number-format__visible', (0, _SkeletonHelper.createSkeletonClass)('font', skeleton, context)),
"aria-hidden": !hover,
...displayParams,
children: display
}), (0, _jsxRuntime.jsx)("span", {
className: "dnb-sr-only",
"data-text": srLabel ? `${(0, _componentHelper.convertJsxToString)(srLabel)}${'\u00a0'}${aria}` : aria
}), copySelection && (0, _jsxRuntime.jsx)("span", {
className: "dnb-number-format__selection dnb-no-focus",
ref: selectionRef,
tabIndex: -1,
onBlur: onBlurHandler,
onCopy: shortcutHandler,
"aria-hidden": true,
children: selected && cleanedValue
}), tooltip && (0, _jsxRuntime.jsx)(_Tooltip.default, {
id: generatedId + '-tooltip',
targetElement: elRef,
tooltip: tooltip
}), copyTooltipActive && (0, _jsxRuntime.jsx)(_Tooltip.default, {
open: copyTooltipActive,
targetElement: elRef,
showDelay: 0,
hideDelay: 0,
triggerOffset: 8,
children: copyTooltipText
})]
});
}
const MemoizedNumberFormat = _react.default.memo(NumberFormat);
(0, _withComponentMarkers.default)(MemoizedNumberFormat, {
_supportsSpacingProps: true
});
var _default = exports.default = MemoizedNumberFormat;
//# sourceMappingURL=NumberFormatBase.js.map