@isma91/react-scheduler 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/.github/workflows/publish.yml +29 -0
  2. package/.github/workflows/tests.yml +35 -0
  3. package/.gitignore +32 -0
  4. package/.husky/pre-commit +2 -0
  5. package/.prettierignore +1 -0
  6. package/.prettierrc.json +7 -0
  7. package/.yarnrc.yml +1 -0
  8. package/LICENSE +24 -0
  9. package/README.md +172 -0
  10. package/dist/LICENSE +24 -0
  11. package/dist/README.md +172 -0
  12. package/dist/SchedulerComponent.d.ts +3 -0
  13. package/dist/components/common/Cell.d.ts +13 -0
  14. package/dist/components/common/LocaleArrow.d.ts +8 -0
  15. package/dist/components/common/ResourceHeader.d.ts +6 -0
  16. package/dist/components/common/Tabs.d.ts +16 -0
  17. package/dist/components/common/TodayTypo.d.ts +8 -0
  18. package/dist/components/common/WithResources.d.ts +6 -0
  19. package/dist/components/events/Actions.d.ts +8 -0
  20. package/dist/components/events/AgendaEventsList.d.ts +7 -0
  21. package/dist/components/events/CurrentTimeBar.d.ts +11 -0
  22. package/dist/components/events/EmptyAgenda.d.ts +2 -0
  23. package/dist/components/events/EventItem.d.ts +10 -0
  24. package/dist/components/events/EventItemPopover.d.ts +9 -0
  25. package/dist/components/events/MonthEvents.d.ts +13 -0
  26. package/dist/components/events/TodayEvents.d.ts +16 -0
  27. package/dist/components/hoc/DateProvider.d.ts +5 -0
  28. package/dist/components/inputs/DatePicker.d.ts +14 -0
  29. package/dist/components/inputs/Input.d.ts +19 -0
  30. package/dist/components/inputs/SelectInput.d.ts +22 -0
  31. package/dist/components/month/MonthTable.d.ts +8 -0
  32. package/dist/components/nav/DayDateBtn.d.ts +6 -0
  33. package/dist/components/nav/MonthDateBtn.d.ts +6 -0
  34. package/dist/components/nav/Navigation.d.ts +3 -0
  35. package/dist/components/nav/WeekDateBtn.d.ts +8 -0
  36. package/dist/components/week/WeekTable.d.ts +11 -0
  37. package/dist/helpers/constants.d.ts +4 -0
  38. package/dist/helpers/generals.d.ts +78 -0
  39. package/dist/hooks/useArrowDisable.d.ts +5 -0
  40. package/dist/hooks/useCellAttributes.d.ts +18 -0
  41. package/dist/hooks/useDragAttributes.d.ts +10 -0
  42. package/dist/hooks/useEventPermissions.d.ts +7 -0
  43. package/dist/hooks/useStore.d.ts +2 -0
  44. package/dist/hooks/useSyncScroll.d.ts +8 -0
  45. package/dist/hooks/useWindowResize.d.ts +4 -0
  46. package/dist/index.d.ts +3 -0
  47. package/dist/index.js +2853 -0
  48. package/dist/package.json +65 -0
  49. package/dist/positionManger/context.d.ts +14 -0
  50. package/dist/positionManger/provider.d.ts +5 -0
  51. package/dist/positionManger/usePosition.d.ts +4 -0
  52. package/dist/store/context.d.ts +2 -0
  53. package/dist/store/default.d.ts +245 -0
  54. package/dist/store/provider.d.ts +7 -0
  55. package/dist/store/types.d.ts +27 -0
  56. package/dist/styles/styles.d.ts +30 -0
  57. package/dist/types.d.ts +372 -0
  58. package/dist/views/Day.d.ts +2 -0
  59. package/dist/views/DayAgenda.d.ts +7 -0
  60. package/dist/views/Editor.d.ts +11 -0
  61. package/dist/views/Month.d.ts +2 -0
  62. package/dist/views/MonthAgenda.d.ts +7 -0
  63. package/dist/views/Week.d.ts +2 -0
  64. package/dist/views/WeekAgenda.d.ts +8 -0
  65. package/eslint.config.js +79 -0
  66. package/index.html +41 -0
  67. package/jest.config.ts +194 -0
  68. package/package.json +137 -0
  69. package/public/favicon.ico +0 -0
  70. package/public/logo192.png +0 -0
  71. package/public/logo512.png +0 -0
  72. package/public/manifest.json +25 -0
  73. package/public/robots.txt +3 -0
  74. package/scripts/post-pack.js +34 -0
  75. package/src/App.tsx +25 -0
  76. package/src/Page1.tsx +67 -0
  77. package/src/events.tsx +227 -0
  78. package/src/index.tsx +21 -0
  79. package/src/lib/SchedulerComponent.tsx +78 -0
  80. package/src/lib/__tests__/index.test.tsx +24 -0
  81. package/src/lib/components/common/Cell.tsx +52 -0
  82. package/src/lib/components/common/LocaleArrow.tsx +38 -0
  83. package/src/lib/components/common/ResourceHeader.tsx +73 -0
  84. package/src/lib/components/common/Tabs.tsx +119 -0
  85. package/src/lib/components/common/TodayTypo.tsx +44 -0
  86. package/src/lib/components/common/WithResources.tsx +98 -0
  87. package/src/lib/components/events/Actions.tsx +65 -0
  88. package/src/lib/components/events/AgendaEventsList.tsx +115 -0
  89. package/src/lib/components/events/CurrentTimeBar.tsx +59 -0
  90. package/src/lib/components/events/EmptyAgenda.tsx +27 -0
  91. package/src/lib/components/events/EventItem.tsx +180 -0
  92. package/src/lib/components/events/EventItemPopover.tsx +179 -0
  93. package/src/lib/components/events/MonthEvents.tsx +141 -0
  94. package/src/lib/components/events/TodayEvents.tsx +99 -0
  95. package/src/lib/components/hoc/DateProvider.tsx +19 -0
  96. package/src/lib/components/inputs/DatePicker.tsx +95 -0
  97. package/src/lib/components/inputs/Input.tsx +113 -0
  98. package/src/lib/components/inputs/SelectInput.tsx +164 -0
  99. package/src/lib/components/month/MonthTable.tsx +207 -0
  100. package/src/lib/components/nav/DayDateBtn.tsx +77 -0
  101. package/src/lib/components/nav/MonthDateBtn.tsx +80 -0
  102. package/src/lib/components/nav/Navigation.tsx +201 -0
  103. package/src/lib/components/nav/WeekDateBtn.tsx +89 -0
  104. package/src/lib/components/week/WeekTable.tsx +229 -0
  105. package/src/lib/helpers/constants.ts +4 -0
  106. package/src/lib/helpers/generals.tsx +354 -0
  107. package/src/lib/hooks/useArrowDisable.ts +26 -0
  108. package/src/lib/hooks/useCellAttributes.ts +67 -0
  109. package/src/lib/hooks/useDragAttributes.ts +31 -0
  110. package/src/lib/hooks/useEventPermissions.ts +42 -0
  111. package/src/lib/hooks/useStore.ts +8 -0
  112. package/src/lib/hooks/useSyncScroll.ts +31 -0
  113. package/src/lib/hooks/useWindowResize.ts +37 -0
  114. package/src/lib/index.tsx +14 -0
  115. package/src/lib/positionManger/context.ts +14 -0
  116. package/src/lib/positionManger/provider.tsx +113 -0
  117. package/src/lib/positionManger/usePosition.ts +8 -0
  118. package/src/lib/store/context.ts +5 -0
  119. package/src/lib/store/default.ts +157 -0
  120. package/src/lib/store/provider.tsx +211 -0
  121. package/src/lib/store/types.ts +33 -0
  122. package/src/lib/styles/styles.ts +256 -0
  123. package/src/lib/types.ts +423 -0
  124. package/src/lib/views/Day.tsx +265 -0
  125. package/src/lib/views/DayAgenda.tsx +57 -0
  126. package/src/lib/views/Editor.tsx +258 -0
  127. package/src/lib/views/Month.tsx +82 -0
  128. package/src/lib/views/MonthAgenda.tsx +84 -0
  129. package/src/lib/views/Week.tsx +92 -0
  130. package/src/lib/views/WeekAgenda.tsx +81 -0
  131. package/src/vite-env.d.ts +3 -0
  132. package/tsconfig.build.json +5 -0
  133. package/tsconfig.json +27 -0
  134. package/vite.config.js +40 -0
@@ -0,0 +1,84 @@
1
+ import { useMemo } from "react";
2
+ import { format, isSameMonth, getDaysInMonth, isToday } from "date-fns";
3
+ import { AgendaDiv } from "../styles/styles";
4
+ import { DefaultResource, ProcessedEvent } from "../types";
5
+ import useStore from "../hooks/useStore";
6
+ import { Typography } from "@mui/material";
7
+ import { filterTodayAgendaEvents, isTimeZonedToday } from "../helpers/generals";
8
+ import AgendaEventsList from "../components/events/AgendaEventsList";
9
+ import EmptyAgenda from "../components/events/EmptyAgenda";
10
+
11
+ type Props = {
12
+ events: ProcessedEvent[];
13
+ resource?: DefaultResource;
14
+ };
15
+ const MonthAgenda = ({ events, resource }: Props) => {
16
+ const {
17
+ month,
18
+ handleGotoDay,
19
+ locale,
20
+ timeZone,
21
+ selectedDate,
22
+ translations,
23
+ alwaysShowAgendaDays,
24
+ stickyNavigationOffset,
25
+ stickyNavigationHeight,
26
+ } = useStore();
27
+ const { disableGoToDay, headRenderer } = month!;
28
+ const daysOfMonth = getDaysInMonth(selectedDate);
29
+ const daysList = Array.from({ length: daysOfMonth }, (_, i) => i + 1);
30
+
31
+ const monthEvents = useMemo(() => {
32
+ return events.filter((event) => isSameMonth(event.start, selectedDate));
33
+ }, [events, selectedDate]);
34
+
35
+ if (!alwaysShowAgendaDays && !monthEvents.length) {
36
+ return <EmptyAgenda />;
37
+ }
38
+
39
+ return (
40
+ <AgendaDiv stickyOffset={stickyNavigationOffset} stickyHeight={stickyNavigationHeight}>
41
+ {daysList.map((i) => {
42
+ const day = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), i);
43
+ const today = isTimeZonedToday({ dateLeft: day, timeZone });
44
+ const dayEvents = filterTodayAgendaEvents(events, day);
45
+
46
+ if (!alwaysShowAgendaDays && !dayEvents.length) return null;
47
+
48
+ return (
49
+ <div key={i} className={`rs__agenda_row ${isToday(day) ? "rs__today_cell" : ""}`}>
50
+ <div className="rs__cell rs__agenda__cell">
51
+ {typeof headRenderer === "function" ? (
52
+ <div>{headRenderer({ day, events, resource })}</div>
53
+ ) : (
54
+ <Typography
55
+ sx={{ fontWeight: today ? "bold" : "inherit" }}
56
+ color={today ? "primary" : "inherit"}
57
+ variant="body2"
58
+ className={!disableGoToDay ? "rs__hover__op" : ""}
59
+ onClick={(e) => {
60
+ e.stopPropagation();
61
+ if (!disableGoToDay) {
62
+ handleGotoDay(day);
63
+ }
64
+ }}
65
+ >
66
+ {format(day, "dd E", { locale })}
67
+ </Typography>
68
+ )}
69
+ </div>
70
+ <div className="rs__cell rs__agenda_items">
71
+ {dayEvents.length > 0 ? (
72
+ <AgendaEventsList day={day} events={dayEvents} />
73
+ ) : (
74
+ <Typography sx={{ padding: 1 }}>{translations.noDataToDisplay}</Typography>
75
+ )}
76
+ </div>
77
+ </div>
78
+ );
79
+ })}
80
+ </AgendaDiv>
81
+ );
82
+ };
83
+
84
+ export { MonthAgenda };
@@ -0,0 +1,92 @@
1
+ import { useEffect, useCallback } from "react";
2
+ import { startOfWeek, addDays, eachMinuteOfInterval, endOfDay, startOfDay, set } from "date-fns";
3
+ import { DefaultResource } from "../types";
4
+ import { calcCellHeight, calcMinuteHeight, getResourcedEvents } from "../helpers/generals";
5
+ import { WithResources } from "../components/common/WithResources";
6
+ import useStore from "../hooks/useStore";
7
+ import { WeekAgenda } from "./WeekAgenda";
8
+ import WeekTable from "../components/week/WeekTable";
9
+
10
+ const Week = () => {
11
+ const {
12
+ week,
13
+ selectedDate,
14
+ height,
15
+ events,
16
+ getRemoteEvents,
17
+ triggerLoading,
18
+ handleState,
19
+ resources,
20
+ resourceFields,
21
+ fields,
22
+ agenda,
23
+ } = useStore();
24
+ const { weekStartOn, weekDays, startHour, endHour, step } = week!;
25
+ const _weekStart = startOfWeek(selectedDate, { weekStartsOn: weekStartOn });
26
+ const daysList = weekDays.map((d) => addDays(_weekStart, d));
27
+ const weekStart = startOfDay(daysList[0]);
28
+ const weekEnd = endOfDay(daysList[daysList.length - 1]);
29
+ const START_TIME = set(selectedDate, { hours: startHour, minutes: 0, seconds: 0 });
30
+ const END_TIME = set(selectedDate, { hours: endHour, minutes: -step, seconds: 0 });
31
+ const hours = eachMinuteOfInterval(
32
+ {
33
+ start: START_TIME,
34
+ end: END_TIME,
35
+ },
36
+ { step }
37
+ );
38
+ const CELL_HEIGHT = calcCellHeight(height, hours.length);
39
+ const MINUTE_HEIGHT = calcMinuteHeight(CELL_HEIGHT, step);
40
+
41
+ const fetchEvents = useCallback(async () => {
42
+ try {
43
+ triggerLoading(true);
44
+
45
+ const events = await getRemoteEvents!({
46
+ start: weekStart,
47
+ end: weekEnd,
48
+ view: "week",
49
+ });
50
+ if (Array.isArray(events)) {
51
+ handleState(events, "events");
52
+ }
53
+ } catch (error) {
54
+ throw error;
55
+ } finally {
56
+ triggerLoading(false);
57
+ }
58
+ // eslint-disable-next-line react-hooks/exhaustive-deps
59
+ }, [getRemoteEvents]);
60
+
61
+ useEffect(() => {
62
+ if (getRemoteEvents instanceof Function) {
63
+ fetchEvents();
64
+ }
65
+ }, [fetchEvents, getRemoteEvents]);
66
+
67
+ const renderTable = (resource?: DefaultResource) => {
68
+ let resourcedEvents = events;
69
+ if (resource) {
70
+ resourcedEvents = getResourcedEvents(events, resource, resourceFields, fields);
71
+ }
72
+
73
+ if (agenda) {
74
+ return <WeekAgenda daysList={daysList} resource={resource} events={resourcedEvents} />;
75
+ }
76
+
77
+ return (
78
+ <WeekTable
79
+ resourcedEvents={resourcedEvents}
80
+ resource={resource}
81
+ hours={hours}
82
+ cellHeight={CELL_HEIGHT}
83
+ minutesHeight={MINUTE_HEIGHT}
84
+ daysList={daysList}
85
+ />
86
+ );
87
+ };
88
+
89
+ return resources.length ? <WithResources renderChildren={renderTable} /> : renderTable();
90
+ };
91
+
92
+ export { Week };
@@ -0,0 +1,81 @@
1
+ import { useMemo } from "react";
2
+ import { format, isToday } from "date-fns";
3
+ import { AgendaDiv } from "../styles/styles";
4
+ import { DefaultResource, ProcessedEvent } from "../types";
5
+ import useStore from "../hooks/useStore";
6
+ import { Typography } from "@mui/material";
7
+ import { filterTodayAgendaEvents, isTimeZonedToday } from "../helpers/generals";
8
+ import AgendaEventsList from "../components/events/AgendaEventsList";
9
+ import EmptyAgenda from "../components/events/EmptyAgenda";
10
+
11
+ type Props = {
12
+ daysList: Date[];
13
+ resource?: DefaultResource;
14
+ events: ProcessedEvent[];
15
+ };
16
+ const WeekAgenda = ({ daysList, resource, events }: Props) => {
17
+ const {
18
+ week,
19
+ handleGotoDay,
20
+ locale,
21
+ timeZone,
22
+ translations,
23
+ alwaysShowAgendaDays,
24
+ stickyNavigationOffset,
25
+ stickyNavigationHeight,
26
+ } = useStore();
27
+ const { disableGoToDay, headRenderer } = week!;
28
+
29
+ const hasEvents = useMemo(() => {
30
+ return daysList.some((day) => filterTodayAgendaEvents(events, day).length > 0);
31
+ }, [daysList, events]);
32
+
33
+ if (!alwaysShowAgendaDays && !hasEvents) {
34
+ return <EmptyAgenda />;
35
+ }
36
+
37
+ return (
38
+ <AgendaDiv stickyOffset={stickyNavigationOffset} stickyHeight={stickyNavigationHeight}>
39
+ {daysList.map((day, i) => {
40
+ const today = isTimeZonedToday({ dateLeft: day, timeZone });
41
+ const dayEvents = filterTodayAgendaEvents(events, day);
42
+
43
+ if (!alwaysShowAgendaDays && !dayEvents.length) return null;
44
+
45
+ return (
46
+ <div key={i} className={`rs__agenda_row ${isToday(day) ? "rs__today_cell" : ""}`}>
47
+ <div className="rs__cell rs__agenda__cell">
48
+ {typeof headRenderer === "function" ? (
49
+ <div>{headRenderer({ day, events, resource })}</div>
50
+ ) : (
51
+ <Typography
52
+ sx={{ fontWeight: today ? "bold" : "inherit" }}
53
+ color={today ? "primary" : "inherit"}
54
+ variant="body2"
55
+ className={!disableGoToDay ? "rs__hover__op" : ""}
56
+ onClick={(e) => {
57
+ e.stopPropagation();
58
+ if (!disableGoToDay) {
59
+ handleGotoDay(day);
60
+ }
61
+ }}
62
+ >
63
+ {format(day, "dd E", { locale })}
64
+ </Typography>
65
+ )}
66
+ </div>
67
+ <div className="rs__cell rs__agenda_items">
68
+ {dayEvents.length > 0 ? (
69
+ <AgendaEventsList day={day} events={dayEvents} />
70
+ ) : (
71
+ <Typography sx={{ padding: 1 }}>{translations.noDataToDisplay}</Typography>
72
+ )}
73
+ </div>
74
+ </div>
75
+ );
76
+ })}
77
+ </AgendaDiv>
78
+ );
79
+ };
80
+
81
+ export { WeekAgenda };
@@ -0,0 +1,3 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ /// <reference types="vite-plugin-svgr/client" />
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": ["src/lib/**/*"],
4
+ "exclude": ["node_modules", "**/__tests__/**"]
5
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "incremental": true,
5
+ "target": "ES2022",
6
+ "useDefineForClassFields": true,
7
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
8
+ "module": "ESNext",
9
+ "skipLibCheck": true,
10
+ "esModuleInterop": true,
11
+
12
+ /* Bundler mode */
13
+ "moduleResolution": "bundler",
14
+ "allowImportingTsExtensions": true,
15
+ "isolatedModules": true,
16
+ "moduleDetection": "force",
17
+ "noEmit": true,
18
+ "jsx": "react-jsx",
19
+
20
+ /* Linting */
21
+ "strict": true,
22
+ "noUnusedLocals": true,
23
+ "noUnusedParameters": true,
24
+ "noFallthroughCasesInSwitch": true
25
+ },
26
+ "include": ["src"]
27
+ }
package/vite.config.js ADDED
@@ -0,0 +1,40 @@
1
+ import { dirname, resolve } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { defineConfig } from "vite";
4
+ import react from "@vitejs/plugin-react";
5
+ import dts from "vite-plugin-dts";
6
+ import tsconfigPaths from "vite-tsconfig-paths";
7
+ import peerDepsExternal from "rollup-plugin-peer-deps-external";
8
+
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+
11
+ export default defineConfig(() => ({
12
+ plugins: [
13
+ react(),
14
+ tsconfigPaths({
15
+ configNames: ["tsconfig.json"],
16
+ }),
17
+ dts({ tsconfigPath: "./tsconfig.build.json" }),
18
+ peerDepsExternal(),
19
+ ],
20
+ server: {
21
+ port: 3000,
22
+ host: true,
23
+ },
24
+ preview: {
25
+ port: 3000,
26
+ },
27
+ build: {
28
+ lib: {
29
+ entry: {
30
+ index: resolve(__dirname, "src/lib/index.tsx"),
31
+ },
32
+ name: "Scheduler",
33
+ formats: ["es"],
34
+ },
35
+ copyPublicDir: false,
36
+ },
37
+ resolve: {
38
+ extensions: [".js", ".ts", ".tsx", ".jsx"],
39
+ },
40
+ }));