UNPKG

suomifi-ui-components

Version:
354 lines (348 loc) 16 kB
'use strict'; var tslib = require('tslib'); var React = require('react'); var styled = require('styled-components'); var classnames = require('classnames'); var suomifiIcons = require('suomifi-icons'); var AutoId = require('../../utils/AutoId/AutoId.js'); var SuomifiThemeProvider = require('../../theme/SuomifiThemeProvider/SuomifiThemeProvider.js'); require('../../theme/SuomifiTheme/SuomifiTheme.js'); var SpacingProvider = require('../../theme/SpacingProvider/SpacingProvider.js'); var Debounce = require('../../utils/Debounce/Debounce.js'); var aria = require('../../../utils/aria/aria.js'); var logger = require('../../../utils/log/logger.js'); var common = require('../../../utils/common/common.js'); require('../../../reset/HtmlA/HtmlA.js'); var HtmlButton = require('../../../reset/HtmlButton/HtmlButton.js'); var HtmlDiv = require('../../../reset/HtmlDiv/HtmlDiv.js'); require('../../../reset/HtmlFieldSet/HtmlFieldSet.js'); require('../../../reset/HtmlH/HtmlH.js'); var HtmlInput = require('../../../reset/HtmlInput/HtmlInput.js'); require('../../../reset/HtmlLabel/HtmlLabel.js'); require('../../../reset/HtmlLegend/HtmlLegend.js'); require('../../../reset/HtmlLi/HtmlLi.js'); require('../../../reset/HtmlNav/HtmlNav.js'); require('../../../reset/HtmlOl/HtmlOl.js'); require('../../../reset/HtmlSpan/HtmlSpan.js'); require('../../../reset/HtmlTextarea/HtmlTextarea.js'); require('../../../reset/HtmlUl/HtmlUl.js'); require('../../../reset/HtmlTable/HtmlTable.js'); require('../../../reset/HtmlTable/HtmlTableCaption.js'); require('../../../reset/HtmlTable/HtmlTableHeader.js'); require('../../../reset/HtmlTable/HtmlTableRow.js'); require('../../../reset/HtmlTable/HtmlTableBody.js'); require('../../../reset/HtmlTable/HtmlTableHeaderCell.js'); require('../../../reset/HtmlTable/HtmlTableCell.js'); var DatePicker = require('./DatePicker/DatePicker.js'); var Label = require('../Label/Label.js'); var StatusText = require('../StatusText/StatusText.js'); var HintText = require('../HintText/HintText.js'); var VisuallyHidden = require('../../VisuallyHidden/VisuallyHidden.js'); var DateInput_baseStyles = require('./DateInput.baseStyles.js'); var datePickerTexts = require('./datePickerTexts.js'); var dateUtils = require('./dateUtils.js'); var spacing = require('../../theme/utils/spacing.js'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var React__default = /*#__PURE__*/_interopDefault(React); var classnames__default = /*#__PURE__*/_interopDefault(classnames); var baseClassName = 'fi-date-input'; var dateInputClassNames = { baseClassName: baseClassName, fullWidth: "".concat(baseClassName, "--full-width"), hasPicker: "".concat(baseClassName, "--has-picker"), disabled: "".concat(baseClassName, "--disabled"), error: "".concat(baseClassName, "--error"), success: "".concat(baseClassName, "--success"), labelIsVisible: "".concat(baseClassName, "_label--visible"), inputAndPickerWrapper: "".concat(baseClassName, "_input-and-picker-wrapper"), inputElementContainer: "".concat(baseClassName, "_input-element-container"), inputElement: "".concat(baseClassName, "_input"), pickerElementContainer: "".concat(baseClassName, "_picker-element-container"), pickerButton: "".concat(baseClassName, "_picker-button"), pickerButtonDisabled: "".concat(baseClassName, "_picker-button--disabled"), pickerIcon: "".concat(baseClassName, "_picker-icon"), styleWrapper: "".concat(baseClassName, "_wrapper"), statusTextHasContent: "".concat(baseClassName, "_statusText--has-content") }; var BaseDateInput = function BaseDateInput(props) { var _a, _b, _c, _d; var className = props.className, labelText = props.labelText, labelMode = props.labelMode, propOnChange = props.onChange, onDatePickerButtonBlur = props.onDatePickerButtonBlur, optionalText = props.optionalText, status = props.status, statusText = props.statusText, hintText = props.hintText, visualPlaceholder = props.visualPlaceholder, id = props.id, fullWidth = props.fullWidth, forwardedRef = props.forwardedRef, debounce = props.debounce, _e = props.statusTextAriaLiveMode, statusTextAriaLiveMode = _e === void 0 ? 'assertive' : _e, ariaDescribedBy = props["aria-describedby"], defaultValue = props.defaultValue, value = props.value, _f = props.datePickerEnabled, datePickerEnabled = _f === void 0 ? false : _f, customDatePickerProps = props.datePickerProps, _g = props.datePickerPosition, datePickerPosition = _g === void 0 ? 'left' : _g, _h = props.smallScreen, smallScreen = _h === void 0 ? false : _h, _j = props.datePickerTexts, datePickerTexts$1 = _j === void 0 ? undefined : _j, _k = props.language, language = _k === void 0 ? datePickerTexts.defaultLanguage : _k, _l = props.dateAdapter, dateAdapter = _l === void 0 ? dateUtils.defaultDateAdapter() : _l, shouldDisableDate = props.shouldDisableDate, userMinDate = props.minDate, userMaxDate = props.maxDate, initialDate = props.initialDate, tooltipComponent = props.tooltipComponent, style = props.style, rest = tslib.__rest(props, ["className", "labelText", "labelMode", "onChange", "onDatePickerButtonBlur", "optionalText", "status", "statusText", "hintText", "visualPlaceholder", "id", "fullWidth", "forwardedRef", "debounce", "statusTextAriaLiveMode", 'aria-describedby', "defaultValue", "value", "datePickerEnabled", "datePickerProps", "datePickerPosition", "smallScreen", "datePickerTexts", "language", "dateAdapter", "shouldDisableDate", "minDate", "maxDate", "initialDate", "tooltipComponent", "style"]); var defaultMinDate = dateUtils.moveYears(dateUtils.firstDayOfMonth(new Date()), -10); var defaultMaxDate = dateUtils.moveYears(dateUtils.lastDayOfMonth(new Date()), 10); var userProvidedMinDate = userMinDate; var userProvidedMaxDate = userMaxDate; var effectiveMinDate; var effectiveMaxDate; if (userProvidedMinDate && userProvidedMaxDate) { effectiveMinDate = userProvidedMinDate; effectiveMaxDate = userProvidedMaxDate; } else if (userProvidedMinDate && !userProvidedMaxDate) { effectiveMinDate = userProvidedMinDate; effectiveMaxDate = userProvidedMinDate > defaultMaxDate ? dateUtils.moveYears(userProvidedMinDate, 10) : defaultMaxDate; } else if (!userProvidedMinDate && userProvidedMaxDate) { effectiveMaxDate = userProvidedMaxDate; effectiveMinDate = userProvidedMaxDate < defaultMinDate ? dateUtils.moveYears(userProvidedMaxDate, -10) : defaultMinDate; } else { effectiveMinDate = defaultMinDate; effectiveMaxDate = defaultMaxDate; } var _m = spacing.separateMarginProps(rest), passProps = _m[1]; var hintTextId = "".concat(id, "-hintText"); var statusTextId = "".concat(id, "-statusText"); var inputRef = React.useRef(); var openButtonRef = React.useRef(null); var _o = React.useState(''), inputValue = _o[0], setInputValue = _o[1]; var _p = React.useState(''), buttonDateLabel = _p[0], setButtonDateLabel = _p[1]; var _q = React.useState(null), inputValueAsDate = _q[0], setInputValueAsDate = _q[1]; var _r = React.useState(false), calendarVisible = _r[0], setCalendarVisible = _r[1]; var _s = React.useState(datePickerTexts.datePickerDefaultTexts.fi), texts = _s[0], setTexts = _s[1]; var definedRef = forwardedRef || null; React.useEffect(function () { if (defaultValue) { setInputValue(String(defaultValue)); } }, []); React.useEffect(function () { var useValue = 'value' in props && value ? value : inputValue; if (useValue) { var date = validateDatePickerValue(useValue); if (date) { setButtonDateLabel("".concat(texts.openButtonLabel, ", ").concat(texts.selectedDateLabel, " ").concat(dateUtils.cellDateAriaLabel(date, texts))); } } }, [value, inputValue]); React.useEffect(function () { var lang; if (datePickerTexts.languages.includes(language)) { lang = language; } else { lang = datePickerTexts.defaultLanguage; logger.getLogger().warn("Language \"".concat(language, "\" is not supported")); } setTexts(tslib.__assign(tslib.__assign({}, datePickerTexts.datePickerDefaultTexts[lang]), datePickerTexts$1)); }, [language, datePickerTexts$1]); var toggleCalendar = function toggleCalendar(open, focus) { var _a, _b; if (focus === void 0) { focus = false; } setCalendarVisible(open); if (open) { updateInputValueAsDate(((_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.value) || null); } if (!open && focus) { (_b = openButtonRef.current) === null || _b === void 0 ? void 0 : _b.focus(); } }; var conditionalSetInputValue = function conditionalSetInputValue(newValue) { if (!('value' in props)) { setInputValue(newValue); } }; var validateDatePickerValue = function validateDatePickerValue(newValue) { var date = dateAdapter.parse(newValue); if (Number.isNaN(date.valueOf())) { logger.getLogger().warn("Date input value \"".concat(newValue, "\" could not be parsed to Date")); return null; } if (!dateUtils.dayIsInRange(date, effectiveMinDate, effectiveMaxDate)) { logger.getLogger().warn("Date input value \"".concat(newValue, "\" is not within interval [minDate, maxDate]")); return null; } return date; }; var updateInputValueAsDate = function updateInputValueAsDate(newValue) { if (newValue === null) { setInputValueAsDate(newValue); } else { var date = validateDatePickerValue(newValue); setInputValueAsDate(date); } }; var onDatePickerChange = function onDatePickerChange(date) { if (passProps.disabled) { return; } var newValue = dateAdapter.format(date); conditionalSetInputValue(newValue); if (propOnChange) { propOnChange({ value: newValue, date: date }); } }; return /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDiv, { className: classnames__default.default(baseClassName, className, (_a = {}, _a[dateInputClassNames.disabled] = !!passProps.disabled, _a[dateInputClassNames.error] = status === 'error', _a[dateInputClassNames.success] = status === 'success', _a[dateInputClassNames.fullWidth] = fullWidth, _a[dateInputClassNames.hasPicker] = datePickerEnabled, _a)), style: style }, /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDiv, { className: dateInputClassNames.styleWrapper }, /*#__PURE__*/React__default.default.createElement(Label.Label, { htmlFor: id, labelMode: labelMode, optionalText: optionalText, className: classnames__default.default((_b = {}, _b[dateInputClassNames.labelIsVisible] = labelMode !== 'hidden', _b)), tooltipComponent: tooltipComponent }, labelText), /*#__PURE__*/React__default.default.createElement(HintText.HintText, { id: hintTextId }, hintText), /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDiv, { className: dateInputClassNames.inputAndPickerWrapper }, /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDiv, { className: dateInputClassNames.inputElementContainer }, /*#__PURE__*/React__default.default.createElement(Debounce.Debounce, { waitFor: debounce }, function (debouncer) { return /*#__PURE__*/React__default.default.createElement(HtmlInput.HtmlInput, tslib.__assign({ autoComplete: "off" }, passProps, { value: 'value' in props ? value : inputValue, id: id, className: dateInputClassNames.inputElement, forwardedRef: common.forkRefs(inputRef, definedRef), placeholder: visualPlaceholder, "aria-invalid": status === 'error' ? true : undefined }, aria.getConditionalAriaProp('aria-describedby', [statusText ? statusTextId : undefined, hintText ? hintTextId : undefined, ariaDescribedBy]), { onChange: function onChange(event) { var eventValue = event.currentTarget.value; conditionalSetInputValue(eventValue); if (propOnChange) { debouncer(propOnChange, { value: eventValue, date: dateAdapter.parse(eventValue) }); } } })); })), datePickerEnabled && ( /*#__PURE__*/React__default.default.createElement(HtmlDiv.HtmlDiv, { className: dateInputClassNames.pickerElementContainer }, /*#__PURE__*/React__default.default.createElement(HtmlButton.HtmlButton, { forwardedRef: openButtonRef, className: classnames__default.default(dateInputClassNames.pickerButton, (_c = {}, _c[dateInputClassNames.pickerButtonDisabled] = passProps.disabled, _c)), onClick: function onClick() { return toggleCalendar(!calendarVisible); }, disabled: passProps.disabled, onBlur: function onBlur(event) { if (!!onDatePickerButtonBlur) { onDatePickerButtonBlur(event); } } }, /*#__PURE__*/React__default.default.createElement(VisuallyHidden.VisuallyHidden, null, buttonDateLabel || texts.openButtonLabel), /*#__PURE__*/React__default.default.createElement(suomifiIcons.IconCalendar, { className: dateInputClassNames.pickerIcon, "aria-hidden": true })), /*#__PURE__*/React__default.default.createElement(DatePicker.DatePicker, { openButtonRef: openButtonRef, isOpen: calendarVisible, onClose: function onClose(focus) { return toggleCalendar(false, focus); }, onChange: function onChange(eventValue) { return onDatePickerChange(eventValue); }, shouldDisableDate: shouldDisableDate, initialDate: initialDate, inputValue: inputValueAsDate, texts: texts, minDate: effectiveMinDate, maxDate: effectiveMaxDate, smallScreen: smallScreen, userProps: customDatePickerProps, position: datePickerPosition })))), /*#__PURE__*/React__default.default.createElement(StatusText.StatusText, { id: statusTextId, className: classnames__default.default((_d = {}, _d[dateInputClassNames.statusTextHasContent] = !!statusText, _d)), status: status, ariaLiveMode: statusTextAriaLiveMode, disabled: passProps.disabled }, statusText))); }; var StyledDateInput = styled.styled(function (_a) { _a.theme; _a.globalMargins; var passProps = tslib.__rest(_a, ["theme", "globalMargins"]); return /*#__PURE__*/React__default.default.createElement(BaseDateInput, tslib.__assign({}, passProps)); }).withConfig({ componentId: "sc-1ix9bm-0" })(templateObject_1 || (templateObject_1 = tslib.__makeTemplateObject(["\n ", "\n"], ["\n ", "\n"])), function (_a) { var theme = _a.theme, globalMargins = _a.globalMargins, rest = tslib.__rest(_a, ["theme", "globalMargins"]); var _b = spacing.separateMarginProps(rest), marginProps = _b[0]; var cleanedGlobalMargins = common.filterDuplicateKeys(globalMargins.dateInput, marginProps); return DateInput_baseStyles.baseStyles(theme, cleanedGlobalMargins, marginProps); }); var DateInput = /*#__PURE__*/React.forwardRef(function (props, ref) { var propId = props.id, passProps = tslib.__rest(props, ["id"]); return /*#__PURE__*/React__default.default.createElement(SpacingProvider.SpacingConsumer, null, function (_a) { var margins = _a.margins; return /*#__PURE__*/React__default.default.createElement(SuomifiThemeProvider.SuomifiThemeConsumer, null, function (_a) { var suomifiTheme = _a.suomifiTheme; return /*#__PURE__*/React__default.default.createElement(AutoId.AutoId, { id: propId }, function (id) { return /*#__PURE__*/React__default.default.createElement(StyledDateInput, tslib.__assign({ theme: suomifiTheme, id: id, forwardedRef: ref, globalMargins: margins }, passProps)); }); }); }); }); DateInput.displayName = 'DateInput'; var templateObject_1; exports.DateInput = DateInput; exports.dateInputClassNames = dateInputClassNames; //# sourceMappingURL=DateInput.js.map