@saas-ui/date-picker
Version:
Chakra UI - Date Picker Component
1,669 lines (1,637 loc) • 44.9 kB
JavaScript
'use client'
// src/date-picker.tsx
import { useRef } from "react";
import {
useDatePickerState
} from "@react-stately/datepicker";
import { useDatePicker } from "@react-aria/datepicker";
import { useLocale } from "@react-aria/i18n";
import {
useMultiStyleConfig,
Popover,
useTheme
} from "@chakra-ui/react";
// src/date-picker-context.tsx
import * as React from "react";
import {
useCalendarCell as useAriaCalendarCell
} from "@react-aria/calendar";
import { createContext, dataAttr } from "@chakra-ui/utils";
import {
getDayOfWeek,
isSameDay,
now
} from "@internationalized/date";
// src/date-utils.ts
import { CalendarDateTime, DateFormatter } from "@internationalized/date";
var isDateInRange = (date, range) => {
if (!date || !range) {
return false;
}
return !!((range == null ? void 0 : range.start) && date.compare(range.start) >= 0 && (range == null ? void 0 : range.end) && date.compare(range.end) <= 0);
};
// src/date-picker-context.tsx
import { usePopoverContext } from "@chakra-ui/react";
var [DatePickerStylesProvider, useDatePickerStyles] = createContext({
name: "DatePickerStylesContext"
});
var [DatePickerProvider, useContext] = createContext({
name: "DatePickerProvider"
});
var useDatePickerContext = () => {
const context = useContext();
if ("dateRange" in context.state) {
throw new Error(
"useDatePickerContext must be used within a DatePickerProvider"
);
}
return context;
};
var useDateRangePickerContext = () => {
const context = useContext();
if (!("dateRange" in context.state)) {
throw new Error(
"useDateRangePickerContext must be used within a DateRangePicker"
);
}
return context;
};
var useDatePickerDialog = () => {
const { dialogProps, state, datePickerRef } = useContext();
React.useEffect(() => {
if (state.isOpen) {
setTimeout(() => {
var _a;
const parent = (_a = datePickerRef.current) == null ? void 0 : _a.parentNode;
const el = (parent == null ? void 0 : parent.querySelector("[data-selected]")) || (parent == null ? void 0 : parent.querySelector("[data-today]")) || (parent == null ? void 0 : parent.querySelector(
'td button:not([aria-disabled="true"])'
));
el == null ? void 0 : el.focus();
}, 0);
}
}, [datePickerRef, state.isOpen]);
return {
dialogProps: {
...dialogProps
}
};
};
var useDatePickerInput = () => {
const popover = usePopoverContext();
const { onClick, ...triggerProps } = popover.getTriggerProps();
const context = useDatePickerContext();
const { state, locale, groupProps, datePickerRef } = context;
const buttonProps = {
...context.buttonProps,
...triggerProps
};
return {
fieldProps: context.fieldProps,
groupProps,
buttonProps,
datePickerRef,
locale,
state
};
};
var useDateRangePickerInput = () => {
const popover = usePopoverContext();
const { onClick, ...triggerProps } = popover.getTriggerProps();
const context = useDateRangePickerContext();
const { state, locale, groupProps, datePickerRef } = context;
const buttonProps = {
...context.buttonProps,
...triggerProps
};
return {
groupProps,
buttonProps,
datePickerRef,
locale,
state,
startFieldProps: context.startFieldProps,
endFieldProps: context.endFieldProps
};
};
var useCalendarCell = (props, state, ref) => {
const context = useContext();
const { date, currentMonth } = props;
const {
cellProps,
buttonProps,
isSelected,
isInvalid,
formattedDate,
isOutsideVisibleRange,
isUnavailable
} = useAriaCalendarCell({ date }, state, ref);
const highlightedRange = "highlightedRange" in state && state.highlightedRange;
const dayOfWeek = getDayOfWeek(props.date, context.locale);
const isSelectionStart = isSelected && highlightedRange && isSameDay(date, highlightedRange.start);
const isSelectionEnd = isSelected && highlightedRange && isSameDay(date, highlightedRange.end);
const isRangeStart = isSelected && (dayOfWeek === 0 || date.day === 1);
const isRangeEnd = isSelected && (dayOfWeek === 6 || date.day === currentMonth.calendar.getDaysInMonth(currentMonth));
const isRange = isSelected && highlightedRange && isDateInRange(date, highlightedRange);
return {
cellProps,
buttonProps: {
...buttonProps,
["data-selected"]: dataAttr(isSelected),
["data-invalid"]: dataAttr(isInvalid),
["data-selection-start"]: dataAttr(isSelectionStart != null ? isSelectionStart : void 0),
["data-selection-end"]: dataAttr(isSelectionEnd != null ? isSelectionEnd : void 0),
["data-range-start"]: dataAttr(isRangeStart),
["data-range-end"]: dataAttr(isRangeEnd),
["data-highlighted"]: dataAttr(isRange != null ? isRange : void 0),
["data-today"]: dataAttr(isSameDay(date, now(context.timeZone))),
["data-outside-visible-range"]: dataAttr(isOutsideVisibleRange),
["data-unavailable"]: dataAttr(isUnavailable)
},
isSelected,
isInvalid,
formattedDate
};
};
// src/date-picker-styles.ts
import { createMultiStyleConfigHelpers } from "@chakra-ui/styled-system";
import { transparentize } from "@chakra-ui/theme-tools";
var parts = [
"dialog",
"calendar",
"header",
"title",
"weekday",
"day",
"dayButton",
"dayLabel"
];
var { definePartsStyle, defineMultiStyleConfig } = createMultiStyleConfigHelpers(parts);
var baseStyle = definePartsStyle((props) => {
const { colorScheme: c } = props;
const selected = {
bg: `${c}.500`,
color: "white",
_dark: {
bg: `${c}.500`,
color: "white"
}
};
return {
dialog: {},
calendar: {},
header: {
alignItems: "center"
},
title: {
fontWeight: "bold",
fontSize: "sm",
flex: 1,
px: 3
},
weekday: {
fontWeight: "normal",
color: "muted",
fontSize: "sm",
h: 10
},
day: {
py: "1px",
position: "relative"
},
dayButton: {
borderRadius: "md",
fontSize: "sm",
px: 3,
h: 8,
outline: "none",
_focus: {
outline: "none"
},
_focusVisible: {
outline: "none",
boxShadow: "outline",
borderRadius: "md"
},
"&[data-today]": {
bg: "blackAlpha.50",
_dark: {
bg: "whiteAlpha.50"
}
},
_hover: {
bg: "blackAlpha.100",
borderRadius: "md",
_dark: {
bg: "whiteAlpha.100"
}
},
_selected: selected,
_highlighted: {
bg: `${c}.100`,
borderRadius: "none",
color: "black",
_dark: {
bg: transparentize(`${c}.400`, 0.2)(props.theme),
color: "white"
},
"&[data-range-start]": {
borderStartRadius: "md"
},
"&[data-range-end]": {
borderEndRadius: "md"
},
"&[data-selection-start]": {
borderStartRadius: "md",
color: "white",
_before: {
content: '""',
position: "absolute",
inset: "1px",
borderRadius: "md",
...selected
}
},
"&[data-selection-end]": {
borderEndRadius: "md",
color: "white",
_before: {
content: '""',
position: "absolute",
inset: "1px",
borderRadius: "md",
...selected
}
}
},
_disabled: {
color: "muted",
cursor: "not-allowed",
_hover: {
bg: "transparent"
}
},
"&[data-week-start], &[data-month-start]": { borderStartRadius: "md" },
"&[data-week-end], &[data-month-end]": {
borderEndRadius: "md"
}
},
dayLabel: {
position: "relative",
zIndex: 1
},
year: {
py: 2,
px: 3,
fontSize: "sm",
borderRadius: "md",
transitionProperty: "common",
transitionDuration: "normal"
}
};
});
var datePickerStyleConfig = defineMultiStyleConfig({
defaultProps: {
colorScheme: "primary"
},
baseStyle
});
// src/date-picker.tsx
import { getLocalTimeZone } from "@internationalized/date";
import { runIfFn } from "@chakra-ui/utils";
import { flushSync } from "react-dom";
import { jsx } from "react/jsx-runtime";
var DatePickerContainer = (props) => {
var _a;
const {
children,
value: valueProp,
minValue,
maxValue,
defaultValue,
onChange,
closeOnSelect,
createCalendar: createCalendar3,
...rest
} = props;
const {
locale: localeProp,
timeZone = getLocalTimeZone() || "UTC",
hourCycle = 12,
firstDayOfWeek
} = props;
const { locale } = useLocale();
const theme = useTheme();
const styleConfig = (_a = theme.components["SuiDatePicker"]) != null ? _a : datePickerStyleConfig;
const styles = useMultiStyleConfig("SuiDatePicker", {
styleConfig,
...props
});
const state = useDatePickerState({
value: valueProp,
minValue,
maxValue,
defaultValue,
onChange,
shouldCloseOnSelect: closeOnSelect,
...rest
});
const datePickerRef = useRef(null);
const {
groupProps,
labelProps,
fieldProps,
buttonProps,
dialogProps,
descriptionProps,
errorMessageProps,
calendarProps,
isInvalid,
validationDetails,
validationErrors
} = useDatePicker(
{
["aria-label"]: "Date Picker",
value: state.value,
minValue,
maxValue,
onChange: state.setValue,
...rest
},
state,
datePickerRef
);
const context = {
locale: localeProp || locale,
state,
hourCycle,
timeZone,
firstDayOfWeek,
groupProps,
labelProps,
fieldProps,
buttonProps,
dialogProps,
calendarProps,
descriptionProps,
errorMessageProps,
datePickerRef,
isInvalid,
validationDetails,
validationErrors,
createCalendar: createCalendar3
};
return /* @__PURE__ */ jsx(DatePickerProvider, { value: context, children: /* @__PURE__ */ jsx(DatePickerStylesProvider, { value: styles, children: runIfFn(children, state) }) });
};
var DatePicker = (props) => {
const {
children,
arrowPadding,
arrowShadowColor,
arrowSize,
autoFocus,
boundary,
closeDelay,
closeOnBlur,
closeOnEsc,
computePositionOnMount,
defaultIsOpen,
direction,
eventListeners,
flip,
gutter,
isLazy = false,
lazyBehavior = "keepMounted",
modifiers,
offset,
openDelay,
placement,
preventOverflow,
returnFocusOnClose,
strategy,
trigger,
...containerProps
} = props;
const popoverProps = {
arrowPadding,
arrowShadowColor,
arrowSize,
autoFocus,
boundary,
closeDelay,
closeOnBlur,
closeOnEsc,
computePositionOnMount,
defaultIsOpen,
direction,
eventListeners,
flip,
gutter,
isLazy,
lazyBehavior,
modifiers,
offset,
openDelay,
placement,
preventOverflow,
returnFocusOnClose,
strategy,
trigger
};
return /* @__PURE__ */ jsx(DatePickerContainer, { ...containerProps, defaultOpen: defaultIsOpen, children: (state) => {
return /* @__PURE__ */ jsx(
Popover,
{
...popoverProps,
isOpen: state.isOpen,
onOpen: () => flushSync(() => state.setOpen(true)),
onClose: () => flushSync(() => state.setOpen(false)),
children
}
);
} });
};
var DatePickerStatic = (props) => {
const { children, ...rest } = props;
return /* @__PURE__ */ jsx(DatePickerContainer, { ...rest, children });
};
// src/date-picker-dialog.tsx
import { cx } from "@chakra-ui/utils";
import {
PopoverAnchor,
PopoverArrow,
PopoverBody,
PopoverContent,
PopoverTrigger
} from "@chakra-ui/react";
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
var DatePickerTrigger = PopoverTrigger;
var DatePickerAnchor = PopoverAnchor;
var DatePickerDialog = (props) => {
const { children, hideArrow = true, ...rest } = props;
const { dialogProps } = useDatePickerDialog();
const styles = useDatePickerStyles();
return /* @__PURE__ */ jsxs(
PopoverContent,
{
...rest,
...dialogProps,
width: "auto",
minW: "300px",
sx: styles.dialog,
className: cx("sui-date-picker__dialog", props.className),
children: [
!hideArrow && /* @__PURE__ */ jsx2(PopoverArrow, {}),
/* @__PURE__ */ jsx2(PopoverBody, { children })
]
}
);
};
// src/calendar.tsx
import { chakra as chakra3, forwardRef as forwardRef2 } from "@chakra-ui/react";
import { ChevronLeftIcon, ChevronRightIcon } from "@saas-ui/core";
// src/button.tsx
import {
Button,
forwardRef,
IconButton
} from "@chakra-ui/react";
import { callAllHandlers } from "@chakra-ui/utils";
import { Pressable } from "@react-aria/interactions";
import { jsx as jsx3 } from "react/jsx-runtime";
var FieldButton = forwardRef(
(props, ref) => {
const { onPress, onFocusChange, onFocus, onBlur, ...rest } = props;
return /* @__PURE__ */ jsx3(Pressable, { onPress, children: /* @__PURE__ */ jsx3(
Button,
{
ref,
size: "sm",
h: "1.75rem",
mr: "2",
onFocus: () => callAllHandlers(() => onFocusChange == null ? void 0 : onFocusChange(true), props.onFocus),
onBlur: () => callAllHandlers(() => onFocusChange == null ? void 0 : onFocusChange(false), props.onBlur),
...rest,
children: props.children
}
) });
}
);
var NavButton = forwardRef((props, ref) => {
const { onPress, onFocusChange, onFocus, onBlur, ...rest } = props;
return /* @__PURE__ */ jsx3(Pressable, { onPress, children: /* @__PURE__ */ jsx3(
IconButton,
{
ref,
size: "sm",
variant: "ghost",
onFocus: () => callAllHandlers(() => onFocusChange == null ? void 0 : onFocusChange(true), props.onFocus),
onBlur: () => callAllHandlers(() => onFocusChange == null ? void 0 : onFocusChange(false), props.onBlur),
...rest,
children: props.children
}
) });
});
// src/calendar-context.ts
import { createContext as createContext2 } from "@chakra-ui/utils";
var [CalendarProvider, useCalendarContext] = createContext2({
name: "CalendarProvider"
});
// src/calendar-grid.tsx
import { useCalendarGrid } from "@react-aria/calendar";
import {
getWeeksInMonth,
endOfMonth
} from "@internationalized/date";
// src/calendar-cell.tsx
import { useRef as useRef2 } from "react";
import { isSameMonth } from "@internationalized/date";
import { chakra } from "@chakra-ui/react";
import { jsx as jsx4 } from "react/jsx-runtime";
var CalendarCell = ({
state,
date,
currentMonth
}) => {
const ref = useRef2(null);
const { cellProps, buttonProps, formattedDate } = useCalendarCell(
{
date,
currentMonth
},
state,
ref
);
const isOutsideMonth = !isSameMonth(currentMonth, date);
const styles = useDatePickerStyles();
const cellStyles = {
textAlign: "center",
padding: 0,
...styles.day
};
const buttonStyles = {
...styles.dayButton
};
return /* @__PURE__ */ jsx4(chakra.td, { as: "td", ...cellProps, __css: cellStyles, children: /* @__PURE__ */ jsx4(
chakra.button,
{
...buttonProps,
type: "button",
ref,
hidden: isOutsideMonth,
width: "100%",
__css: buttonStyles,
children: /* @__PURE__ */ jsx4(chakra.span, { __css: styles.dayLabel, children: formattedDate })
}
) });
};
// src/calendar-grid.tsx
import { chakra as chakra2 } from "@chakra-ui/react";
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
var CalendarGrid = ({ offset = {} }) => {
const { state, locale, firstDayOfWeek } = useCalendarContext();
const startDate = state.visibleRange.start.add(offset);
const endDate = endOfMonth(startDate);
const { gridProps, headerProps, weekDays } = useCalendarGrid(
{
startDate,
endDate,
firstDayOfWeek
},
state
);
const styles = useDatePickerStyles();
const gridStyles = {
...styles.grid
};
const weeksInMonth = getWeeksInMonth(
state.visibleRange.start,
locale,
firstDayOfWeek
);
return /* @__PURE__ */ jsxs2(chakra2.table, { ...gridProps, __css: gridStyles, children: [
/* @__PURE__ */ jsx5(chakra2.thead, { ...headerProps, children: /* @__PURE__ */ jsx5(chakra2.tr, { children: weekDays.map((day, index) => /* @__PURE__ */ jsx5(chakra2.th, { __css: styles.weekday, children: day }, index)) }) }),
/* @__PURE__ */ jsx5(chakra2.tbody, { children: [...new Array(weeksInMonth).keys()].map((weekIndex) => /* @__PURE__ */ jsx5(chakra2.tr, { children: state.getDatesInWeek(weekIndex, startDate).map(
(date, i) => date ? /* @__PURE__ */ jsx5(
CalendarCell,
{
state,
date,
currentMonth: startDate
},
i
) : /* @__PURE__ */ jsx5(chakra2.td, { __css: { padding: 0 } }, i)
) }, weekIndex)) })
] });
};
// src/use-calendar.ts
import { useCalendar as useAriaCalendar } from "@react-aria/calendar";
import { useCalendarState } from "@react-stately/calendar";
import { useRef as useRef3, useState, useMemo, useEffect as useEffect2 } from "react";
import { GregorianCalendar } from "@internationalized/date";
import { useControllableState } from "@chakra-ui/react";
var defaultCreateCalendar = (name) => {
switch (name) {
case "gregory":
return new GregorianCalendar();
default:
throw new Error(`Unsupported calendar ${name}`);
}
};
var useCalendar = (props) => {
var _a;
const {
locale,
firstDayOfWeek,
calendarProps: contextCalendarProps,
createCalendar: createCalendar3 = defaultCreateCalendar
} = useDatePickerContext();
const [action, setAction] = useState("calendar");
const [focusedValue, setFocusedValue] = useControllableState({
value: props.focusedValue,
defaultValue: (_a = props.defaultFocusedValue) != null ? _a : contextCalendarProps.value,
onChange: props.onFocusChange
});
const state = useCalendarState({
...contextCalendarProps,
focusedValue: focusedValue != null ? focusedValue : void 0,
onFocusChange: setFocusedValue,
locale,
firstDayOfWeek,
createCalendar: createCalendar3
});
useEffect2(() => {
if (state.value) {
setFocusedValue(state.value);
}
}, [state.value]);
const ref = useRef3(null);
const {
calendarProps,
prevButtonProps,
nextButtonProps,
errorMessageProps,
title
} = useAriaCalendar(
{
firstDayOfWeek,
...props
},
state
);
const titleProps = useMemo(() => {
return {
onClick() {
setAction(action === "calendar" ? "years" : "calendar");
}
};
}, [action]);
return {
state,
locale,
firstDayOfWeek,
calendarProps,
prevButtonProps,
nextButtonProps,
errorMessageProps,
titleProps,
title,
ref,
action
};
};
// src/calendar.tsx
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
var DatePickerCalendar = (props) => {
return /* @__PURE__ */ jsxs3(CalendarContainer, { ...props, children: [
/* @__PURE__ */ jsxs3(CalendarHeader, { children: [
/* @__PURE__ */ jsx6(CalendarTitle, {}),
/* @__PURE__ */ jsx6(CalendarPrevious, {}),
/* @__PURE__ */ jsx6(CalendarNext, {})
] }),
/* @__PURE__ */ jsx6(CalendarGrid, {})
] });
};
var CalendarContainer = (props) => {
const { children, ...rest } = props;
const styles = useDatePickerStyles();
const calendarStyles = {
...styles.calendar
};
const context = useCalendar(props);
const { calendarProps, ref } = context;
return /* @__PURE__ */ jsx6(CalendarProvider, { value: context, children: /* @__PURE__ */ jsx6(chakra3.div, { ...rest, ...calendarProps, ref, __css: calendarStyles, children }) });
};
var CalendarHeader = (props) => {
const { children, ...rest } = props;
const styles = useDatePickerStyles();
const headerStyles = {
display: "flex",
flexDirection: "row",
alignItems: "center",
pb: 4,
...styles.header
};
return /* @__PURE__ */ jsx6(chakra3.div, { ...rest, __css: headerStyles, children });
};
var CalendarTitle = (props) => {
const { title } = useCalendarContext();
const styles = useDatePickerStyles();
const titleStyles = {
...styles.title
};
return /* @__PURE__ */ jsx6(chakra3.h5, { ...props, __css: titleStyles, children: title });
};
var CalendarNext = forwardRef2(
(props, ref) => {
const { icon = /* @__PURE__ */ jsx6(ChevronRightIcon, { boxSize: 5 }), ...rest } = props;
const { nextButtonProps } = useCalendarContext();
return /* @__PURE__ */ jsx6(
NavButton,
{
ref,
"aria-label": "Next",
...nextButtonProps,
icon,
...rest
}
);
}
);
var CalendarPrevious = forwardRef2(
(props, ref) => {
const { icon = /* @__PURE__ */ jsx6(ChevronLeftIcon, { boxSize: 5 }), ...rest } = props;
const { prevButtonProps } = useCalendarContext();
return /* @__PURE__ */ jsx6(
NavButton,
{
ref,
"aria-label": "Previous",
...prevButtonProps,
icon,
...rest
}
);
}
);
// src/date-range-picker.tsx
import * as React2 from "react";
import {
useDateRangePickerState
} from "@react-stately/datepicker";
import { useDateRangePicker } from "@react-aria/datepicker";
import {
useMultiStyleConfig as useMultiStyleConfig2,
Popover as Popover2,
useTheme as useTheme2
} from "@chakra-ui/react";
import { useLocale as useLocale2 } from "@react-aria/i18n";
import { getLocalTimeZone as getLocalTimeZone2 } from "@internationalized/date";
import { flushSync as flushSync2 } from "react-dom";
import { jsx as jsx7 } from "react/jsx-runtime";
var DateRangePickerContainer = (props) => {
var _a;
const {
value: valueProp,
defaultValue,
onChange,
createCalendar: createCalendar3,
...rest
} = props;
const {
locale: localeProp,
hourCycle = 12,
firstDayOfWeek,
minValue,
maxValue,
timeZone = getLocalTimeZone2(),
granularity = "day",
closeOnSelect
} = props;
const { locale } = useLocale2();
const theme = useTheme2();
const styleConfig = (_a = theme.components["SuiDatePicker"]) != null ? _a : datePickerStyleConfig;
const styles = useMultiStyleConfig2("SuiDatePicker", {
styleConfig,
...props
});
const state = useDateRangePickerState({
/* @ts-ignore doesn't accept null in strict mode, but it's supported */
value: valueProp,
defaultValue,
minValue,
maxValue,
/* @ts-ignore */
onChange,
shouldCloseOnSelect: closeOnSelect || granularity === "day"
});
const datePickerRef = React2.useRef(null);
const {
groupProps,
labelProps,
startFieldProps,
endFieldProps,
buttonProps,
dialogProps,
calendarProps,
descriptionProps,
errorMessageProps,
isInvalid,
validationDetails,
validationErrors
} = useDateRangePicker(
{
["aria-label"]: "Date Range Picker",
...rest
},
state,
datePickerRef
);
const context = {
state,
locale: localeProp || locale,
hourCycle,
timeZone,
firstDayOfWeek,
groupProps,
labelProps,
startFieldProps,
endFieldProps,
buttonProps,
dialogProps,
calendarProps,
descriptionProps,
errorMessageProps,
datePickerRef,
isInvalid,
validationDetails,
validationErrors,
createCalendar: createCalendar3
};
return /* @__PURE__ */ jsx7(DatePickerProvider, { value: context, children: /* @__PURE__ */ jsx7(DatePickerStylesProvider, { value: styles, children: /* @__PURE__ */ jsx7(
Popover2,
{
...props,
isOpen: state.isOpen,
onOpen: () => flushSync2(() => state.setOpen(true)),
onClose: () => flushSync2(() => state.setOpen(false))
}
) }) });
};
var DateRangePicker = (props) => {
return /* @__PURE__ */ jsx7(DateRangePickerContainer, { ...props });
};
var DateRangePickerDialog = DatePickerDialog;
// src/date-range-calendar.tsx
import { chakra as chakra4 } from "@chakra-ui/react";
// src/use-range-calendar.ts
import { useRangeCalendar as useAriaRangeCalendar } from "@react-aria/calendar";
import { useRangeCalendarState } from "@react-stately/calendar";
import { useRef as useRef5, useState as useState2, useMemo as useMemo2 } from "react";
var useRangeCalendar = (props) => {
const {
locale,
firstDayOfWeek,
timeZone,
calendarProps: contextCalendarProps,
createCalendar: createCalendar3 = defaultCreateCalendar
} = useDateRangePickerContext();
const [action, setAction] = useState2("calendar");
const state = useRangeCalendarState({
...contextCalendarProps,
visibleDuration: { months: 2 },
locale,
firstDayOfWeek,
createCalendar: createCalendar3
});
const ref = useRef5(null);
const {
calendarProps,
prevButtonProps,
nextButtonProps,
errorMessageProps,
title
} = useAriaRangeCalendar(
{
firstDayOfWeek,
...props
},
state,
ref
);
const titleProps = useMemo2(() => {
return {
onClick() {
setAction(action === "calendar" ? "years" : "calendar");
}
};
}, [action]);
return {
state,
locale,
firstDayOfWeek,
calendarProps,
prevButtonProps,
nextButtonProps,
errorMessageProps,
titleProps,
title,
ref,
action
};
};
// src/date-range-calendar.tsx
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
var DateRangePickerCalendar = (props) => {
return /* @__PURE__ */ jsxs4(RangeCalendarContainer, { ...props, children: [
/* @__PURE__ */ jsxs4(CalendarHeader, { children: [
/* @__PURE__ */ jsx8(CalendarTitle, {}),
/* @__PURE__ */ jsx8(CalendarPrevious, {}),
/* @__PURE__ */ jsx8(CalendarNext, {})
] }),
/* @__PURE__ */ jsxs4(chakra4.div, { display: "flex", alignItems: "flex-start", gap: "8", children: [
/* @__PURE__ */ jsx8(CalendarGrid, {}),
/* @__PURE__ */ jsx8(CalendarGrid, { offset: { months: 1 } })
] })
] });
};
var RangeCalendarContainer = (props) => {
const { children, ...rest } = props;
const styles = useDatePickerStyles();
const calendarStyles = {
...styles.calendar
};
const context = useRangeCalendar(rest);
const { calendarProps, ref } = context;
return /* @__PURE__ */ jsx8(CalendarProvider, { value: context, children: /* @__PURE__ */ jsx8(chakra4.div, { ...calendarProps, ref, __css: calendarStyles, children }) });
};
// src/date-input.tsx
import {
forwardRef as forwardRef5,
InputGroup,
InputRightElement,
Portal
} from "@chakra-ui/react";
// src/date-field.tsx
import * as React3 from "react";
import {
useDateFieldState,
useTimeFieldState
} from "@react-stately/datepicker";
import {
useDateField,
useDateSegment,
useTimeField
} from "@react-aria/datepicker";
import { createCalendar } from "@internationalized/date";
import {
chakra as chakra6,
FormLabel,
forwardRef as forwardRef4,
useFormControl,
useMergeRefs
} from "@chakra-ui/react";
// src/segmented-input.tsx
import {
chakra as chakra5,
forwardRef as forwardRef3,
omitThemingProps,
useMultiStyleConfig as useMultiStyleConfig3,
useStyleConfig,
useTheme as useTheme3
} from "@chakra-ui/react";
import { createContext as createContext3, dataAttr as dataAttr2, mapResponsive } from "@chakra-ui/utils";
// src/segmented-input-styles.ts
var baseStyle2 = ({ colorScheme }) => {
return {
px: "0.1rem",
textAlign: "end",
outline: "none",
rounded: "md",
["&[data-placeholder]"]: {
color: "muted"
},
["&[data-placeholder]+[data-literal]"]: {
color: "muted"
},
_focus: {
background: `${colorScheme}.500`,
color: "white"
},
"&[data-read-only]": {
bg: "transparent",
color: "muted"
}
};
};
var segmented_input_styles_default = {
baseStyle: baseStyle2,
defaultProps: {
colorScheme: "primary"
}
};
// src/segmented-input.tsx
import { jsx as jsx9 } from "react/jsx-runtime";
var sizes = {
sm: "2.2rem",
md: "2.5rem",
lg: "3rem"
};
var [SegmentedInputStylesProvider, useSegmentedInputStyles] = createContext3({
name: "SegmentedInputStylesContext"
});
var SegmentedInput = forwardRef3(
({ children, size, ...rest }, ref) => {
var _a;
const styles = useMultiStyleConfig3("Input", {
size,
...rest
});
const ownProps = omitThemingProps(rest);
const pe = mapResponsive(size, (s) => {
return sizes[s];
}) || sizes.md;
const inputStyles = {
display: "flex",
alignItems: "center",
/* @ts-ignore */
_focusWithin: (_a = styles.field) == null ? void 0 : _a._focusVisible,
...styles.field
};
return /* @__PURE__ */ jsx9(SegmentedInputStylesProvider, { value: styles, children: /* @__PURE__ */ jsx9(chakra5.div, { ...ownProps, pe, __css: inputStyles, ref, children }) });
}
);
SegmentedInput.displayName = "SegmentedInput";
var InputSegment = forwardRef3(
(props, ref) => {
const {
children,
type,
minValue,
maxValue,
isPlaceholder,
isEditable,
...rest
} = props;
const theme = useTheme3();
const isThemed = !!theme.components["SuiInputSegment"];
const styles = useStyleConfig("SuiInputSegment", {
styleConfig: !isThemed ? segmented_input_styles_default : void 0,
...rest
});
const minWidth = type && ["day", "month"].includes(type) ? 1 : String(maxValue).length;
const segmentStyles = {
boxSizing: "content-box",
fontVariantNumeric: "tabular-nums",
minWidth: maxValue != null ? minWidth + "ch" : "auto",
...styles
};
const isLiteral = type === "literal";
return /* @__PURE__ */ jsx9(
chakra5.div,
{
...rest,
ref,
"data-literal": dataAttr2(isLiteral),
"data-placeholder": dataAttr2(isPlaceholder),
"data-read-only": dataAttr2(!isEditable),
__css: segmentStyles,
children
}
);
}
);
InputSegment.displayName = "SegmentedInputSegment";
// src/date-field.tsx
import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
var DateField = forwardRef4(
(props, forwardedRef) => {
const state = useDateFieldState({
...props,
createCalendar
});
const ref = React3.useRef(null);
const {
fieldProps: { id, ...fieldProps }
} = useDateField(props, state, ref);
const inputProps = useFormControl(fieldProps);
const styles = useDatePickerStyles();
const dateFieldStyles = {
display: "flex",
width: "full",
...styles.dateField
};
return /* @__PURE__ */ jsx10(
chakra6.div,
{
...inputProps,
"aria-labelledby": `${inputProps.id}-label`,
ref: useMergeRefs(ref, forwardedRef),
__css: dateFieldStyles,
children: state.segments.map((segment, i) => /* @__PURE__ */ jsx10(DateSegment, { segment, state }, i))
}
);
}
);
DateField.displayName = "DateField";
var TimeField = (props) => {
const {
label = "Time",
defaultValue,
onChange,
onBlur,
onFocus,
onKeyDown,
onKeyUp,
hourCycle,
...rest
} = props;
const timeFieldProps = {
label,
defaultValue,
onChange,
onBlur,
onFocus,
onKeyDown,
onKeyUp,
hourCycle
};
const state = useTimeFieldState({
...props,
onChange
});
const ref = React3.useRef(null);
const { labelProps, fieldProps } = useTimeField(timeFieldProps, state, ref);
return /* @__PURE__ */ jsxs5(chakra6.div, { mt: 2, ...rest, children: [
/* @__PURE__ */ jsx10(FormLabel, { ...labelProps, children: label }),
/* @__PURE__ */ jsx10(SegmentedInput, { ...fieldProps, ref, display: "inline-flex", pr: 2, children: state.segments.map((segment, i) => /* @__PURE__ */ jsx10(DateSegment, { segment, state }, i)) })
] });
};
TimeField.displayName = "TimeField";
var DatePickerTimeField = (props) => {
const {
locale,
state: { timeValue, setTimeValue },
hourCycle
} = useDatePickerContext();
return /* @__PURE__ */ jsx10(
TimeField,
{
...props,
locale: props.locale || locale,
hourCycle,
value: timeValue,
onChange: (value) => {
setTimeValue(value);
}
}
);
};
DatePickerTimeField.displayName = "DatePickerTimeField";
var DatePickerStartTimeField = (props) => {
const {
locale,
state: { timeRange, setTime },
hourCycle
} = useDateRangePickerContext();
return /* @__PURE__ */ jsx10(
TimeField,
{
...props,
locale: props.locale || locale,
value: timeRange == null ? void 0 : timeRange.start,
onChange: (v) => setTime("start", v),
hourCycle
}
);
};
DatePickerStartTimeField.displayName = "DatePickerStartTimeField";
var DatePickerEndTimeField = (props) => {
const {
locale,
state: { timeRange, setTime },
hourCycle
} = useDateRangePickerContext();
return /* @__PURE__ */ jsx10(
TimeField,
{
...props,
locale: props.locale || locale,
value: timeRange == null ? void 0 : timeRange.end,
onChange: (v) => setTime("end", v),
hourCycle
}
);
};
DatePickerEndTimeField.displayName = "DatePickerEndTimeField";
var DateRangePickerTimeField = (props) => {
const { startLabel = "Start time", endLabel = "End time", ...rest } = props;
return /* @__PURE__ */ jsxs5(chakra6.div, { display: "flex", gap: "2", ...rest, children: [
/* @__PURE__ */ jsx10(DatePickerStartTimeField, { label: startLabel }),
/* @__PURE__ */ jsx10(DatePickerEndTimeField, { label: endLabel })
] });
};
DateRangePickerTimeField.displayName = "DateRangePickerTimeField";
var DateSegment = ({ segment, state }) => {
const ref = React3.useRef(null);
const {
segmentProps: { style, ...segmentProps }
} = useDateSegment(segment, state, ref);
return /* @__PURE__ */ jsx10(InputSegment, { ref, sx: style, ...segment, ...segmentProps, children: segment.text });
};
// src/icons.tsx
import { createIcon } from "@saas-ui/core";
import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
var CalendarIcon = createIcon({
displayName: "CalendarIcon",
path: /* @__PURE__ */ jsxs6("g", { children: [
/* @__PURE__ */ jsx11("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }),
/* @__PURE__ */ jsx11("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
/* @__PURE__ */ jsx11("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
/* @__PURE__ */ jsx11("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
] })
});
// src/date-input.tsx
import { Fragment, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
var DateInput = forwardRef5((props, ref) => {
const {
children,
calendarIcon,
size,
variant,
inputProps,
dialogProps,
portal,
...rest
} = props;
const zIndex = typeof portal === "boolean" ? void 0 : portal;
const dialog = /* @__PURE__ */ jsx12(DatePickerDialog, { zIndex, ...dialogProps, children: /* @__PURE__ */ jsxs7(Fragment, { children: [
/* @__PURE__ */ jsx12(DatePickerCalendar, {}),
children
] }) });
return /* @__PURE__ */ jsxs7(DatePicker, { placement: "bottom-end", granularity: "day", ...rest, children: [
/* @__PURE__ */ jsx12(
DatePickerInput,
{
calendarIcon,
size,
variant,
ref,
...inputProps
}
),
portal ? /* @__PURE__ */ jsx12(Portal, { children: dialog }) : dialog
] });
});
DateInput.displayName = "DateInput";
var DateTimeInput = forwardRef5((props, ref) => {
const { children, ...rest } = props;
return /* @__PURE__ */ jsx12(DateInput, { ref, granularity: "minute", ...rest, children: /* @__PURE__ */ jsxs7(Fragment, { children: [
/* @__PURE__ */ jsx12(DatePickerTimeField, {}),
children
] }) });
});
DateTimeInput.displayName = "DateTimeInput";
var DatePickerInput = forwardRef5(
(props, ref) => {
const { calendarIcon, size, variant, ...rest } = props;
const {
locale,
state,
groupProps,
fieldProps,
buttonProps,
datePickerRef
} = useDatePickerInput();
const themeProps = { size, variant };
return /* @__PURE__ */ jsx12(DatePickerAnchor, { children: /* @__PURE__ */ jsxs7(
InputGroup,
{
ref: datePickerRef,
...rest,
...groupProps,
...themeProps,
children: [
/* @__PURE__ */ jsx12(SegmentedInput, { ...themeProps, children: /* @__PURE__ */ jsx12(DateField, { ref, locale, ...fieldProps }) }),
/* @__PURE__ */ jsx12(InputRightElement, { py: "1", children: /* @__PURE__ */ jsx12(
FieldButton,
{
variant: "ghost",
flex: "1",
height: "100%",
...buttonProps,
isActive: state.isOpen,
children: calendarIcon || /* @__PURE__ */ jsx12(CalendarIcon, {})
}
) })
]
}
) });
}
);
DatePickerInput.displayName = "DatePickerInput";
// src/date-range-input.tsx
import {
chakra as chakra7,
forwardRef as forwardRef6,
InputGroup as InputGroup2,
InputRightElement as InputRightElement2,
Portal as Portal2
} from "@chakra-ui/react";
import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
var DateRangeInput = forwardRef6(
(props, ref) => {
const {
children,
size,
variant,
calendarIcon,
inputProps,
dialogProps,
portal,
...rest
} = props;
const zIndex = typeof portal === "boolean" ? void 0 : portal;
const dialog = /* @__PURE__ */ jsx13(DatePickerDialog, { zIndex, ...dialogProps, children: /* @__PURE__ */ jsxs8(Fragment2, { children: [
/* @__PURE__ */ jsx13(DateRangePickerCalendar, {}),
children
] }) });
return /* @__PURE__ */ jsxs8(DateRangePicker, { placement: "bottom-start", ...rest, children: [
/* @__PURE__ */ jsx13(
DateRangePickerInput,
{
ref,
calendarIcon,
size,
variant,
...inputProps
}
),
portal ? /* @__PURE__ */ jsx13(Portal2, { children: dialog }) : dialog
] });
}
);
var DateRangePickerInput = forwardRef6(
(props, ref) => {
const { calendarIcon, size, variant, ...rest } = props;
const {
state,
locale,
groupProps,
startFieldProps,
endFieldProps,
buttonProps,
datePickerRef
} = useDateRangePickerInput();
const themeProps = { size, variant };
return /* @__PURE__ */ jsx13(DatePickerAnchor, { children: /* @__PURE__ */ jsxs8(
InputGroup2,
{
...rest,
...groupProps,
...themeProps,
ref: datePickerRef,
width: "auto",
display: "inline-flex",
children: [
/* @__PURE__ */ jsx13(DatePickerAnchor, { children: /* @__PURE__ */ jsxs8(SegmentedInput, { ...themeProps, children: [
/* @__PURE__ */ jsx13(DateField, { locale, ...startFieldProps, ref }),
/* @__PURE__ */ jsx13(chakra7.span, { "aria-hidden": "true", paddingX: "1", children: "\u2013" }),
/* @__PURE__ */ jsx13(DateField, { locale, ...endFieldProps })
] }) }),
/* @__PURE__ */ jsx13(InputRightElement2, { py: "1", children: /* @__PURE__ */ jsx13(
FieldButton,
{
variant: "ghost",
flex: "1",
height: "100%",
...buttonProps,
isActive: state.isOpen,
children: calendarIcon || /* @__PURE__ */ jsx13(CalendarIcon, {})
}
) })
]
}
) });
}
);
// src/date-picker-modal.tsx
import { VStack } from "@chakra-ui/react";
import { Modal } from "@saas-ui/modals";
import { Button as Button2, ButtonGroup } from "@chakra-ui/react";
// src/use-date-picker-modal.ts
import {
useControllableState as useControllableState2,
useDisclosure
} from "@chakra-ui/react";
var useDatePickerModal = (props) => {
const {
defaultIsOpen,
isOpen: isOpenProp,
onOpen: onOpenProp,
onClose: onCloseProp,
onSubmit: onSubmitProp,
defaultValue = null,
value: valueProp,
onChange
} = props;
const [value, setValue] = useControllableState2({
defaultValue,
value: valueProp,
onChange
});
const { onClose, onOpen, isOpen } = useDisclosure({
defaultIsOpen,
isOpen: isOpenProp,
onOpen: onOpenProp,
onClose: onCloseProp
});
const onSubmit = () => {
onSubmitProp == null ? void 0 : onSubmitProp(value);
onClose();
};
const modalProps = {
isOpen,
onClose,
onOpen
};
const datePickerProps = {
value,
onChange(value2) {
setValue(value2);
}
};
return {
onClose,
onSubmit,
modalProps,
datePickerProps
};
};
// src/date-picker-modal.tsx
import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
var DatePickerModal = (props) => {
const { children, ...rest } = props;
const { modalProps, datePickerProps, onClose, onSubmit } = useDatePickerModal(rest);
const footer = /* @__PURE__ */ jsxs9(ButtonGroup, { children: [
/* @__PURE__ */ jsx14(Button2, { variant: "ghost", onClick: onClose, children: "Cancel" }),
/* @__PURE__ */ jsx14(Button2, { colorScheme: "primary", onClick: onSubmit, children: "Submit" })
] });
return /* @__PURE__ */ jsx14(
Modal,
{
title: "Select a date",
size: "xs",
footer,
...rest,
...modalProps,
children: /* @__PURE__ */ jsx14(VStack, { children: /* @__PURE__ */ jsxs9(DatePickerStatic, { ...datePickerProps, children: [
/* @__PURE__ */ jsx14(DatePickerCalendar, {}),
children
] }) })
}
);
};
// src/index.ts
import {
parseAbsolute,
parseAbsoluteToLocal,
parseDate,
parseDateTime,
parseTime,
parseZonedDateTime,
isSameDay as isSameDay2,
isSameMonth as isSameMonth2,
isSameYear,
isEqualDay,
isEqualMonth,
isEqualYear,
isToday,
getDayOfWeek as getDayOfWeek2,
now as now2,
today,
getHoursInDay,
getLocalTimeZone as getLocalTimeZone3,
startOfMonth,
startOfWeek,
startOfYear,
endOfMonth as endOfMonth2,
endOfWeek,
endOfYear,
getMinimumMonthInYear,
getMinimumDayInMonth,
getWeeksInMonth as getWeeksInMonth2,
minDate,
maxDate,
isWeekend,
isWeekday,
createCalendar as createCalendar2,
CalendarDate as CalendarDate3,
CalendarDateTime as CalendarDateTime2,
Time,
ZonedDateTime,
GregorianCalendar as GregorianCalendar2,
JapaneseCalendar,
BuddhistCalendar,
TaiwanCalendar,
PersianCalendar,
IndianCalendar,
IslamicCivilCalendar,
IslamicTabularCalendar,
IslamicUmalquraCalendar,
HebrewCalendar,
EthiopicCalendar,
EthiopicAmeteAlemCalendar,
CopticCalendar,
DateFormatter as DateFormatter2,
toCalendarDate,
toCalendarDateTime,
toTime,
toCalendar,
toZoned,
toTimeZone,
toLocalTimeZone
} from "@internationalized/date";
export {
BuddhistCalendar,
CalendarDate3 as CalendarDate,
CalendarDateTime2 as CalendarDateTime,
CopticCalendar,
DateFormatter2 as DateFormatter,
DateInput,
DatePicker,
DatePickerAnchor,
DatePickerCalendar,
DatePickerContainer,
DatePickerDialog,
DatePickerEndTimeField,
DatePickerInput,
DatePickerModal,
DatePickerStartTimeField,
DatePickerStatic,
DatePickerTimeField,
DatePickerTrigger,
DateRangeInput,
DateRangePicker,
DateRangePickerCalendar,
DateRangePickerContainer,
DateRangePickerDialog,
DateRangePickerTimeField,
DateTimeInput,
EthiopicAmeteAlemCalendar,
EthiopicCalendar,
GregorianCalendar2 as GregorianCalendar,
HebrewCalendar,
IndianCalendar,
InputSegment,
IslamicCivilCalendar,
IslamicTabularCalendar,
IslamicUmalquraCalendar,
JapaneseCalendar,
PersianCalendar,
SegmentedInput,
TaiwanCalendar,
Time,
ZonedDateTime,
createCalendar2 as createCalendar,
endOfMonth2 as endOfMonth,
endOfWeek,
endOfYear,
getDayOfWeek2 as getDayOfWeek,
getHoursInDay,
getLocalTimeZone3 as getLocalTimeZone,
getMinimumDayInMonth,
getMinimumMonthInYear,
getWeeksInMonth2 as getWeeksInMonth,
isEqualDay,
isEqualMonth,
isEqualYear,
isSameDay2 as isSameDay,
isSameMonth2 as isSameMonth,
isSameYear,
isToday,
isWeekday,
isWeekend,
maxDate,
minDate,
now2 as now,
parseAbsolute,
parseAbsoluteToLocal,
parseDate,
parseDateTime,
parseTime,
parseZonedDateTime,
startOfMonth,
startOfWeek,
startOfYear,
toCalendar,
toCalendarDate,
toCalendarDateTime,
toLocalTimeZone,
toTime,
toTimeZone,
toZoned,
today,
useDatePickerInput,
useDateRangePickerInput
};
//# sourceMappingURL=index.mjs.map