UNPKG

@helpwave/hightide

Version:

helpwave's component and theming library

164 lines (161 loc) 5.38 kB
// src/components/date/TimePicker.tsx import { useEffect, useRef, useState } from "react"; import { Scrollbars } from "react-custom-scrollbars-2"; // src/util/noop.ts var noop = () => void 0; // src/util/array.ts var range = (start, end, allowEmptyRange = false) => { if (end < start) { if (!allowEmptyRange) { console.warn(`range: end (${end}) < start (${start}) should be allowed explicitly, set allowEmptyRange to true`); } return []; } return Array.from({ length: end - start + 1 }, (_, index) => index + start); }; var closestMatch = (list, firstCloser) => { return list.reduce((item1, item2) => { return firstCloser(item1, item2) ? item1 : item2; }); }; // src/components/date/TimePicker.tsx import clsx from "clsx"; import { jsx, jsxs } from "react/jsx-runtime"; var TimePicker = ({ time = /* @__PURE__ */ new Date(), onChange = noop, is24HourFormat = true, minuteIncrement = "5min", maxHeight = 300, className = "" }) => { const minuteRef = useRef(null); const hourRef = useRef(null); const isPM = time.getHours() >= 11; const hours = is24HourFormat ? range(0, 23) : range(1, 12); let minutes = range(0, 59); useEffect(() => { const scrollToItem = () => { if (minuteRef.current) { const container = minuteRef.current.parentElement; const hasOverflow = container.scrollHeight > maxHeight; if (hasOverflow) { minuteRef.current.scrollIntoView({ behavior: "instant", block: "nearest" }); } } }; scrollToItem(); }, [minuteRef, minuteRef.current]); useEffect(() => { const scrollToItem = () => { if (hourRef.current) { const container = hourRef.current.parentElement; const hasOverflow = container.scrollHeight > maxHeight; if (hasOverflow) { hourRef.current.scrollIntoView({ behavior: "instant", block: "nearest" }); } } }; scrollToItem(); }, [hourRef, hourRef.current]); switch (minuteIncrement) { case "5min": minutes = minutes.filter((value) => value % 5 === 0); break; case "10min": minutes = minutes.filter((value) => value % 10 === 0); break; case "15min": minutes = minutes.filter((value) => value % 15 === 0); break; case "30min": minutes = minutes.filter((value) => value % 30 === 0); break; } const closestMinute = closestMatch(minutes, (item1, item2) => Math.abs(item1 - time.getMinutes()) < Math.abs(item2 - time.getMinutes())); const style = (selected) => clsx( "chip-full hover:brightness-90 hover:bg-primary hover:text-on-primary rounded-md mr-3", { "bg-primary text-on-primary": selected, "bg-white text-black": !selected } ); const onChangeWrapper = (transformer) => { const newDate = new Date(time); transformer(newDate); onChange(newDate); }; return /* @__PURE__ */ jsxs("div", { className: clsx("row gap-x-2 w-fit min-w-[150px] select-none", className), children: [ /* @__PURE__ */ jsx(Scrollbars, { autoHeight: true, autoHeightMax: maxHeight, style: { height: "100%" }, children: /* @__PURE__ */ jsx("div", { className: "col gap-y-1 h-full", children: hours.map((hour) => { const currentHour = hour === time.getHours() - (!is24HourFormat && isPM ? 12 : 0); return /* @__PURE__ */ jsx( "button", { ref: currentHour ? hourRef : void 0, className: style(currentHour), onClick: () => onChangeWrapper((newDate) => newDate.setHours(hour + (!is24HourFormat && isPM ? 12 : 0))), children: hour.toString().padStart(2, "0") }, hour ); }) }) }), /* @__PURE__ */ jsx(Scrollbars, { autoHeight: true, autoHeightMax: maxHeight, style: { height: "100%" }, children: /* @__PURE__ */ jsx("div", { className: "col gap-y-1 h-full", children: minutes.map((minute) => { const currentMinute = minute === closestMinute; return /* @__PURE__ */ jsx( "button", { ref: currentMinute ? minuteRef : void 0, className: style(currentMinute), onClick: () => onChangeWrapper((newDate) => newDate.setMinutes(minute)), children: minute.toString().padStart(2, "0") }, minute + minuteIncrement ); }) }) }), !is24HourFormat && /* @__PURE__ */ jsxs("div", { className: "col gap-y-1", children: [ /* @__PURE__ */ jsx( "button", { className: style(!isPM), onClick: () => onChangeWrapper((newDate) => isPM && newDate.setHours(newDate.getHours() - 12)), children: "AM" } ), /* @__PURE__ */ jsx( "button", { className: style(isPM), onClick: () => onChangeWrapper((newDate) => !isPM && newDate.setHours(newDate.getHours() + 12)), children: "PM" } ) ] }) ] }); }; var ControlledTimePicker = ({ time, onChange = noop, ...props }) => { const [value, setValue] = useState(time); useEffect(() => setValue(time), [time]); return /* @__PURE__ */ jsx( TimePicker, { ...props, time: value, onChange: (time1) => { setValue(time1); onChange(time1); } } ); }; export { ControlledTimePicker, TimePicker }; //# sourceMappingURL=TimePicker.mjs.map