UNPKG

react-time-picker

Version:

A time picker for your React app.

109 lines (108 loc) 4.49 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { useEffect, useLayoutEffect } from 'react'; import clsx from 'clsx'; import updateInputWidth, { getFontShorthand } from 'update-input-width'; const isBrowser = typeof window !== 'undefined'; const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect; const isIEOrEdgeLegacy = isBrowser && /(MSIE|Trident\/|Edge\/)/.test(navigator.userAgent); const isFirefox = isBrowser && /Firefox/.test(navigator.userAgent); function onFocus(event) { const { target } = event; if (isIEOrEdgeLegacy) { requestAnimationFrame(() => target.select()); } else { target.select(); } } function updateInputWidthOnLoad(element) { if (document.readyState === 'complete') { return; } function onLoad() { updateInputWidth(element); } window.addEventListener('load', onLoad); } function updateInputWidthOnFontLoad(element) { if (!document.fonts) { return; } const font = getFontShorthand(element); if (!font) { return; } const isFontLoaded = document.fonts.check(font); if (isFontLoaded) { return; } function onLoadingDone() { updateInputWidth(element); } document.fonts.addEventListener('loadingdone', onLoadingDone); } function getSelectionString(input) { /** * window.getSelection().toString() returns empty string in IE11 and Firefox, * so alternatives come first. */ if (input && 'selectionStart' in input && input.selectionStart !== null && 'selectionEnd' in input && input.selectionEnd !== null) { return input.value.slice(input.selectionStart, input.selectionEnd); } if ('getSelection' in window) { const selection = window.getSelection(); return selection === null || selection === void 0 ? void 0 : selection.toString(); } return null; } function makeOnKeyPress(maxLength) { if (maxLength === null) { return undefined; } /** * Prevents keystrokes that would not produce a number or when value after keystroke would * exceed maxLength. */ return function onKeyPress(event) { if (isFirefox) { // See https://github.com/wojtekmaj/react-time-picker/issues/92 return; } const { key, target: input } = event; const { value } = input; const isNumberKey = key.length === 1 && /\d/.test(key); const selection = getSelectionString(input); if (!isNumberKey || !(selection || value.length < maxLength)) { event.preventDefault(); } }; } export default function Input({ ariaLabel, autoFocus, className, disabled, inputRef, max, min, name, nameForClass, onChange, onKeyDown, onKeyUp, placeholder = '--', required, showLeadingZeros, step, value, }) { useIsomorphicLayoutEffect(() => { if (!inputRef || !inputRef.current) { return; } updateInputWidth(inputRef.current); updateInputWidthOnLoad(inputRef.current); updateInputWidthOnFontLoad(inputRef.current); }, [inputRef, value]); const hasLeadingZero = showLeadingZeros && value && Number(value) < 10 && (value === '0' || !value.toString().startsWith('0')); const maxLength = max ? max.toString().length : null; return (_jsxs(_Fragment, { children: [hasLeadingZero ? _jsx("span", { className: `${className}__leadingZero`, children: "0" }) : null, _jsx("input", { "aria-label": ariaLabel, autoComplete: "off", // biome-ignore lint/a11y/noAutofocus: This is up to developers' decision autoFocus: autoFocus, className: clsx(`${className}__input`, `${className}__${nameForClass || name}`, hasLeadingZero && `${className}__input--hasLeadingZero`), "data-input": "true", disabled: disabled, inputMode: "numeric", max: max, min: min, name: name, onChange: onChange, onFocus: onFocus, onKeyDown: onKeyDown, onKeyPress: makeOnKeyPress(maxLength), onKeyUp: (event) => { updateInputWidth(event.target); if (onKeyUp) { onKeyUp(event); } }, placeholder: placeholder, // Assertion is needed for React 18 compatibility ref: inputRef, required: required, step: step, type: "number", value: value !== null ? value : '' })] })); }