@shinyongjun/react-datepicker
Version:
DatePicker component in React App.
264 lines • 9.94 kB
JavaScript
'use client';
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import { jsx as _jsx } from "react/jsx-runtime";
import { useEffect, useMemo, useRef, useState, } from 'react';
import { NAME_SPACE, VALUE_TYPES } from '../../constants/core';
import { getDateValueUnit, getTimeValueUnit } from '../../utils/datetime';
import { addLeadingZero, isNumeric } from '../../utils/string';
// Function to select text
function selectText(element) {
var selection = window.getSelection();
var range = document.createRange();
range.selectNodeContents(element);
if (selection) {
selection.removeAllRanges();
selection.addRange(range);
}
}
// 형제 Input Element중 NextInputElement를 검색.
function getNextSiblingsWithDataValueTrue(currentElement) {
var siblingElements = [];
var nextSibling = currentElement.nextElementSibling;
while (nextSibling) {
if (nextSibling.dataset.value === 'true') {
siblingElements.push(nextSibling);
}
nextSibling = nextSibling.nextElementSibling;
}
return siblingElements;
}
function InputUnit(_a) {
var type = _a.type, dateValue = _a.dateValue, setDateValue = _a.setDateValue, onChange = _a.onChange, timeValue = _a.timeValue, setTimeValue = _a.setTimeValue, viewDate = _a.viewDate, setViewDate = _a.setViewDate, disabled = _a.disabled, isMounted = _a.isMounted, timePicker = _a.timePicker;
var inputRef = useRef(null);
var nextRef = useRef();
var isValue = useMemo(function () { return VALUE_TYPES.includes(type); }, [type]);
var isDisabled = useMemo(function () {
if (['hh', 'mm', 'ss'].includes(type)) {
if (!timePicker)
return true;
if (type === 'hh' && !timePicker.hour)
return true;
if (type === 'mm' && !timePicker.minute)
return true;
if (type === 'ss' && !timePicker.second)
return true;
}
return false;
}, [type, timePicker]);
var displayUnit = useMemo(function () {
switch (type) {
case 'YYYY':
case 'MM':
case 'DD':
return getDateValueUnit(dateValue, type);
case 'hh':
case 'mm':
case 'ss':
return getTimeValueUnit(timeValue, type);
case ' ':
return ' ';
default:
return type;
}
}, [type, dateValue, timeValue]);
var _b = useState(displayUnit), text = _b[0], setText = _b[1];
var utilSetDateValue = function (_a) {
var year = _a.year, month = _a.month, date = _a.date;
setDateValue({
year: year !== null ? year : dateValue.year,
month: month !== null ? month : dateValue.month,
date: date !== null ? date : dateValue.date,
});
};
var utilSetTimeValue = function (_a) {
var hour = _a.hour, minute = _a.minute, second = _a.second;
setTimeValue({
hour: hour !== null ? hour : timeValue.hour,
minute: minute !== null ? minute : timeValue.minute,
second: second !== null ? second : timeValue.second,
});
};
// Input에서 Focus가 사라졌을 때 입력된 값을 타입에 맞게 value에 저장
var setValue = function (element) {
var value = element.textContent || type;
if (!isNumeric(value)) {
return setText(type);
}
var conditions = {
YYYY: Number(value) > 9999 ? '9999' : value,
MM: Number(value) > 12 ? '12' : addLeadingZero(value),
DD: Number(value) > 31 ? '31' : addLeadingZero(value),
hh: Number(value) > 23 ? '23' : addLeadingZero(value),
mm: Number(value) > 59 ? '59' : addLeadingZero(value),
ss: Number(value) > 59 ? '59' : addLeadingZero(value),
};
var processedValue = conditions[type] || value;
if (text !== processedValue) {
setText(processedValue);
// element.innerText = processedValue;
}
};
var focusController = function () {
var _a;
if (nextRef.current) {
nextRef.current.focus();
}
else {
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.blur();
}
};
// Type마다 특정 자리수 입력 시 다음 Input으로 focusing
var inputHandler = function (e) {
var _a, _b;
var target = e.target;
var count = ((_a = target.textContent) === null || _a === void 0 ? void 0 : _a.length) || 0;
var value = Number(target.textContent);
// 숫자 외 입력 방어 코드
if ((_b = target.textContent) === null || _b === void 0 ? void 0 : _b.match(/[^0-9]/g)) {
setText(type);
target.innerText = type;
selectText(target);
return;
}
switch (type) {
case 'YYYY':
if (count >= 4) {
focusController();
}
return;
case 'MM':
if (value >= 2 || count >= 2) {
focusController();
}
return;
case 'DD':
if (value >= 4 || count >= 2) {
focusController();
}
return;
case 'hh':
if (value >= 3 || count >= 2) {
focusController();
}
return;
case 'mm':
if (value >= 6 || count >= 2) {
focusController();
}
return;
case 'ss':
if (value >= 6 || count >= 2) {
focusController();
}
return;
default:
return;
}
};
// 허용된 입력 외 prevent
var numberChecker = function (e) {
if (isDisabled)
e.preventDefault();
var allowKeys = [
'Backspace',
'ArrowLeft',
'ArrowRight',
'ArrowDown',
'ArrowUp',
'Tab',
];
if (!allowKeys.includes(e.key) && !(e.key >= '0' && e.key <= '9')) {
e.preventDefault();
}
};
var focusHandler = function (e) {
if (disabled)
return;
setTimeout(function () {
selectText(e.target);
}, 10);
};
var clickHandler = function (e) {
if (disabled)
return;
if (!isValue) {
if (nextRef.current) {
nextRef.current.focus();
}
}
else {
var target = e.target;
selectText(target);
}
};
var blurHandler = function (e) {
if (disabled)
return;
setValue(e.target);
};
useEffect(function () {
if (!isMounted)
return;
setText(displayUnit);
if (dateValue.year !== null &&
dateValue.month !== null &&
dateValue.date !== null) {
if (onChange) {
onChange(new Date(dateValue.year, dateValue.month, dateValue.date, timeValue.hour, timeValue.minute, timeValue.second));
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [displayUnit]);
// Text의 변화를 감지하여 Value에 최종 저장
useEffect(function () {
if (!isNumeric(text))
return;
switch (type) {
case 'YYYY':
utilSetDateValue(__assign(__assign({}, dateValue), { year: Number(text) }));
setViewDate("".concat(text, "-").concat(viewDate.split('-')[1], "-").concat(viewDate.split('-')[2]));
return;
case 'MM':
utilSetDateValue(__assign(__assign({}, dateValue), { month: Number(text) - 1 }));
setViewDate("".concat(viewDate.split('-')[0], "-").concat(text, "-").concat(viewDate.split('-')[2]));
return;
case 'DD':
utilSetDateValue(__assign(__assign({}, dateValue), { date: Number(text) }));
return;
case 'hh':
utilSetTimeValue(__assign(__assign({}, timeValue), { hour: Number(text) }));
return;
case 'mm':
utilSetTimeValue(__assign(__assign({}, timeValue), { minute: Number(text) }));
return;
case 'ss':
utilSetTimeValue(__assign(__assign({}, timeValue), { second: Number(text) }));
return;
default:
return;
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [text]);
// 다음 Input Unit을 nextRef에 저장.
useEffect(function () {
if (inputRef.current) {
var nextSiblings = getNextSiblingsWithDataValueTrue(inputRef.current);
if (nextSiblings.length) {
nextRef.current = nextSiblings[0];
}
}
}, []);
return (_jsx("div", { role: "presentation", ref: inputRef, "data-value": isValue, className: "".concat(NAME_SPACE, "__input-unit"), dangerouslySetInnerHTML: { __html: text }, contentEditable: isValue && !disabled, suppressContentEditableWarning: true, onFocus: focusHandler, onClick: clickHandler, onInput: inputHandler, onKeyDown: numberChecker, onBlur: blurHandler, inputMode: "numeric" }));
}
export default InputUnit;
//# sourceMappingURL=InputUnit.js.map