@digitransit-component/digitransit-component-datetimepicker 5.0.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.development.js +2 -2
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +3 -3
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/helpers/utils.js","../src/helpers/DesktopDatetimepicker.js","../src/helpers/mobileDetection.js","../../../../node_modules/style-inject/dist/style-inject.es.js","../src/helpers/MobileDatepicker.js","../../../../node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js","../../../../node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js","../src/helpers/MobileTimepicker.js","../src/helpers/MobilePickerModal.js","../src/helpers/Datetimepicker.js","../src/helpers/dateTimeInputIsSupported.js","../src/helpers/translations.js","../src/helpers/i18n.js","../src/index.js"],"sourcesContent":["import { DateTime } from 'luxon';\n\n/**\n * Handle typing time and adding necessary :\n *\n * @param {string} typedValue\n *\n * @return {string}\n */\nexport function parseTypedTime(typedValue) {\n let actualValue = typedValue;\n if (\n actualValue.length === 3 &&\n actualValue.split('').every(n => Number.isInteger(Number(n)))\n ) {\n // add ':' if user types three numbers in a row\n if (Number(actualValue.slice(0, 2)) <= 23) {\n actualValue = `${actualValue.slice(0, 2)}:${actualValue[2]}`;\n } else {\n actualValue = `${actualValue[0]}:${actualValue.slice(1)}`;\n }\n }\n return actualValue;\n}\n\nconst validateClock = (hours, minutes) => {\n const hoursValid = !Number.isNaN(hours) && hours >= 0 && hours <= 23;\n const minutesLen = minutes.length;\n const minutesValid =\n minutesLen === 2\n ? !Number.isNaN(minutes) && Number(minutes) >= 0 && Number(minutes <= 59)\n : !Number.isNaN(minutes) && Number(minutes) >= 0 && Number(minutes <= 5);\n return hoursValid && minutesValid;\n};\n\nexport function validateInput(inputValue) {\n // We don't accept seconds in the input\n if (inputValue.split(':').length > 2) {\n return false;\n }\n if (inputValue.length <= 2) {\n // Too many options, don't validate\n return true;\n }\n if (inputValue.length === 3) {\n let hours;\n let minutes;\n if (inputValue.includes(':')) {\n [hours, minutes] = inputValue.split(':');\n } else if (inputValue.startsWith('0')) {\n hours = inputValue.substring(0, inputValue.length - 1);\n minutes = inputValue.substring(inputValue.length - 1 || 0);\n if (Number(minutes) > 5) {\n return false;\n }\n } else {\n // This is how basically moment handles string formatting.\n // If the first letter of the string is 1, then rest are minutes.\n // if the first letter is 2, then if second letter is 0,1,2 or 3, then second letter is hour, else rest are minutes\n // else, first letter is hour, rest of them are minutes.\n const values = inputValue.split('');\n if (Number(values[0]) === 1) {\n [hours, minutes] = [values[0].concat(values[1]), values[2]];\n } else if (Number(values[0]) === 2) {\n if (Number(values[1] <= 3)) {\n [hours, minutes] = [values[0].concat(values[1]), values[2]];\n } else {\n [hours, minutes] = [values[0], values[1].concat(values[2])];\n }\n } else {\n [hours, minutes] = [values[0], values[1].concat(values[2])];\n }\n return validateClock(hours, minutes);\n }\n return validateClock(hours, minutes);\n }\n if (inputValue.length === 5 || inputValue.length === 4) {\n const values = inputValue.split(':');\n const hours = values[0];\n const minutes = values[1];\n if (\n inputValue.startsWith('0') &&\n minutes.length === 1 &&\n Number(minutes) > 5\n ) {\n return false;\n }\n\n return validateClock(hours, minutes);\n }\n return true;\n}\n\nexport const getTs = (inputValue, currentTimestamp) => {\n const trimmed = inputValue.trim();\n if (trimmed.match(/^[0-9]{1,2}(\\.|:)[0-9]{2}$/) !== null) {\n const splitter = trimmed.includes('.') ? '.' : ':';\n const values = trimmed.split(splitter);\n const hours = Number(values[0]);\n const hoursValid = !Number.isNaN(hours) && hours >= 0 && hours <= 23;\n const minutes = Number(values[1]);\n const minutesValid =\n !Number.isNaN(minutes) && minutes >= 0 && minutes <= 59;\n if (!minutesValid || !hoursValid) {\n return null;\n }\n const newStamp = DateTime.fromMillis(currentTimestamp)\n .set({\n hour: hours,\n minute: minutes,\n second: 0,\n millisecond: 0,\n })\n .valueOf();\n return newStamp;\n }\n return null;\n};\n\nexport default { parseTypedTime, validateInput, getTs };\n","import PropTypes from 'prop-types';\nimport React, { useState, useEffect } from 'react';\nimport { DateTime, Settings } from 'luxon';\nimport { useTranslation } from 'react-i18next';\nimport Select from 'react-select';\nimport cx from 'classnames';\nimport { parseTypedTime, validateInput, getTs } from './utils';\nimport styles from './styles.scss';\n\n/**\n * Component to display a date or time input on desktop.\n *\n * @param {Object} props\n * @param {Number} props.value Currently selected time. Unix timestamp in milliseconds\n * @param {function} props.onChange This is called with new timestamp when input is changed\n * @param {function} props.getDisplay Function to get a string representation from a timestamp\n * @param {array} props.timeChoices Array of timestamps to choose from\n * @param {string} id Id prefix for labels and aria attributes. Should be unique in page\n * @param {string} label Text to show as input label\n * @param {node} icon JSX for icon to show in input\n * @param {boolean} disableTyping Set to true to disable typing in the input\n * @param {boolean} datePicker Is the picker DatePicker or TimePicker\n *\n * @example\n * <DesktopDatetimepicker\n * value={1590133823000}\n * onChange={timestamp => update(timestamp)}\n * getDisplay={timestamp => formatTime(timestamp)}\n * timeChoices={[1590133823000]}\n * id=\"timeinput\"\n * icon=\"<Icon />\"\n * disableTyping={false} // can be omitted if not true\n * datePicker={true} // can be omitted if not true\n */\nfunction DesktopDatetimepicker({\n value,\n onChange,\n getDisplay,\n timeChoices,\n id,\n label,\n icon,\n disableTyping,\n timeZone,\n datePicker,\n translationSettings,\n}) {\n Settings.defaultZone = timeZone;\n const [t] = useTranslation();\n const [displayValue, changeDisplayValue] = useState(getDisplay(value));\n const [typing, setTyping] = useState(false);\n const [showAllOptions, setShowAllOptions] = useState(true);\n const [invalidInput, setinvalidInput] = useState(false);\n useEffect(() => {\n changeDisplayValue(getDisplay(value));\n if (!datePicker) {\n setinvalidInput(false);\n }\n }, [value]);\n\n // newValue is string\n const handleTimestamp = newValue => {\n const asNumber = Number(newValue);\n try {\n DateTime.fromMillis(asNumber);\n } catch (e) {\n // If the value is not a valid timestamp, we don't change it\n return;\n }\n onChange(asNumber);\n };\n function isinvalidInput(str) {\n const regex = /[a-zA-Z§ÄäÖö.-\\s]/g;\n if (str.length < displayValue?.length) {\n const valid = validateInput(str);\n setinvalidInput(!valid);\n\n return true;\n }\n if (regex.test(str)) {\n return false;\n }\n const time = str.length > 5 ? str.slice(0, -1) : str;\n const valid = validateInput(time);\n setinvalidInput(!valid);\n return str.length <= 5;\n }\n const onInputChange = (newValue, { action }) => {\n if (action === 'menu-close') {\n setShowAllOptions(true);\n } else if (showAllOptions) {\n setShowAllOptions(false);\n }\n if (disableTyping || (newValue && !isinvalidInput(newValue))) {\n return;\n }\n if (action === 'input-change') {\n const validated = parseTypedTime(newValue);\n changeDisplayValue(validated);\n setTyping(true);\n }\n };\n const options = timeChoices.map(time => {\n return { value: time.toString(), label: getDisplay(time) };\n });\n\n // Time picker has a list of minutes, instead of 15 minutes. We need to filter those out\n // so closest option will show up in the list.\n const closestOptions = datePicker\n ? options\n : options.filter(o => o.label.split(':')[1] % 15 === 0);\n const closestOption =\n closestOptions.length > 0\n ? closestOptions?.reduce((a, b) =>\n Math.abs(value - a.value) < Math.abs(value - b.value) ? a : b,\n )\n : undefined;\n const inputId = `${id}-input`;\n const labelId = `${id}-label`;\n const filterOptions = (option, input) => {\n const hour = input.length <= 2 ? input : input.split(':')[0];\n const isValidHour = /^([0-1]?[0-9]|2[0-3])$/.test(hour);\n const comp = hour.length === 1 ? '0'.concat(input) : input;\n return isValidHour\n ? option.label.split(':')[0] === comp.split(':')[0]\n : true;\n };\n const ariaError = t('invalid-input', translationSettings);\n return (\n <label className={styles['combobox-container']} htmlFor={inputId}>\n <span className={styles['sr-only']} id={labelId}>\n {label} {displayValue}\n </span>\n {icon}\n <Select\n aria-labelledby={labelId}\n ariaLiveMessages={{\n guidance: context => {\n // When user types invalid value, isDisabled becomes undefined instead of false\n if (context.isDisabled === undefined && invalidInput) {\n return ariaError;\n }\n return '.'; // this can't be empty for some reason\n },\n onChange: () => {\n return '';\n },\n onFilter: () => {\n return '';\n },\n onFocus: ({ context, label: itemLabel }) => {\n if (context === 'menu') {\n return itemLabel;\n }\n return '';\n },\n }}\n options={options}\n inputId={inputId}\n onChange={time => {\n const currentTime = DateTime.fromMillis(value).toFormat('HH:mm');\n const ts = getTs(displayValue, value);\n if (typing) {\n if (ts !== null) {\n if (currentTime !== displayValue && time.value === value) {\n handleTimestamp(ts);\n } else {\n handleTimestamp(time.value);\n }\n setTyping(false);\n } else {\n if (time.value !== value) {\n handleTimestamp(time.value);\n } else {\n // reset value\n changeDisplayValue(getDisplay(value));\n }\n setTyping(false);\n }\n if (!datePicker) {\n setinvalidInput(false);\n }\n return;\n }\n if (!datePicker) {\n setinvalidInput(false);\n }\n handleTimestamp(time.value);\n }}\n components={{\n IndicatorsContainer: () => null,\n }}\n className={cx(\n styles['datetimepicker-select-container'],\n invalidInput ? 'datetimepicker-invalid-input' : '',\n )}\n classNamePrefix=\"datetimepicker-select\"\n onInputChange={onInputChange}\n inputValue={!disableTyping && displayValue}\n value={closestOption}\n noOptionsMessage={() => {\n return '';\n }}\n filterOption={(option, input) => {\n if (datePicker) {\n return true;\n }\n const completeInput =\n input.length === 5 ||\n (input.length === 4 && input.split(':')[0].length === 1);\n const isMod15 = option.label.split(':')[1] % 15 === 0;\n const minuteInput = input.split(':')[1]?.length === 1;\n\n if (showAllOptions && isMod15) {\n return true;\n }\n if (minuteInput) {\n const inputH =\n input.split(':')[0].length === 1\n ? '0'.concat(input.split(':')[0])\n : input.split(':')[0];\n const inputM = input.split(':')[1];\n const optH = option.label.split(':')[0];\n const optM = option.label.split(':')[1];\n if (inputH === optH) {\n const time = Number(inputM) * 10;\n const total = Number(optM) - time;\n if (total >= 0 && total <= 9) {\n return true;\n }\n return false;\n }\n }\n if (completeInput && !showAllOptions) {\n return input.length === 4\n ? '0'.concat(input) === option.label\n : input === option.label;\n }\n if (isMod15) {\n return filterOptions(option, input);\n }\n\n return false;\n }}\n controlShouldRenderValue={disableTyping}\n tabSelectsValue={false}\n placeholder=\"\"\n onFocus={e => {\n if (!disableTyping) {\n e.target.select();\n }\n }}\n onBlur={() => {\n // removing focus also locks in value\n if (typing) {\n const validated = getTs(displayValue, value);\n if (validated !== null) {\n handleTimestamp(validated);\n setTyping(false);\n } else {\n changeDisplayValue(getDisplay(value));\n setTyping(false);\n }\n }\n if (!datePicker) {\n setinvalidInput(false);\n }\n }}\n onKeyDown={e => {\n if (['ArrowDown', 'ArrowUp'].includes(e.key)) {\n setTyping(false);\n }\n }}\n isSearchable={!disableTyping}\n />\n </label>\n );\n}\nDesktopDatetimepicker.propTypes = {\n value: PropTypes.number.isRequired,\n onChange: PropTypes.func.isRequired,\n getDisplay: PropTypes.func.isRequired,\n timeChoices: PropTypes.arrayOf(PropTypes.number).isRequired,\n id: PropTypes.string.isRequired,\n label: PropTypes.node.isRequired,\n icon: PropTypes.node.isRequired,\n disableTyping: PropTypes.bool,\n timeZone: PropTypes.string,\n datePicker: PropTypes.bool,\n translationSettings: PropTypes.shape({ lng: PropTypes.string.isRequired }),\n};\n\nDesktopDatetimepicker.defaultProps = {\n disableTyping: false,\n timeZone: 'Europe/Helsinki',\n datePicker: false,\n translationSettings: { lng: 'fi' },\n};\n\nexport default DesktopDatetimepicker;\n","/**\n * Detect if user is on a mobile device by parsing userAgent. This is not 100% reliable but close enough.\n *\n * @return {boolean}\n */\nfunction isMobile() {\n const userAgent = navigator.userAgent || navigator.vendor || window.opera;\n const mobile =\n /(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(\n userAgent,\n );\n return mobile;\n}\n\n/**\n * Detect if user is on an android device. Not 100% reliable.\n */\nfunction isAndroid() {\n const userAgent = navigator.userAgent.toLowerCase();\n return userAgent.indexOf('android') > -1;\n}\n\nexport { isMobile, isAndroid };\n","function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n","import PropTypes from 'prop-types';\nimport React, { useState, useRef, useLayoutEffect } from 'react';\nimport { DateTime, Settings } from 'luxon';\nimport Autosuggest from 'react-autosuggest';\nimport styles from './styles.scss';\nimport { isAndroid } from './mobileDetection';\n\n/**\n * Component to display a date input on mobile\n */\nfunction MobileDatepicker({\n value,\n getDisplay,\n onChange,\n itemCount,\n startTime,\n id,\n label,\n icon,\n timeZone,\n}) {\n Settings.defaultZone = timeZone;\n const [open, changeOpen] = useState(false);\n const scrollRef = useRef(null);\n const dateChoices = Array(itemCount)\n .fill()\n .map((_, i) => DateTime.fromMillis(startTime).plus({ days: i }).toMillis());\n const minute = 1000 * 60;\n const diffs = dateChoices.map(t => value - t);\n const scrollIndex = diffs.findIndex(t => t < minute); // when time is now, the times might differ by less than one minute\n const elementHeight = 50;\n // scroll to selected time when dropdown is opened\n useLayoutEffect(() => {\n if (open && scrollRef.current) {\n scrollRef.current.scrollTop = elementHeight * scrollIndex;\n }\n }, [value, open]);\n const nativeInput = !isAndroid();\n const inputId = `${id}-input`;\n const labelId = `${id}-label`;\n return (\n <label className={styles['input-container']} htmlFor={inputId}>\n <span>{icon}</span>\n <span className={styles['sr-only']} id={labelId}>\n {label}\n </span>\n {nativeInput ? (\n <select\n className={styles['mobile-input-display']}\n onChange={e => onChange(Number(e.target.value))}\n value={value}\n >\n {dateChoices.map(date => {\n return (\n <option key={date} value={date}>\n {getDisplay(date)}\n </option>\n );\n })}\n </select>\n ) : (\n <Autosuggest\n id={id}\n suggestions={dateChoices}\n getSuggestionValue={s => s.toString()}\n renderSuggestion={s => getDisplay(s)}\n onSuggestionsFetchRequested={() => null}\n shouldRenderSuggestions={() => true}\n inputProps={{\n value: getDisplay(value),\n onChange: (_, { newValue }) => {\n onChange(Number(newValue));\n },\n onFocus: () => {\n changeOpen(true);\n },\n onBlur: () => {\n changeOpen(false);\n },\n 'aria-labelledby': labelId,\n 'aria-autocomplete': 'none',\n readOnly: true,\n }}\n focusInputOnSuggestionClick={false}\n onSuggestionsClearRequested={() => null}\n renderSuggestionsContainer={({ containerProps, children }) => {\n // set refs for autosuggest library and scrollbar positioning\n const { ref, ...otherRefs } = containerProps;\n const containerRef = elem => {\n if (elem) {\n scrollRef.current = elem;\n ref(elem);\n }\n };\n return (\n <div tabIndex=\"-1\" {...otherRefs} ref={containerRef}>\n {children}\n </div>\n );\n }}\n theme={styles}\n />\n )}\n </label>\n );\n}\nMobileDatepicker.propTypes = {\n value: PropTypes.number.isRequired,\n getDisplay: PropTypes.func.isRequired,\n onChange: PropTypes.func.isRequired,\n itemCount: PropTypes.number.isRequired,\n startTime: PropTypes.number.isRequired,\n id: PropTypes.string.isRequired,\n label: PropTypes.string.isRequired,\n icon: PropTypes.node,\n dateTimeCombined: PropTypes.bool,\n timeZone: PropTypes.string,\n};\n\nMobileDatepicker.defaultProps = {\n icon: null,\n dateTimeCombined: false,\n timeZone: 'Europe/Helsinki',\n};\n\nexport default MobileDatepicker;\n","import objectWithoutPropertiesLoose from \"./objectWithoutPropertiesLoose.js\";\nfunction _objectWithoutProperties(e, t) {\n if (null == e) return {};\n var o,\n r,\n i = objectWithoutPropertiesLoose(e, t);\n if (Object.getOwnPropertySymbols) {\n var n = Object.getOwnPropertySymbols(e);\n for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);\n }\n return i;\n}\nexport { _objectWithoutProperties as default };","function _objectWithoutPropertiesLoose(r, e) {\n if (null == r) return {};\n var t = {};\n for (var n in r) if ({}.hasOwnProperty.call(r, n)) {\n if (-1 !== e.indexOf(n)) continue;\n t[n] = r[n];\n }\n return t;\n}\nexport { _objectWithoutPropertiesLoose as default };","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { Settings } from 'luxon';\nimport cx from 'classnames';\nimport styles from './styles.scss';\nimport { parseTypedTime, getTs, validateInput } from './utils';\n\n/**\n * Component to display a time input on mobile\n */\nfunction MobileTimepicker({\n value,\n getDisplay,\n onChange,\n id,\n label,\n icon,\n timeZone,\n}) {\n const [inputValue, changeInputValue] = useState(getDisplay(value));\n const [isValidInput, setValidInput] = useState(true);\n Settings.defaultZone = timeZone;\n const inputId = `${id}-input`;\n const labelId = `${id}-label`;\n const showError = !isValidInput;\n return (\n <label className={styles['input-container']} htmlFor={inputId}>\n <span>{icon}</span>\n <span className={styles['sr-only']} id={labelId}>\n {label}\n </span>\n <input\n id={inputId}\n inputMode=\"numeric\"\n type=\"text\"\n maxLength=\"6\"\n className={cx(\n styles['time-input-mobile'],\n showError ? 'mobile-datetimepicker-invalid-input' : '',\n )}\n value={inputValue}\n onFocus={e => {\n e.target.setSelectionRange(0, 0); // set caret to start of input\n }}\n onChange={event => {\n let newValue = event.target.value.replace('.', ':');\n\n const valid = validateInput(newValue);\n setValidInput(valid);\n if (\n // number typed as first char => clear rest of the input\n newValue.match(/[0-9]{3}:[0-9]{2}/) &&\n newValue.slice(1) === inputValue\n ) {\n newValue = newValue.charAt(0);\n }\n if (newValue.length > 5) {\n return;\n }\n const actual = parseTypedTime(newValue);\n changeInputValue(actual);\n const timestamp = getTs(actual, value);\n if (timestamp) {\n onChange(timestamp);\n }\n }}\n />\n </label>\n );\n}\nMobileTimepicker.propTypes = {\n value: PropTypes.number.isRequired,\n getDisplay: PropTypes.func.isRequired,\n onChange: PropTypes.func.isRequired,\n id: PropTypes.string.isRequired,\n label: PropTypes.string.isRequired,\n icon: PropTypes.node,\n timeZone: PropTypes.string,\n};\n\nMobileTimepicker.defaultProps = {\n icon: null,\n timeZone: 'Europe/Helsinki',\n};\n\nexport default MobileTimepicker;\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { DateTime, Settings } from 'luxon';\nimport { useTranslation } from 'react-i18next';\nimport uniqueId from 'lodash/uniqueId';\nimport Modal from 'react-modal';\nimport Icon from '@digitransit-component/digitransit-component-icon';\nimport MobileDatepicker from './MobileDatepicker';\nimport MobileTimepicker from './MobileTimepicker';\nimport styles from './styles.scss';\n\nSettings.defaultLocale = 'en';\n\n/**\n * @param {object} props\n * @param {'arrival'|'departure'} props.departureOrArrival Whether the picker is for arrival or departure time\n * @param {function} props.onNowClick Called when the \"Now\" button is clicked\n * @param {string} props.lang Language code for translations\n * @param {string} props.color Color for the component, used in styles\n * @param {string} props.timeZone Time zone to use for date and time calculations\n * @param {function} props.onSubmit Called when the user submits the selected date and time\n * @param {function} props.onCancel called when the user cancels the selection\n * @param {number} props.timestamp Initial timestamp to display in the picker\n * @param {function} props.getTimeDisplay Called to get the display string for a given timestamp\n * @param {number} props.dateSelectItemCount Determines how many date options are shown in the date picker\n * @param {function} props.getDateDisplay Called to get the display string for a given date\n * @param {object} props.fontWeights Font weights used in the component styles\n * @returns {JSX.Element}\n */\nfunction MobilePickerModal({\n departureOrArrival,\n onNowClick,\n lang,\n color,\n timeZone,\n onSubmit,\n onCancel,\n timestamp,\n getTimeDisplay,\n dateSelectItemCount,\n getDateDisplay,\n fontWeights,\n onAfterClose,\n}) {\n Settings.defaultZone = timeZone;\n const [t] = useTranslation();\n const translationSettings = { lng: lang };\n\n const [displayTimestamp, changeTimestamp] = useState(timestamp);\n\n const [departureOrArrivalCurrent, changeDepartureOrArrival] =\n useState(departureOrArrival);\n\n function onArrivalClick() {\n changeDepartureOrArrival('arrival');\n }\n\n function onDepartureClick() {\n changeDepartureOrArrival('departure');\n }\n\n // for input labels\n const [htmlId] = useState(uniqueId('datetimepicker-'));\n const dateSelectStartTime = DateTime.now()\n .startOf('day')\n .set({\n hour: DateTime.fromMillis(displayTimestamp).hour,\n minute: DateTime.fromMillis(displayTimestamp).minute,\n })\n .toMillis();\n\n return (\n <Modal\n appElement={document ? document.querySelector('#app') : undefined}\n isOpen\n className={styles['mobile-modal-content']}\n overlayClassName={styles['mobile-modal-overlay']}\n onAfterClose={onAfterClose}\n >\n <div\n id=\"digitransit-mobile-datetime\"\n style={{\n '--color': `${color}`,\n '--font-weight-medium': fontWeights.medium,\n }}\n >\n <div className={styles['top-row']}>\n <h3 className={styles['modal-title']}>\n {t('choose-time', translationSettings)}\n </h3>\n <button\n type=\"button\"\n className={styles['departure-now-button']}\n onClick={onNowClick}\n >\n {t('departure-now', translationSettings)}\n </button>\n </div>\n <div className={styles['tab-row']}>\n <label\n htmlFor={`${htmlId}-modal-departure`}\n className={`${styles['radio-tab-label']}\n ${\n styles[\n departureOrArrivalCurrent === 'departure'\n ? 'active'\n : undefined\n ]\n }`}\n >\n {t('departure', translationSettings)}\n <input\n id={`${htmlId}-modal-departure`}\n name=\"departureOrArrival\"\n type=\"radio\"\n value=\"departure\"\n className={styles['radio-textbutton']}\n onChange={() => {\n onDepartureClick();\n }}\n checked={departureOrArrivalCurrent === 'departure'}\n />\n </label>\n <label\n htmlFor={`${htmlId}-modal-arrival`}\n className={`${styles['radio-tab-label']}\n ${\n styles[\n departureOrArrivalCurrent === 'arrival'\n ? 'active'\n : undefined\n ]\n }`}\n >\n {t('arrival', translationSettings)}\n <input\n id={`${htmlId}-modal-arrival`}\n name=\"departureOrArrival\"\n type=\"radio\"\n value=\"arrival\"\n className={styles['radio-textbutton']}\n onChange={() => {\n onArrivalClick();\n }}\n checked={departureOrArrivalCurrent === 'arrival'}\n />\n </label>\n </div>\n <div className={styles['input-row']}>\n <MobileDatepicker\n value={displayTimestamp}\n getDisplay={getDateDisplay}\n onChange={changeTimestamp}\n itemCount={dateSelectItemCount}\n startTime={dateSelectStartTime}\n id={`${htmlId}-date`}\n label={t('date', translationSettings)}\n icon={\n <span\n className={`${styles['combobox-icon']} ${styles['date-input-icon']}`}\n >\n <Icon img=\"calendar\" color={color} />\n </span>\n }\n timeZone={timeZone}\n />\n <MobileTimepicker\n value={displayTimestamp}\n getDisplay={getTimeDisplay}\n onChange={changeTimestamp}\n id={`${htmlId}-time`}\n label={t('time', translationSettings)}\n icon={\n <span\n className={`${styles['combobox-icon']} ${styles['time-input-icon']}`}\n >\n <Icon img=\"time\" color={color} />\n </span>\n }\n timeZone={timeZone}\n />\n </div>\n <div className={styles['buttons-row']}>\n <button\n type=\"button\"\n className={styles['ready-button']}\n onClick={() =>\n onSubmit(displayTimestamp, departureOrArrivalCurrent)\n }\n >\n {t('ready', translationSettings)}\n </button>\n <button\n type=\"button\"\n className={styles['cancel-button']}\n onClick={onCancel}\n >\n {t('cancel', translationSettings)}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n\nMobilePickerModal.propTypes = {\n timeZone: PropTypes.string,\n departureOrArrival: PropTypes.oneOf(['departure', 'arrival']).isRequired,\n onNowClick: PropTypes.func.isRequired,\n lang: PropTypes.string.isRequired,\n color: PropTypes.string,\n onSubmit: PropTypes.func.isRequired,\n onCancel: PropTypes.func.isRequired,\n onAfterClose: PropTypes.func.isRequired,\n timestamp: PropTypes.number.isRequired,\n getTimeDisplay: PropTypes.func.isRequired,\n dateSelectItemCount: PropTypes.number.isRequired,\n getDateDisplay: PropTypes.func.isRequired,\n fontWeights: PropTypes.shape({\n medium: PropTypes.number.isRequired,\n }).isRequired,\n};\n\nMobilePickerModal.defaultProps = {\n color: '#007ac9',\n timeZone: 'Europe/Helsinki',\n};\n\nexport default MobilePickerModal;\n","import PropTypes from 'prop-types';\nimport React, { useState, useEffect, useRef, useMemo } from 'react';\nimport { DateTime, Settings } from 'luxon';\nimport uniqueId from 'lodash/uniqueId';\nimport { useTranslation } from 'react-i18next';\nimport Icon from '@digitransit-component/digitransit-component-icon';\nimport DesktopDatetimepicker from './DesktopDatetimepicker';\nimport styles from './styles.scss';\nimport { isMobile } from './mobileDetection';\nimport dateTimeInputIsSupported from './dateTimeInputIsSupported';\nimport MobilePickerModal from './MobilePickerModal';\n\nSettings.defaultLocale = 'en';\n\n/**\n * This component renders combobox style inputs for selecting date and time. This is a controlled component, timestamp is the current value of both inputs.\n * @param {Object} props\n *\n * @param {Number} props.timestamp Currently selected time as a unix timestamp in milliseconds. Set to null to signify that \"now\" is selected. Displayed time is updated in realtime when set to null\n * @param {function} props.onTimeChange Called with new timestamp when time input changes\n * @param {function} props.onDateChange Called with new timestamp when date input changes\n * @param {'arrival'|'departure'} props.departureOrArrival Determine if input is set to choose departure or arrival time\n * @param {function} props.onNowClick Called when \"depart now\" button is clicked\n * @param {function} props.onDepartureClick Called when \"departure\" button is clicked\n * @param {function} props.onArrivalClick Called when \"arrival\" button is clicked\n * @param {node} props.embedWhenClosed JSX element to render in the corner when input is closed\n * @param {node} props.embedWhenOpen JSX element to render when input is open\n * @param {string} props.lang Language selection\n * @param {number} props.serviceTimeRange Determine number of days shown in timepicker. Optional. default is 30.\n * @param {function} props.onOpen Determine what to do when timepicker is open. Optional. no default implementation.\n * @param {function} props.onClose Determine what to do when timepicker is closed. Optional. no default implementation.\n * @param {function} props.openPicker Determine if timepicker should be open in intial render. Optional. Default is undefined.\n *\n *\n * @example\n * <Datetimepicker\n * timestamp={1590133823000}\n * onTimeChange={(newTimestamp) => update(newTimestamp)}\n * onDateChange={(newTimestamp) => update(newTimestamp)}\n * departureOrArrival={'departure'}\n * onNowClick={() => setTimestampToNull()}\n * onDepartureClick={() => departureClicked()}\n * onArrivalClick={() => arrivalClicked()}\n * embedWhenClosed={<button />}\n * lang={'en'}\n * serviceTimeRange={15}\n * />\n */\nfunction Datetimepicker({\n timestamp,\n onTimeChange,\n onDateChange,\n departureOrArrival,\n onNowClick,\n onDepartureClick,\n onArrivalClick,\n embedWhenClosed,\n embedWhenOpen,\n lang,\n color,\n timeZone,\n onModalSubmit,\n fontWeights,\n serviceTimeRange,\n onOpen,\n onClose,\n openPicker,\n}) {\n Settings.defaultZone = timeZone;\n const [t] = useTranslation();\n const [isOpen, changeOpen] = useState(openPicker || false);\n const [displayTimestamp, changeDisplayTimestamp] = useState(\n timestamp || DateTime.now().toMillis(),\n );\n // timer for updating displayTimestamp in real time\n const [timerId, setTimer] = useState(null);\n // for input labels\n const [htmlId] = useState(uniqueId('datetimepicker-'));\n const [useMobileInputs] = useState(isMobile() && dateTimeInputIsSupported());\n const openPickerRef = useRef();\n const inputRef = useRef();\n const alertRef = useRef();\n\n const translationSettings = { lng: lang };\n\n useEffect(() => {\n Settings.defaultLocale = lang;\n }, [lang]);\n\n const nowSelected = timestamp === null;\n useEffect(() => {\n if (nowSelected) {\n changeDisplayTimestamp(DateTime.now().toMillis());\n } else {\n // clear timer\n if (timerId) {\n clearInterval(timerId);\n setTimer(null);\n }\n changeDisplayTimestamp(timestamp);\n }\n }, [timestamp]);\n\n // set timer to update displayTimestamp when minute changes if nowSelected\n useEffect(() => {\n if (!nowSelected) {\n return undefined;\n }\n if (timerId) {\n clearInterval(timerId);\n }\n const newId = setInterval(() => {\n const now = DateTime.now();\n const sameMinute = DateTime.fromMillis(displayTimestamp).hasSame(\n now,\n 'minute',\n );\n if (!sameMinute) {\n clearInterval(newId);\n setTimer(null);\n changeDisplayTimestamp(now.toMillis());\n }\n }, 5000);\n setTimer(newId);\n return () => clearInterval(newId);\n }, [displayTimestamp]);\n\n /**\n * @param {number} date Date in milliseconds since unix epoch\n * @returns {string} formatted date\n */\n const getDateDisplay = date => {\n const time = DateTime.fromMillis(date);\n const now = DateTime.now();\n let formatted;\n if (time.hasSame(now, 'day')) {\n formatted = t('today', translationSettings);\n formatted = `${formatted.charAt(0).toUpperCase()}${formatted.slice(1)}`;\n } else if (time.hasSame(now.plus({ days: 1 }), 'day')) {\n formatted = t('tomorrow', translationSettings);\n formatted = `${formatted.charAt(0).toUpperCase()}${formatted.slice(1)}`;\n } else {\n formatted = time.toFormat('ccc d.L.');\n }\n return formatted;\n };\n\n // param time is timestamp\n const getTimeDisplay = time => {\n return DateTime.fromMillis(time).toFormat('HH:mm');\n };\n\n // compute choices only when timestamp changes instead of every render\n const [timeChoices, dateChoices] = useMemo(() => {\n const selectedMoment = DateTime.fromMillis(\n timestamp || DateTime.now().toMillis(),\n );\n const timeSelectStartTime = selectedMoment.startOf('day').toMillis();\n const isMobileCurrently = isMobile();\n let newTimeChoices = [];\n let current = selectedMoment.startOf('day');\n while (current.hasSame(timeSelectStartTime, 'day')) {\n newTimeChoices.push(current.valueOf());\n if (isMobileCurrently) {\n current = current.plus({ minutes: 15 });\n } else {\n current = current.plus({ minutes: 1 });\n }\n }\n if (timestamp === null) {\n // if time is set to now\n // add times in 5 min intervals for next 30 mins\n const fiveMinutes = 1000 * 60 * 5;\n const nextFiveMin =\n Math.ceil(displayTimestamp / fiveMinutes) * fiveMinutes;\n const timesToAdd = Array(7)\n .fill()\n .map((_, i) => nextFiveMin + i * fiveMinutes);\n const closestIndexAfter = newTimeChoices\n .map(time => displayTimestamp - time)\n .findIndex(time => time <= 0);\n newTimeChoices.splice(closestIndexAfter, 0, ...timesToAdd);\n newTimeChoices = Array.from(new Set(newTimeChoices)); // remove duplicates\n }\n const dateSelectStartTime = DateTime.now().startOf('day').set({\n hour: selectedMoment.hour,\n minute: selectedMoment.minute,\n });\n const newDateChoices = Array(serviceTimeRange)\n .fill()\n .map((_, i) => dateSelectStartTime.plus({ days: i }).toMillis());\n return [newTimeChoices, newDateChoices];\n }, [timestamp]);\n\n function showScreenreaderCloseAlert() {\n if (alertRef.current) {\n alertRef.current.innerHTML = t('accessible-closed', translationSettings);\n setTimeout(() => {\n alertRef.current.innerHTML = null;\n }, 100);\n }\n }\n\n function showScreenreaderOpenAlert() {\n if (alertRef.current) {\n alertRef.current.innerHTML = t('accessible-opened', translationSettings);\n setTimeout(() => {\n alertRef.current.innerHTML = null;\n }, 100);\n }\n }\n\n const handleClose = () => {\n changeOpen(false);\n showScreenreaderCloseAlert();\n if (onClose) {\n onClose();\n }\n };\n\n const handleNowClick = () => {\n handleClose();\n onNowClick();\n };\n\n function renderOpen() {\n if (useMobileInputs) {\n return (\n isOpen && (\n <MobilePickerModal\n departureOrArrival={departureOrArrival}\n onNowClick={handleNowClick}\n lang={lang}\n color={color}\n onSubmit={(newTimestamp, newDepartureOrArrival) => {\n onModalSubmit(newTimestamp, newDepartureOrArrival);\n changeOpen(false);\n showScreenreaderCloseAlert();\n }}\n onCancel={handleClose}\n onAfterClose={() =>\n requestAnimationFrame(() => {\n openPickerRef.current?.focus();\n })\n }\n getTimeDisplay={getTimeDisplay}\n timeZone={timeZone}\n timestamp={displayTimestamp}\n getDateDisplay={getDateDisplay}\n dateSelectItemCount={serviceTimeRange}\n getDisplay={getTimeDisplay}\n fontWeights={fontWeights}\n />\n )\n );\n }\n return (\n <>\n <div\n className={`${styles['datetimepicker-open-container']} ${\n !isOpen ? styles.hidden : ''\n }`}\n >\n <div\n className={\n isOpen\n ? `${styles['top-row-container']} datetimepicker-top-row`\n : `${styles.hidden} datetimepicker-top-row`\n }\n >\n {' '}\n <span role=\"alert\" className={styles['sr-only']} ref={alertRef} />\n <span />\n {/* This empty span prevents a weird focus bug on chrome */}\n <span className={styles['departure-or-arrival-container']}>\n <label\n htmlFor={`${htmlId}-departure`}\n className={`${styles['radio-textbutton-label']}\n ${\n styles[\n departureOrArrival === 'departure' ? 'active' : undefined\n ]\n }`}\n >\n {t('departure', translationSettings)}\n <input\n id={`${htmlId}-departure`}\n name=\"departureOrArrival\"\n type=\"radio\"\n value=\"departure\"\n className={styles['radio-textbutton']}\n onChange={() => {\n onDepartureClick();\n }}\n checked={departureOrArrival === 'departure'}\n />\n </label>\n <label\n htmlFor={`${htmlId}-arrival`}\n className={`${styles['radio-textbutton-label']}\n ${\n styles[\n departureOrArrival === 'arrival' ? 'active' : undefined\n ]\n }`}\n >\n {t('arrival', translationSettings)}\n <input\n id={`${htmlId}-arrival`}\n name=\"departureOrArrival\"\n type=\"radio\"\n value=\"arrival\"\n className={styles['radio-textbutton']}\n onChange={() => {\n onArrivalClick();\n }}\n checked={departureOrArrival === 'arrival'}\n />\n </label>\n </span>\n <button\n id={`${htmlId}-now`}\n type=\"button\"\n className={styles['departure-now-button']}\n onClick={handleNowClick}\n ref={inputRef}\n >\n {t('departure-now', translationSettings)}\n </button>\n <span className={styles['right-edge']}>\n <button\n type=\"button\"\n className={styles['close-button']}\n aria-controls={`${htmlId}-root`}\n aria-expanded=\"true\"\n onClick={handleClose}\n >\n <span className={styles['close-icon']}>\n <Icon img=\"close\" color={color} />\n </span>\n <span className={styles['sr-only']}>\n {t('accessible-close', translationSettings)}\n </span>\n </button>\n </span>\n </div>\n <div\n className={\n isOpen\n ? `${styles['picker-container']}`\n : `${styles.hidden} datetimepicker-top-row`\n }\n >\n <span className={styles['combobox-left']}>\n <DesktopDatetimepicker\n value={displayTimestamp}\n onChange={newValue => {\n onDateChange(newValue);\n }}\n getDisplay={getDateDisplay}\n timeChoices={dateChoices}\n validate={() => null}\n icon={\n <span\n className={`${styles['combobox-icon']} ${styles['date-input-icon']}`}\n >\n <Icon img=\"calendar\" color={color} />\n </span>\n }\n id={`${htmlId}-date`}\n label={t('date', translationSettings)}\n disableTyping\n timeZone={timeZone}\n datePicker\n />\n </span>\n <span className={styles['combobox-right']}>\n <DesktopDatetimepicker\n value={displayTimestamp}\n onChange={newValue => {\n onTimeChange(newValue);\n }}\n getDisplay={getTimeDisplay}\n timeChoices={timeChoices}\n icon={\n <span\n className={`${styles['combobox-icon']} ${styles['time-input-icon']}`}\n >\n <Icon img=\"time\" color={color} />\n </span>\n }\n id={`${htmlId}-time`}\n label={t('time', translationSettings)}\n timeZone={timeZone}\n translationSettings={translationSettings}\n />\n </span>\n </div>\n </div>\n <span className={isOpen ? '' : styles.hidden}>{embedWhenOpen}</span>\n <div className={isOpen ? 'datetimepicker-bottom-row-open' : ''} />\n </>\n );\n }\n\n const formatToprowSummary = () => {\n if (nowSelected && departureOrArrival === 'departure') {\n return <span>{t('departure-now', translationSettings)}</span>;\n }\n const dateDisplay = getDateDisplay(displayTimestamp);\n const timeDisplay = getTimeDisplay(displayTimestamp);\n const summary = t(\n departureOrArrival === 'departure' ? 'departure' : 'arrival',\n translationSettings,\n );\n const isToday = DateTime.now().hasSame(\n DateTime.fromMillis(displayTimestamp),\n 'day',\n );\n const isTomorrow = DateTime.now()\n .plus({ days: 1 })\n .hasSame(DateTime.fromMillis(displayTimestamp), 'day');\n if (isToday) {\n return <span>{`${summary} ${timeDisplay}`}</span>;\n }\n if (isTomorrow) {\n return (\n <span>{`${summary} ${dateDisplay.toLowerCase()} ${timeDisplay}`}</span>\n );\n }\n return <span>{`${summary} ${dateDisplay} ${timeDisplay}`}</span>;\n };\n\n return (\n <fieldset\n className={styles['dt-datetimepicker']}\n id={`${htmlId}-root`}\n style={{\n '--color': `${color}`,\n '--font-weight-medium': fontWeights.medium,\n }}\n >\n <legend className={styles['sr-only']}>\n {t('accessible-title', translationSettings)}\n </legend>\n <span className={styles['sr-only']}>\n {t('accessible-update-instructions', translationSettings)}\n </span>\n <div\n className={\n !isOpen\n ? `${styles['top-row-container']} ${styles.closed} datetimepicker-top-row`\n : `${styles.hidden} datetimepicker-top-row`\n }\n >\n <label className={styles['label-open']} htmlFor={`${htmlId}-open`}>\n <span className={styles['time-icon']}>\n <Icon img=\"time\" color={color} />\n </span>\n <span className={styles['sr-only']}>\n {t('accessible-open', translationSettings)}\n </span>\n <span role=\"alert\" className={styles['sr-only']} ref={alertRef} />\n <button\n id={`${htmlId}-open`}\n type=\"button\"\n className={`${styles.textbutton} ${styles.active} ${styles['open-button']}`}\n aria-controls={`${htmlId}-root`}\n aria-expanded=\"false\"\n onClick={() => {\n changeOpen(true);\n showScreenreaderOpenAlert();\n if (onOpen) {\n onOpen();\n }\n }}\n ref={openPickerRef}\n >\n {formatToprowSummary()}\n <span className={styles['dropdown-icon']}>\n <Icon img=\"arrow-dropdown\" color={color} />\n </span>\n </button>\n </label>\n <span className={styles['right-edge']}>{embedWhenClosed}</span>\n </div>\n <div />\n {renderOpen()}\n </fieldset>\n );\n}\n\nDatetimepicker.propTypes = {\n timestamp: PropTypes.number,\n timeZone: PropTypes.string,\n onTimeChange: PropTypes.func.isRequired,\n onDateChange: PropTypes.func.isRequired,\n departureOrArrival: PropTypes.oneOf(['departure', 'arrival']).isRequired,\n onNowClick: PropTypes.func.isRequired,\n onDepartureClick: PropTypes.func.isRequired,\n onArrivalClick: PropTypes.func.isRequired,\n embedWhenClosed: PropTypes.node,\n embedWhenOpen: PropTypes.node,\n lang: PropTypes.string.isRequired,\n color: PropTypes.string,\n onModalSubmit: PropTypes.func.isRequired,\n fontWeights: PropTypes.shape({\n medium: PropTypes.number.isRequired,\n }).isRequired,\n serviceTimeRange: PropTypes.number.isRequired,\n onOpen: PropTypes.func,\n onClose: PropTypes.func,\n openPicker: PropTypes.bool,\n};\n\nDatetimepicker.defaultProps = {\n timestamp: null,\n embedWhenClosed: null,\n embedWhenOpen: null,\n color: '#007ac9',\n timeZone: 'Europe/Helsinki',\n onOpen: null,\n onClose: null,\n openPicker: undefined,\n};\n\nexport default Datetimepicker;\n","/**\n * Detect if input type=\"date\" and type=\"time\" are supported in by the browser\n *\n * @return {boolean}\n */\nfunction dateTimeInputIsSupported() {\n if (typeof window === 'undefined' || window === null) {\n return false;\n }\n const elem = document.createElement('input');\n elem.type = 'date';\n if (elem.type !== 'date') {\n return false;\n }\n elem.type = 'time';\n if (elem.type !== 'time') {\n return false;\n }\n return true;\n}\n\nexport default dateTimeInputIsSupported;\n","const translations = {\n de: {\n translation: {\n today: 'Heute',\n tomorrow: 'Morgen',\n 'accessible-close': 'Schließe die Auswahl',\n 'accessible-closed': 'Auswahl geschlossen',\n 'accessible-open': 'Öffne die Auswahl',\n 'accessible-opened': 'Auswahl geöffnet',\n 'accessible-title': 'Datum und Uhrzeitauswahl',\n arrival: 'Ankunft',\n date: 'Datum',\n departure: 'Abfahrt',\n 'departure-now': 'Abfahrt jetzt',\n 'choose-time': 'Zeit wählen',\n ready: 'Fertig',\n time: 'Zeit',\n cancel: 'Abbrechen',\n },\n },\n en: {\n translation: {\n today: 'Today',\n tomorrow: 'Tomorrow',\n 'accessible-close': 'Close the picker',\n 'accessible-closed': 'Timepicker closed',\n 'accessible-open': 'Open the picker',\n 'accessible-opened': 'Timepicker opened',\n 'accessible-title': 'Date and timepicker',\n 'accessible-update-instructions':\n 'Changing time parameters will trigger a new search.',\n arrival: 'Arrival',\n date: 'Date',\n departure: 'Departure',\n 'departure-now': 'Leaving now',\n time: 'Time',\n 'choose-time': 'Choose time',\n ready: 'Ready',\n cancel: 'Cancel',\n 'invalid-input': 'The time you entered is invalid',\n },\n },\n fi: {\n translation: {\n today: 'Tänään',\n tomorrow: 'Huomenna',\n 'accessible-close': 'Sulje valitsin',\n 'accessible-closed': 'Valitsin suljettu',\n 'accessible-open': 'Avaa valitsin',\n 'accessible-opened': 'Valitsin avattu',\n 'accessible-title': 'Aika- ja päivämäärävalitsin',\n 'accessible-update-instructions':\n 'Aikavalintojen muuttaminen laukaisee uuden haun.',\n arrival: 'Perillä',\n date: 'Päivä',\n departure: 'Lähtöaika',\n 'departure-now': 'Lähtö nyt',\n time: 'Aika',\n 'choose-time': 'Valitse aika',\n ready: 'Valmis',\n cancel: 'Peruuta',\n 'invalid-input': 'Syöttämäsi aika on virheellinen',\n },\n },\n pl: {\n translation: {\n today: 'Dziś',\n tomorrow: 'Jutro',\n 'accessible-close': 'Zamknij wybornik',\n 'accessible-closed': 'Zamknięto wybornik',\n 'accessible-open': 'Otwórz wybornik',\n 'accessible-opened': 'Otwarto wybornik',\n 'accessible-title': 'Wybór daty i godziny',\n 'accessible-update-instructions':\n 'Zmiana wybranej godziny wywoła nowe wyszukiwanie.',\n arrival: 'Przyjazd',\n date: 'Data',\n departure: 'Wyjazd',\n 'departure-now': 'Wyjeżdżam teraz',\n time: 'Godzina',\n 'choose-time': 'Wybierz godzinę',\n ready: 'Gotowe',\n cancel: 'Anuluj',\n 'invalid-input': 'Wprowadzona godzina jest nieprawidłowa',\n },\n },\n sv: {\n translation: {\n today: 'I dag',\n tomorrow: 'I morgon',\n 'accessible-close': 'Stäng väljaren',\n 'accessible-closed': 'Väljaren stängde',\n 'accessible-open': 'Öppna väljaren',\n 'accessible-opened': 'Väljaren öppnade',\n 'accessible-title': 'Tid- och datumväljaren',\n 'accessible-update-instructions':\n 'Om du ändrar tiderna, startas en ny sökning automatiskt.',\n arrival: 'Anländer',\n date: 'Datum',\n departure: 'Avgångstid',\n 'departure-now': 'Avgår nu',\n time: 'Tid',\n 'choose-time': 'Välj tid',\n ready: 'Färdig',\n cancel: 'Avbryt',\n 'invalid-input': 'Tiden du angav är felaktig',\n },\n },\n};\n\nexport default translations;\n","import { createInstance } from 'i18next';\nimport translations from './translations';\n\nconst i18n = createInstance({\n fallbackLng: 'fi',\n // debug: true,\n resources: translations,\n defaultNS: 'translation',\n react: {\n useSuspense: true,\n },\n});\n\ni18n.init();\n\nexport default i18n;\n","import PropTypes from 'prop-types';\nimport React, { useState, useEffect } from 'react';\nimport { I18nextProvider } from 'react-i18next';\nimport { Settings, DateTime } from 'luxon';\nimport debounce from 'lodash/debounce';\nimport Datetimepicker from './helpers/Datetimepicker';\nimport i18n from './helpers/i18n';\n\n/**\n * This component renders an input to choose a date and time. Renders separate input fields for date and time selection. Values for timestamp and arriveBy correspond to Digitransit query params time and arriveBy. This component will display a native date input on mobile and a custom one for desktop. Mobile detection is done by parsing user agent.\n *\n * @alias Datetimepicker\n *\n * @param {Object} props\n *\n * @param {boolean} props.realtime Determine if selected time should be updated in realtime when 'now' is selected.\n * @param {Number} props.initialTimestamp Initial value for selected time. Unix timestamp in seconds. Updating this will change timepicker value but the correct value is kept in component state even if this is not updated.\n * @param {boolean} props.initialArriveBy Initial value for arriveBy. Determines if picker is in arrival mode (true) or departure mode (false). Correct value is kept in component state even if this is not updated. Changing this will also trigger change in the component.\n * @param {function} props.onTimeChange Called with (time, arriveBy) when time input changes. time is number timestamp in seconds, arriveBy is boolean\n * @param {function} props.onDateChange Called with (time, arriveBy) when date input changes. time is number timestamp in seconds, arriveBy is boolean\n * @param {function} props.onNowClick Called when \"depart now\" button is clicked. time is current input value in seconds\n * @param {function} props.onDepartureClick Called with (time) when \"departure\" button is clicked. time is current input value in seconds\n * @param {function} props.onArrivalClick Called with (time) when \"arrival\" button is clicked. time is current input value in seconds\n * @param {node} props.embedWhenClosed JSX element to render in the corner when input is closed\n * @param {node} props.embedWhenOpen JSX element to render when input is open\n * @param {string} props.lang Language selection. Default 'en'\n * @param {number} props.serviceTimeRange Determine number of days shown in timepicker. Optional. default is 30.\n * @param {function} props.onOpen Determine what to do when timepicker is open. Optional. no default implementation.\n * @param {function} props.onClose Determine what to do when timepicker is closed. Optional. no default implementation.\n * @param {function} props.openPicker Determine if timepicker should be open in intial render. Optional. Default is undefined.\n * @example\n * <Datetimepicker\n * realtime={true}\n * initialTimestamp={1590133823}\n * initialArriveBy={false}\n * onTimeChange={(time, arriveBy) => changeUrl(time, arriveBy)}\n * onDateChange={(time, arriveBy) => changeUrl(time, arriveBy)}\n * onNowClick={(time) => changeUrl(undefined, undefined)}\n * onDepartureClick={(time) => changeUrl(time, 'true')}\n * onArrivalClick={(time) => changeUrl(time, undefined)}\n * embedWhenClosed={<button />}\n * lang={'en'}\n * serviceTimeRange={15}\n * />\n */\nfunction DatetimepickerStateContainer({\n realtime,\n initialArriveBy,\n initialTimestamp,\n onDepartureClick,\n onArrivalClick,\n onTimeChange,\n onDateChange,\n onNowClick,\n embedWhenClosed,\n embedWhenOpen,\n lang,\n color,\n timeZone,\n fontWeights,\n serviceTimeRange,\n onOpen,\n onClose,\n openPicker,\n}) {\n Settings.defaultLocale = lang;\n Settings.defaultZone = timeZone;\n const initialNow = realtime ? null : DateTime.now().toMillis();\n const [timestamp, changeTimestampState] = useState(\n initialTimestamp ? initialTimestamp * 1000 : initialNow,\n );\n const [departureOrArrival, changeDepartureOrArrival] = useState(\n initialArriveBy === true ? 'arrival' : 'departure',\n );\n\n // update state if props change\n useEffect(() => {\n const bothNull = timestamp === null && initialTimestamp === undefined;\n const oneNull = timestamp === null || initialTimestamp === undefined;\n const sameTime = Math.round(timestamp / 1000) === initialTimestamp;\n const timestampChanged = !bothNull && (oneNull || !sameTime);\n if (timestampChanged) {\n if (initialTimestamp === undefined) {\n changeTimestampState(null);\n } else {\n changeTimestampState(initialTimestamp * 1000);\n }\n }\n if (!initialArriveBy === (departureOrArrival === 'arrival')) {\n changeDepartureOrArrival(\n initialArriveBy === true ? 'arrival' : 'departure',\n );\n }\n }, [initialTimestamp, initialArriveBy]);\n\n const timeChanged = debounce(newTime => {\n if (newTime === null) {\n changeTimestampState(DateTime.now().toMillis());\n onTimeChange(\n DateTime.now().toUnixInteger(),\n departureOrArrival === 'arrival',\n );\n return;\n }\n changeTimestampState(newTime);\n onTimeChange(Math.round(newTime / 1000), departureOrArrival === 'arrival');\n }, 10);\n\n const dateChanged = debounce(newDate => {\n if (newDate === null) {\n changeTimestampState(DateTime.now().toMillis());\n onDateChange(\n DateTime.now().toUnixInteger(),\n departureOrArrival === 'arrival',\n );\n return;\n }\n changeTimestampState(newDate);\n onDateChange(Math.round(newDate / 1000), departureOrArrival === 'arrival');\n }, 10);\n\n const nowClicked = () => {\n changeDepartureOrArrival('departure');\n const newTimestamp = realtime ? null : DateTime.now().toMillis();\n changeTimestampState(newTimestamp);\n onNowClick(Math.round(newTimestamp / 1000));\n };\n\n const departureClicked = () => {\n let changed = false;\n let newTime = timestamp;\n if (timestamp === null) {\n const now = DateTime.now().toMillis();\n changeTimestampState(now);\n newTime = now;\n changed = true;\n }\n if (departureOrArrival !== 'departure') {\n changeDepartureOrArrival('departure');\n changed = true;\n }\n if (changed) {\n onDepartureClick(Math.round(newTime / 1000));\n }\n };\n\n const arrivalClicked = () => {\n let changed = false;\n let newTime = timestamp;\n if (timestamp === null) {\n const now = DateTime.now().toMillis();\n changeTimestampState(now);\n newTime = now;\n changed = true;\n }\n if (departureOrArrival !== 'arrival') {\n changeDepartureOrArrival('arrival');\n changed = true;\n }\n if (changed) {\n onArrivalClick(Math.round(newTime / 1000));\n }\n };\n const onModalSubmit = (time, mode) => {\n changeTimestampState(time);\n changeDepartureOrArrival(mode);\n onTimeChange(Math.round(time / 1000), mode === 'arrival', true);\n };\n\n return (\n <I18nextProvider i18n={i18n}>\n <Datetimepicker\n timestamp={timestamp}\n onTimeChange={timeChanged}\n onDateChange={dateChanged}\n departureOrArrival={departureOrArrival}\n onNowClick={nowClicked}\n onDepartureClick={departureClicked}\n onArrivalClick={arrivalClicked}\n embedWhenClosed={embedWhenClosed}\n embedWhenOpen={embedWhenOpen}\n lang={lang}\n color={color}\n timeZone={timeZone}\n onModalSubmit={onModalSubmit}\n fontWeights={fontWeights}\n serviceTimeRange={serviceTimeRange}\n onOpen={onOpen}\n onClose={onClose}\n openPicker={openPicker}\n />\n </I18nextProvider>\n );\n}\n\nDatetimepickerStateContainer.propTypes = {\n realtime: PropTypes.bool,\n initialTimestamp: PropTypes.number,\n initialArriveBy: PropTypes.bool,\n onDepartureClick: PropTypes.func.isRequired,\n onArrivalClick: PropTypes.func.isRequired,\n onTimeChange: PropTypes.func.isRequired,\n onDateChange: PropTypes.func.isRequired,\n onNowClick: PropTypes.func.isRequired,\n embedWhenClosed: PropTypes.node,\n embedWhenOpen: PropTypes.node,\n lang: PropTypes.string,\n color: PropTypes.string,\n timeZone: PropTypes.string,\n fontWeights: PropTypes.shape({\n medium: PropTypes.number,\n }),\n serviceTimeRange: PropTypes.number,\n onOpen: PropTypes.func,\n onClose: PropTypes.func,\n openPicker: PropTypes.bool,\n};\n\nDatetimepickerStateContainer.defaultProps = {\n realtime: false,\n initialArriveBy: undefined,\n initialTimestamp: undefined,\n embedWhenClosed: null,\n embedWhenOpen: null,\n lang: 'en',\n color: '#007ac9',\n timeZone: 'Europe/Helsinki',\n fontWeights: {\n medium: 500,\n },\n onOpen: null,\n onClose: null,\n openPicker: undefined,\n serviceTimeRange: 30,\n};\n\nexport default DatetimepickerStateContainer;\n"],"names":["parseTypedTime","typedValue","actualValue","length","split","every","n","Number","isInteger","slice","validateClock","hours","minutes","hoursValid","isNaN","minutesValid","validateInput","inputValue","includes","startsWith","values","concat","substring","getTs","currentTimestamp","trimmed","trim","match","splitter","DateTime","fromMillis","set","hour","minute","second","millisecond","valueOf","DesktopDatetimepicker","value","onChange","getDisplay","timeChoices","id","label","icon","disableTyping","timeZone","datePicker","translationSettings","Settings","defaultZone","t","useTranslation","displayValue","changeDisplayValue","useState","typing","setTyping","showAllOptions","setShowAllOptions","invalidInput","setinvalidInput","useEffect","handleTimestamp","newValue","asNumber","e","options","map","time","toString","closestOptions","filter","o","closestOption","reduce","a","b","Math","abs","undefined","inputId","labelId","ariaError","React","createElement","className","styles","htmlFor","Select","ariaLiveMessages","guidance","context","isDisabled","onFilter","onFocus","itemLabel","currentTime","toFormat","ts","components","IndicatorsContainer","cx","classNamePrefix","onInputChange","action","str","valid","test","isinvalidInput","validated","noOptionsMessage","filterOption","option","input","_input$split$","completeInput","isMod15","minuteInput","inputH","inputM","optH","optM","total","filterOptions","isValidHour","comp","controlShouldRenderValue","tabSelectsValue","placeholder","target","select","onBlur","onKeyDown","key","isSearchable","isMobile","userAgent","navigator","vendor","window","opera","css","ref","insertAt","document","head","getElementsByTagName","style","type","firstChild","insertBefore","appendChild","styleSheet","cssText","createTextNode","process","env","NODE_ENV","propTypes","PropTypes","number","isRequired","func","arrayOf","string","node","bool","shape","lng","defaultProps","MobileDatepicker","itemCount","startTime","open","changeOpen","scrollRef","useRef","dateChoices","Array","fill","_","i","plus","days","toMillis","scrollIndex","findIndex","useLayoutEffect","current","scrollTop","nativeInput","toLowerCase","indexOf","date","Autosuggest","suggestions","getSuggestionValue","s","renderSuggestion","onSuggestionsFetchRequested","shouldRenderSuggestions","inputProps","readOnly","focusInputOnSuggestionClick","onSuggestionsClearRequested","renderSuggestionsContainer","containerProps","children","otherRefs","r","hasOwnProperty","call","objectWithoutPropertiesLoose","Object","getOwnPropertySymbols","propertyIsEnumerable","_objectWithoutProperties","_excluded","assign","tabIndex","elem","theme","MobileTimepicker","changeInputValue","isValidInput","setValidInput","showError","inputMode","maxLength","setSelectionRange","event","replace","charAt","actual","timestamp","MobilePickerModal","departureOrArrival","onNowClick","lang","color","onSubmit","onCancel","getTimeDisplay","dateSelectItemCount","getDateDisplay","fontWeights","onAfterClose","displayTimestamp","changeTimestamp","departureOrArrivalCurrent","changeDepartureOrArrival","htmlId","uniqueId","dateSelectStartTime","now","startOf","Modal","appElement","querySelector","isOpen","overlayClassName","medium","onClick","name","checked","Icon","img","Datetimepicker","onTimeChange","onDateChange","onDepartureClick","onArrivalClick","embedWhenClosed","embedWhenOpen","onModalSubmit","serviceTimeRange","onOpen","onClose","openPicker","changeDisplayTimestamp","timerId","setTimer","useMobileInputs","dateTimeInputIsSupported","openPickerRef","inputRef","alertRef","defaultLocale","nowSelected","clearInterval","newId","setInterval","hasSame","formatted","toUpperCase","useMemo","selectedMoment","timeSelectStartTime","isMobileCurrently","newTimeChoices","push","fiveMinutes","nextFiveMin","ceil","timesToAdd","closestIndexAfter","splice","from","Set","showScreenreaderCloseAlert","innerHTML","setTimeout","handleClose","handleNowClick","hidden","closed","role","textbutton","active","formatToprowSummary","dateDisplay","timeDisplay","summary","isToday","isTomorrow","newTimestamp","newDepartureOrArrival","requestAnimationFrame","_openPickerRef$curren","focus","Fragment","validate","dateTimeCombined","oneOf","i18n","createInstance","fallbackLng","resources","de","translation","today","tomorrow","arrival","departure","ready","cancel","en","fi","pl","sv","defaultNS","react","useSuspense","DatetimepickerStateContainer","realtime","initialArriveBy","initialTimestamp","initialNow","changeTimestampState","bothNull","oneNull","sameTime","round","timeChanged","debounce","newTime","toUnixInteger","dateChanged","newDate","I18nextProvider","nowClicked","departureClicked","changed","arrivalClicked","mode","init"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/helpers/utils.js","../src/helpers/DesktopDatetimepicker.js","../src/helpers/mobileDetection.js","../../../../node_modules/style-inject/dist/style-inject.es.js","../src/helpers/MobileDatepicker.js","../src/helpers/MobileTimepicker.js","../src/helpers/MobilePickerModal.js","../src/helpers/Datetimepicker.js","../src/helpers/dateTimeInputIsSupported.js","../src/helpers/translations.js","../src/helpers/i18n.js","../src/index.js"],"sourcesContent":["import { DateTime } from 'luxon';\n\n/**\n * Handle typing time and adding necessary :\n *\n * @param {string} typedValue\n *\n * @return {string}\n */\nexport function parseTypedTime(typedValue) {\n let actualValue = typedValue;\n if (\n actualValue.length === 3 &&\n actualValue.split('').every(n => Number.isInteger(Number(n)))\n ) {\n // add ':' if user types three numbers in a row\n if (Number(actualValue.slice(0, 2)) <= 23) {\n actualValue = `${actualValue.slice(0, 2)}:${actualValue[2]}`;\n } else {\n actualValue = `${actualValue[0]}:${actualValue.slice(1)}`;\n }\n }\n return actualValue;\n}\n\nconst validateClock = (hours, minutes) => {\n const hoursValid = !Number.isNaN(hours) && hours >= 0 && hours <= 23;\n const minutesLen = minutes.length;\n const minutesValid =\n minutesLen === 2\n ? !Number.isNaN(minutes) && Number(minutes) >= 0 && Number(minutes <= 59)\n : !Number.isNaN(minutes) && Number(minutes) >= 0 && Number(minutes <= 5);\n return hoursValid && minutesValid;\n};\n\nexport function validateInput(inputValue) {\n // We don't accept seconds in the input\n if (inputValue.split(':').length > 2) {\n return false;\n }\n if (inputValue.length <= 2) {\n // Too many options, don't validate\n return true;\n }\n if (inputValue.length === 3) {\n let hours;\n let minutes;\n if (inputValue.includes(':')) {\n [hours, minutes] = inputValue.split(':');\n } else if (inputValue.startsWith('0')) {\n hours = inputValue.substring(0, inputValue.length - 1);\n minutes = inputValue.substring(inputValue.length - 1 || 0);\n if (Number(minutes) > 5) {\n return false;\n }\n } else {\n // This is how basically moment handles string formatting.\n // If the first letter of the string is 1, then rest are minutes.\n // if the first letter is 2, then if second letter is 0,1,2 or 3, then second letter is hour, else rest are minutes\n // else, first letter is hour, rest of them are minutes.\n const values = inputValue.split('');\n if (Number(values[0]) === 1) {\n [hours, minutes] = [values[0].concat(values[1]), values[2]];\n } else if (Number(values[0]) === 2) {\n if (Number(values[1] <= 3)) {\n [hours, minutes] = [values[0].concat(values[1]), values[2]];\n } else {\n [hours, minutes] = [values[0], values[1].concat(values[2])];\n }\n } else {\n [hours, minutes] = [values[0], values[1].concat(values[2])];\n }\n return validateClock(hours, minutes);\n }\n return validateClock(hours, minutes);\n }\n if (inputValue.length === 5 || inputValue.length === 4) {\n const values = inputValue.split(':');\n const hours = values[0];\n const minutes = values[1];\n if (\n inputValue.startsWith('0') &&\n minutes.length === 1 &&\n Number(minutes) > 5\n ) {\n return false;\n }\n\n return validateClock(hours, minutes);\n }\n return true;\n}\n\nexport const getTs = (inputValue, currentTimestamp) => {\n const trimmed = inputValue.trim();\n if (trimmed.match(/^[0-9]{1,2}(\\.|:)[0-9]{2}$/) !== null) {\n const splitter = trimmed.includes('.') ? '.' : ':';\n const values = trimmed.split(splitter);\n const hours = Number(values[0]);\n const hoursValid = !Number.isNaN(hours) && hours >= 0 && hours <= 23;\n const minutes = Number(values[1]);\n const minutesValid =\n !Number.isNaN(minutes) && minutes >= 0 && minutes <= 59;\n if (!minutesValid || !hoursValid) {\n return null;\n }\n const newStamp = DateTime.fromMillis(currentTimestamp)\n .set({\n hour: hours,\n minute: minutes,\n second: 0,\n millisecond: 0,\n })\n .valueOf();\n return newStamp;\n }\n return null;\n};\n\nexport default { parseTypedTime, validateInput, getTs };\n","import PropTypes from 'prop-types';\nimport React, { useState, useEffect } from 'react';\nimport { DateTime, Settings } from 'luxon';\nimport { useTranslation } from 'react-i18next';\nimport Select from 'react-select';\nimport cx from 'classnames';\nimport { parseTypedTime, validateInput, getTs } from './utils';\nimport styles from './styles.scss';\n\n/**\n * Component to display a date or time input on desktop.\n *\n * @param {Object} props\n * @param {Number} props.value Currently selected time. Unix timestamp in milliseconds\n * @param {function} props.onChange This is called with new timestamp when input is changed\n * @param {function} props.getDisplay Function to get a string representation from a timestamp\n * @param {array} props.timeChoices Array of timestamps to choose from\n * @param {string} id Id prefix for labels and aria attributes. Should be unique in page\n * @param {string} label Text to show as input label\n * @param {node} icon JSX for icon to show in input\n * @param {boolean} disableTyping Set to true to disable typing in the input\n * @param {boolean} datePicker Is the picker DatePicker or TimePicker\n *\n * @example\n * <DesktopDatetimepicker\n * value={1590133823000}\n * onChange={timestamp => update(timestamp)}\n * getDisplay={timestamp => formatTime(timestamp)}\n * timeChoices={[1590133823000]}\n * id=\"timeinput\"\n * icon=\"<Icon />\"\n * disableTyping={false} // can be omitted if not true\n * datePicker={true} // can be omitted if not true\n */\nfunction DesktopDatetimepicker({\n value,\n onChange,\n getDisplay,\n timeChoices,\n id,\n label,\n icon,\n disableTyping,\n timeZone,\n datePicker,\n translationSettings,\n}) {\n Settings.defaultZone = timeZone;\n const [t] = useTranslation();\n const [displayValue, changeDisplayValue] = useState(getDisplay(value));\n const [typing, setTyping] = useState(false);\n const [showAllOptions, setShowAllOptions] = useState(true);\n const [invalidInput, setinvalidInput] = useState(false);\n useEffect(() => {\n changeDisplayValue(getDisplay(value));\n if (!datePicker) {\n setinvalidInput(false);\n }\n }, [value]);\n\n // newValue is string\n const handleTimestamp = newValue => {\n const asNumber = Number(newValue);\n try {\n DateTime.fromMillis(asNumber);\n } catch (e) {\n // If the value is not a valid timestamp, we don't change it\n return;\n }\n onChange(asNumber);\n };\n function isinvalidInput(str) {\n const regex = /[a-zA-Z§ÄäÖö.-\\s]/g;\n if (str.length < displayValue?.length) {\n const valid = validateInput(str);\n setinvalidInput(!valid);\n\n return true;\n }\n if (regex.test(str)) {\n return false;\n }\n const time = str.length > 5 ? str.slice(0, -1) : str;\n const valid = validateInput(time);\n setinvalidInput(!valid);\n return str.length <= 5;\n }\n const onInputChange = (newValue, { action }) => {\n if (action === 'menu-close') {\n setShowAllOptions(true);\n } else if (showAllOptions) {\n setShowAllOptions(false);\n }\n if (disableTyping || (newValue && !isinvalidInput(newValue))) {\n return;\n }\n if (action === 'input-change') {\n const validated = parseTypedTime(newValue);\n changeDisplayValue(validated);\n setTyping(true);\n }\n };\n const options = timeChoices.map(time => {\n return { value: time.toString(), label: getDisplay(time) };\n });\n\n // Time picker has a list of minutes, instead of 15 minutes. We need to filter those out\n // so closest option will show up in the list.\n const closestOptions = datePicker\n ? options\n : options.filter(o => o.label.split(':')[1] % 15 === 0);\n const closestOption =\n closestOptions.length > 0\n ? closestOptions?.reduce((a, b) =>\n Math.abs(value - a.value) < Math.abs(value - b.value) ? a : b,\n )\n : undefined;\n const inputId = `${id}-input`;\n const labelId = `${id}-label`;\n const filterOptions = (option, input) => {\n const hour = input.length <= 2 ? input : input.split(':')[0];\n const isValidHour = /^([0-1]?[0-9]|2[0-3])$/.test(hour);\n const comp = hour.length === 1 ? '0'.concat(input) : input;\n return isValidHour\n ? option.label.split(':')[0] === comp.split(':')[0]\n : true;\n };\n const ariaError = t('invalid-input', translationSettings);\n return (\n <label className={styles['combobox-container']} htmlFor={inputId}>\n <span className={styles['sr-only']} id={labelId}>\n {label} {displayValue}\n </span>\n {icon}\n <Select\n aria-labelledby={labelId}\n ariaLiveMessages={{\n guidance: context => {\n // When user types invalid value, isDisabled becomes undefined instead of false\n if (context.isDisabled === undefined && invalidInput) {\n return ariaError;\n }\n return '.'; // this can't be empty for some reason\n },\n onChange: () => {\n return '';\n },\n onFilter: () => {\n return '';\n },\n onFocus: ({ context, label: itemLabel }) => {\n if (context === 'menu') {\n return itemLabel;\n }\n return '';\n },\n }}\n options={options}\n inputId={inputId}\n onChange={time => {\n const currentTime = DateTime.fromMillis(value).toFormat('HH:mm');\n const ts = getTs(displayValue, value);\n if (typing) {\n if (ts !== null) {\n if (currentTime !== displayValue && time.value === value) {\n handleTimestamp(ts);\n } else {\n handleTimestamp(time.value);\n }\n setTyping(false);\n } else {\n if (time.value !== value) {\n handleTimestamp(time.value);\n } else {\n // reset value\n changeDisplayValue(getDisplay(value));\n }\n setTyping(false);\n }\n if (!datePicker) {\n setinvalidInput(false);\n }\n return;\n }\n if (!datePicker) {\n setinvalidInput(false);\n }\n handleTimestamp(time.value);\n }}\n components={{\n IndicatorsContainer: () => null,\n }}\n className={cx(\n styles['datetimepicker-select-container'],\n invalidInput ? 'datetimepicker-invalid-input' : '',\n )}\n classNamePrefix=\"datetimepicker-select\"\n onInputChange={onInputChange}\n inputValue={!disableTyping && displayValue}\n value={closestOption}\n noOptionsMessage={() => {\n return '';\n }}\n filterOption={(option, input) => {\n if (datePicker) {\n return true;\n }\n const completeInput =\n input.length === 5 ||\n (input.length === 4 && input.split(':')[0].length === 1);\n const isMod15 = option.label.split(':')[1] % 15 === 0;\n const minuteInput = input.split(':')[1]?.length === 1;\n\n if (showAllOptions && isMod15) {\n return true;\n }\n if (minuteInput) {\n const inputH =\n input.split(':')[0].length === 1\n ? '0'.concat(input.split(':')[0])\n : input.split(':')[0];\n const inputM = input.split(':')[1];\n const optH = option.label.split(':')[0];\n const optM = option.label.split(':')[1];\n if (inputH === optH) {\n const time = Number(inputM) * 10;\n const total = Number(optM) - time;\n if (total >= 0 && total <= 9) {\n return true;\n }\n return false;\n }\n }\n if (completeInput && !showAllOptions) {\n return input.length === 4\n ? '0'.concat(input) === option.label\n : input === option.label;\n }\n if (isMod15) {\n return filterOptions(option, input);\n }\n\n return false;\n }}\n controlShouldRenderValue={disableTyping}\n tabSelectsValue={false}\n placeholder=\"\"\n onFocus={e => {\n if (!disableTyping) {\n e.target.select();\n }\n }}\n onBlur={() => {\n // removing focus also locks in value\n if (typing) {\n const validated = getTs(displayValue, value);\n if (validated !== null) {\n handleTimestamp(validated);\n setTyping(false);\n } else {\n changeDisplayValue(getDisplay(value));\n setTyping(false);\n }\n }\n if (!datePicker) {\n setinvalidInput(false);\n }\n }}\n onKeyDown={e => {\n if (['ArrowDown', 'ArrowUp'].includes(e.key)) {\n setTyping(false);\n }\n }}\n isSearchable={!disableTyping}\n />\n </label>\n );\n}\nDesktopDatetimepicker.propTypes = {\n value: PropTypes.number.isRequired,\n onChange: PropTypes.func.isRequired,\n getDisplay: PropTypes.func.isRequired,\n timeChoices: PropTypes.arrayOf(PropTypes.number).isRequired,\n id: PropTypes.string.isRequired,\n label: PropTypes.node.isRequired,\n icon: PropTypes.node.isRequired,\n disableTyping: PropTypes.bool,\n timeZone: PropTypes.string,\n datePicker: PropTypes.bool,\n translationSettings: PropTypes.shape({ lng: PropTypes.string.isRequired }),\n};\n\nDesktopDatetimepicker.defaultProps = {\n disableTyping: false,\n timeZone: 'Europe/Helsinki',\n datePicker: false,\n translationSettings: { lng: 'fi' },\n};\n\nexport default DesktopDatetimepicker;\n","/**\n * Detect if user is on a mobile device by parsing userAgent. This is not 100% reliable but close enough.\n *\n * @return {boolean}\n */\nfunction isMobile() {\n const userAgent = navigator.userAgent || navigator.vendor || window.opera;\n const mobile =\n /(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(\n userAgent,\n );\n return mobile;\n}\n\n/**\n * Detect if user is on an android device. Not 100% reliable.\n */\nfunction isAndroid() {\n const userAgent = navigator.userAgent.toLowerCase();\n return userAgent.indexOf('android') > -1;\n}\n\nexport { isMobile, isAndroid };\n","function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n","import PropTypes from 'prop-types';\nimport React from 'react';\nimport { DateTime, Settings } from 'luxon';\nimport { useSelect } from 'downshift';\nimport cx from 'classnames';\nimport styles from './styles.scss';\nimport { isAndroid } from './mobileDetection';\n\nconst AndroidSelect = ({\n value,\n dateChoices,\n id,\n getDisplay,\n onChange,\n labelId,\n inputId,\n}) => {\n const items = dateChoices.map(date => ({\n value: date,\n label: getDisplay(date),\n }));\n const selectedItem =\n items.find(option => option.value === value) || items[0] || null;\n const {\n isOpen,\n getToggleButtonProps,\n getMenuProps,\n getItemProps,\n highlightedIndex,\n } = useSelect({\n selectedItem,\n items,\n itemToString: item => item?.label ?? '',\n onSelectedItemChange: ({ selectedItem: nextSelectedItem }) => {\n if (nextSelectedItem) {\n onChange(nextSelectedItem.value);\n }\n },\n id,\n });\n\n return (\n <div className={styles.container}>\n <div\n {...getToggleButtonProps({ 'aria-labelledby': labelId, id: inputId })}\n >\n <div className={styles.input}>{selectedItem.label}</div>\n </div>\n <div\n className={cx([styles.suggestionsContainerOpen, !isOpen && 'hidden'])}\n >\n <ul {...getMenuProps()}>\n {isOpen &&\n items.map((option, index) => (\n <li\n key={option.value}\n className={cx([\n styles.suggestion,\n index === highlightedIndex && styles.suggestionHighlighted,\n ])}\n {...getItemProps({ index })}\n >\n <span>{option.label}</span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n );\n};\n\nAndroidSelect.propTypes = {\n value: PropTypes.number.isRequired,\n dateChoices: PropTypes.arrayOf(PropTypes.number).isRequired,\n id: PropTypes.string.isRequired,\n getDisplay: PropTypes.func.isRequired,\n onChange: PropTypes.func.isRequired,\n labelId: PropTypes.string.isRequired,\n inputId: PropTypes.string.isRequired,\n};\n\n/**\n * Component to display a date input on mobile\n */\nfunction MobileDatepicker({\n value,\n getDisplay,\n onChange,\n itemCount,\n startTime,\n id,\n label,\n icon,\n timeZone,\n}) {\n Settings.defaultZone = timeZone;\n const dateChoices = Array(itemCount)\n .fill()\n .map((_, i) => DateTime.fromMillis(startTime).plus({ days: i }).toMillis());\n const nativeInput = !isAndroid();\n const labelId = `${id}-label`;\n const inputId = `${id}-input`;\n\n return (\n <label className={styles['input-container']} htmlFor={inputId}>\n <span>{icon}</span>\n <span className={styles['sr-only']} id={labelId}>\n {label}\n </span>\n {nativeInput ? (\n <select\n id={inputId}\n className={styles['mobile-input-display']}\n onChange={e => onChange(Number(e.target.value))}\n value={value}\n >\n {dateChoices.map(date => {\n return (\n <option key={date} value={date}>\n {getDisplay(date)}\n </option>\n );\n })}\n </select>\n ) : (\n <AndroidSelect\n {...{\n value,\n dateChoices,\n id,\n getDisplay,\n onChange,\n labelId,\n inputId,\n }}\n />\n )}\n </label>\n );\n}\nMobileDatepicker.propTypes = {\n value: PropTypes.number.isRequired,\n getDisplay: PropTypes.func.isRequired,\n onChange: PropTypes.func.isRequired,\n itemCount: PropTypes.number.isRequired,\n startTime: PropTypes.number.isRequired,\n id: PropTypes.string.isRequired,\n label: PropTypes.string.isRequired,\n icon: PropTypes.node,\n timeZone: PropTypes.string,\n};\n\nMobileDatepicker.defaultProps = {\n icon: null,\n timeZone: 'Europe/Helsinki',\n};\n\nexport default MobileDatepicker;\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { Settings } from 'luxon';\nimport cx from 'classnames';\nimport styles from './styles.scss';\nimport { parseTypedTime, getTs, validateInput } from './utils';\n\n/**\n * Component to display a time input on mobile\n */\nfunction MobileTimepicker({\n value,\n getDisplay,\n onChange,\n id,\n label,\n icon,\n timeZone,\n}) {\n const [inputValue, changeInputValue] = useState(getDisplay(value));\n const [isValidInput, setValidInput] = useState(true);\n Settings.defaultZone = timeZone;\n const inputId = `${id}-input`;\n const labelId = `${id}-label`;\n const showError = !isValidInput;\n return (\n <label className={styles['input-container']} htmlFor={inputId}>\n <span>{icon}</span>\n <span className={styles['sr-only']} id={labelId}>\n {label}\n </span>\n <input\n id={inputId}\n inputMode=\"numeric\"\n type=\"text\"\n maxLength=\"6\"\n className={cx(\n styles['time-input-mobile'],\n showError ? 'mobile-datetimepicker-invalid-input' : '',\n )}\n value={inputValue}\n onFocus={e => {\n e.target.setSelectionRange(0, 0); // set caret to start of input\n }}\n onChange={event => {\n let newValue = event.target.value.replace('.', ':');\n\n const valid = validateInput(newValue);\n setValidInput(valid);\n if (\n // number typed as first char => clear rest of the input\n newValue.match(/[0-9]{3}:[0-9]{2}/) &&\n newValue.slice(1) === inputValue\n ) {\n newValue = newValue.charAt(0);\n }\n if (newValue.length > 5) {\n return;\n }\n const actual = parseTypedTime(newValue);\n changeInputValue(actual);\n const timestamp = getTs(actual, value);\n if (timestamp) {\n onChange(timestamp);\n }\n }}\n />\n </label>\n );\n}\nMobileTimepicker.propTypes = {\n value: PropTypes.number.isRequired,\n getDisplay: PropTypes.func.isRequired,\n onChange: PropTypes.func.isRequired,\n id: PropTypes.string.isRequired,\n label: PropTypes.string.isRequired,\n icon: PropTypes.node,\n timeZone: PropTypes.string,\n};\n\nMobileTimepicker.defaultProps = {\n icon: null,\n timeZone: 'Europe/Helsinki',\n};\n\nexport default MobileTimepicker;\n","import PropTypes from 'prop-types';\nimport React, { useState } from 'react';\nimport { DateTime, Settings } from 'luxon';\nimport { useTranslation } from 'react-i18next';\nimport uniqueId from 'lodash/uniqueId';\nimport Modal from 'react-modal';\nimport Icon from '@digitransit-component/digitransit-component-icon';\nimport MobileDatepicker from './MobileDatepicker';\nimport MobileTimepicker from './MobileTimepicker';\nimport styles from './styles.scss';\n\nSettings.defaultLocale = 'en';\n\n/**\n * @param {object} props\n * @param {'arrival'|'departure'} props.departureOrArrival Whether the picker is for arrival or departure time\n * @param {function} props.onNowClick Called when the \"Now\" button is clicked\n * @param {string} props.lang Language code for translations\n * @param {string} props.color Color for the component, used in styles\n * @param {string} props.timeZone Time zone to use for date and time calculations\n * @param {function} props.onSubmit Called when the user submits the selected date and time\n * @param {function} props.onCancel called when the user cancels the selection\n * @param {number} props.timestamp Initial timestamp to display in the picker\n * @param {function} props.getTimeDisplay Called to get the display string for a given timestamp\n * @param {number} props.dateSelectItemCount Determines how many date options are shown in the date picker\n * @param {function} props.getDateDisplay Called to get the display string for a given date\n * @param {object} props.fontWeights Font weights used in the component styles\n * @returns {JSX.Element}\n */\nfunction MobilePickerModal({\n departureOrArrival,\n onNowClick,\n lang,\n color,\n timeZone,\n onSubmit,\n onCancel,\n timestamp,\n getTimeDisplay,\n dateSelectItemCount,\n getDateDisplay,\n fontWeights,\n onAfterClose,\n}) {\n Settings.defaultZone = timeZone;\n const [t] = useTranslation();\n const translationSettings = { lng: lang };\n\n const [displayTimestamp, changeTimestamp] = useState(timestamp);\n\n const [departureOrArrivalCurrent, changeDepartureOrArrival] =\n useState(departureOrArrival);\n\n function onArrivalClick() {\n changeDepartureOrArrival('arrival');\n }\n\n function onDepartureClick() {\n changeDepartureOrArrival('departure');\n }\n\n // for input labels\n const [htmlId] = useState(uniqueId('datetimepicker-'));\n const dateSelectStartTime = DateTime.now()\n .startOf('day')\n .set({\n hour: DateTime.fromMillis(displayTimestamp).hour,\n minute: DateTime.fromMillis(displayTimestamp).minute,\n })\n .toMillis();\n\n return (\n <Modal\n appElement={document ? document.querySelector('#app') : undefined}\n isOpen\n className={styles['mobile-modal-content']}\n overlayClassName={styles['mobile-modal-overlay']}\n onAfterClose={onAfterClose}\n >\n <div\n id=\"digitransit-mobile-datetime\"\n style={{\n '--color': `${color}`,\n '--font-weight-medium': fontWeights.medium,\n }}\n >\n <div className={styles['top-row']}>\n <h3 className={styles['modal-title']}>\n {t('choose-time', translationSettings)}\n </h3>\n <button\n type=\"button\"\n className={styles['departure-now-button']}\n onClick={onNowClick}\n >\n {t('departure-now', translationSettings)}\n </button>\n </div>\n <div className={styles['tab-row']}>\n <label\n htmlFor={`${htmlId}-modal-departure`}\n className={`${styles['radio-tab-label']}\n ${\n styles[\n departureOrArrivalCurrent === 'departure'\n ? 'active'\n : undefined\n ]\n }`}\n >\n {t('departure', translationSettings)}\n <input\n id={`${htmlId}-modal-departure`}\n name=\"departureOrArrival\"\n type=\"radio\"\n value=\"departure\"\n className={styles['radio-textbutton']}\n onChange={() => {\n onDepartureClick();\n }}\n checked={departureOrArrivalCurrent === 'departure'}\n />\n </label>\n <label\n htmlFor={`${htmlId}-modal-arrival`}\n className={`${styles['radio-tab-label']}\n ${\n styles[\n departureOrArrivalCurrent === 'arrival'\n ? 'active'\n : undefined\n ]\n }`}\n >\n {t('arrival', translationSettings)}\n <input\n id={`${htmlId}-modal-arrival`}\n name=\"departureOrArrival\"\n type=\"radio\"\n value=\"arrival\"\n className={styles['radio-textbutton']}\n onChange={() => {\n onArrivalClick();\n }}\n checked={departureOrArrivalCurrent === 'arrival'}\n />\n </label>\n </div>\n <div className={styles['input-row']}>\n <MobileDatepicker\n value={displayTimestamp}\n getDisplay={getDateDisplay}\n onChange={changeTimestamp}\n itemCount={dateSelectItemCount}\n startTime={dateSelectStartTime}\n id={`${htmlId}-date`}\n label={t('date', translationSettings)}\n icon={\n <span\n className={`${styles['combobox-icon']} ${styles['date-input-icon']}`}\n >\n <Icon img=\"calendar\" color={color} />\n </span>\n }\n timeZone={timeZone}\n />\n <MobileTimepicker\n value={displayTimestamp}\n getDisplay={getTimeDisplay}\n onChange={changeTimestamp}\n id={`${htmlId}-time`}\n label={t('time', translationSettings)}\n icon={\n <span\n className={`${styles['combobox-icon']} ${styles['time-input-icon']}`}\n >\n <Icon img=\"time\" color={color} />\n </span>\n }\n timeZone={timeZone}\n />\n </div>\n <div className={styles['buttons-row']}>\n <button\n type=\"button\"\n className={styles['ready-button']}\n onClick={() =>\n onSubmit(displayTimestamp, departureOrArrivalCurrent)\n }\n >\n {t('ready', translationSettings)}\n </button>\n <button\n type=\"button\"\n className={styles['cancel-button']}\n onClick={onCancel}\n >\n {t('cancel', translationSettings)}\n </button>\n </div>\n </div>\n </Modal>\n );\n}\n\nMobilePickerModal.propTypes = {\n timeZone: PropTypes.string,\n departureOrArrival: PropTypes.oneOf(['departure', 'arrival']).isRequired,\n onNowClick: PropTypes.func.isRequired,\n lang: PropTypes.string.isRequired,\n color: PropTypes.string,\n onSubmit: PropTypes.func.isRequired,\n onCancel: PropTypes.func.isRequired,\n onAfterClose: PropTypes.func.isRequired,\n timestamp: PropTypes.number.isRequired,\n getTimeDisplay: PropTypes.func.isRequired,\n dateSelectItemCount: PropTypes.number.isRequired,\n getDateDisplay: PropTypes.func.isRequired,\n fontWeights: PropTypes.shape({\n medium: PropTypes.number.isRequired,\n }).isRequired,\n};\n\nMobilePickerModal.defaultProps = {\n color: '#007ac9',\n timeZone: 'Europe/Helsinki',\n};\n\nexport default MobilePickerModal;\n","import PropTypes from 'prop-types';\nimport React, { useState, useEffect, useRef, useMemo } from 'react';\nimport { DateTime, Settings } from 'luxon';\nimport uniqueId from 'lodash/uniqueId';\nimport { useTranslation } from 'react-i18next';\nimport Icon from '@digitransit-component/digitransit-component-icon';\nimport DesktopDatetimepicker from './DesktopDatetimepicker';\nimport styles from './styles.scss';\nimport { isMobile } from './mobileDetection';\nimport dateTimeInputIsSupported from './dateTimeInputIsSupported';\nimport MobilePickerModal from './MobilePickerModal';\n\nSettings.defaultLocale = 'en';\n\n/**\n * This component renders combobox style inputs for selecting date and time. This is a controlled component, timestamp is the current value of both inputs.\n * @param {Object} props\n *\n * @param {Number} props.timestamp Currently selected time as a unix timestamp in milliseconds. Set to null to signify that \"now\" is selected. Displayed time is updated in realtime when set to null\n * @param {function} props.onTimeChange Called with new timestamp when time input changes\n * @param {function} props.onDateChange Called with new timestamp when date input changes\n * @param {'arrival'|'departure'} props.departureOrArrival Determine if input is set to choose departure or arrival time\n * @param {function} props.onNowClick Called when \"depart now\" button is clicked\n * @param {function} props.onDepartureClick Called when \"departure\" button is clicked\n * @param {function} props.onArrivalClick Called when \"arrival\" button is clicked\n * @param {node} props.embedWhenClosed JSX element to render in the corner when input is closed\n * @param {node} props.embedWhenOpen JSX element to render when input is open\n * @param {string} props.lang Language selection\n * @param {number} props.serviceTimeRange Determine number of days shown in timepicker. Optional. default is 30.\n * @param {function} props.onOpen Determine what to do when timepicker is open. Optional. no default implementation.\n * @param {function} props.onClose Determine what to do when timepicker is closed. Optional. no default implementation.\n * @param {function} props.openPicker Determine if timepicker should be open in intial render. Optional. Default is undefined.\n *\n *\n * @example\n * <Datetimepicker\n * timestamp={1590133823000}\n * onTimeChange={(newTimestamp) => update(newTimestamp)}\n * onDateChange={(newTimestamp) => update(newTimestamp)}\n * departureOrArrival={'departure'}\n * onNowClick={() => setTimestampToNull()}\n * onDepartureClick={() => departureClicked()}\n * onArrivalClick={() => arrivalClicked()}\n * embedWhenClosed={<button />}\n * lang={'en'}\n * serviceTimeRange={15}\n * />\n */\nfunction Datetimepicker({\n timestamp,\n onTimeChange,\n onDateChange,\n departureOrArrival,\n onNowClick,\n onDepartureClick,\n onArrivalClick,\n embedWhenClosed,\n embedWhenOpen,\n lang,\n color,\n timeZone,\n onModalSubmit,\n fontWeights,\n serviceTimeRange,\n onOpen,\n onClose,\n openPicker,\n}) {\n Settings.defaultZone = timeZone;\n const [t] = useTranslation();\n const [isOpen, changeOpen] = useState(openPicker || false);\n const [displayTimestamp, changeDisplayTimestamp] = useState(\n timestamp || DateTime.now().toMillis(),\n );\n // timer for updating displayTimestamp in real time\n const [timerId, setTimer] = useState(null);\n // for input labels\n const [htmlId] = useState(uniqueId('datetimepicker-'));\n const [useMobileInputs] = useState(isMobile() && dateTimeInputIsSupported());\n const openPickerRef = useRef();\n const inputRef = useRef();\n const alertRef = useRef();\n\n const translationSettings = { lng: lang };\n\n useEffect(() => {\n Settings.defaultLocale = lang;\n }, [lang]);\n\n const nowSelected = timestamp === null;\n useEffect(() => {\n if (nowSelected) {\n changeDisplayTimestamp(DateTime.now().toMillis());\n } else {\n // clear timer\n if (timerId) {\n clearInterval(timerId);\n setTimer(null);\n }\n changeDisplayTimestamp(timestamp);\n }\n }, [timestamp]);\n\n // set timer to update displayTimestamp when minute changes if nowSelected\n useEffect(() => {\n if (!nowSelected) {\n return undefined;\n }\n if (timerId) {\n clearInterval(timerId);\n }\n const newId = setInterval(() => {\n const now = DateTime.now();\n const sameMinute = DateTime.fromMillis(displayTimestamp).hasSame(\n now,\n 'minute',\n );\n if (!sameMinute) {\n clearInterval(newId);\n setTimer(null);\n changeDisplayTimestamp(now.toMillis());\n }\n }, 5000);\n setTimer(newId);\n return () => clearInterval(newId);\n }, [displayTimestamp]);\n\n /**\n * @param {number} date Date in milliseconds since unix epoch\n * @returns {string} formatted date\n */\n const getDateDisplay = date => {\n const time = DateTime.fromMillis(date);\n const now = DateTime.now();\n let formatted;\n if (time.hasSame(now, 'day')) {\n formatted = t('today', translationSettings);\n formatted = `${formatted.charAt(0).toUpperCase()}${formatted.slice(1)}`;\n } else if (time.hasSame(now.plus({ days: 1 }), 'day')) {\n formatted = t('tomorrow', translationSettings);\n formatted = `${formatted.charAt(0).toUpperCase()}${formatted.slice(1)}`;\n } else {\n formatted = time.toFormat('ccc d.L.');\n }\n return formatted;\n };\n\n // param time is timestamp\n const getTimeDisplay = time => {\n return DateTime.fromMillis(time).toFormat('HH:mm');\n };\n\n // compute choices only when timestamp changes instead of every render\n const [timeChoices, dateChoices] = useMemo(() => {\n const selectedMoment = DateTime.fromMillis(\n timestamp || DateTime.now().toMillis(),\n );\n const timeSelectStartTime = selectedMoment.startOf('day').toMillis();\n const isMobileCurrently = isMobile();\n let newTimeChoices = [];\n let current = selectedMoment.startOf('day');\n while (current.hasSame(timeSelectStartTime, 'day')) {\n newTimeChoices.push(current.valueOf());\n if (isMobileCurrently) {\n current = current.plus({ minutes: 15 });\n } else {\n current = current.plus({ minutes: 1 });\n }\n }\n if (timestamp === null) {\n // if time is set to now\n // add times in 5 min intervals for next 30 mins\n const fiveMinutes = 1000 * 60 * 5;\n const nextFiveMin =\n Math.ceil(displayTimestamp / fiveMinutes) * fiveMinutes;\n const timesToAdd = Array(7)\n .fill()\n .map((_, i) => nextFiveMin + i * fiveMinutes);\n const closestIndexAfter = newTimeChoices\n .map(time => displayTimestamp - time)\n .findIndex(time => time <= 0);\n newTimeChoices.splice(closestIndexAfter, 0, ...timesToAdd);\n newTimeChoices = Array.from(new Set(newTimeChoices)); // remove duplicates\n }\n const dateSelectStartTime = DateTime.now().startOf('day').set({\n hour: selectedMoment.hour,\n minute: selectedMoment.minute,\n });\n const newDateChoices = Array(serviceTimeRange)\n .fill()\n .map((_, i) => dateSelectStartTime.plus({ days: i }).toMillis());\n return [newTimeChoices, newDateChoices];\n }, [timestamp]);\n\n function showScreenreaderCloseAlert() {\n if (alertRef.current) {\n alertRef.current.innerHTML = t('accessible-closed', translationSettings);\n setTimeout(() => {\n alertRef.current.innerHTML = null;\n }, 100);\n }\n }\n\n function showScreenreaderOpenAlert() {\n if (alertRef.current) {\n alertRef.current.innerHTML = t('accessible-opened', translationSettings);\n setTimeout(() => {\n alertRef.current.innerHTML = null;\n }, 100);\n }\n }\n\n const handleClose = () => {\n changeOpen(false);\n showScreenreaderCloseAlert();\n if (onClose) {\n onClose();\n }\n };\n\n const handleNowClick = () => {\n handleClose();\n onNowClick();\n };\n\n function renderOpen() {\n if (useMobileInputs) {\n return (\n isOpen && (\n <MobilePickerModal\n departureOrArrival={departureOrArrival}\n onNowClick={handleNowClick}\n lang={lang}\n color={color}\n onSubmit={(newTimestamp, newDepartureOrArrival) => {\n onModalSubmit(newTimestamp, newDepartureOrArrival);\n changeOpen(false);\n showScreenreaderCloseAlert();\n }}\n onCancel={handleClose}\n onAfterClose={() =>\n requestAnimationFrame(() => {\n openPickerRef.current?.focus();\n })\n }\n getTimeDisplay={getTimeDisplay}\n timeZone={timeZone}\n timestamp={displayTimestamp}\n getDateDisplay={getDateDisplay}\n dateSelectItemCount={serviceTimeRange}\n getDisplay={getTimeDisplay}\n fontWeights={fontWeights}\n />\n )\n );\n }\n return (\n <>\n <div\n className={`${styles['datetimepicker-open-container']} ${\n !isOpen ? styles.hidden : ''\n }`}\n >\n <div\n className={\n isOpen\n ? `${styles['top-row-container']} datetimepicker-top-row`\n : `${styles.hidden} datetimepicker-top-row`\n }\n >\n {' '}\n <span role=\"alert\" className={styles['sr-only']} ref={alertRef} />\n <span />\n {/* This empty span prevents a weird focus bug on chrome */}\n <span className={styles['departure-or-arrival-container']}>\n <label\n htmlFor={`${htmlId}-departure`}\n className={`${styles['radio-textbutton-label']}\n ${\n styles[\n departureOrArrival === 'departure' ? 'active' : undefined\n ]\n }`}\n >\n {t('departure', translationSettings)}\n <input\n id={`${htmlId}-departure`}\n name=\"departureOrArrival\"\n type=\"radio\"\n value=\"departure\"\n className={styles['radio-textbutton']}\n onChange={() => {\n onDepartureClick();\n }}\n checked={departureOrArrival === 'departure'}\n />\n </label>\n <label\n htmlFor={`${htmlId}-arrival`}\n className={`${styles['radio-textbutton-label']}\n ${\n styles[\n departureOrArrival === 'arrival' ? 'active' : undefined\n ]\n }`}\n >\n {t('arrival', translationSettings)}\n <input\n id={`${htmlId}-arrival`}\n name=\"departureOrArrival\"\n type=\"radio\"\n value=\"arrival\"\n className={styles['radio-textbutton']}\n onChange={() => {\n onArrivalClick();\n }}\n checked={departureOrArrival === 'arrival'}\n />\n </label>\n </span>\n <button\n id={`${htmlId}-now`}\n type=\"button\"\n className={styles['departure-now-button']}\n onClick={handleNowClick}\n ref={inputRef}\n >\n {t('departure-now', translationSettings)}\n </button>\n <span className={styles['right-edge']}>\n <button\n type=\"button\"\n className={styles['close-button']}\n aria-controls={`${htmlId}-root`}\n aria-expanded=\"true\"\n onClick={handleClose}\n >\n <span className={styles['close-icon']}>\n <Icon img=\"close\" color={color} />\n </span>\n <span className={styles['sr-only']}>\n {t('accessible-close', translationSettings)}\n </span>\n </button>\n </span>\n </div>\n <div\n className={\n isOpen\n ? `${styles['picker-container']}`\n : `${styles.hidden} datetimepicker-top-row`\n }\n >\n <span className={styles['combobox-left']}>\n <DesktopDatetimepicker\n value={displayTimestamp}\n onChange={newValue => {\n onDateChange(newValue);\n }}\n getDisplay={getDateDisplay}\n timeChoices={dateChoices}\n validate={() => null}\n icon={\n <span\n className={`${styles['combobox-icon']} ${styles['date-input-icon']}`}\n >\n <Icon img=\"calendar\" color={color} />\n </span>\n }\n id={`${htmlId}-date`}\n label={t('date', translationSettings)}\n disableTyping\n timeZone={timeZone}\n datePicker\n />\n </span>\n <span className={styles['combobox-right']}>\n <DesktopDatetimepicker\n value={displayTimestamp}\n onChange={newValue => {\n onTimeChange(newValue);\n }}\n getDisplay={getTimeDisplay}\n timeChoices={timeChoices}\n icon={\n <span\n className={`${styles['combobox-icon']} ${styles['time-input-icon']}`}\n >\n <Icon img=\"time\" color={color} />\n </span>\n }\n id={`${htmlId}-time`}\n label={t('time', translationSettings)}\n timeZone={timeZone}\n translationSettings={translationSettings}\n />\n </span>\n </div>\n </div>\n <span className={isOpen ? '' : styles.hidden}>{embedWhenOpen}</span>\n <div className={isOpen ? 'datetimepicker-bottom-row-open' : ''} />\n </>\n );\n }\n\n const formatToprowSummary = () => {\n if (nowSelected && departureOrArrival === 'departure') {\n return <span>{t('departure-now', translationSettings)}</span>;\n }\n const dateDisplay = getDateDisplay(displayTimestamp);\n const timeDisplay = getTimeDisplay(displayTimestamp);\n const summary = t(\n departureOrArrival === 'departure' ? 'departure' : 'arrival',\n translationSettings,\n );\n const isToday = DateTime.now().hasSame(\n DateTime.fromMillis(displayTimestamp),\n 'day',\n );\n const isTomorrow = DateTime.now()\n .plus({ days: 1 })\n .hasSame(DateTime.fromMillis(displayTimestamp), 'day');\n if (isToday) {\n return <span>{`${summary} ${timeDisplay}`}</span>;\n }\n if (isTomorrow) {\n return (\n <span>{`${summary} ${dateDisplay.toLowerCase()} ${timeDisplay}`}</span>\n );\n }\n return <span>{`${summary} ${dateDisplay} ${timeDisplay}`}</span>;\n };\n\n return (\n <fieldset\n className={styles['dt-datetimepicker']}\n id={`${htmlId}-root`}\n style={{\n '--color': `${color}`,\n '--font-weight-medium': fontWeights.medium,\n }}\n >\n <legend className={styles['sr-only']}>\n {t('accessible-title', translationSettings)}\n </legend>\n <span className={styles['sr-only']}>\n {t('accessible-update-instructions', translationSettings)}\n </span>\n <div\n className={\n !isOpen\n ? `${styles['top-row-container']} ${styles.closed} datetimepicker-top-row`\n : `${styles.hidden} datetimepicker-top-row`\n }\n >\n <label className={styles['label-open']} htmlFor={`${htmlId}-open`}>\n <span className={styles['time-icon']}>\n <Icon img=\"time\" color={color} />\n </span>\n <span className={styles['sr-only']}>\n {t('accessible-open', translationSettings)}\n </span>\n <span role=\"alert\" className={styles['sr-only']} ref={alertRef} />\n <button\n id={`${htmlId}-open`}\n type=\"button\"\n className={`${styles.textbutton} ${styles.active} ${styles['open-button']}`}\n aria-controls={`${htmlId}-root`}\n aria-expanded=\"false\"\n onClick={() => {\n changeOpen(true);\n showScreenreaderOpenAlert();\n if (onOpen) {\n onOpen();\n }\n }}\n ref={openPickerRef}\n >\n {formatToprowSummary()}\n <span className={styles['dropdown-icon']}>\n <Icon img=\"arrow-dropdown\" color={color} />\n </span>\n </button>\n </label>\n <span className={styles['right-edge']}>{embedWhenClosed}</span>\n </div>\n <div />\n {renderOpen()}\n </fieldset>\n );\n}\n\nDatetimepicker.propTypes = {\n timestamp: PropTypes.number,\n timeZone: PropTypes.string,\n onTimeChange: PropTypes.func.isRequired,\n onDateChange: PropTypes.func.isRequired,\n departureOrArrival: PropTypes.oneOf(['departure', 'arrival']).isRequired,\n onNowClick: PropTypes.func.isRequired,\n onDepartureClick: PropTypes.func.isRequired,\n onArrivalClick: PropTypes.func.isRequired,\n embedWhenClosed: PropTypes.node,\n embedWhenOpen: PropTypes.node,\n lang: PropTypes.string.isRequired,\n color: PropTypes.string,\n onModalSubmit: PropTypes.func.isRequired,\n fontWeights: PropTypes.shape({\n medium: PropTypes.number.isRequired,\n }).isRequired,\n serviceTimeRange: PropTypes.number.isRequired,\n onOpen: PropTypes.func,\n onClose: PropTypes.func,\n openPicker: PropTypes.bool,\n};\n\nDatetimepicker.defaultProps = {\n timestamp: null,\n embedWhenClosed: null,\n embedWhenOpen: null,\n color: '#007ac9',\n timeZone: 'Europe/Helsinki',\n onOpen: null,\n onClose: null,\n openPicker: undefined,\n};\n\nexport default Datetimepicker;\n","/**\n * Detect if input type=\"date\" and type=\"time\" are supported in by the browser\n *\n * @return {boolean}\n */\nfunction dateTimeInputIsSupported() {\n if (typeof window === 'undefined' || window === null) {\n return false;\n }\n const elem = document.createElement('input');\n elem.type = 'date';\n if (elem.type !== 'date') {\n return false;\n }\n elem.type = 'time';\n if (elem.type !== 'time') {\n return false;\n }\n return true;\n}\n\nexport default dateTimeInputIsSupported;\n","const translations = {\n de: {\n translation: {\n today: 'Heute',\n tomorrow: 'Morgen',\n 'accessible-close': 'Schließe die Auswahl',\n 'accessible-closed': 'Auswahl geschlossen',\n 'accessible-open': 'Öffne die Auswahl',\n 'accessible-opened': 'Auswahl geöffnet',\n 'accessible-title': 'Datum und Uhrzeitauswahl',\n arrival: 'Ankunft',\n date: 'Datum',\n departure: 'Abfahrt',\n 'departure-now': 'Abfahrt jetzt',\n 'choose-time': 'Zeit wählen',\n ready: 'Fertig',\n time: 'Zeit',\n cancel: 'Abbrechen',\n },\n },\n en: {\n translation: {\n today: 'Today',\n tomorrow: 'Tomorrow',\n 'accessible-close': 'Close the picker',\n 'accessible-closed': 'Timepicker closed',\n 'accessible-open': 'Open the picker',\n 'accessible-opened': 'Timepicker opened',\n 'accessible-title': 'Date and timepicker',\n 'accessible-update-instructions':\n 'Changing time parameters will trigger a new search.',\n arrival: 'Arrival',\n date: 'Date',\n departure: 'Departure',\n 'departure-now': 'Leaving now',\n time: 'Time',\n 'choose-time': 'Choose time',\n ready: 'Ready',\n cancel: 'Cancel',\n 'invalid-input': 'The time you entered is invalid',\n },\n },\n fi: {\n translation: {\n today: 'Tänään',\n tomorrow: 'Huomenna',\n 'accessible-close': 'Sulje valitsin',\n 'accessible-closed': 'Valitsin suljettu',\n 'accessible-open': 'Avaa valitsin',\n 'accessible-opened': 'Valitsin avattu',\n 'accessible-title': 'Aika- ja päivämäärävalitsin',\n 'accessible-update-instructions':\n 'Aikavalintojen muuttaminen laukaisee uuden haun.',\n arrival: 'Perillä',\n date: 'Päivä',\n departure: 'Lähtöaika',\n 'departure-now': 'Lähtö nyt',\n time: 'Aika',\n 'choose-time': 'Valitse aika',\n ready: 'Valmis',\n cancel: 'Peruuta',\n 'invalid-input': 'Syöttämäsi aika on virheellinen',\n },\n },\n pl: {\n translation: {\n today: 'Dziś',\n tomorrow: 'Jutro',\n 'accessible-close': 'Zamknij wybornik',\n 'accessible-closed': 'Zamknięto wybornik',\n 'accessible-open': 'Otwórz wybornik',\n 'accessible-opened': 'Otwarto wybornik',\n 'accessible-title': 'Wybór daty i godziny',\n 'accessible-update-instructions':\n 'Zmiana wybranej godziny wywoła nowe wyszukiwanie.',\n arrival: 'Przyjazd',\n date: 'Data',\n departure: 'Wyjazd',\n 'departure-now': 'Wyjeżdżam teraz',\n time: 'Godzina',\n 'choose-time': 'Wybierz godzinę',\n ready: 'Gotowe',\n cancel: 'Anuluj',\n 'invalid-input': 'Wprowadzona godzina jest nieprawidłowa',\n },\n },\n sv: {\n translation: {\n today: 'I dag',\n tomorrow: 'I morgon',\n 'accessible-close': 'Stäng väljaren',\n 'accessible-closed': 'Väljaren stängde',\n 'accessible-open': 'Öppna väljaren',\n 'accessible-opened': 'Väljaren öppnade',\n 'accessible-title': 'Tid- och datumväljaren',\n 'accessible-update-instructions':\n 'Om du ändrar tiderna, startas en ny sökning automatiskt.',\n arrival: 'Anländer',\n date: 'Datum',\n departure: 'Avgångstid',\n 'departure-now': 'Avgår nu',\n time: 'Tid',\n 'choose-time': 'Välj tid',\n ready: 'Färdig',\n cancel: 'Avbryt',\n 'invalid-input': 'Tiden du angav är felaktig',\n },\n },\n};\n\nexport default translations;\n","import { createInstance } from 'i18next';\nimport translations from './translations';\n\nconst i18n = createInstance({\n fallbackLng: 'fi',\n // debug: true,\n resources: translations,\n defaultNS: 'translation',\n react: {\n useSuspense: true,\n },\n});\n\ni18n.init();\n\nexport default i18n;\n","import PropTypes from 'prop-types';\nimport React, { useState, useEffect } from 'react';\nimport { I18nextProvider } from 'react-i18next';\nimport { Settings, DateTime } from 'luxon';\nimport debounce from 'lodash/debounce';\nimport Datetimepicker from './helpers/Datetimepicker';\nimport i18n from './helpers/i18n';\n\n/**\n * This component renders an input to choose a date and time. Renders separate input fields for date and time selection. Values for timestamp and arriveBy correspond to Digitransit query params time and arriveBy. This component will display a native date input on mobile and a custom one for desktop. Mobile detection is done by parsing user agent.\n *\n * @alias Datetimepicker\n *\n * @param {Object} props\n *\n * @param {boolean} props.realtime Determine if selected time should be updated in realtime when 'now' is selected.\n * @param {Number} props.initialTimestamp Initial value for selected time. Unix timestamp in seconds. Updating this will change timepicker value but the correct value is kept in component state even if this is not updated.\n * @param {boolean} props.initialArriveBy Initial value for arriveBy. Determines if picker is in arrival mode (true) or departure mode (false). Correct value is kept in component state even if this is not updated. Changing this will also trigger change in the component.\n * @param {function} props.onTimeChange Called with (time, arriveBy) when time input changes. time is number timestamp in seconds, arriveBy is boolean\n * @param {function} props.onDateChange Called with (time, arriveBy) when date input changes. time is number timestamp in seconds, arriveBy is boolean\n * @param {function} props.onNowClick Called when \"depart now\" button is clicked. time is current input value in seconds\n * @param {function} props.onDepartureClick Called with (time) when \"departure\" button is clicked. time is current input value in seconds\n * @param {function} props.onArrivalClick Called with (time) when \"arrival\" button is clicked. time is current input value in seconds\n * @param {node} props.embedWhenClosed JSX element to render in the corner when input is closed\n * @param {node} props.embedWhenOpen JSX element to render when input is open\n * @param {string} props.lang Language selection. Default 'en'\n * @param {number} props.serviceTimeRange Determine number of days shown in timepicker. Optional. default is 30.\n * @param {function} props.onOpen Determine what to do when timepicker is open. Optional. no default implementation.\n * @param {function} props.onClose Determine what to do when timepicker is closed. Optional. no default implementation.\n * @param {function} props.openPicker Determine if timepicker should be open in intial render. Optional. Default is undefined.\n * @example\n * <Datetimepicker\n * realtime={true}\n * initialTimestamp={1590133823}\n * initialArriveBy={false}\n * onTimeChange={(time, arriveBy) => changeUrl(time, arriveBy)}\n * onDateChange={(time, arriveBy) => changeUrl(time, arriveBy)}\n * onNowClick={(time) => changeUrl(undefined, undefined)}\n * onDepartureClick={(time) => changeUrl(time, 'true')}\n * onArrivalClick={(time) => changeUrl(time, undefined)}\n * embedWhenClosed={<button />}\n * lang={'en'}\n * serviceTimeRange={15}\n * />\n */\nfunction DatetimepickerStateContainer({\n realtime,\n initialArriveBy,\n initialTimestamp,\n onDepartureClick,\n onArrivalClick,\n onTimeChange,\n onDateChange,\n onNowClick,\n embedWhenClosed,\n embedWhenOpen,\n lang,\n color,\n timeZone,\n fontWeights,\n serviceTimeRange,\n onOpen,\n onClose,\n openPicker,\n}) {\n Settings.defaultLocale = lang;\n Settings.defaultZone = timeZone;\n const initialNow = realtime ? null : DateTime.now().toMillis();\n const [timestamp, changeTimestampState] = useState(\n initialTimestamp ? initialTimestamp * 1000 : initialNow,\n );\n const [departureOrArrival, changeDepartureOrArrival] = useState(\n initialArriveBy === true ? 'arrival' : 'departure',\n );\n\n // update state if props change\n useEffect(() => {\n const bothNull = timestamp === null && initialTimestamp === undefined;\n const oneNull = timestamp === null || initialTimestamp === undefined;\n const sameTime = Math.round(timestamp / 1000) === initialTimestamp;\n const timestampChanged = !bothNull && (oneNull || !sameTime);\n if (timestampChanged) {\n if (initialTimestamp === undefined) {\n changeTimestampState(null);\n } else {\n changeTimestampState(initialTimestamp * 1000);\n }\n }\n if (!initialArriveBy === (departureOrArrival === 'arrival')) {\n changeDepartureOrArrival(\n initialArriveBy === true ? 'arrival' : 'departure',\n );\n }\n }, [initialTimestamp, initialArriveBy]);\n\n const timeChanged = debounce(newTime => {\n if (newTime === null) {\n changeTimestampState(DateTime.now().toMillis());\n onTimeChange(\n DateTime.now().toUnixInteger(),\n departureOrArrival === 'arrival',\n );\n return;\n }\n changeTimestampState(newTime);\n onTimeChange(Math.round(newTime / 1000), departureOrArrival === 'arrival');\n }, 10);\n\n const dateChanged = debounce(newDate => {\n if (newDate === null) {\n changeTimestampState(DateTime.now().toMillis());\n onDateChange(\n DateTime.now().toUnixInteger(),\n departureOrArrival === 'arrival',\n );\n return;\n }\n changeTimestampState(newDate);\n onDateChange(Math.round(newDate / 1000), departureOrArrival === 'arrival');\n }, 10);\n\n const nowClicked = () => {\n changeDepartureOrArrival('departure');\n const newTimestamp = realtime ? null : DateTime.now().toMillis();\n changeTimestampState(newTimestamp);\n onNowClick(Math.round(newTimestamp / 1000));\n };\n\n const departureClicked = () => {\n let changed = false;\n let newTime = timestamp;\n if (timestamp === null) {\n const now = DateTime.now().toMillis();\n changeTimestampState(now);\n newTime = now;\n changed = true;\n }\n if (departureOrArrival !== 'departure') {\n changeDepartureOrArrival('departure');\n changed = true;\n }\n if (changed) {\n onDepartureClick(Math.round(newTime / 1000));\n }\n };\n\n const arrivalClicked = () => {\n let changed = false;\n let newTime = timestamp;\n if (timestamp === null) {\n const now = DateTime.now().toMillis();\n changeTimestampState(now);\n newTime = now;\n changed = true;\n }\n if (departureOrArrival !== 'arrival') {\n changeDepartureOrArrival('arrival');\n changed = true;\n }\n if (changed) {\n onArrivalClick(Math.round(newTime / 1000));\n }\n };\n const onModalSubmit = (time, mode) => {\n changeTimestampState(time);\n changeDepartureOrArrival(mode);\n onTimeChange(Math.round(time / 1000), mode === 'arrival', true);\n };\n\n return (\n <I18nextProvider i18n={i18n}>\n <Datetimepicker\n timestamp={timestamp}\n onTimeChange={timeChanged}\n onDateChange={dateChanged}\n departureOrArrival={departureOrArrival}\n onNowClick={nowClicked}\n onDepartureClick={departureClicked}\n onArrivalClick={arrivalClicked}\n embedWhenClosed={embedWhenClosed}\n embedWhenOpen={embedWhenOpen}\n lang={lang}\n color={color}\n timeZone={timeZone}\n onModalSubmit={onModalSubmit}\n fontWeights={fontWeights}\n serviceTimeRange={serviceTimeRange}\n onOpen={onOpen}\n onClose={onClose}\n openPicker={openPicker}\n />\n </I18nextProvider>\n );\n}\n\nDatetimepickerStateContainer.propTypes = {\n realtime: PropTypes.bool,\n initialTimestamp: PropTypes.number,\n initialArriveBy: PropTypes.bool,\n onDepartureClick: PropTypes.func.isRequired,\n onArrivalClick: PropTypes.func.isRequired,\n onTimeChange: PropTypes.func.isRequired,\n onDateChange: PropTypes.func.isRequired,\n onNowClick: PropTypes.func.isRequired,\n embedWhenClosed: PropTypes.node,\n embedWhenOpen: PropTypes.node,\n lang: PropTypes.string,\n color: PropTypes.string,\n timeZone: PropTypes.string,\n fontWeights: PropTypes.shape({\n medium: PropTypes.number,\n }),\n serviceTimeRange: PropTypes.number,\n onOpen: PropTypes.func,\n onClose: PropTypes.func,\n openPicker: PropTypes.bool,\n};\n\nDatetimepickerStateContainer.defaultProps = {\n realtime: false,\n initialArriveBy: undefined,\n initialTimestamp: undefined,\n embedWhenClosed: null,\n embedWhenOpen: null,\n lang: 'en',\n color: '#007ac9',\n timeZone: 'Europe/Helsinki',\n fontWeights: {\n medium: 500,\n },\n onOpen: null,\n onClose: null,\n openPicker: undefined,\n serviceTimeRange: 30,\n};\n\nexport default DatetimepickerStateContainer;\n"],"names":["parseTypedTime","typedValue","actualValue","length","split","every","n","Number","isInteger","slice","validateClock","hours","minutes","hoursValid","isNaN","minutesValid","validateInput","inputValue","includes","startsWith","values","concat","substring","getTs","currentTimestamp","trimmed","trim","match","splitter","DateTime","fromMillis","set","hour","minute","second","millisecond","valueOf","DesktopDatetimepicker","value","onChange","getDisplay","timeChoices","id","label","icon","disableTyping","timeZone","datePicker","translationSettings","Settings","defaultZone","t","useTranslation","displayValue","changeDisplayValue","useState","typing","setTyping","showAllOptions","setShowAllOptions","invalidInput","setinvalidInput","useEffect","handleTimestamp","newValue","asNumber","e","options","map","time","toString","closestOptions","filter","o","closestOption","reduce","a","b","Math","abs","undefined","inputId","labelId","ariaError","React","createElement","className","styles","htmlFor","Select","ariaLiveMessages","guidance","context","isDisabled","onFilter","onFocus","itemLabel","currentTime","toFormat","ts","components","IndicatorsContainer","cx","classNamePrefix","onInputChange","action","str","valid","test","isinvalidInput","validated","noOptionsMessage","filterOption","option","input","_input$split$","completeInput","isMod15","minuteInput","inputH","inputM","optH","optM","total","filterOptions","isValidHour","comp","controlShouldRenderValue","tabSelectsValue","placeholder","target","select","onBlur","onKeyDown","key","isSearchable","isMobile","userAgent","navigator","vendor","window","opera","css","ref","insertAt","document","head","getElementsByTagName","style","type","firstChild","insertBefore","appendChild","styleSheet","cssText","createTextNode","process","env","NODE_ENV","propTypes","PropTypes","number","isRequired","func","arrayOf","string","node","bool","shape","lng","defaultProps","AndroidSelect","dateChoices","items","date","selectedItem","find","isOpen","getToggleButtonProps","getMenuProps","getItemProps","highlightedIndex","useSelect","itemToString","item","_item$label","onSelectedItemChange","nextSelectedItem","container","suggestionsContainerOpen","index","Object","assign","suggestion","suggestionHighlighted","MobileDatepicker","itemCount","startTime","Array","fill","_","i","plus","days","toMillis","nativeInput","toLowerCase","indexOf","MobileTimepicker","changeInputValue","isValidInput","setValidInput","showError","inputMode","maxLength","setSelectionRange","event","replace","charAt","actual","timestamp","MobilePickerModal","departureOrArrival","onNowClick","lang","color","onSubmit","onCancel","getTimeDisplay","dateSelectItemCount","getDateDisplay","fontWeights","onAfterClose","displayTimestamp","changeTimestamp","departureOrArrivalCurrent","changeDepartureOrArrival","htmlId","uniqueId","dateSelectStartTime","now","startOf","Modal","appElement","querySelector","overlayClassName","medium","onClick","name","checked","Icon","img","Datetimepicker","onTimeChange","onDateChange","onDepartureClick","onArrivalClick","embedWhenClosed","embedWhenOpen","onModalSubmit","serviceTimeRange","onOpen","onClose","openPicker","changeOpen","changeDisplayTimestamp","timerId","setTimer","useMobileInputs","elem","dateTimeInputIsSupported","openPickerRef","useRef","inputRef","alertRef","defaultLocale","nowSelected","clearInterval","newId","setInterval","hasSame","formatted","toUpperCase","useMemo","selectedMoment","timeSelectStartTime","isMobileCurrently","newTimeChoices","current","push","fiveMinutes","nextFiveMin","ceil","timesToAdd","closestIndexAfter","findIndex","splice","from","Set","showScreenreaderCloseAlert","innerHTML","setTimeout","handleClose","handleNowClick","hidden","closed","role","textbutton","active","formatToprowSummary","dateDisplay","timeDisplay","summary","isToday","isTomorrow","newTimestamp","newDepartureOrArrival","requestAnimationFrame","_openPickerRef$curren","focus","Fragment","validate","oneOf","i18n","createInstance","fallbackLng","resources","de","translation","today","tomorrow","arrival","departure","ready","cancel","en","fi","pl","sv","defaultNS","react","useSuspense","DatetimepickerStateContainer","realtime","initialArriveBy","initialTimestamp","initialNow","changeTimestampState","bothNull","oneNull","sameTime","round","timeChanged","debounce","newTime","toUnixInteger","dateChanged","newDate","I18nextProvider","nowClicked","departureClicked","changed","arrivalClicked","mode","init"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digitransit-component/digitransit-component-datetimepicker",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.1",
|
|
4
4
|
"description": "digitransit-component datetimepicker module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -31,16 +31,16 @@
|
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"@digitransit-component/digitransit-component-icon": "^2.0.0",
|
|
33
33
|
"classnames": "2.5.1",
|
|
34
|
+
"downshift": "9.0.10",
|
|
34
35
|
"i18next": "^22.5.1",
|
|
35
36
|
"lodash": "4.17.21",
|
|
36
37
|
"lodash-es": "4.17.21",
|
|
37
38
|
"luxon": "^3.6.1",
|
|
38
39
|
"prop-types": "^15.8.1",
|
|
39
40
|
"react": "^16.13.0",
|
|
40
|
-
"react-autosuggest": "^10.0.0",
|
|
41
41
|
"react-i18next": "^12.3.1",
|
|
42
42
|
"react-modal": "~3.11.2",
|
|
43
43
|
"react-select": "5.8.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "bf035f812f0cea9230af08994c03886551d89176"
|
|
46
46
|
}
|