UNPKG

react-date-picker

Version:

A carefully crafted date picker for React

333 lines (277 loc) 8.05 kB
import leftPad from '../utils/leftPad' import clamp from '../utils/clamp' import times from '../utils/times' const isValid = (value, format) => { value *= 1 return value >= format.min && value <= format.max } const replaceAt = ({ value, index, len = 1, str }) => { return value.substring(0, index) + str + value.substring(index + len) } const handleArrow = (format, { currentValue, key, dir }) => { dir = dir || (key == 'ArrowUp' ? 1 : -1) return { value: clamp(currentValue * 1 + dir, { min: format.min, max: format.max, circular: true }), caretPos: true } } const handleArrowLeftPad = (format, config) => { const { value, caretPos } = handleArrow(format, config) return { value: leftPad(value), caretPos } } const handlePage = (format, config) => { config.dir = config.dir || (config.key == 'PageUp' ? 10 : -10) return handleArrow(format, config) } const handlePageLeftPad = (format, config) => { config.dir = config.dir || (config.key == 'PageUp' ? 10 : -10) return handleArrowLeftPad(format, config) } const handleUpdate = (value, format, { range }) => { value *= 1 const len = range.end - range.start + 1 const pow10 = ('1' + times(3 - len).map(() => '0').join('')) * 1 const modLen = value % pow10 let newValue = clamp(value, { min: format.min, max: format.max, circular: false }) if (pow10 > 1 && (value % pow10 == 0)) { // the user is modifying the millenium or century newValue += modLen // so we try to keep the century newValue = clamp(newValue, { min: format.min, max: format.max, circular: false }) } return newValue } const handleUnidentified = (format, { event, currentValue, range }) => { const newChar = String.fromCharCode(event.which) let index = range.start - format.start const caretPos = { start: range.start + 1 } if (newChar * 1 != newChar) { return { preventDefault: false, value: currentValue, // caretPos } } let value let valid value = replaceAt({ value: currentValue, index, str: newChar }) valid = isValid(value, format) if (!valid && index == 0 && newChar == `${format.max}`[0]) { valid = true value = format.max caretPos.start++ } if (!valid) { do { value = times(index).map(() => '0').join('') + replaceAt({ value: currentValue, index, str: newChar }).substring(index) valid = isValid(value, format) index++ if (!valid) { caretPos.start++ } } while (!valid && index <= format.end) } if (valid) { value = handleUpdate(value, format, { range }) } else { const defaultValue = format.default value = 1 * replaceAt({ value: defaultValue, index: defaultValue.length - 1, str: newChar }) if (isValid(value, format)) { caretPos.start = format.start + defaultValue.length } else { caretPos.start = range.start + 1 value = currentValue } } return { value, caretPos } } const handleUnidentifiedLeftPad = (format, config) => { const { value, caretPos, preventDefault } = handleUnidentified(format, config) return { value: leftPad(value), caretPos, preventDefault } } const handleYearUnidentified = handleUnidentified const handleDelete = (format, { range, currentValue, dir }) => { dir = dir || 0 if (range.start <= format.start && range.end >= format.end) { return { value: format.default, caretPos: true } } const len = range.end - range.start + 1 const str = times(len).map(() => '0').join('') const index = range.start - format.start + dir let value = replaceAt({ value: currentValue, index, str, len }) * 1 value = leftPad(handleUpdate(value, format, { range })) return { value, caretPos: { start: range.start + (dir < 0 ? -1 : 1) } } } const handleBackspace = (format, config) => { config.dir = -1 return handleDelete(format, config) } const toggleMeridiem = ({ upper, value }) => { if (upper) { return value == 'AM' ? 'PM' : 'AM' } return value == 'am' ? 'pm' : 'am' } const handleMeridiemArrow = (format, { currentValue }) => { return { value: toggleMeridiem({ upper: format.upper, value: currentValue }), caretPos: true } } const handleMeridiemDelete = (format, { dir, range }) => { dir = dir || 0 if (range.start <= format.start && range.end >= format.end) { return { value: format.default, caretPos: true } } return { value: format.upper ? 'AM' : 'am', caretPos: { start: range.start + (dir < 0 ? -1 : 1) } } } const handleMeridiemBackspace = (format, config) => { config.dir = -1 return handleMeridiemDelete(format, config) } const getFormats = () => { return { YYYY: { min: 100, max: 9999, default: '0100', handleDelete, handleBackspace, handleArrow, handlePageUp: handlePage, handlePageDown: handlePage, handleUnidentified: handleYearUnidentified }, // YY: { // default: '00' // }, // M: { min: 1, max: 12, default: '1', maxLen: 2 }, MM: { min: 1, max: 12, default: '01', handleDelete, handleBackspace, handlePageUp: handlePageLeftPad, handlePageDown: handlePageLeftPad, handleUnidentified: handleUnidentifiedLeftPad, handleArrow: handleArrowLeftPad }, // D: { min: 1, max: 31, default: '1', maxLen: 2 }, DD: { min: 1, max: 31, default: '01', handlePageUp: handlePageLeftPad, handlePageDown: handlePageLeftPad, handleDelete, handleBackspace, handleUnidentified: handleUnidentifiedLeftPad, handleArrow: handleArrowLeftPad }, // H: { // min: 0, max: 23, default: '0', maxLen: 2, // handleDelete, // handleBackspace, // handleArrow: handleArrowLeftPad, // handlePageUp: handlePageLeftPad, // handlePageDown: handlePageLeftPad // }, HH: { time: true, min: 0, max: 23, default: '00', handleDelete, handleBackspace, handleUnidentified: handleUnidentifiedLeftPad, handleArrow: handleArrowLeftPad, handlePageUp: handlePageLeftPad, handlePageDown: handlePageLeftPad }, // h: { min: 1, max: 12, default: '1', maxLen: 2, // handleArrow: handleArrowLeftPad, // handlePageUp: handlePageLeftPad, // handlePageDown: handlePageLeftPad // }, hh: { min: 1, max: 12, default: '01', time: true, handleDelete, handleBackspace, handleUnidentified: handleUnidentifiedLeftPad, handleArrow: handleArrowLeftPad, handlePageUp: handlePageLeftPad, handlePageDown: handlePageLeftPad }, a: { time: true, length: 2, default: 'am', handleArrow: handleMeridiemArrow, handlePageUp: handleMeridiemArrow, handlePageDown: handleMeridiemArrow, handleDelete: handleMeridiemDelete, handleBackspace: handleMeridiemBackspace }, A: { length: 2, time: true, default: 'AM', upper: true, handleArrow: handleMeridiemArrow, handlePageUp: handleMeridiemArrow, handlePageDown: handleMeridiemArrow, handleDelete: handleMeridiemDelete, handleBackspace: handleMeridiemBackspace }, // m: { min: 0, max: 59, default: '0', maxLen: 2 }, mm: { min: 0, max: 59, default: '00', time: true, handleDelete, handleBackspace, handleUnidentified: handleUnidentifiedLeftPad, handleArrow: handleArrowLeftPad, handlePageUp: handlePageLeftPad, handlePageDown: handlePageLeftPad }, // s: { min: 0, max: 59, default: '0' }, ss: { time: true, min: 0, max: 59, default: '00', handleDelete, handleBackspace, handleUnidentified: handleUnidentifiedLeftPad, handleArrow: handleArrowLeftPad, handlePageUp: handlePageLeftPad, handlePageDown: handlePageLeftPad } } } export { getFormats } export default getFormats()