Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,15 @@ All props are _optional_
| view | string. Initial view to load. options: "week", "month", "day". <br> _Default_: "week" (if it's not null)
| agenda | boolean. Activate agenda view
| alwaysShowAgendaDays | boolean. if true, day rows without events will be shown
| month | Object. Month view props. <br> _default_: <pre>{<br>weekDays: [0, 1, 2, 3, 4, 5], <br>weekStartOn: 6, <br>startHour: 9, <br>endHour: 17,<br>cellRenderer?:(props: CellProps) => JSX.Element,<br>navigation: true,<br>disableGoToDay: false<br>}</pre>
| week | Object. Week view props. <br> _default_: <pre>{ <br>weekDays: [0, 1, 2, 3, 4, 5], <br>weekStartOn: 6, <br>startHour: 9, <br>endHour: 17,<br>step: 60,<br>cellRenderer?:(props: CellProps) => JSX.Element,<br>navigation: true,<br>disableGoToDay: false<br>}</pre>
| day | Object. Day view props. <br> _default_: <pre>{<br>startHour: 9, <br>endHour: 17, <br>step: 60,<br>cellRenderer?:(props: CellProps) => JSX.Element,<br>hourRenderer?:(hour: string) => JSX.Element,<br>navigation: true<br>}</pre>
| month | Object. Month view props. <br> _default_: <pre>{<br>weekDays: [0, 1, 2, 3, 4, 5], <br>weekStartOn: 6, <br>startHour: 9, <br>endHour: 17,<br>cellRenderer?:(props: CellProps) => React.ReactNode,<br>navigation: true,<br>disableGoToDay: false<br>}</pre>
| week | Object. Week view props. <br> _default_: <pre>{ <br>weekDays: [0, 1, 2, 3, 4, 5], <br>weekStartOn: 6, <br>startHour: 9, <br>endHour: 17,<br>step: 60,<br>cellRenderer?:(props: CellProps) => React.ReactNode,<br>navigation: true,<br>disableGoToDay: false<br>}</pre>
| day | Object. Day view props. <br> _default_: <pre>{<br>startHour: 9, <br>endHour: 17, <br>step: 60,<br>cellRenderer?:(props: CellProps) => React.ReactNode,<br>hourRenderer?:(hour: string) => React.ReactNode,<br>navigation: true<br>}</pre>
| selectedDate | Date. Initial selected date. <br>_Default_: `new Date()`
| navigation | boolean. Show/Hide top bar date navigation. <br>_Default_: `true`
| navigationPickerProps | CalendarPickerProps for top bar date navigation. Ref [CalendarPicker API](https://mui.com/x/api/date-pickers/calendar-picker/#main-content)
| disableViewNavigator | boolean. Show/Hide top bar date View navigator. <br>_Default_: `false`
| events | Array of ProcessedEvent. <br>_Default_: [] <br> <pre>type ProcessedEvent = {<br>event*id: number or string;<br>title: string;<br>subtitle?: string;<br>start: Date;<br>end: Date;<br>disabled?: boolean;<br>recurring: RRule;<br>color?: string or "palette.path";<br>textColor?: string or "palette.path";<br>editable?: boolean;<br>deletable?: boolean;<br>draggable?: boolean;<br>allDay?: boolean;<br>agendaAvatar?: React.ReactElement \| string<br>sx?: Mui sx prop<br>} </pre>
| eventRenderer | Function(event:ProcessedEvent): JSX.Element.<br> A function that overrides the event item render function, see demo \_Custom Event Renderer* below
| eventRenderer | Function(event:ProcessedEvent): React.ReactNode.<br> A function that overrides the event item render function, see demo \_Custom Event Renderer* below
| editable | boolean. If `true`, the scheduler cell click will not open the editor, and the event item will not show the edit button, this is applied to all events, and can be overridden in each event property, see `ProcessedEvent` type.
| deletable | boolean. Whether the event item will show the delete button, this is applied to all events, and can be overridden in each event property, see `ProcessedEvent` type.
| draggable | boolean. Whether activate drag&drop for the events, this is applied to all events, and can be overridden in each event property, see `ProcessedEvent` type.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"@eslint/js": "^9.20.0",
"@mui/icons-material": ">=7.0.0",
"@mui/material": ">=7.0.0",
"@mui/x-date-pickers": ">=7.27.0",
"@mui/x-date-pickers": "7.27.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
Expand Down Expand Up @@ -105,7 +105,7 @@
"peerDependencies": {
"@mui/icons-material": ">=7.0.0",
"@mui/material": ">=7.0.0",
"@mui/x-date-pickers": ">=7.0.0",
"@mui/x-date-pickers": ">=7.0.0 & <8.0.0",
"date-fns": ">=4.0.0",
"react": ">=18.0.0",
"react-dom": ">=18.0.0",
Expand Down
5 changes: 2 additions & 3 deletions src/lib/components/common/Cell.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Button } from "@mui/material";
import { useCellAttributes } from "../../hooks/useCellAttributes";
import { CellRenderedProps } from "../../types";
import { JSX } from "react";

interface CellProps {
day: Date;
Expand All @@ -10,8 +9,8 @@ interface CellProps {
end: Date;
resourceKey: string;
resourceVal: string | number;
cellRenderer?(props: CellRenderedProps): JSX.Element;
children?: JSX.Element;
cellRenderer?(props: CellRenderedProps): React.ReactNode;
children?: React.ReactNode;
}

const Cell = ({
Expand Down
6 changes: 3 additions & 3 deletions src/lib/components/common/Tabs.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CSSProperties, JSX } from "react";
import { CSSProperties } from "react";
import { Tabs, Tab } from "@mui/material";
import { styled } from "@mui/material/styles";
import { Theme } from "@mui/system";
Expand Down Expand Up @@ -63,8 +63,8 @@ const StyledTaps = styled("div")(({ theme }: { theme: Theme }) => ({

export type ButtonTabProps = {
id: string | number;
label: string | JSX.Element;
component: JSX.Element;
label: string | React.ReactNode;
component: React.ReactNode;
};
interface ButtonTabsProps {
tabs: ButtonTabProps[];
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/events/MonthEvents.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Fragment, JSX, useMemo } from "react";
import { Fragment, useMemo } from "react";
import {
closestTo,
isBefore,
Expand Down Expand Up @@ -45,7 +45,7 @@ const MonthEvents = ({
const { renderedSlots } = usePosition();

const renderEvents = useMemo(() => {
const elements: JSX.Element[] = [];
const elements: React.ReactNode[] = [];

for (let i = 0; i < Math.min(events.length, LIMIT + 1); i++) {
const event = convertEventTimeZone(events[i], timeZone);
Expand Down
8 changes: 5 additions & 3 deletions src/lib/components/month/MonthTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
startOfDay,
startOfMonth,
} from "date-fns";
import { Fragment, JSX, useCallback } from "react";
import { Fragment, useCallback } from "react";
import {
getHourFormat,
getRecurrencesForDate,
Expand Down Expand Up @@ -60,7 +60,7 @@ const MonthTable = ({ daysList, resource, eachWeekStart }: Props) => {
if (resource) {
resourcedEvents = getResourcedEvents(events, resource, resourceFields, fields);
}
const rows: JSX.Element[] = [];
const rows: React.ReactNode[] = [];

for (const startDay of eachWeekStart) {
const cells = weekDays.map((d) => {
Expand Down Expand Up @@ -92,7 +92,9 @@ const MonthTable = ({ daysList, resource, eachWeekStart }: Props) => {
/>
<Fragment>
{typeof headRenderer === "function" ? (
<div style={{ position: "absolute", top: 0 }}>{headRenderer(today)}</div>
<div style={{ position: "absolute", top: 0 }}>
{headRenderer({ day: today, events: resourcedEvents, resource })}
</div>
) : (
<Avatar
style={{
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/nav/WeekDateBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { useState } from "react";
import DateProvider from "../hoc/DateProvider";
import { Button, Popover } from "@mui/material";
import { endOfWeek, format, startOfWeek, addDays } from "date-fns";
import { WeekProps } from "../../views/Week";
import { LocaleArrow } from "../common/LocaleArrow";
import { DateCalendar } from "@mui/x-date-pickers";
import useStore from "../../hooks/useStore";
import useArrowDisable from "../../hooks/useArrowDisable";
import { WeekProps } from "../../types";

interface WeekDateBtnProps {
selectedDate: Date;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/week/WeekTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const WeekTable = ({
style={{ height: headerHeight }}
>
{typeof headRenderer === "function" ? (
<div>{headRenderer(date)}</div>
<div>{headRenderer({ day: date, events: resourcedEvents, resource })}</div>
) : (
<TodayTypo
date={date}
Expand Down
53 changes: 40 additions & 13 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@ import { DragEvent } from "react";
import { SelectOption } from "./components/inputs/SelectInput";
import { View } from "./components/nav/Navigation";
import { Store } from "./store/types";
import { DayProps } from "./views/Day";
import { StateItem } from "./views/Editor";
import { MonthProps } from "./views/Month";
import { WeekProps } from "./views/Week";
import type { RRule } from "rrule";
import type { JSX } from "react";

export type DayHours =
| 0
Expand Down Expand Up @@ -39,6 +35,37 @@ export type DayHours =
| 23
| 24;

export type WeekDays = 0 | 1 | 2 | 3 | 4 | 5 | 6;

interface CommonWeekViewProps {
weekDays: WeekDays[];
weekStartOn: WeekDays;
disableGoToDay?: boolean;
}

interface CommonViewProps {
startHour: DayHours;
endHour: DayHours;
cellRenderer?(props: CellRenderedProps): React.ReactNode;
headRenderer?(props: {
day: Date;
events: ProcessedEvent[];
resource?: DefaultResource;
}): React.ReactNode;
navigation?: boolean;
step: number;
}

export interface MonthProps extends CommonWeekViewProps, CommonViewProps {}

export interface WeekProps extends CommonWeekViewProps, CommonViewProps {
hourRenderer?(hour: string): React.ReactNode;
}

export interface DayProps extends CommonViewProps {
hourRenderer?(hour: string): React.ReactNode;
}

export interface CellRenderedProps {
day: Date;
start: Date;
Expand Down Expand Up @@ -225,39 +252,39 @@ export interface SchedulerProps {
/**Events to display */
events: ProcessedEvent[];
/** Custom event render method */
eventRenderer?: (props: EventRendererProps) => JSX.Element | null;
eventRenderer?: (props: EventRendererProps) => React.ReactNode | null;
/**Async function to load remote data with current view data. */
getRemoteEvents?(params: RemoteQuery): Promise<ProcessedEvent[] | void>;
/**Custom additional fields with it's settings */
fields: FieldProps[];
/**Table loading state */
loading?: boolean;
/** Custom loading component */
loadingComponent?: JSX.Element;
loadingComponent?: React.ReactNode;
/**Async function triggered when add/edit event */
onConfirm?(event: ProcessedEvent, action: EventActions): Promise<ProcessedEvent>;
/**Async function triggered when delete event */
onDelete?(deletedId: string | number): Promise<string | number | void>;
/**Override editor modal */
customEditor?(scheduler: SchedulerHelpers): JSX.Element;
customEditor?(scheduler: SchedulerHelpers): React.ReactNode;
/** Custom viewer/popper component. If used, `viewerExtraComponent` & `viewerTitleComponent` will be ignored */
customViewer?(event: ProcessedEvent, close: () => void): JSX.Element;
customViewer?(event: ProcessedEvent, close: () => void): React.ReactNode;
/**Additional component in event viewer popper */
viewerExtraComponent?:
| JSX.Element
| ((fields: FieldProps[], event: ProcessedEvent) => JSX.Element);
| React.ReactNode
| ((fields: FieldProps[], event: ProcessedEvent) => React.ReactNode);
/**Override viewer title component */
viewerTitleComponent?(event: ProcessedEvent): JSX.Element;
viewerTitleComponent?(event: ProcessedEvent): React.ReactNode;
/**Override viewer subtitle component */
viewerSubtitleComponent?(event: ProcessedEvent): JSX.Element;
viewerSubtitleComponent?(event: ProcessedEvent): React.ReactNode;
/** if true, the viewer popover will be disabled globally */
disableViewer?: boolean;
/**Resources array to split event views with resources */
resources: DefaultResource[];
/**Map resources fields */
resourceFields: ResourceFields;
/**Override header component of resource */
resourceHeaderComponent?(resource: DefaultResource): JSX.Element;
resourceHeaderComponent?(resource: DefaultResource): React.ReactNode;
/** Triggered when resource tabs changes */
onResourceChange?(resource: DefaultResource): void;
/**Resource header view mode
Expand Down
18 changes: 4 additions & 14 deletions src/lib/views/Day.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useCallback, Fragment, JSX } from "react";
import { useEffect, useCallback, Fragment } from "react";
import { Typography } from "@mui/material";
import {
format,
Expand All @@ -14,7 +14,7 @@ import {
} from "date-fns";
import TodayTypo from "../components/common/TodayTypo";
import EventItem from "../components/events/EventItem";
import { CellRenderedProps, DayHours, DefaultResource, ProcessedEvent } from "../types";
import { DefaultResource, ProcessedEvent } from "../types";
import {
calcCellHeight,
calcMinuteHeight,
Expand All @@ -31,16 +31,6 @@ import { MULTI_DAY_EVENT_HEIGHT } from "../helpers/constants";
import useStore from "../hooks/useStore";
import { DayAgenda } from "./DayAgenda";

export interface DayProps {
startHour: DayHours;
endHour: DayHours;
step: number;
cellRenderer?(props: CellRenderedProps): JSX.Element;
headRenderer?(day: Date): JSX.Element;
hourRenderer?(hour: string): JSX.Element;
navigation?: boolean;
}

const Day = () => {
const {
day,
Expand Down Expand Up @@ -142,7 +132,7 @@ const Day = () => {
}

if (agenda) {
return <DayAgenda events={resourcedEvents} />;
return <DayAgenda resource={resource} events={resourcedEvents} />;
}

// Equalizing multi-day section height
Expand All @@ -163,7 +153,7 @@ const Day = () => {
style={{ height: headerHeight }}
>
{typeof headRenderer === "function" ? (
<div>{headRenderer(selectedDate)}</div>
<div>{headRenderer({ day: selectedDate, events: resourcedEvents, resource })}</div>
) : (
<TodayTypo date={selectedDate} locale={locale} />
)}
Expand Down
7 changes: 4 additions & 3 deletions src/lib/views/DayAgenda.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMemo } from "react";
import { format } from "date-fns";
import { AgendaDiv } from "../styles/styles";
import { ProcessedEvent } from "../types";
import { DefaultResource, ProcessedEvent } from "../types";
import useStore from "../hooks/useStore";
import { Typography } from "@mui/material";
import { filterTodayAgendaEvents } from "../helpers/generals";
Expand All @@ -10,8 +10,9 @@ import EmptyAgenda from "../components/events/EmptyAgenda";

type Props = {
events: ProcessedEvent[];
resource?: DefaultResource;
};
const DayAgenda = ({ events }: Props) => {
const DayAgenda = ({ events, resource }: Props) => {
const { day, locale, selectedDate, translations, alwaysShowAgendaDays } = useStore();
const { headRenderer } = day!;

Expand All @@ -28,7 +29,7 @@ const DayAgenda = ({ events }: Props) => {
<div className="rs__agenda_row rs__today_cell">
<div className="rs__cell rs__agenda__cell">
{typeof headRenderer === "function" ? (
<div>{headRenderer(selectedDate)}</div>
<div>{headRenderer({ day: selectedDate, events, resource })}</div>
) : (
<Typography variant="body2">{format(selectedDate, "dd E", { locale })}</Typography>
)}
Expand Down
18 changes: 3 additions & 15 deletions src/lib/views/Month.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
import { useEffect, useCallback, JSX } from "react";
import { useEffect, useCallback } from "react";
import { addDays, eachWeekOfInterval, endOfMonth, startOfMonth } from "date-fns";
import { CellRenderedProps, DayHours, DefaultResource } from "../types";
import { DefaultResource } from "../types";
import { getResourcedEvents, sortEventsByTheEarliest } from "../helpers/generals";
import { WithResources } from "../components/common/WithResources";
import useStore from "../hooks/useStore";
import { MonthAgenda } from "./MonthAgenda";
import MonthTable from "../components/month/MonthTable";

export type WeekDays = 0 | 1 | 2 | 3 | 4 | 5 | 6;
export interface MonthProps {
weekDays: WeekDays[];
weekStartOn: WeekDays;
startHour: DayHours;
endHour: DayHours;
cellRenderer?(props: CellRenderedProps): JSX.Element;
headRenderer?(day: Date): JSX.Element;
navigation?: boolean;
disableGoToDay?: boolean;
}

const Month = () => {
const {
month,
Expand Down Expand Up @@ -80,7 +68,7 @@ const Month = () => {
resourcedEvents = getResourcedEvents(events, resource, resourceFields, fields);
}

return <MonthAgenda events={resourcedEvents} />;
return <MonthAgenda resource={resource} events={resourcedEvents} />;
}

return <MonthTable daysList={daysList} eachWeekStart={eachWeekStart} resource={resource} />;
Expand Down
7 changes: 4 additions & 3 deletions src/lib/views/MonthAgenda.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useMemo } from "react";
import { format, isSameMonth, getDaysInMonth, isToday } from "date-fns";
import { AgendaDiv } from "../styles/styles";
import { ProcessedEvent } from "../types";
import { DefaultResource, ProcessedEvent } from "../types";
import useStore from "../hooks/useStore";
import { Typography } from "@mui/material";
import { filterTodayAgendaEvents, isTimeZonedToday } from "../helpers/generals";
Expand All @@ -10,8 +10,9 @@ import EmptyAgenda from "../components/events/EmptyAgenda";

type Props = {
events: ProcessedEvent[];
resource?: DefaultResource;
};
const MonthAgenda = ({ events }: Props) => {
const MonthAgenda = ({ events, resource }: Props) => {
const {
month,
handleGotoDay,
Expand Down Expand Up @@ -46,7 +47,7 @@ const MonthAgenda = ({ events }: Props) => {
<div key={i} className={`rs__agenda_row ${isToday(day) ? "rs__today_cell" : ""}`}>
<div className="rs__cell rs__agenda__cell">
{typeof headRenderer === "function" ? (
<div>{headRenderer(day)}</div>
<div>{headRenderer({ day, events, resource })}</div>
) : (
<Typography
sx={{ fontWeight: today ? "bold" : "inherit" }}
Expand Down
Loading