diff --git a/apps/docs/components/ExampleDateTimeRangePicker.tsx b/apps/docs/components/ExampleDateTimeRangePicker.tsx new file mode 100644 index 00000000..3daffc92 --- /dev/null +++ b/apps/docs/components/ExampleDateTimeRangePicker.tsx @@ -0,0 +1,16 @@ +import { DateTimeRangePicker } from '@enterwell/react-ui'; +import { useState } from 'react'; + +export function ExampleDateTimeRangePicker() { + const [start, setStart] = useState(new Date(new Date().getTime() - 1000 * 60 * 60 * 24)); + const [end, setEnd] = useState(new Date()); + + return ( + // @highlight-start + { setStart(start); setEnd(end); }} /> + // @highlight-end + ) +} \ No newline at end of file diff --git a/apps/docs/components/ExampleTimeInput.tsx b/apps/docs/components/ExampleTimeInput.tsx new file mode 100644 index 00000000..3f2d88eb --- /dev/null +++ b/apps/docs/components/ExampleTimeInput.tsx @@ -0,0 +1,14 @@ +import { TimeInput } from '@enterwell/react-ui'; +import { useState } from 'react'; + +export function ExampleTimeInput() { + const [value, setValue] = useState('12:00'); + + return ( + // @highlight-start + + // @highlight-end + ) +} \ No newline at end of file diff --git a/apps/docs/components/theme.ts b/apps/docs/components/theme.ts index c9338213..cd4f821a 100644 --- a/apps/docs/components/theme.ts +++ b/apps/docs/components/theme.ts @@ -4,7 +4,7 @@ export const theme = createTheme({ palette: { mode: 'dark', primary: { - main: '#ffffff', + main: '#eeeeee', }, secondary: { main: '#b5b5b5', diff --git a/apps/docs/pages/react-ui/components/date-time-range-picker.mdx b/apps/docs/pages/react-ui/components/date-time-range-picker.mdx new file mode 100644 index 00000000..13cef101 --- /dev/null +++ b/apps/docs/pages/react-ui/components/date-time-range-picker.mdx @@ -0,0 +1,33 @@ +--- +title: DateTimeRangePicker +--- + +import { DateTimeRangePicker } from '@enterwell/react-ui'; +import { ComponentWithSource } from '../../../components/docs/ComponentWithSource.tsx'; +import { ExampleDateTimeRangePicker } from '../../../components/ExampleDateTimeRangePicker.tsx'; +import { ComponentDescription, ComponentParameters, ComponentSource } from '../../../components/docs/ComponentDocs'; + +# DateTimeRangePicker + +## Description + + + +### Parameters + + + +## Example + + + +## Inspect + +
+ Source code + +
\ No newline at end of file diff --git a/apps/docs/pages/react-ui/components/time-input.mdx b/apps/docs/pages/react-ui/components/time-input.mdx new file mode 100644 index 00000000..5f4d2237 --- /dev/null +++ b/apps/docs/pages/react-ui/components/time-input.mdx @@ -0,0 +1,33 @@ +--- +title: TimeInput +--- + +import { TimeInput } from '@enterwell/react-ui'; +import { ComponentWithSource } from '../../../components/docs/ComponentWithSource.tsx'; +import { ExampleTimeInput } from '../../../components/ExampleTimeInput.tsx'; +import { ComponentDescription, ComponentParameters, ComponentSource } from '../../../components/docs/ComponentDocs'; + +# TimeInput + +## Description + + + +### Parameters + + + +## Example + + + +## Inspect + +
+ Source code + +
\ No newline at end of file diff --git a/packages/react-ui/DateTimeRangePicker/DateTimeRangePicker.tsx b/packages/react-ui/DateTimeRangePicker/DateTimeRangePicker.tsx new file mode 100644 index 00000000..5d0fa164 --- /dev/null +++ b/packages/react-ui/DateTimeRangePicker/DateTimeRangePicker.tsx @@ -0,0 +1,288 @@ +import { + Box, Button, Grid, Popover, TextField, useTheme, useMediaQuery +} from '@mui/material'; +import { ComponentProps, MouseEvent, useEffect, useMemo, useState } from 'react'; +import { StaticDateRangePicker, LocalizationProvider } from '@mui/x-date-pickers-pro'; +import { AdapterDateFns } from '@mui/x-date-pickers-pro/AdapterDateFns'; +import hrLocale from 'date-fns/locale/hr'; +import { parse, format, isSameDay, startOfDay, endOfDay, startOfYesterday, endOfYesterday, sub, startOfMonth, endOfMonth, intervalToDuration } from 'date-fns'; +import { TimeInput } from '../TimeInput'; +import { DateTimeRangePickerInput } from './DateTimeRangePickerInput'; +import { Stack } from '@mui/system'; + +// TODO: Test cases +// - Test if start date format shows only date when time is 00:00 +// - Test if end date format shows only date when time is 23:59 +// - Test if start date and start time is combined correctly (without time-zone offsets) +// - Test if end date and end time is combined correctly (without time-zone offsets) + +function durationGetTime(duration: Duration) { + return (typeof duration.years !== 'undefined' ? duration.years * 365 * 24 * 60 * 60 * 1000 : 0) + + (typeof duration.months !== 'undefined' ? duration.months * 30 * 24 * 60 * 60 * 1000 : 0) + + (typeof duration.weeks !== 'undefined' ? duration.weeks * 7 * 24 * 60 * 60 * 1000 : 0) + + (typeof duration.days !== 'undefined' ? duration.days * 24 * 60 * 60 * 1000 : 0) + + (typeof duration.hours !== 'undefined' ? duration.hours * 60 * 60 * 1000 : 0) + + (typeof duration.minutes !== 'undefined' ? duration.minutes * 60 * 1000 : 0) + + (typeof duration.seconds !== 'undefined' ? duration.seconds * 1000 : 0); +} + +/** + * The date time range picker preselect option. + * @public + */ +export type DateTimeRangePickerPreselectOption = { + name: string, + startDate: Date, + endDate: Date +}; + +/** + * The date time range picker props. + * @public + */ +export type DateTimeRangePickerProps = Omit, "onClick" | "value" | "title" | "onChange"> & { + start: Date; + end: Date; + hideTime?: boolean; + useSeconds?: boolean; + dense?: boolean; + preselectOptions?: DateTimeRangePickerPreselectOption[]; + onChange: (startDate: Date, endDate: Date) => void; +}; + +/** +* The date time range picker. +* +* @param props - The props; +* @returns Returns date time range picker component. +* @public +*/ +export function DateTimeRangePicker({ + start, + end, + hideTime, + useSeconds, + preselectOptions, + onChange, + ...rest +}: DateTimeRangePickerProps) { + const [anchorEl, setAnchorEl] = useState(null); + const [startTime, setStartTime] = useState(format(start, 'HH:mm')); + const [endTime, setEndTime] = useState(format(end, 'HH:mm')); + + // Use js dates because we use date-fns adapter + const defaultStartDate = startOfDay(start); + const defaultEndDate = startOfDay(end); + + const [dateValue, setDateValue] = useState<[Date | null, Date | null]>([defaultStartDate, defaultEndDate]); + const theme = useTheme(); + const isDesktop = useMediaQuery(theme.breakpoints.up('sm')); + + // Reset cached value when props change (only when not in popover) + useEffect(() => { + if (!anchorEl) { + setDateValue([defaultStartDate, defaultEndDate]); + } + }, [start, end]); + + /** + * Handles the picker input click. + * This will open picker popover. + * + * @param event - The click event + */ + const handleOpen = (event: MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + /** + * Handles the picker close. + * This will close the picker and reset selection. + */ + const handleClose = () => { + setAnchorEl(null); + setDateValue([defaultStartDate, defaultEndDate]); + setStartTime(format(start, 'HH:mm')); + setEndTime(format(end, 'HH:mm')); + }; + + /** + * Combines the date and time into Date objects. + * + * @returns First element is start date and time, seconds is end date and time. + */ + const combineDateAndTime = () => { + if (dateValue[0] == null || dateValue[1] == null) + return []; + + let startDurationTime = durationGetTime(intervalToDuration({ start: startOfDay(new Date()), end: parse(startTime, "HH:mm", new Date()) })); + const endDurationTime = durationGetTime(intervalToDuration({ start: startOfDay(new Date()), end: parse(endTime, "HH:mm", new Date()) })); + + // Check if start is after end - set equal + if (dateValue[0] != null + && dateValue[1] != null + && isSameDay(dateValue[0], dateValue[1]) + && startDurationTime > endDurationTime) { + startDurationTime = endDurationTime; + } + + const startDateTime = dateValue[0] ? startOfDay(dateValue[0]) : undefined; + if (startDateTime != null) { + startDateTime.setMilliseconds(startDateTime.getMilliseconds() + startDurationTime); + } + const endDateTime = dateValue[1] ? startOfDay(dateValue[1]) : undefined; + if (endDateTime != null) { + endDateTime.setMilliseconds(endDateTime.getMilliseconds() + endDurationTime); + } + return [startDateTime, endDateTime]; + }; + + /** + * Handles the picker accept option. + */ + const handleAccept = () => { + const combined = combineDateAndTime(); + if (combined[0] != null && combined[1] != null) { + onChange(combined[0], combined[1]); + setAnchorEl(null); + } + }; + + /** + * Handle the preselect option click. + * This will set start and end date to preselected values. + * + * @param startDate The start date and time. + * @param endDate The end date and time. + */ + const handlePreselect = (startDate: Date, endDate: Date) => { + setDateValue([startDate, endDate]); + }; + + const open = Boolean(anchorEl); + const id = open ? 'simple-popover' : undefined; + + const preselectedOptionsOrDefault: { name: string, startDate: Date, endDate: Date }[] = useMemo(() => { + if (preselectOptions) + return preselectOptions; + + return [ + { name: 'Danas', startDate: startOfDay(new Date()), endDate: endOfDay(new Date()) }, + { name: 'Jučer', startDate: startOfYesterday(), endDate: endOfYesterday() }, + { name: 'Proteklih 7 dana', startDate: sub(startOfDay(new Date()), { days: 7 }), endDate: endOfDay(new Date()) }, + { name: 'Proteklih 30 dana', startDate: sub(startOfDay(new Date()), { days: 30 }), endDate: endOfDay(new Date()) }, + { name: 'Ovaj mjesec', startDate: startOfMonth(new Date()), endDate: endOfDay(new Date()) }, + { name: 'Prošli mjesec', startDate: sub(startOfMonth(new Date()), { months: 1 }), endDate: endOfMonth(sub(startOfMonth(new Date()), { months: 1 })) } + ]; + }, [preselectOptions]); + + return ( + <> + + + + + + + + + + {preselectedOptionsOrDefault.map((opt) => ( + + ))} + + + + + + setDateValue([e.target.value as unknown as Date, dateValue[1]])} + fullWidth + size="small" + label="Od" + InputLabelProps={{ + shrink: true, + }} + /> + setDateValue([dateValue[0], e.target.value as unknown as Date])} + fullWidth + size="small" + label="Do" + InputLabelProps={{ + shrink: true, + }} + /> + + {!hideTime && ( + + + + + )} + + ( + + + + + )} + /> + + + + + + + ); +}; diff --git a/packages/react-ui/DateTimeRangePicker/DateTimeRangePickerInput.tsx b/packages/react-ui/DateTimeRangePicker/DateTimeRangePickerInput.tsx new file mode 100644 index 00000000..d139abf0 --- /dev/null +++ b/packages/react-ui/DateTimeRangePicker/DateTimeRangePickerInput.tsx @@ -0,0 +1,29 @@ +import { TextField } from '@mui/material'; +import { format, isSameMinute, startOfDay, endOfDay, isSameSecond } from 'date-fns'; +import { type ComponentProps, type MouseEventHandler } from 'react'; + +export type DateTimeRangePickerInputProps = Omit, "onClick" | "value" | "title" | "onChange"> & { + start: Date; + end: Date; + hideTime?: boolean; + useSeconds?: boolean; + onClick: MouseEventHandler; +} + +export function DateTimeRangePickerInput({ + start, end, hideTime, useSeconds, onClick, ...rest +}: DateTimeRangePickerInputProps) { + const compareFn = useSeconds ? isSameSecond : isSameMinute; + + const startValueStringFormat = hideTime || compareFn(startOfDay(start), start) + ? 'dd.MM.yyyy.' + : 'dd.MM.yyyy. HH:mm'; + const endValueStringFormat = hideTime || compareFn(endOfDay(end), end) + ? 'dd.MM.yyyy.' + : 'dd.MM.yyyy. HH:mm'; + const valueString = `${format(start, startValueStringFormat)} do ${format(end, endValueStringFormat)}`; + + return ( + + ); +} diff --git a/packages/react-ui/DateTimeRangePicker/index.tsx b/packages/react-ui/DateTimeRangePicker/index.tsx new file mode 100644 index 00000000..0b7e537e --- /dev/null +++ b/packages/react-ui/DateTimeRangePicker/index.tsx @@ -0,0 +1 @@ +export * from "./DateTimeRangePicker"; diff --git a/packages/react-ui/PageDrawer/PageDrawer.tsx b/packages/react-ui/PageDrawer/PageDrawer.tsx index e6544db6..f2388797 100644 --- a/packages/react-ui/PageDrawer/PageDrawer.tsx +++ b/packages/react-ui/PageDrawer/PageDrawer.tsx @@ -9,6 +9,7 @@ import { useDebounce, useResizeObserver } from '@enterwell/react-hooks'; * @public */ export type PageDrawerProps = HTMLAttributes & { + color?: string; expanded?: boolean; onChange?: () => void; }; @@ -20,7 +21,7 @@ export type PageDrawerProps = HTMLAttributes & { * @returns The PageDrawer component. * @public */ -export function PageDrawer({ expanded, onChange, children, ...rest }: PageDrawerProps): JSX.Element { +export function PageDrawer({ expanded, onChange, children, color, ...rest }: PageDrawerProps): JSX.Element { const [drawerSize, setDrawerSize] = useState(0); const drawerSizeDebounced = useDebounce(drawerSize, 50); const resizeObserverRef = useResizeObserver((_, entry) => { @@ -34,9 +35,7 @@ export function PageDrawer({ expanded, onChange, children, ...rest }: PageDrawer ref={resizeObserverRef} sx={{ position: 'absolute', - bottom: 0, - left: 0, - right: 0, + inset: 'auto 0 0 0', bgcolor: 'transparent', backgroundImage: 'none', border: 'none', @@ -55,8 +54,8 @@ export function PageDrawer({ expanded, onChange, children, ...rest }: PageDrawer minHeight: 32, height: 32, '.MuiAccordionSummary-expandIconWrapper': { - bgcolor: 'rgba(234, 135, 20, 0.2)', - color: '#EA8714', + bgcolor: color ?? 'primary.dark', + color: 'primary.main', borderRadius: 1 }, '&.Mui-expanded': { @@ -77,8 +76,9 @@ export function PageDrawer({ expanded, onChange, children, ...rest }: PageDrawer > 0 ? ':' + s.toString().padStart(2, '0') : ''}`; +} + +/** + * The time input props. + * @public + */ +export type TimeInputProps = ComponentProps & { + useSeconds?: boolean; + onTimeChange?: (time: string) => void; +} + +/** +* The time input component. +* +* @param props - The props; +* @returns The time input component. +* @public +*/ +export function TimeInput({ + value, + defaultValue, + useSeconds, + onChange, + onKeyDown, + onBlur, + onTimeChange, + ...rest +}: TimeInputProps) { + /** + * Handles the input blur. + * This will call onTimeChange callback. + */ + const handleBlur = (event: FocusEvent) => { + if (onBlur) { + onBlur(event); + } + if (onTimeChange) { + onTimeChange(processTime(value ?? defaultValue, useSeconds ?? false)); + } + }; + + /** + * Handles the input change. + * This will call onTimeChange callback. + */ + function handleChange(event: ChangeEvent) { + if (onChange) { + onChange(event); + } + if (onTimeChange) { + onTimeChange(event.target.value); + } + } + + /** + * Handles the input key down. + * This will call onTimeChange callback if the key is Enter. + */ + function handleKeyDown(event: React.KeyboardEvent) { + if (onKeyDown) { + onKeyDown(event); + } + if (event.key === 'Enter' && onTimeChange) { + onTimeChange(processTime(value ?? defaultValue, useSeconds ?? false)); + } + } + + return ( + + ); +} diff --git a/packages/react-ui/TimeInput/index.tsx b/packages/react-ui/TimeInput/index.tsx new file mode 100644 index 00000000..2d91c139 --- /dev/null +++ b/packages/react-ui/TimeInput/index.tsx @@ -0,0 +1 @@ +export * from "./TimeInput"; diff --git a/packages/react-ui/changes/Added DateTimeRangePicker component b/packages/react-ui/changes/Added DateTimeRangePicker component new file mode 100644 index 00000000..e69de29b diff --git a/packages/react-ui/changes/Added TimeInput component b/packages/react-ui/changes/Added TimeInput component new file mode 100644 index 00000000..e69de29b diff --git a/packages/react-ui/index.tsx b/packages/react-ui/index.tsx index c7352024..a9e78685 100644 --- a/packages/react-ui/index.tsx +++ b/packages/react-ui/index.tsx @@ -1,6 +1,8 @@ 'use client'; // component exports +export * from "./TimeInput"; +export * from "./DateTimeRangePicker"; export * from "./ConfirmDialog"; export * from "./DropdownButton"; export * from "./PageDrawer"; \ No newline at end of file diff --git a/packages/react-ui/package.json b/packages/react-ui/package.json index 673e9e6b..11e5c070 100644 --- a/packages/react-ui/package.json +++ b/packages/react-ui/package.json @@ -24,16 +24,18 @@ "lint": "eslint ." }, "devDependencies": { - "@enterwell/react-hooks": "workspace:*", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@enterwell/react-hooks": "workspace:*", "@microsoft/api-extractor": "^7.36.4", "@mui/icons-material": "^5.14.8", "@mui/material": "^5.14.8", "@mui/system": "^5.14.8", + "@mui/x-date-pickers-pro": "5.0.20", "@types/node": "^20.5.2", "@types/react": "^18.2.0", "@types/react-dom": "^18.2.0", + "date-fns": "^2.30.0", "eslint-config-custom": "workspace:*", "react": "^18.2.0", "rimraf": "^5.0.1", @@ -46,6 +48,7 @@ "@emotion/styled": "^11.11.0", "@mui/material": "^5.14.8", "@mui/system": "^5.14.8", + "@mui/x-date-pickers-pro": "5.0.20", "react": "^18.2.0", "react-dom": "^18.2.0" } diff --git a/packages/react-ui/temp/react-ui.api.md b/packages/react-ui/temp/react-ui.api.md index 48c3002d..18d3968f 100644 --- a/packages/react-ui/temp/react-ui.api.md +++ b/packages/react-ui/temp/react-ui.api.md @@ -11,21 +11,35 @@ import { DialogProps } from '@mui/material'; import { HTMLAttributes } from 'react'; import * as react_jsx_runtime from 'react/jsx-runtime'; import { ReactElement } from 'react'; +import { TextField } from '@mui/material'; // @public -export function ConfirmDialog({ isOpen, message, maxWidth, fullWidth, color, confirmButtonText, cancelButtonText, onConfirm, onCancel, ...rest }: ConfirmDialogProps): react_jsx_runtime.JSX.Element; +export function ConfirmDialog({ isOpen, header, message, maxWidth, fullWidth, color, confirmButtonText, cancelButtonText, onConfirm, onCancel, ...rest }: ConfirmDialogProps): react_jsx_runtime.JSX.Element; // @public export type ConfirmDialogProps = Omit & { isOpen: boolean; - message: string; - color: ComponentProps['color']; + header: string; + message?: string; + color?: ComponentProps['color']; confirmButtonText?: string; cancelButtonText?: string; onConfirm: () => void; onCancel: () => void; }; +// @public +export function DateTimeRangePicker({ start: propStartDate, end: propEndDate, hideTime, onChange, ...rest }: DateTimeRangePickerProps): react_jsx_runtime.JSX.Element; + +// @public +export type DateTimeRangePickerProps = Omit, "onClick" | "value" | "title" | "onChange"> & { + start: Date; + end: Date; + onChange: (startDate: Date, endDate: Date) => void; + hideTime?: boolean; + dense?: boolean; +}; + // @public export function DropdownButton({ options, onClick, icon, ...rest }: DropdownButtonProps): react_jsx_runtime.JSX.Element; @@ -51,6 +65,15 @@ export type PageDrawerProps = HTMLAttributes & { onChange?: () => void; }; +// @public +export function TimeInput({ value, defaultValue, useSeconds, onChange, onBlur, onTimeChange, ...rest }: TimeInputProps): react_jsx_runtime.JSX.Element; + +// @public +export type TimeInputProps = ComponentProps & { + useSeconds?: boolean; + onTimeChange?: (time: string) => void; +}; + // (No @packageDocumentation comment for this package) ``` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 60f9aef0..2aa5d8a1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -176,6 +176,9 @@ importers: '@mui/system': specifier: ^5.14.8 version: 5.14.8(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.21)(react@18.2.0) + '@mui/x-date-pickers-pro': + specifier: 5.0.20 + version: 5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.8)(@mui/system@5.14.8)(date-fns@2.30.0)(react-dom@18.2.0)(react@18.2.0) '@types/node': specifier: ^20.5.2 version: 20.5.2 @@ -185,6 +188,9 @@ importers: '@types/react-dom': specifier: ^18.2.0 version: 18.2.7 + date-fns: + specifier: ^2.30.0 + version: 2.30.0 eslint-config-custom: specifier: workspace:* version: link:../eslint-config-custom @@ -454,6 +460,55 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true + /@date-io/core@2.17.0: + resolution: {integrity: sha512-+EQE8xZhRM/hsY0CDTVyayMDDY5ihc4MqXCrPxooKw19yAzUIC6uUqsZeaOFNL9YKTNxYKrJP5DFgE8o5xRCOw==} + dev: true + + /@date-io/date-fns@2.17.0(date-fns@2.30.0): + resolution: {integrity: sha512-L0hWZ/mTpy3Gx/xXJ5tq5CzHo0L7ry6KEO9/w/JWiFWFLZgiNVo3ex92gOl3zmzjHqY/3Ev+5sehAr8UnGLEng==} + peerDependencies: + date-fns: ^2.0.0 + peerDependenciesMeta: + date-fns: + optional: true + dependencies: + '@date-io/core': 2.17.0 + date-fns: 2.30.0 + dev: true + + /@date-io/dayjs@2.17.0: + resolution: {integrity: sha512-Iq1wjY5XzBh0lheFA0it6Dsyv94e8mTiNR8vuTai+KopxDkreL3YjwTmZHxkgB7/vd0RMIACStzVgWvPATnDCA==} + peerDependencies: + dayjs: ^1.8.17 + peerDependenciesMeta: + dayjs: + optional: true + dependencies: + '@date-io/core': 2.17.0 + dev: true + + /@date-io/luxon@2.17.0: + resolution: {integrity: sha512-l712Vdm/uTddD2XWt9TlQloZUiTiRQtY5TCOG45MQ/8u0tu8M17BD6QYHar/3OrnkGybALAMPzCy1r5D7+0HBg==} + peerDependencies: + luxon: ^1.21.3 || ^2.x || ^3.x + peerDependenciesMeta: + luxon: + optional: true + dependencies: + '@date-io/core': 2.17.0 + dev: true + + /@date-io/moment@2.17.0: + resolution: {integrity: sha512-e4nb4CDZU4k0WRVhz1Wvl7d+hFsedObSauDHKtZwU9kt7gdYEAzKgnrSCTHsEaXrDumdrkCYTeZ0Tmyk7uV4tw==} + peerDependencies: + moment: ^2.24.0 + peerDependenciesMeta: + moment: + optional: true + dependencies: + '@date-io/core': 2.17.0 + dev: true + /@emotion/babel-plugin@11.11.0: resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} dependencies: @@ -1171,6 +1226,110 @@ packages: react: 18.2.0 react-is: 18.2.0 + /@mui/x-date-pickers-pro@5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.8)(@mui/system@5.14.8)(date-fns@2.30.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-syNnokcG4lvj9SIcnfji6eVvpSpuHs+7jqLsJYDBTogxK53ctSXQVMb5GQ16ioTzEQSqZojhngHSj+/s11Ao1Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@mui/material': ^5.4.1 + '@mui/system': ^5.4.1 + date-fns: ^2.25.0 + dayjs: ^1.10.7 + luxon: ^1.28.0 || ^2.0.0 || ^3.0.0 + moment: ^2.29.1 + react: ^17.0.2 || ^18.0.0 + react-dom: ^17.0.2 || ^18.0.0 + peerDependenciesMeta: + date-fns: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + dependencies: + '@babel/runtime': 7.22.15 + '@date-io/date-fns': 2.17.0(date-fns@2.30.0) + '@date-io/dayjs': 2.17.0 + '@date-io/luxon': 2.17.0 + '@date-io/moment': 2.17.0 + '@mui/material': 5.14.8(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.21)(react-dom@18.2.0)(react@18.2.0) + '@mui/system': 5.14.8(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.21)(react@18.2.0) + '@mui/utils': 5.14.8(react@18.2.0) + '@mui/x-date-pickers': 5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.8)(@mui/system@5.14.8)(date-fns@2.30.0)(react-dom@18.2.0)(react@18.2.0) + '@mui/x-license-pro': 5.17.12(react@18.2.0) + clsx: 1.2.1 + date-fns: 2.30.0 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) + rifm: 0.12.1(react@18.2.0) + transitivePeerDependencies: + - '@emotion/react' + - '@emotion/styled' + dev: true + + /@mui/x-date-pickers@5.0.20(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@mui/material@5.14.8)(@mui/system@5.14.8)(date-fns@2.30.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ERukSeHIoNLbI1C2XRhF9wRhqfsr+Q4B1SAw2ZlU7CWgcG8UBOxgqRKDEOVAIoSWL+DWT6GRuQjOKvj6UXZceA==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.9.0 + '@emotion/styled': ^11.8.1 + '@mui/material': ^5.4.1 + '@mui/system': ^5.4.1 + date-fns: ^2.25.0 + dayjs: ^1.10.7 + luxon: ^1.28.0 || ^2.0.0 || ^3.0.0 + moment: ^2.29.1 + react: ^17.0.2 || ^18.0.0 + react-dom: ^17.0.2 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + date-fns: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + dependencies: + '@babel/runtime': 7.22.15 + '@date-io/core': 2.17.0 + '@date-io/date-fns': 2.17.0(date-fns@2.30.0) + '@date-io/dayjs': 2.17.0 + '@date-io/luxon': 2.17.0 + '@date-io/moment': 2.17.0 + '@emotion/react': 11.11.1(@types/react@18.2.21)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.21)(react@18.2.0) + '@mui/material': 5.14.8(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.21)(react-dom@18.2.0)(react@18.2.0) + '@mui/system': 5.14.8(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.21)(react@18.2.0) + '@mui/utils': 5.14.8(react@18.2.0) + '@types/react-transition-group': 4.4.6 + clsx: 1.2.1 + date-fns: 2.30.0 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) + rifm: 0.12.1(react@18.2.0) + dev: true + + /@mui/x-license-pro@5.17.12(react@18.2.0): + resolution: {integrity: sha512-UzFaE+9A30kfguCuME0D5zqsItqbHZ3xZwmyrJr8MvZOEoqiJWF4NT4Pvlg2nqaPYt/h81j7sjVFa3KiwT0vbg==} + engines: {node: '>=12.0.0'} + peerDependencies: + react: ^17.0.2 || ^18.0.0 + dependencies: + '@babel/runtime': 7.22.15 + '@mui/utils': 5.14.8(react@18.2.0) + react: 18.2.0 + dev: true + /@napi-rs/simple-git-android-arm-eabi@0.1.9: resolution: {integrity: sha512-9D4JnfePMpgL4pg9aMUX7/TIWEUQ+Tgx8n3Pf8TNCMGjUbImJyYsDSLJzbcv9wH7srgn4GRjSizXFJHAPjzEug==} engines: {node: '>= 10'} @@ -2511,7 +2670,6 @@ packages: /clsx@1.2.1: resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} engines: {node: '>=6'} - dev: false /clsx@2.0.0: resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} @@ -2962,6 +3120,13 @@ packages: engines: {node: '>= 14'} dev: true + /date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} + engines: {node: '>=0.11'} + dependencies: + '@babel/runtime': 7.22.15 + dev: true + /dayjs@1.11.9: resolution: {integrity: sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==} dev: false @@ -7002,6 +7167,14 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + /rifm@0.12.1(react@18.2.0): + resolution: {integrity: sha512-OGA1Bitg/dSJtI/c4dh90svzaUPt228kzFsUkJbtA2c964IqEAwWXeL9ZJi86xWv3j5SMqRvGULl7bA6cK0Bvg==} + peerDependencies: + react: '>=16.8' + dependencies: + react: 18.2.0 + dev: true + /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true