@intility/bifrost-react-datepicker
Version:
React detepicker for Intility's design system, Bifrost.
171 lines (170 loc) • 7.74 kB
JavaScript
"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { createContext, forwardRef, useContext, useMemo, useState } from "react";
import classNames from "classnames";
import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons/faExclamationTriangle";
import { faCheck } from "@fortawesome/free-solid-svg-icons/faCheck";
import { faClock } from "@fortawesome/free-solid-svg-icons/faClock";
import { faCalendarAlt } from "@fortawesome/free-solid-svg-icons/faCalendarAlt";
import ReactDatePickerDefaultExport, { CalendarContainer } from "react-datepicker";
import Label from "@intility/bifrost-react/Label";
import Icon from "@intility/bifrost-react/Icon";
import Feedback from "@intility/bifrost-react/Feedback";
import Description from "@intility/bifrost-react/Description";
import Dropdown from "@intility/bifrost-react/Dropdown";
import useLocale from "@intility/bifrost-react/hooks/useLocale";
import useUniqueId from "@intility/bifrost-react/hooks/useUniqueId";
import enGbLocale from "./locales/en-gb.js";
import nbNoLocale from "./locales/nb-no.js";
import svSeLocale from "./locales/sv-se.js";
function CalendarContainerOverride(props) {
const { ref, placement } = useContext(DatePickerCtx);
return /*#__PURE__*/ _jsx(Dropdown, {
unstyled: true,
noArrow: true,
offset: [
0,
4
],
visible: true,
content: /*#__PURE__*/ _jsx(CalendarContainer, {
...props
}),
placement: placement || "bottom",
reference: ref?.input
});
}
const DatePickerCtx = /*#__PURE__*/ createContext({
ref: null
});
const ReactDatePicker = ReactDatePickerDefaultExport.default ?? ReactDatePickerDefaultExport;
export const DatePicker = /*#__PURE__*/ forwardRef(({ label, hideLabel = false, icon, rightIcon = false, disabled = false, readOnly = false, state = "default", feedback, required = false, description, requiredNoLabel = false, optional = false, className, style, isClearable = false, id, timeIntervals = 30, inline = false, small = false, ...props }, ref)=>{
const { dateOptions } = useLocale();
const inputId = useUniqueId(id);
const [datePickerRef, setDatePickerRef] = useState(null);
const contextValue = useMemo(()=>({
placement: props.popperPlacement,
ref: datePickerRef
}), [
props.popperPlacement,
datePickerRef
]);
let datepickerLocale = enGbLocale;
switch(dateOptions.locale){
case "nb-no":
datepickerLocale = nbNoLocale;
break;
case "sv-se":
datepickerLocale = svSeLocale;
break;
}
const mode = props?.showYearPicker && "year" || props?.showMonthYearPicker && "monthYear" || props?.showTimeSelectOnly && "time" || (props?.showTimeSelect || props?.showTimeInput) && "dateTime" || "date";
let displayIcon;
if (state === "warning" || state === "alert") {
displayIcon = faExclamationTriangle;
} else if (state === "success") {
displayIcon = faCheck;
} else if (icon) {
displayIcon = icon;
} else if (mode === "time") {
displayIcon = faClock;
} else {
displayIcon = faCalendarAlt;
}
const placeholderText = datepickerLocale.placeholder[mode];
const dateFormat = datepickerLocale.format[mode];
// apparently, some versions (within the same major release) of `react-datepicker` passes a
// Date object to `formatWeekDay` instead of a string
function firstLetterOfDay(day) {
if (typeof day === "string") return day.slice(0, 1).toUpperCase();
if (day instanceof Date) {
return day.toLocaleString(dateOptions.locale, {
weekday: "narrow"
}).toUpperCase();
}
return day;
}
return /*#__PURE__*/ _jsx(DatePickerCtx.Provider, {
value: contextValue,
children: /*#__PURE__*/ _jsxs("div", {
className: classNames(className, "bf-datepicker-container", {
"bf-datepicker-disabled": disabled,
"bf-datepicker-success": state === "success",
"bf-datepicker-warning": state === "warning",
"bf-datepicker-alert": state === "alert",
"bf-datepicker-small": small
}),
style: style,
"data-testid": "bf-datepicker-container",
children: [
!hideLabel && /*#__PURE__*/ _jsx(Label, {
htmlFor: inputId,
required: required && !requiredNoLabel,
optional: optional,
disabled: disabled,
readOnly: readOnly,
children: label
}),
/*#__PURE__*/ _jsx(Description, {
children: description
}),
/*#__PURE__*/ _jsxs("div", {
className: classNames("bf-datepicker-icon-container", {
"bf-datepicker-icon-right": rightIcon,
"bf-datepicker-icon-left": !rightIcon,
"bf-show-time-select": props.showTimeSelect,
"bf-show-time-select-only": props.showTimeSelectOnly,
"bf-datepicker-clearable": isClearable
}),
children: [
/*#__PURE__*/ _jsx(ReactDatePicker, {
readOnly: readOnly,
className: classNames("bf-datepicker", "bf-open-sans", className),
id: inputId,
dateFormat: dateFormat,
timeFormat: datepickerLocale.format.time,
showMonthDropdown: true,
useShortMonthInDropdown: true,
showYearDropdown: true,
yearDropdownItemNumber: 5,
disabled: disabled,
locale: datepickerLocale.locale,
placeholderText: placeholderText,
isClearable: isClearable,
inline: inline,
formatWeekDay: firstLetterOfDay,
...props?.showTimeSelect && {
fixedHeight: true
},
timeIntervals: timeIntervals,
autoComplete: "off",
ref: (r)=>{
setDatePickerRef(r);
if (typeof ref === "function") {
ref(r);
} else if (ref) {
ref.current = r;
}
},
calendarContainer: inline ? undefined : CalendarContainerOverride,
...props
}),
!inline && /*#__PURE__*/ _jsx("span", {
className: classNames("bf-datepicker-icon", {
"bf-state-icon": state
}),
children: /*#__PURE__*/ _jsx(Icon, {
icon: displayIcon
})
})
]
}),
/*#__PURE__*/ _jsx(Feedback, {
children: feedback
})
]
})
});
});
DatePicker.displayName = "DatePicker";
export default DatePicker;