@harvest-profit/npk
Version:
NPK UI Design System
127 lines • 5.59 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const useMask_1 = __importDefault(require("../hooks/useMask"));
const masks_1 = require("../Input/masks");
// Handles the individual segments of the date/time input
const InputSegment = ({ segment, ...props }) => {
let mask = null;
let placeholder = '';
switch (segment) {
case 'year':
mask = masks_1.calendarYearMask;
placeholder = 'yyyy';
break;
case 'month':
mask = masks_1.calendarMonthMask;
placeholder = 'mm';
break;
case 'monthName':
mask = masks_1.calendarMonthNameMask;
placeholder = 'mmm';
break;
case 'day':
mask = masks_1.calendarDayMask;
placeholder = 'dd';
break;
case 'hour':
mask = masks_1.calendarHourMask;
placeholder = '––';
break;
case 'minute':
mask = masks_1.calendarMinuteMask;
placeholder = '––';
break;
case 'TOD':
mask = masks_1.calendarTimeOfDayMask;
placeholder = 'AM';
break;
}
const formatValue = (inputValue) => {
if (inputValue === '0')
return '';
return mask(props).formatter(`${inputValue || ''}`);
};
const [value, setValue] = (0, react_1.useState)(formatValue(props.value) || '');
const validatingValueRef = (0, react_1.useRef)(value);
const [isFocused, setIsFocused] = (0, react_1.useState)(false);
const inputMask = (0, useMask_1.default)({
...props,
mask: mask(props),
// Since we are using a span[contentEditable] as the input, we need to use the valueRef to get the current value instead of relying on event.target.value.
valueRef: validatingValueRef,
navigateWithArrows: true,
// On top of input validation, we also need to process the key strokes to update the value since we are using a span[contentEditable] as the input.
// This allows us to autocomplete certain values (e.g. a = AM, p = PM) and also handle backspace/delete.
onKeyDown: (e, specialKey) => {
let newValue = validatingValueRef.current;
if (!specialKey) {
newValue = newValue + e.key;
}
else if (e.key === 'Backspace' || e.key === 'Delete') {
if (segment === 'TOD')
newValue = '';
newValue = newValue.slice(0, newValue.length - 1);
}
else {
if (e.key !== 'Tab')
e.preventDefault();
return;
}
if (segment === 'TOD') {
setValue((0, masks_1.calendarTimeOfDayMask)().autoComplete(newValue, e.key));
}
else if (segment === 'monthName') {
setValue((0, masks_1.calendarMonthNameMask)().autoComplete(newValue, e.key));
}
else {
setValue(newValue);
}
e.preventDefault();
}
});
(0, react_1.useEffect)(() => {
// if the value is a complete value (2 digits for month, day, hour, minute, 4 digits for year)
// We want to set the validatingValueRef to an empty string so that when the input is focused again,
// the user can type in a complete new value instead of having to delete the old value
if (['month', 'day', 'hour', 'minute'].includes(segment) && value.length === 2) {
validatingValueRef.current = '';
}
else if (['year'].includes(segment) && value.length === 4) {
validatingValueRef.current = '';
}
else if (['monthName'].includes(segment) && value.length >= 3) {
validatingValueRef.current = '';
}
else {
validatingValueRef.current = value;
}
// Publish the change to the parent component if the value is different
if (props.onChange && formatValue(props.value) !== formatValue(value))
props.onChange(value);
}, [value]);
(0, react_1.useEffect)(() => {
if (!isFocused && formatValue(props.value) !== formatValue(value))
setValue(formatValue(props.value));
}, [props.value]);
const onBlur = (e) => {
setIsFocused(false);
if (props.setIsFocused)
props.setIsFocused(false);
setValue(inputMask.formatter(value));
};
const onFocus = (e) => {
setIsFocused(true);
if (props.setIsFocused)
props.setIsFocused(true);
};
// Use a placeholder if the value is empty
const valueIsEmpty = value === '' || value === undefined || value === null;
return ((0, jsx_runtime_1.jsx)("span", { tabIndex: 0, "data-component": "input-segment", onKeyDown: inputMask.onKeyDown, onClick: e => e.preventDefault(), onBlur: onBlur, onFocus: onFocus, enterKeyHint: "next", inputMode: "numeric", contentEditable: true, suppressContentEditableWarning: true, role: "spinbutton", style: { minWidth: segment === 'year' ? '2.35em' : '1.35em', caretColor: 'transparent' }, "data-placeholder": valueIsEmpty, children: valueIsEmpty ? placeholder : value }));
};
exports.default = InputSegment;
//# sourceMappingURL=InputSegment.js.map