@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
401 lines (400 loc) • 19.4 kB
JavaScript
"use strict";
"use client";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
require("core-js/modules/es.string.replace.js");
require("core-js/modules/web.dom-collections.iterator.js");
var _react = _interopRequireWildcard(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _componentHelper = require("../../shared/component-helper");
var _AlignmentHelper2 = _interopRequireDefault(require("../../shared/AlignmentHelper"));
var _SpacingHelper = require("../space/SpacingHelper");
var _SkeletonHelper = require("../skeleton/SkeletonHelper");
var _Context = _interopRequireDefault(require("../../shared/Context"));
var _Suffix = _interopRequireDefault(require("../../shared/helpers/Suffix"));
var _FormLabel = _interopRequireDefault(require("../form-label/FormLabel"));
var _FormStatus = _interopRequireDefault(require("../form-status/FormStatus"));
var _DatePickerProvider = _interopRequireDefault(require("./DatePickerProvider"));
var _DatePickerRange = _interopRequireDefault(require("./DatePickerRange"));
var _DatePickerInput = _interopRequireDefault(require("./DatePickerInput"));
var _DatePickerAddon = _interopRequireDefault(require("./DatePickerAddon"));
var _DatePickerFooter = _interopRequireDefault(require("./DatePickerFooter"));
var _filterValidProps = require("../../shared/helpers/filterValidProps");
var _shared = require("../../shared");
var _withSnakeCaseProps = require("../../shared/helpers/withSnakeCaseProps");
var _DatePickerPortal = _interopRequireDefault(require("./DatePickerPortal"));
var _DateFormatUtils = require("../date-format/DateFormatUtils");
var _AlignmentHelper;
const _excluded = ["hidePicker"],
_excluded2 = ["label", "title", "labelDirection", "labelSrOnly", "onlyMonth", "hideLastWeek", "disableAutofocus", "firstDay", "resetDate", "link", "sync", "inputElement", "addonElement", "shortcuts", "disabled", "stretch", "skeleton", "size", "status", "statusState", "statusProps", "statusNoAnimation", "globalStatus", "suffix", "maskOrder", "maskPlaceholder", "submitButtonText", "cancelButtonText", "resetButtonText", "showResetButton", "className", "tooltip", "skipPortal", "labelAlignment"];
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
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; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
const defaultProps = {
hideNavigation: false,
hideDays: false,
onlyMonth: false,
hideLastWeek: false,
disableAutofocus: false,
enableKeyboardNav: false,
showInput: false,
resetDate: true,
range: false,
link: false,
sync: true,
statusState: 'error',
opened: false,
noAnimation: false,
direction: 'auto',
skipPortal: false,
yearNavigation: false
};
function DatePicker(externalProps) {
const props = _objectSpread(_objectSpread({}, defaultProps), externalProps);
const {
preventClose,
onHide,
onShow,
onSubmit,
onCancel,
onReset,
noAnimation,
showInput,
alignPicker,
showSubmitButton,
showCancelButton,
range,
hideDays,
hideNavigation,
correctInvalidDate,
opened: openedProp,
endDate: endDateProp
} = (0, _withSnakeCaseProps.convertSnakeCaseProps)(props);
const [opened, setOpened] = (0, _react.useState)(openedProp);
const [hidden, setHidden] = (0, _react.useState)(!opened);
const [dates, setDates] = (0, _react.useState)({});
const context = (0, _react.useContext)(_Context.default);
const blurDelay = 201;
const id = props.id || (0, _componentHelper.makeUniqueId)();
const innerRef = (0, _react.useRef)();
const triangleRef = (0, _react.useRef)();
const submitButtonRef = (0, _react.useRef)();
const getReturnObject = (0, _react.useRef)();
const hideTimeout = (0, _react.useRef)();
const outsideClick = (0, _react.useRef)();
const calendarContainerRef = (0, _react.useRef)();
const translation = (0, _shared.useTranslation)().DatePicker;
if (correctInvalidDate) {
(0, _componentHelper.warn)(`Use 'Field.Date' instead, for built in validation (https://eufemia.dnb.no/uilib/extensions/forms/feature-fields/Date/#date-limit-validation).`);
}
if (endDateProp && !range) {
(0, _componentHelper.warn)(`The DatePicker got a "endDate". You have to set range={true} as well!.`);
}
const removeOutsideClickHandler = (0, _react.useCallback)(() => {
if (outsideClick.current) {
outsideClick.current.remove();
}
}, []);
const hidePicker = (0, _react.useCallback)(args => {
if (preventClose) {
return;
}
if (args && args.event && args.event.persist) {
args.event.persist();
}
setOpened(false);
hideTimeout.current = setTimeout(() => {
setHidden(true);
onHide === null || onHide === void 0 ? void 0 : onHide(_objectSpread({}, getReturnObject.current(args)));
if (args !== null && args !== void 0 && args['focusOnHide']) {
try {
submitButtonRef.current.focus({
preventScroll: true
});
} catch (e) {
(0, _componentHelper.warn)(e);
}
}
}, noAnimation ? 1 : blurDelay);
removeOutsideClickHandler();
}, [noAnimation, preventClose, onHide, removeOutsideClickHandler]);
const setOutsideClickHandler = (0, _react.useCallback)(() => {
outsideClick.current = (0, _componentHelper.detectOutsideClick)([innerRef.current, calendarContainerRef], _ref => {
let {
event
} = _ref;
hidePicker(_objectSpread(_objectSpread({}, event), {}, {
focusOnHide: event === null || event === void 0 ? void 0 : event['code']
}));
});
}, [hidePicker]);
const setTrianglePosition = (0, _react.useCallback)(() => {
const triangleWidth = 16;
if (showInput && triangleRef.current && innerRef.current) {
try {
const shellWidth = innerRef.current.querySelector('.dnb-input__shell').getBoundingClientRect().width;
const buttonWidth = innerRef.current.querySelector('.dnb-input__submit-button__button').getBoundingClientRect().width;
if (alignPicker === 'right') {
const distance = buttonWidth / 2 - triangleWidth / 2;
triangleRef.current.style.marginRight = `${distance / 16}rem`;
} else {
const distance = shellWidth - buttonWidth / 2 - triangleWidth / 2;
triangleRef.current.style.marginLeft = `${distance / 16}rem`;
}
} catch (e) {
(0, _componentHelper.warn)(e);
}
}
}, [showInput, alignPicker]);
const showPicker = (0, _react.useCallback)(event => {
if (hideTimeout.current) {
clearTimeout(hideTimeout.current);
}
setOpened(true);
setHidden(false);
onShow === null || onShow === void 0 ? void 0 : onShow(_objectSpread({}, getReturnObject.current(event)));
setOutsideClickHandler();
}, [setOutsideClickHandler, onShow]);
(0, _react.useLayoutEffect)(() => {
if (!hidden) {
setTrianglePosition();
}
}, [hidden, setTrianglePosition]);
(0, _react.useEffect)(() => {
if (openedProp) {
showPicker();
}
}, [openedProp, showPicker]);
const onPickerChange = (0, _react.useCallback)(_ref2 => {
let {
hidePicker: shouldHidePicker = true
} = _ref2,
args = _objectWithoutProperties(_ref2, _excluded);
if (shouldHidePicker && !showSubmitButton && !showCancelButton) {
hidePicker({
focusOnHide: true
});
}
setDates({
startDate: args.startDate,
endDate: args.endDate
});
}, [hidePicker, showSubmitButton, showCancelButton]);
const onSubmitHandler = (0, _react.useCallback)(event => {
hidePicker(event);
onSubmit === null || onSubmit === void 0 ? void 0 : onSubmit(_objectSpread({}, getReturnObject.current({
event
})));
}, [hidePicker, onSubmit]);
const onCancelHandler = (0, _react.useCallback)(event => {
hidePicker();
onCancel === null || onCancel === void 0 ? void 0 : onCancel(_objectSpread({}, getReturnObject.current(event)));
}, [hidePicker, onCancel]);
const onResetHandler = (0, _react.useCallback)(event => {
hidePicker();
onReset === null || onReset === void 0 ? void 0 : onReset(_objectSpread({}, getReturnObject.current(event)));
}, [hidePicker, onReset]);
const togglePicker = (0, _react.useCallback)(args => {
!opened ? showPicker(args) : hidePicker(args);
}, [opened, showPicker, hidePicker]);
const extendedProps = (0, _componentHelper.extendPropsWithContext)(props, defaultProps, {
skeleton: context === null || context === void 0 ? void 0 : context.skeleton
}, (0, _withSnakeCaseProps.convertSnakeCaseProps)(context.getTranslation(props).DatePicker), (0, _filterValidProps.pickFormElementProps)(context === null || context === void 0 ? void 0 : context.FormRow), (0, _withSnakeCaseProps.convertSnakeCaseProps)((0, _filterValidProps.pickFormElementProps)(context === null || context === void 0 ? void 0 : context.formElement)), context.DatePicker);
const {
label,
title,
labelDirection,
labelSrOnly,
onlyMonth,
hideLastWeek,
disableAutofocus,
firstDay,
resetDate,
link,
sync,
inputElement,
addonElement,
shortcuts,
disabled,
stretch,
skeleton,
size,
status,
statusState,
statusProps,
statusNoAnimation,
globalStatus,
suffix,
maskOrder,
maskPlaceholder,
submitButtonText,
cancelButtonText,
resetButtonText,
showResetButton,
className,
tooltip,
skipPortal,
labelAlignment
} = extendedProps,
restProps = _objectWithoutProperties(extendedProps, _excluded2);
const attributes = (0, _react.useMemo)(() => filterOutNonAttributes(restProps), [restProps]);
const showStatus = (0, _componentHelper.getStatusState)(status);
const pickerParams = {};
if (showStatus || suffix) {
pickerParams['aria-describedby'] = (0, _componentHelper.combineDescribedBy)(pickerParams, showStatus ? id + '-status' : null, suffix ? id + '-suffix' : null);
}
const submitParams = {
['aria-expanded']: opened,
ref: submitButtonRef,
tabIndex: extendedProps.tabIndex,
tooltip
};
const selectedDateTitle = (0, _react.useMemo)(() => {
const {
selectedDate,
selectedDateRange
} = translation;
const {
startDate,
endDate
} = dates;
if (!startDate) {
return '';
}
const options = {
locale: context.locale,
options: {
dateStyle: 'full'
}
};
return range && endDate ? selectedDateRange.replace(/%s/, (0, _DateFormatUtils.formatDateRange)({
startDate,
endDate
}, options)) : selectedDate.replace(/%s/, (0, _DateFormatUtils.formatDate)(startDate, options));
}, [range, translation, dates, context.locale]);
const mainParams = {
className: (0, _classnames.default)("dnb-date-picker dnb-form-component", (range || showSubmitButton || showCancelButton || showResetButton) && 'dnb-date-picker--show-footer', (0, _SpacingHelper.createSpacingClasses)(props), className, status && `dnb-date-picker__status--${statusState}`, labelDirection && `dnb-date-picker--${labelDirection}`, opened && 'dnb-date-picker--opened', hidden && 'dnb-date-picker--hidden', showInput && 'dnb-date-picker--show-input', label && labelAlignment === 'right' && 'dnb-date-picker__input--label-alignment-right', alignPicker && `dnb-date-picker--${alignPicker}`, stretch && `dnb-date-picker--stretch`, size && `dnb-date-picker--${size}`),
lang: context.locale
};
const containerClassNames = (0, _classnames.default)('dnb-date-picker__container', opened ? 'dnb-date-picker__container--opened' : 'dnb-date-picker__container--closed', hidden && 'dnb-date-picker__container--hidden', showInput && 'dnb-date-picker__container--show-input', alignPicker && `dnb-date-picker__container--${alignPicker}`, size && `dnb-date-picker--${size}`);
const remainingDOMProps = (0, _componentHelper.validateDOMAttributes)(props, attributes);
const remainingSubmitProps = (0, _componentHelper.validateDOMAttributes)(null, submitParams);
const remainingPickerProps = (0, _componentHelper.validateDOMAttributes)(null, (0, _SkeletonHelper.skeletonDOMAttributes)(pickerParams, skeleton, context));
return _react.default.createElement(_DatePickerProvider.default, _extends({}, props, {
attributes: remainingDOMProps,
setReturnObject: fn => getReturnObject.current = fn,
hidePicker: hidePicker
}), _react.default.createElement("span", mainParams, label && _react.default.createElement(_FormLabel.default, {
id: id + '-label',
forId: id,
text: label,
labelDirection: labelDirection,
srOnly: labelSrOnly,
disabled: disabled,
skeleton: skeleton
}), _react.default.createElement("span", _extends({
className: "dnb-date-picker__inner",
ref: innerRef
}, remainingPickerProps), _AlignmentHelper || (_AlignmentHelper = _react.default.createElement(_AlignmentHelper2.default, null)), _react.default.createElement(_FormStatus.default, _extends({
show: showStatus,
id: id + '-form-status',
globalStatus: globalStatus,
label: String(label),
text_id: id + '-status',
width_selector: id + '-shell',
text: status,
state: statusState,
no_animation: statusNoAnimation,
skeleton: skeleton
}, statusProps)), _react.default.createElement("span", {
className: "dnb-date-picker__row"
}, _react.default.createElement("span", {
className: "dnb-date-picker__shell",
id: `${id}-shell`
}, _react.default.createElement(_DatePickerInput.default, _extends({
id: id,
title: title,
disabled: disabled,
stretch: stretch,
skeleton: skeleton,
maskOrder: maskOrder,
maskPlaceholder: maskPlaceholder,
isRange: range,
showInput: showInput,
selectedDateTitle: selectedDateTitle,
inputElement: inputElement,
opened: opened,
hidden: hidden,
size: size,
status: status ? 'error' : null,
statusState: statusState,
lang: context.locale
}, attributes, {
submitAttributes: remainingSubmitProps,
onSubmit: togglePicker
}, statusProps)), !hidden && _react.default.createElement(_DatePickerPortal.default, {
alignment: alignPicker,
skipPortal: skipPortal,
targetElementRef: innerRef
}, _react.default.createElement("span", {
className: containerClassNames,
ref: calendarContainerRef
}, _react.default.createElement("span", {
className: "dnb-date-picker__triangle",
ref: triangleRef
}), _react.default.createElement(_DatePickerRange.default, {
id: id,
firstDayOfWeek: firstDay,
resetDate: resetDate,
isRange: range,
isLink: link,
isSync: sync,
hideDays: hideDays,
hideNavigation: hideNavigation,
onlyMonth: onlyMonth,
hideNextMonthWeek: hideLastWeek,
noAutoFocus: disableAutofocus,
onPickerChange: onPickerChange,
locale: context.locale
}), (addonElement || shortcuts) && _react.default.createElement(_DatePickerAddon.default, {
renderElement: addonElement,
shortcuts: shortcuts
}), _react.default.createElement(_DatePickerFooter.default, {
isRange: range,
onSubmit: onSubmitHandler,
onCancel: onCancelHandler,
onReset: onResetHandler,
submitButtonText: submitButtonText,
cancelButtonText: cancelButtonText,
resetButtonText: resetButtonText
})))), suffix && _react.default.createElement(_Suffix.default, {
className: "dnb-date-picker__suffix",
id: id + '-suffix',
context: props
}, suffix))), _react.default.createElement("p", {
className: "dnb-sr-only",
"aria-live": "assertive"
}, selectedDateTitle)));
}
const NonAttributes = ['locale', 'id', 'month', 'date', 'startDate', 'endDate', 'minDate', 'maxDate', 'enableKeyboardNav', 'hideNavigation', 'returnFormat', 'dateFormat', 'hideDays', 'correctInvalidDate', 'opened', 'direction', 'range', 'showInput', 'noAnimation', 'onDaysRender', 'onShow', 'onType', 'onHide', 'showSubmitButton', 'showCancelButton', 'selectedDate', 'selectedMonth', 'selectedYear', 'nextMonth', 'nextYear', 'openPickerText', 'placeholderCharacters', 'prevMonth', 'prevYear', 'endMonth', 'startMonth', 'alignPicker', 'preventClose', 'selectedDateRange', 'yearNavigation'];
function filterOutNonAttributes(props) {
return Object.keys(props).reduce((attributes, key) => {
if (!NonAttributes.includes(key)) {
attributes[key] = props[key];
}
return attributes;
}, {});
}
var _default = exports.default = DatePicker;
DatePicker._supportsSpacingProps = true;
//# sourceMappingURL=DatePicker.js.map