@navinc/base-react-components
Version:
Nav's Pattern Library
162 lines (159 loc) • 7.94 kB
JavaScript
;
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DateSegmentComponent = exports.DatePickerWrapper = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const utils_1 = require("@navinc/utils");
const predict_input_value_1 = __importDefault(require("@wojtekmaj/predict-input-value"));
const react_1 = require("react");
const styled_components_1 = __importDefault(require("styled-components"));
const copy_js_1 = require("../copy.js");
const shared_js_1 = require("../form-elements/shared.js");
const input_js_1 = require("../input.js");
const DAYS_IN_MONTH = 31;
const MONTHS_IN_YEAR = 12;
const DAYS_PATTERN = '99';
const MONTHS_PATTERN = '99';
const YEARS_PATTERN = '9999';
const createBackspaceHandler = (ref) => (e) => {
if (ref.current && e.currentTarget.value.length === 0 && e.key === 'Backspace') {
ref.current.focus();
}
};
const createMaxNumberJumper = (ref, maxNumber) => (e) => {
if (ref.current && Number((0, predict_input_value_1.default)(e.nativeEvent)) > maxNumber) {
ref.current.focus();
ref.current.select();
}
};
exports.DatePickerWrapper = styled_components_1.default.div.withConfig({ displayName: "brc-sc-DatePickerWrapper", componentId: "brc-sc-b6oucm" }) `
div > ${copy_js_1.Copy} {
text-align: left;
}
`;
const StyledCopy = (0, styled_components_1.default)(copy_js_1.Copy).withConfig({ displayName: "brc-sc-StyledCopy", componentId: "brc-sc-u1xut2" }) `
margin-bottom: 8px;
`;
const InputWrapper = styled_components_1.default.div.withConfig({ displayName: "brc-sc-InputWrapper", componentId: "brc-sc-rf64u9" }) `
display: flex;
flex-direction: row;
gap: 12px;
${input_js_1.Input} {
&:nth-child(1),
&:nth-child(2) {
width: 25%;
min-width: 3.5em;
}
&:nth-child(3) {
width: 50%;
min-width: 4.5em;
}
}
${shared_js_1.Errors} {
display: none;
}
`;
const DateSegmentComponent = (_a) => {
var { errors = [], hasSpaceForErrors, isInvalid, label, onBlur, onFocus, onChange = utils_1.noop, value, isPrivate } = _a, rest = __rest(_a, ["errors", "hasSpaceForErrors", "isInvalid", "label", "onBlur", "onFocus", "onChange", "value", "isPrivate"]);
const monthRef = (0, react_1.useRef)();
const dayRef = (0, react_1.useRef)();
const yearRef = (0, react_1.useRef)();
const timerRef = (0, react_1.useRef)();
const [focused, setFocused] = (0, react_1.useState)(false);
const [year = '', month = '', day = ''] = value.split('-');
const forwardToDay = createMaxNumberJumper(dayRef, MONTHS_IN_YEAR);
const backToDay = createBackspaceHandler(dayRef);
const forwardToYear = createMaxNumberJumper(yearRef, DAYS_IN_MONTH);
const backToMonth = createBackspaceHandler(monthRef);
const handleMonthChange = (event) => {
const monthValue = (0, utils_1.inputPattern)(event.target, MONTHS_PATTERN);
if (Number(monthValue) > MONTHS_IN_YEAR) {
return;
}
onChange(`${year}-${monthValue}-${day}`);
if (dayRef.current && (monthValue.length >= 2 || Number(monthValue) > 1)) {
dayRef.current.focus();
dayRef.current.select();
}
};
const handleDayChange = (event) => {
const dayValue = (0, utils_1.inputPattern)(event.target, DAYS_PATTERN);
if (Number(dayValue) > DAYS_IN_MONTH) {
return;
}
onChange(`${year}-${month}-${dayValue}`);
if (yearRef.current && (dayValue.length >= 2 || Number(dayValue) > 3)) {
yearRef.current.focus();
yearRef.current.select();
}
};
const handleYearChange = (event) => {
const yearValue = (0, utils_1.inputPattern)(event.target, YEARS_PATTERN);
onChange(`${yearValue}-${month}-${day}`);
};
const isInvalidOrHasErrors = isInvalid || !!errors.length;
const internalOnBlur = () => {
if (timerRef.current) {
clearTimeout(timerRef.current);
}
timerRef.current = setTimeout(() => {
setFocused(false);
}, 0);
};
const handleMonthBlur = () => {
if (monthRef.current) {
const monthValue = monthRef.current.value;
if ((monthValue === null || monthValue === void 0 ? void 0 : monthValue.length) === 1) {
const paddedMonthValue = monthValue.padStart(2, '0');
monthRef.current.value = paddedMonthValue;
onChange(`${year}-${paddedMonthValue}-${day}`);
}
}
internalOnBlur();
};
const handleDayBlur = () => {
if (dayRef.current) {
const dayValue = dayRef.current.value;
if ((dayValue === null || dayValue === void 0 ? void 0 : dayValue.length) === 1) {
const paddedDayValue = dayValue.padStart(2, '0');
dayRef.current.value = paddedDayValue;
onChange(`${year}-${month}-${paddedDayValue}`);
}
}
internalOnBlur();
};
const internalOnFocus = () => {
if (timerRef.current) {
clearTimeout(timerRef.current);
}
setFocused(true);
};
(0, react_1.useEffect)(() => {
if (timerRef.current && !focused) {
onBlur && onBlur();
}
else if (focused) {
onFocus && onFocus();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [focused]);
return ((0, jsx_runtime_1.jsxs)(exports.DatePickerWrapper, Object.assign({}, rest, { children: [label && ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(StyledCopy, { light: true, size: "sm", children: label }) })), (0, jsx_runtime_1.jsxs)(InputWrapper, { children: [(0, jsx_runtime_1.jsx)(input_js_1.Input, { "data-testid": "date-segment-component:month", isInvalid: isInvalidOrHasErrors, label: "MM", name: "month", maxLength: 2, innerRef: monthRef, onBlur: handleMonthBlur, onFocus: internalOnFocus, onChange: handleMonthChange, onKeyDown: forwardToDay, type: "text", inputMode: "numeric", value: month || '', isPrivate: isPrivate }), (0, jsx_runtime_1.jsx)(input_js_1.Input, { "data-testid": "date-segment-component:day", isInvalid: isInvalidOrHasErrors, label: "DD", name: "day", maxLength: 2, innerRef: dayRef, onBlur: handleDayBlur, onFocus: internalOnFocus, onChange: handleDayChange, onKeyDown: (e) => {
backToMonth(e);
forwardToYear(e);
}, type: "text", inputMode: "numeric", value: day || '', isPrivate: isPrivate }), (0, jsx_runtime_1.jsx)(input_js_1.Input, { "data-testid": "date-segment-component:year", isInvalid: isInvalidOrHasErrors, label: "YYYY", name: "year", innerRef: yearRef, onBlur: internalOnBlur, onFocus: internalOnFocus, onChange: handleYearChange, onKeyDown: backToDay, type: "text", inputMode: "numeric", value: year || '', isPrivate: isPrivate })] }), (0, jsx_runtime_1.jsx)(shared_js_1.Errors, { hasSpaceForErrors: hasSpaceForErrors, "data-testid": "date-segment-component:errors", children: !!errors.length && errors.map((err, i) => (0, jsx_runtime_1.jsx)(shared_js_1.Err, { children: err }, `err-${i}`)) })] })));
};
exports.DateSegmentComponent = DateSegmentComponent;
//# sourceMappingURL=date-segment-component.js.map