suomifi-ui-components
Version:
Suomi.fi UI component library
354 lines (348 loc) • 16 kB
JavaScript
'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