@activecollab/components
Version:
ActiveCollab Components
148 lines • 5.38 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import classNames from "classnames";
import nlp from "compromise";
import plg from "compromise-dates";
import moment from "moment";
import styled from "styled-components";
import { isValidTime } from "../../utils/timeUtils";
import { ComboBox } from "../ComboBox/ComboBox";
nlp.plugin(plg);
export const StyledInputTimeWrapper = styled.div.withConfig({
displayName: "InputTime__StyledInputTimeWrapper",
componentId: "sc-71akdh-0"
})(["max-width:176px;flex:1;& .c-combo-box--list{min-width:176px;}"]);
const renderOption = option => {
return /*#__PURE__*/React.createElement("div", {
id: option.id,
"data-testid": "time-option-" + option.id
}, option.name);
};
export const InputTime = _ref => {
let {
mode = "24",
selected: defaultSelected,
min = "00:00",
max = "23:45",
onChange,
step = 15,
size,
className,
placeholder,
triggerMode,
disabled,
invalid,
enableVirtualization = false,
addCustomTimeLabel = "Add",
...rest
} = _ref;
const [isOpen, setIsOpen] = useState(false);
const [search, setSearch] = useState(undefined);
const generateTimeOptions = () => {
const allOptions = [];
const currentTime = moment("00:00", "HH:mm");
while (currentTime.isBefore(moment("24:00", "HH:mm"))) {
allOptions.push({
id: currentTime.format("HH:mm"),
name: currentTime.format(mode === "12" ? "hh:mm A" : "HH:mm")
});
currentTime.add(step, "minutes");
}
return allOptions;
};
const timeOptionsFilter = (options, _min, _max) => {
const minTime = moment(isValidTime(_min) ? _min : "00:00", "HH:mm");
const maxTime = moment(isValidTime(_max) ? _max : "23:45", "HH:mm");
return options.filter(option => moment(option.id, "HH:mm").isSameOrAfter(minTime) && moment(option.id, "HH:mm").isSameOrBefore(maxTime));
};
const [allTimeOptions, setAllTimeOptions] = useState(generateTimeOptions());
const timeOptions = useMemo(() => timeOptionsFilter(allTimeOptions, min, max), [allTimeOptions, min, max]);
const isInOptions = useCallback(option => timeOptions.some(opt => opt.id === option), [timeOptions]);
const isValidDefaultSelected = defaultSelected ? isInOptions(defaultSelected) : false;
const [selected, setSelected] = useState(isValidDefaultSelected ? defaultSelected : undefined);
const handleInputChange = useCallback(text => {
setSearch(text);
if (/\d{1,2}:\d{2}/.test(text.trim())) {
return;
}
const doc = nlp(text);
const parsed = doc.times().get()[0];
if (parsed && parsed["24h"] && parsed["24h"] !== selected) {
const value = moment(parsed).format("HH:mm");
if (timeOptions.some(option => option.id === value)) {
setSelected(value);
onChange == null || onChange(value);
setIsOpen(false);
}
}
}, [onChange, selected, timeOptions]);
const handleEmptyAction = newTime => {
const time = String(newTime);
if (isValidTime(time)) {
const newOption = {
id: time,
name: mode === "12" ? moment(time, "HH:mm").format("hh:mm A") : time
};
const newOptions = [...timeOptions];
const index = newOptions.findIndex(option => moment(option.id, "HH:mm") > moment(time, "HH:mm"));
if (index === -1) {
newOptions.push(newOption);
} else {
newOptions.splice(index, 0, newOption);
}
setAllTimeOptions(newOptions);
onChange == null || onChange(time);
setSelected(time);
}
};
const handleChange = e => {
setSelected(e);
onChange == null || onChange(e);
};
const handleOpen = () => {
setIsOpen(true);
};
const handleClose = () => {
setIsOpen(false);
};
useEffect(() => {
if (isOpen && selected) {
var _document$getElementB;
const selectedItem = (_document$getElementB = document.getElementById(selected)) == null ? void 0 : _document$getElementB.parentElement;
selectedItem == null || selectedItem.scrollIntoView({
behavior: "smooth",
block: "center"
});
}
}, [isOpen, selected]);
useEffect(() => {
if (defaultSelected !== selected && timeOptions.some(opt => opt.id === defaultSelected)) setSelected(defaultSelected);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [defaultSelected, timeOptions]);
const isValid = time => !isInOptions(time) && isValidTime(time);
return /*#__PURE__*/React.createElement(StyledInputTimeWrapper, {
className: classNames("c-input-time", className)
}, /*#__PURE__*/React.createElement(ComboBox, _extends({}, rest, {
options: timeOptions,
open: isOpen,
disabledInternalSort: true,
selected: selected,
keepSameOptionsOrder: true,
onInputChange: handleInputChange,
onChange: handleChange,
handleEmptyAction: handleEmptyAction,
emptyValue: isValid(search) ? addCustomTimeLabel + " " + search : undefined,
forceCloseMenu: true,
placeholder: placeholder,
renderOption: renderOption,
autoHeightMax: 226,
size: size,
onClose: handleClose,
onOpen: handleOpen,
triggerMode: triggerMode,
disabled: disabled,
invalid: invalid,
disableVirtualization: !enableVirtualization
})));
};
//# sourceMappingURL=InputTime.js.map