UNPKG

@dnb/eufemia

Version:

DNB Eufemia Design System UI Library

401 lines (400 loc) 19.4 kB
"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