@korsolutions/ui 0.0.72 → 0.0.75

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 (168) hide show
  1. package/dist/module/components/calendar/calendar/calendar-root.js +57 -0
  2. package/dist/module/components/calendar/calendar/calendar-root.js.map +1 -0
  3. package/dist/module/components/calendar/{components → calendar}/calendar-weeks.js +12 -5
  4. package/dist/module/components/calendar/calendar/calendar-weeks.js.map +1 -0
  5. package/dist/module/components/calendar/calendar/index.js +19 -0
  6. package/dist/module/components/calendar/calendar/index.js.map +1 -0
  7. package/dist/module/components/calendar/calendar/types.js.map +1 -0
  8. package/dist/module/components/calendar/{variants → calendar/variants}/default.js +29 -13
  9. package/dist/module/components/calendar/calendar/variants/default.js.map +1 -0
  10. package/dist/module/components/calendar/calendar/variants/index.js.map +1 -0
  11. package/dist/module/components/calendar/index.js +3 -16
  12. package/dist/module/components/calendar/index.js.map +1 -1
  13. package/dist/module/components/calendar/{context.js → shared/calendar-context.js} +2 -2
  14. package/dist/module/components/calendar/shared/calendar-context.js.map +1 -0
  15. package/dist/module/components/calendar/{components → shared}/calendar-day.js +12 -11
  16. package/dist/module/components/calendar/shared/calendar-day.js.map +1 -0
  17. package/dist/module/components/calendar/{components → shared}/calendar-header.js +1 -1
  18. package/dist/module/components/calendar/shared/calendar-header.js.map +1 -0
  19. package/dist/module/components/calendar/shared/calendar-nav-buttons.js +63 -0
  20. package/dist/module/components/calendar/shared/calendar-nav-buttons.js.map +1 -0
  21. package/dist/module/components/calendar/{components → shared}/calendar-title.js +2 -2
  22. package/dist/module/components/calendar/shared/calendar-title.js.map +1 -0
  23. package/dist/module/components/calendar/{components → shared}/calendar-week-labels.js +1 -1
  24. package/dist/module/components/calendar/shared/calendar-week-labels.js.map +1 -0
  25. package/dist/module/components/calendar/shared/types.js +4 -0
  26. package/dist/module/components/calendar/shared/types.js.map +1 -0
  27. package/dist/module/components/calendar/timeline/calendar-timeline.js +138 -0
  28. package/dist/module/components/calendar/timeline/calendar-timeline.js.map +1 -0
  29. package/dist/module/components/calendar/timeline/index.js +4 -0
  30. package/dist/module/components/calendar/timeline/index.js.map +1 -0
  31. package/dist/module/components/calendar/timeline/types.js +4 -0
  32. package/dist/module/components/calendar/timeline/types.js.map +1 -0
  33. package/dist/module/components/calendar/timeline/variants/default.js +62 -0
  34. package/dist/module/components/calendar/timeline/variants/default.js.map +1 -0
  35. package/dist/module/components/calendar/timeline/variants/index.js +7 -0
  36. package/dist/module/components/calendar/timeline/variants/index.js.map +1 -0
  37. package/dist/module/components/calendar/week-calendar/index.js +4 -0
  38. package/dist/module/components/calendar/week-calendar/index.js.map +1 -0
  39. package/dist/module/components/calendar/week-calendar/types.js +4 -0
  40. package/dist/module/components/calendar/week-calendar/types.js.map +1 -0
  41. package/dist/module/components/calendar/week-calendar/variants/default.js +145 -0
  42. package/dist/module/components/calendar/week-calendar/variants/default.js.map +1 -0
  43. package/dist/module/components/calendar/week-calendar/variants/index.js +7 -0
  44. package/dist/module/components/calendar/week-calendar/variants/index.js.map +1 -0
  45. package/dist/module/components/calendar/week-calendar/week-calendar.js +170 -0
  46. package/dist/module/components/calendar/week-calendar/week-calendar.js.map +1 -0
  47. package/dist/module/components/index.js +1 -1
  48. package/dist/module/index.js +2 -1
  49. package/dist/module/index.js.map +1 -1
  50. package/dist/module/themes/provider.js.map +1 -1
  51. package/dist/module/utils/date-utils.js +45 -17
  52. package/dist/module/utils/date-utils.js.map +1 -1
  53. package/dist/typescript/src/components/calendar/{components → calendar}/calendar-root.d.ts +2 -1
  54. package/dist/typescript/src/components/calendar/calendar/calendar-root.d.ts.map +1 -0
  55. package/dist/typescript/src/components/calendar/calendar/calendar-weeks.d.ts.map +1 -0
  56. package/dist/typescript/src/components/calendar/calendar/index.d.ts +25 -0
  57. package/dist/typescript/src/components/calendar/calendar/index.d.ts.map +1 -0
  58. package/dist/typescript/src/components/calendar/calendar/types.d.ts +7 -0
  59. package/dist/typescript/src/components/calendar/calendar/types.d.ts.map +1 -0
  60. package/dist/typescript/src/components/calendar/calendar/variants/default.d.ts +3 -0
  61. package/dist/typescript/src/components/calendar/calendar/variants/default.d.ts.map +1 -0
  62. package/dist/typescript/src/components/calendar/calendar/variants/index.d.ts.map +1 -0
  63. package/dist/typescript/src/components/calendar/index.d.ts +7 -24
  64. package/dist/typescript/src/components/calendar/index.d.ts.map +1 -1
  65. package/dist/typescript/src/components/calendar/{context.d.ts → shared/calendar-context.d.ts} +10 -4
  66. package/dist/typescript/src/components/calendar/shared/calendar-context.d.ts.map +1 -0
  67. package/dist/typescript/src/components/calendar/shared/calendar-day.d.ts.map +1 -0
  68. package/dist/typescript/src/components/calendar/shared/calendar-header.d.ts.map +1 -0
  69. package/dist/typescript/src/components/calendar/shared/calendar-nav-buttons.d.ts +7 -0
  70. package/dist/typescript/src/components/calendar/shared/calendar-nav-buttons.d.ts.map +1 -0
  71. package/dist/typescript/src/components/calendar/shared/calendar-title.d.ts.map +1 -0
  72. package/dist/typescript/src/components/calendar/shared/calendar-week-labels.d.ts.map +1 -0
  73. package/dist/typescript/src/components/calendar/shared/types.d.ts +18 -0
  74. package/dist/typescript/src/components/calendar/shared/types.d.ts.map +1 -0
  75. package/dist/typescript/src/components/calendar/timeline/calendar-timeline.d.ts +23 -0
  76. package/dist/typescript/src/components/calendar/timeline/calendar-timeline.d.ts.map +1 -0
  77. package/dist/typescript/src/components/calendar/timeline/index.d.ts +4 -0
  78. package/dist/typescript/src/components/calendar/timeline/index.d.ts.map +1 -0
  79. package/dist/typescript/src/components/calendar/timeline/types.d.ts +13 -0
  80. package/dist/typescript/src/components/calendar/timeline/types.d.ts.map +1 -0
  81. package/dist/typescript/src/components/calendar/timeline/variants/default.d.ts +3 -0
  82. package/dist/typescript/src/components/calendar/timeline/variants/default.d.ts.map +1 -0
  83. package/dist/typescript/src/components/calendar/timeline/variants/index.d.ts +4 -0
  84. package/dist/typescript/src/components/calendar/timeline/variants/index.d.ts.map +1 -0
  85. package/dist/typescript/src/components/calendar/week-calendar/index.d.ts +4 -0
  86. package/dist/typescript/src/components/calendar/week-calendar/index.d.ts.map +1 -0
  87. package/dist/typescript/src/components/calendar/week-calendar/types.d.ts +7 -0
  88. package/dist/typescript/src/components/calendar/week-calendar/types.d.ts.map +1 -0
  89. package/dist/typescript/src/components/calendar/week-calendar/variants/default.d.ts +3 -0
  90. package/dist/typescript/src/components/calendar/week-calendar/variants/default.d.ts.map +1 -0
  91. package/dist/typescript/src/components/calendar/week-calendar/variants/index.d.ts +4 -0
  92. package/dist/typescript/src/components/calendar/week-calendar/variants/index.d.ts.map +1 -0
  93. package/dist/typescript/src/components/calendar/week-calendar/week-calendar.d.ts +16 -0
  94. package/dist/typescript/src/components/calendar/week-calendar/week-calendar.d.ts.map +1 -0
  95. package/dist/typescript/src/components/index.d.ts +1 -1
  96. package/dist/typescript/src/index.d.ts.map +1 -1
  97. package/dist/typescript/src/themes/provider.d.ts +4 -0
  98. package/dist/typescript/src/themes/provider.d.ts.map +1 -1
  99. package/dist/typescript/src/utils/date-utils.d.ts +8 -1
  100. package/dist/typescript/src/utils/date-utils.d.ts.map +1 -1
  101. package/package.json +1 -1
  102. package/src/components/calendar/calendar/calendar-root.tsx +73 -0
  103. package/src/components/calendar/{components → calendar}/calendar-weeks.tsx +22 -8
  104. package/src/components/calendar/calendar/index.ts +26 -0
  105. package/src/components/calendar/calendar/types.ts +7 -0
  106. package/src/components/calendar/{variants → calendar/variants}/default.tsx +30 -14
  107. package/src/components/calendar/index.ts +21 -24
  108. package/src/components/calendar/shared/calendar-context.ts +35 -0
  109. package/src/components/calendar/{components → shared}/calendar-day.tsx +41 -13
  110. package/src/components/calendar/{components → shared}/calendar-header.tsx +7 -2
  111. package/src/components/calendar/shared/calendar-nav-buttons.tsx +81 -0
  112. package/src/components/calendar/{components → shared}/calendar-title.tsx +8 -3
  113. package/src/components/calendar/{components → shared}/calendar-week-labels.tsx +8 -2
  114. package/src/components/calendar/shared/types.ts +24 -0
  115. package/src/components/calendar/timeline/calendar-timeline.tsx +204 -0
  116. package/src/components/calendar/timeline/index.ts +6 -0
  117. package/src/components/calendar/timeline/types.ts +13 -0
  118. package/src/components/calendar/timeline/variants/default.tsx +59 -0
  119. package/src/components/calendar/timeline/variants/index.ts +5 -0
  120. package/src/components/calendar/week-calendar/index.ts +3 -0
  121. package/src/components/calendar/week-calendar/types.ts +7 -0
  122. package/src/components/calendar/week-calendar/variants/default.tsx +141 -0
  123. package/src/components/calendar/week-calendar/variants/index.ts +5 -0
  124. package/src/components/calendar/week-calendar/week-calendar.tsx +256 -0
  125. package/src/components/index.ts +1 -1
  126. package/src/index.tsx +2 -0
  127. package/src/themes/provider.tsx +4 -0
  128. package/src/utils/date-utils.ts +53 -21
  129. package/dist/module/components/calendar/components/calendar-day.js.map +0 -1
  130. package/dist/module/components/calendar/components/calendar-header.js.map +0 -1
  131. package/dist/module/components/calendar/components/calendar-nav-button.js +0 -61
  132. package/dist/module/components/calendar/components/calendar-nav-button.js.map +0 -1
  133. package/dist/module/components/calendar/components/calendar-root.js +0 -39
  134. package/dist/module/components/calendar/components/calendar-root.js.map +0 -1
  135. package/dist/module/components/calendar/components/calendar-title.js.map +0 -1
  136. package/dist/module/components/calendar/components/calendar-week-labels.js.map +0 -1
  137. package/dist/module/components/calendar/components/calendar-weeks.js.map +0 -1
  138. package/dist/module/components/calendar/context.js.map +0 -1
  139. package/dist/module/components/calendar/types.js.map +0 -1
  140. package/dist/module/components/calendar/variants/default.js.map +0 -1
  141. package/dist/module/components/calendar/variants/index.js.map +0 -1
  142. package/dist/typescript/src/components/calendar/components/calendar-day.d.ts.map +0 -1
  143. package/dist/typescript/src/components/calendar/components/calendar-header.d.ts.map +0 -1
  144. package/dist/typescript/src/components/calendar/components/calendar-nav-button.d.ts +0 -10
  145. package/dist/typescript/src/components/calendar/components/calendar-nav-button.d.ts.map +0 -1
  146. package/dist/typescript/src/components/calendar/components/calendar-root.d.ts.map +0 -1
  147. package/dist/typescript/src/components/calendar/components/calendar-title.d.ts.map +0 -1
  148. package/dist/typescript/src/components/calendar/components/calendar-week-labels.d.ts.map +0 -1
  149. package/dist/typescript/src/components/calendar/components/calendar-weeks.d.ts.map +0 -1
  150. package/dist/typescript/src/components/calendar/context.d.ts.map +0 -1
  151. package/dist/typescript/src/components/calendar/types.d.ts +0 -37
  152. package/dist/typescript/src/components/calendar/types.d.ts.map +0 -1
  153. package/dist/typescript/src/components/calendar/variants/default.d.ts +0 -3
  154. package/dist/typescript/src/components/calendar/variants/default.d.ts.map +0 -1
  155. package/dist/typescript/src/components/calendar/variants/index.d.ts.map +0 -1
  156. package/src/components/calendar/components/calendar-nav-button.tsx +0 -60
  157. package/src/components/calendar/components/calendar-root.tsx +0 -42
  158. package/src/components/calendar/context.ts +0 -23
  159. package/src/components/calendar/types.ts +0 -39
  160. /package/dist/module/components/calendar/{types.js → calendar/types.js} +0 -0
  161. /package/dist/module/components/calendar/{variants → calendar/variants}/index.js +0 -0
  162. /package/dist/typescript/src/components/calendar/{components → calendar}/calendar-weeks.d.ts +0 -0
  163. /package/dist/typescript/src/components/calendar/{variants → calendar/variants}/index.d.ts +0 -0
  164. /package/dist/typescript/src/components/calendar/{components → shared}/calendar-day.d.ts +0 -0
  165. /package/dist/typescript/src/components/calendar/{components → shared}/calendar-header.d.ts +0 -0
  166. /package/dist/typescript/src/components/calendar/{components → shared}/calendar-title.d.ts +0 -0
  167. /package/dist/typescript/src/components/calendar/{components → shared}/calendar-week-labels.d.ts +0 -0
  168. /package/src/components/calendar/{variants → calendar/variants}/index.ts +0 -0
@@ -0,0 +1,26 @@
1
+ import { CalendarDay } from "../shared/calendar-day";
2
+ import { CalendarHeader } from "../shared/calendar-header";
3
+ import { CalendarNavButtons } from "../shared/calendar-nav-buttons";
4
+ import { CalendarTitle } from "../shared/calendar-title";
5
+ import { CalendarWeekLabels } from "../shared/calendar-week-labels";
6
+ import { CalendarRoot } from "./calendar-root";
7
+ import { CalendarWeeks } from "./calendar-weeks";
8
+
9
+ export const Calendar = {
10
+ Root: CalendarRoot,
11
+ Header: CalendarHeader,
12
+ Title: CalendarTitle,
13
+ NavButtons: CalendarNavButtons,
14
+ CalendarWeekLabels: CalendarWeekLabels,
15
+ Weeks: CalendarWeeks,
16
+ Day: CalendarDay,
17
+ };
18
+
19
+ export type { CalendarDayProps } from "../shared/calendar-day";
20
+ export type { CalendarHeaderProps } from "../shared/calendar-header";
21
+ export type { CalendarNavButtonsProps } from "../shared/calendar-nav-buttons";
22
+ export type { CalendarTitleProps } from "../shared/calendar-title";
23
+ export type { CalendarWeekLabelsProps } from "../shared/calendar-week-labels";
24
+ export type { CalendarRootProps } from "./calendar-root";
25
+ export type { CalendarWeeksProps } from "./calendar-weeks";
26
+ export type { CalendarStyles } from "./types";
@@ -0,0 +1,7 @@
1
+ import type { StyleProp, ViewStyle } from "react-native";
2
+ import type { BaseCalendarStyles } from "../shared/types";
3
+
4
+ export interface CalendarStyles extends BaseCalendarStyles {
5
+ weeks?: StyleProp<ViewStyle>;
6
+ week?: StyleProp<ViewStyle>;
7
+ }
@@ -1,5 +1,6 @@
1
- import { type CalendarStyles } from "../..";
2
- import { useThemedStyles } from "../../../utils/use-themed-styles";
1
+ import { hslaSetRelativeLightness } from "../../../../utils/hsla-utils";
2
+ import { useThemedStyles } from "../../../../utils/use-themed-styles";
3
+ import type { CalendarStyles } from "../types";
3
4
 
4
5
  export const useCalendarVariantDefault = (): CalendarStyles => {
5
6
  return useThemedStyles(
@@ -25,24 +26,38 @@ export const useCalendarVariantDefault = (): CalendarStyles => {
25
26
  fontFamily,
26
27
  color: colors.foreground,
27
28
  },
29
+ navButtons: {
30
+ flexDirection: "row",
31
+ gap: 4,
32
+ },
28
33
  navButton: {
29
34
  default: {
30
35
  width: 32,
31
36
  height: 32,
32
- borderRadius: radius * 0.5,
37
+ borderRadius: radius,
33
38
  alignItems: "center",
34
39
  justifyContent: "center",
35
40
  backgroundColor: "transparent",
36
41
  },
37
42
  disabled: {
38
- opacity: 0.3,
43
+ opacity: 0.5,
44
+ },
45
+ hovered: {
46
+ backgroundColor: hslaSetRelativeLightness(colors.secondary, -1),
39
47
  },
40
48
  },
41
- navButtonText: {
49
+ navButtonIcon: {
42
50
  default: {
43
- fontSize: fontSize * 1.5,
44
51
  color: colors.foreground,
45
- fontWeight: "500",
52
+ size: fontSize * 1.25,
53
+ style: {
54
+ color: colors.foreground,
55
+ fontSize: fontSize * 1.25,
56
+ lineHeight: fontSize * 1.25,
57
+ textAlign: "center",
58
+ fontWeight: "500",
59
+ pointerEvents: "none",
60
+ },
46
61
  },
47
62
  disabled: {
48
63
  color: colors.mutedForeground,
@@ -91,9 +106,6 @@ export const useCalendarVariantDefault = (): CalendarStyles => {
91
106
  disabled: {
92
107
  opacity: 0.3,
93
108
  },
94
- deprioritized: {
95
- backgroundColor: "transparent",
96
- },
97
109
  hovered: {
98
110
  backgroundColor: colors.muted,
99
111
  },
@@ -117,10 +129,14 @@ export const useCalendarVariantDefault = (): CalendarStyles => {
117
129
  disabled: {
118
130
  color: colors.mutedForeground,
119
131
  },
120
- deprioritized: {
121
- color: colors.mutedForeground,
122
- opacity: 0.5,
123
- },
132
+ },
133
+ dayMarker: {
134
+ width: 5,
135
+ height: 5,
136
+ borderRadius: 2.5,
137
+ backgroundColor: colors.primary,
138
+ marginTop: 2,
139
+ alignSelf: "center",
124
140
  },
125
141
  }),
126
142
  );
@@ -1,26 +1,23 @@
1
- import { CalendarDay } from "./components/calendar-day";
2
- import { CalendarHeader } from "./components/calendar-header";
3
- import { CalendarNavButton } from "./components/calendar-nav-button";
4
- import { CalendarRoot } from "./components/calendar-root";
5
- import { CalendarTitle } from "./components/calendar-title";
6
- import { CalendarWeekLabels } from "./components/calendar-week-labels";
7
- import { CalendarWeeks } from "./components/calendar-weeks";
1
+ export { Calendar } from "./calendar";
2
+ export type {
3
+ CalendarDayProps,
4
+ CalendarHeaderProps,
5
+ CalendarNavButtonsProps,
6
+ CalendarRootProps,
7
+ CalendarStyles,
8
+ CalendarTitleProps,
9
+ CalendarWeekLabelsProps,
10
+ CalendarWeeksProps,
11
+ } from "./calendar";
8
12
 
9
- export const Calendar = {
10
- Root: CalendarRoot,
11
- Header: CalendarHeader,
12
- Title: CalendarTitle,
13
- NavButton: CalendarNavButton,
14
- CalendarWeekLabels: CalendarWeekLabels,
15
- Weeks: CalendarWeeks,
16
- Day: CalendarDay,
17
- };
13
+ export { WeekCalendar } from "./week-calendar";
14
+ export type { WeekCalendarProps, WeekCalendarStyles } from "./week-calendar";
18
15
 
19
- export type { CalendarDayProps } from "./components/calendar-day";
20
- export type { CalendarHeaderProps } from "./components/calendar-header";
21
- export type { CalendarNavButtonProps } from "./components/calendar-nav-button";
22
- export type { CalendarRootProps } from "./components/calendar-root";
23
- export type { CalendarTitleProps } from "./components/calendar-title";
24
- export type { CalendarWeekLabelsProps } from "./components/calendar-week-labels";
25
- export type { CalendarWeeksProps } from "./components/calendar-weeks";
26
- export type { CalendarDayState, CalendarStyles } from "./types";
16
+ export { CalendarTimeline } from "./timeline";
17
+ export type {
18
+ CalendarTimelineProps,
19
+ TimelineEventLayout,
20
+ TimelineStyles,
21
+ } from "./timeline";
22
+
23
+ export type { CalendarDayState } from "./shared/types";
@@ -0,0 +1,35 @@
1
+ import React from "react";
2
+ import type { BaseCalendarStyles } from "./types";
3
+
4
+ export interface CalendarContextValue {
5
+ value?: Date | null;
6
+ onChange?: (date: Date | null) => void;
7
+ currentMonth: Date;
8
+ goToPrev: () => void;
9
+ goToNext: () => void;
10
+ isPrevDisabled: boolean;
11
+ isNextDisabled: boolean;
12
+ minDate?: Date;
13
+ maxDate?: Date;
14
+ markedDates?: Date[];
15
+
16
+ // WeekCalendar-specific
17
+ currentWeekStart?: Date;
18
+ setCurrentWeekStart?: (date: Date) => void;
19
+
20
+ styles?: BaseCalendarStyles;
21
+ }
22
+
23
+ export const CalendarContext = React.createContext<
24
+ CalendarContextValue | undefined
25
+ >(undefined);
26
+
27
+ export const useCalendarContext = () => {
28
+ const context = React.useContext(CalendarContext);
29
+ if (!context) {
30
+ throw new Error(
31
+ "Calendar components must be used within a Calendar or WeekCalendar Root",
32
+ );
33
+ }
34
+ return context;
35
+ };
@@ -1,8 +1,21 @@
1
- import { formatDate, isDateAfter, isDateBefore, isDateSameDay, isDateToday, isSameMonth } from "../../../utils/date-utils";
2
1
  import React, { useMemo, useState } from "react";
3
- import { Pressable, Text, type StyleProp, type TextStyle, type ViewStyle } from "react-native";
4
- import { useCalendarContext } from "../context";
5
- import type { CalendarDayState } from "../types";
2
+ import {
3
+ Pressable,
4
+ Text,
5
+ View,
6
+ type StyleProp,
7
+ type TextStyle,
8
+ type ViewStyle,
9
+ } from "react-native";
10
+ import {
11
+ formatDate,
12
+ isDateAfter,
13
+ isDateBefore,
14
+ isDateSameDay,
15
+ isDateToday,
16
+ } from "../../../utils/date-utils";
17
+ import { useCalendarContext } from "./calendar-context";
18
+ import type { CalendarDayState } from "./types";
6
19
 
7
20
  export interface CalendarDayProps {
8
21
  date: Date;
@@ -15,7 +28,6 @@ export interface CalendarDayProps {
15
28
  const calculateState = (
16
29
  date: Date,
17
30
  selected: Date | null | undefined,
18
- isCurrentMonth: boolean,
19
31
  isDisabled: boolean,
20
32
  isHovered: boolean,
21
33
  ): CalendarDayState => {
@@ -23,7 +35,6 @@ const calculateState = (
23
35
  if (selected && isDateSameDay(date, selected)) return "selected";
24
36
  if (isDateToday(date)) return "today";
25
37
  if (isHovered) return "hovered";
26
- if (!isCurrentMonth) return "deprioritized";
27
38
  return "default";
28
39
  };
29
40
 
@@ -31,23 +42,39 @@ export function CalendarDay(props: CalendarDayProps) {
31
42
  const calendar = useCalendarContext();
32
43
  const [isHovered, setIsHovered] = useState(false);
33
44
 
34
- const isCurrentMonth = isSameMonth(props.date, calendar.currentMonth);
35
-
36
45
  const isDisabled = useMemo(() => {
37
- if (calendar.minDate && isDateBefore(props.date, calendar.minDate)) return true;
38
- if (calendar.maxDate && isDateAfter(props.date, calendar.maxDate)) return true;
46
+ if (calendar.minDate && isDateBefore(props.date, calendar.minDate))
47
+ return true;
48
+ if (calendar.maxDate && isDateAfter(props.date, calendar.maxDate))
49
+ return true;
39
50
  return false;
40
51
  }, [props.date, calendar.minDate, calendar.maxDate]);
41
52
 
42
- const state = calculateState(props.date, calendar.value, isCurrentMonth, isDisabled, isHovered);
53
+ const isMarked =
54
+ calendar.markedDates?.some((d) => isDateSameDay(d, props.date)) ?? false;
55
+
56
+ const state = calculateState(
57
+ props.date,
58
+ calendar.value,
59
+ isDisabled,
60
+ isHovered,
61
+ );
43
62
 
44
63
  const handlePress = () => {
45
64
  if (isDisabled || !calendar.onChange) return;
46
65
  calendar.onChange(props.date);
47
66
  };
48
67
 
49
- const composedStyle = [calendar.styles?.dayButton?.default, calendar.styles?.dayButton?.[state], props.style];
50
- const composedTextStyle = [calendar.styles?.dayText?.default, calendar.styles?.dayText?.[state], props.textStyle];
68
+ const composedStyle = [
69
+ calendar.styles?.dayButton?.default,
70
+ calendar.styles?.dayButton?.[state],
71
+ props.style,
72
+ ];
73
+ const composedTextStyle = [
74
+ calendar.styles?.dayText?.default,
75
+ calendar.styles?.dayText?.[state],
76
+ props.textStyle,
77
+ ];
51
78
 
52
79
  return (
53
80
  <Pressable
@@ -58,6 +85,7 @@ export function CalendarDay(props: CalendarDayProps) {
58
85
  style={composedStyle}
59
86
  >
60
87
  <Text style={composedTextStyle}>{formatDate(props.date, "d")}</Text>
88
+ {isMarked && <View style={calendar.styles?.dayMarker} />}
61
89
  </Pressable>
62
90
  );
63
91
  }
@@ -1,6 +1,11 @@
1
1
  import React from "react";
2
- import { View, type StyleProp, type ViewProps, type ViewStyle } from "react-native";
3
- import { useCalendarContext } from "../context";
2
+ import {
3
+ View,
4
+ type StyleProp,
5
+ type ViewProps,
6
+ type ViewStyle,
7
+ } from "react-native";
8
+ import { useCalendarContext } from "./calendar-context";
4
9
 
5
10
  export interface CalendarHeaderProps extends ViewProps {
6
11
  children?: React.ReactNode;
@@ -0,0 +1,81 @@
1
+ import React, { useState } from "react";
2
+ import {
3
+ Pressable,
4
+ StyleSheet,
5
+ Text,
6
+ View,
7
+ type StyleProp,
8
+ type ViewStyle,
9
+ } from "react-native";
10
+ import { useComponentsConfig } from "../../../themes";
11
+ import { useCalendarContext } from "./calendar-context";
12
+ import type { CalendarNavButtonState } from "./types";
13
+
14
+ export interface CalendarNavButtonsProps {
15
+ style?: StyleProp<ViewStyle>;
16
+ }
17
+
18
+ const calculateState = (
19
+ isDisabled: boolean,
20
+ isHovered: boolean,
21
+ ): CalendarNavButtonState => {
22
+ if (isDisabled) return "disabled";
23
+ if (isHovered) return "hovered";
24
+ return "default";
25
+ };
26
+
27
+ export function CalendarNavButtons(props: CalendarNavButtonsProps) {
28
+ const { style } = props;
29
+ const { goToPrev, goToNext, isPrevDisabled, isNextDisabled, styles } =
30
+ useCalendarContext();
31
+ const config = useComponentsConfig();
32
+ const PrevIcon = config?.calendar?.prevIcon;
33
+ const NextIcon = config?.calendar?.nextIcon;
34
+ const [prevHovered, setPrevHovered] = useState(false);
35
+ const [nextHovered, setNextHovered] = useState(false);
36
+
37
+ const prevState = calculateState(isPrevDisabled, prevHovered);
38
+ const nextState = calculateState(isNextDisabled, nextHovered);
39
+
40
+ const prevIconProps = StyleSheet.flatten([
41
+ styles?.navButtonIcon?.default,
42
+ styles?.navButtonIcon?.[prevState],
43
+ ]);
44
+ const nextIconProps = StyleSheet.flatten([
45
+ styles?.navButtonIcon?.default,
46
+ styles?.navButtonIcon?.[nextState],
47
+ ]);
48
+
49
+ const composedStyle = [styles?.navButtons, style];
50
+
51
+ return (
52
+ <View style={composedStyle}>
53
+ <Pressable
54
+ onPress={goToPrev}
55
+ onHoverIn={() => setPrevHovered(true)}
56
+ onHoverOut={() => setPrevHovered(false)}
57
+ disabled={isPrevDisabled}
58
+ style={[styles?.navButton?.default, styles?.navButton?.[prevState]]}
59
+ >
60
+ {PrevIcon ? (
61
+ <PrevIcon {...prevIconProps} />
62
+ ) : (
63
+ <Text style={prevIconProps?.style}>‹</Text>
64
+ )}
65
+ </Pressable>
66
+ <Pressable
67
+ onPress={goToNext}
68
+ onHoverIn={() => setNextHovered(true)}
69
+ onHoverOut={() => setNextHovered(false)}
70
+ disabled={isNextDisabled}
71
+ style={[styles?.navButton?.default, styles?.navButton?.[nextState]]}
72
+ >
73
+ {NextIcon ? (
74
+ <NextIcon {...nextIconProps} />
75
+ ) : (
76
+ <Text style={nextIconProps?.style}>›</Text>
77
+ )}
78
+ </Pressable>
79
+ </View>
80
+ );
81
+ }
@@ -1,7 +1,12 @@
1
- import { formatDate } from "../../../utils/date-utils";
2
1
  import React from "react";
3
- import { Text, type StyleProp, type TextProps, type TextStyle } from "react-native";
4
- import { useCalendarContext } from "../context";
2
+ import {
3
+ Text,
4
+ type StyleProp,
5
+ type TextProps,
6
+ type TextStyle,
7
+ } from "react-native";
8
+ import { formatDate } from "../../../utils/date-utils";
9
+ import { useCalendarContext } from "./calendar-context";
5
10
 
6
11
  export interface CalendarTitleProps extends TextProps {
7
12
  children?: React.ReactNode;
@@ -1,6 +1,12 @@
1
1
  import React from "react";
2
- import { Text, View, type StyleProp, type TextStyle, type ViewStyle } from "react-native";
3
- import { useCalendarContext } from "../context";
2
+ import {
3
+ Text,
4
+ View,
5
+ type StyleProp,
6
+ type TextStyle,
7
+ type ViewStyle,
8
+ } from "react-native";
9
+ import { useCalendarContext } from "./calendar-context";
4
10
 
5
11
  export interface CalendarWeekLabelProps {
6
12
  children: string;
@@ -0,0 +1,24 @@
1
+ import type { StyleProp, TextStyle, ViewStyle } from "react-native";
2
+ import type { IconProps } from "../../icon";
3
+
4
+ export type CalendarDayState =
5
+ | "default"
6
+ | "selected"
7
+ | "today"
8
+ | "disabled"
9
+ | "hovered";
10
+ export type CalendarNavButtonState = "default" | "disabled" | "hovered";
11
+
12
+ export interface BaseCalendarStyles {
13
+ root?: StyleProp<ViewStyle>;
14
+ header?: StyleProp<ViewStyle>;
15
+ headerTitle?: StyleProp<TextStyle>;
16
+ navButtons?: StyleProp<ViewStyle>;
17
+ navButton?: Partial<Record<CalendarNavButtonState, ViewStyle>>;
18
+ navButtonIcon?: Partial<Record<CalendarNavButtonState, IconProps>>;
19
+ weekLabels?: StyleProp<ViewStyle>;
20
+ weekLabel?: StyleProp<TextStyle>;
21
+ dayButton?: Partial<Record<CalendarDayState, StyleProp<ViewStyle>>>;
22
+ dayText?: Partial<Record<CalendarDayState, StyleProp<TextStyle>>>;
23
+ dayMarker?: StyleProp<ViewStyle>;
24
+ }
@@ -0,0 +1,204 @@
1
+ import React, { useMemo } from "react";
2
+ import { ScrollView, Text, View, type StyleProp, type ViewStyle } from "react-native";
3
+ import { isDateSameDay } from "../../../utils/date-utils";
4
+ import { TimelineVariants } from "./variants";
5
+
6
+ const HOUR_HEIGHT = 60;
7
+
8
+ function formatHour(hour: number): string {
9
+ if (hour === 0) return "12 AM";
10
+ if (hour < 12) return `${hour} AM`;
11
+ if (hour === 12) return "12 PM";
12
+ return `${hour - 12} PM`;
13
+ }
14
+
15
+ function getMinutesFromStartOfDay(date: Date): number {
16
+ return date.getHours() * 60 + date.getMinutes();
17
+ }
18
+
19
+ export interface TimelineEventLayout {
20
+ top: number;
21
+ height: number;
22
+ left: string;
23
+ width: string;
24
+ }
25
+
26
+ export interface CalendarTimelineProps<T> {
27
+ events?: T[];
28
+ date: Date;
29
+ startHour?: number;
30
+ endHour?: number;
31
+ getStart: (event: T) => Date;
32
+ getEnd: (event: T) => Date;
33
+ keyExtractor: (event: T) => string;
34
+ renderEvent: (event: T, layout: TimelineEventLayout) => React.ReactNode;
35
+ variant?: keyof typeof TimelineVariants;
36
+ style?: StyleProp<ViewStyle>;
37
+ }
38
+
39
+ function groupOverlappingEvents<T>(
40
+ events: T[],
41
+ getStart: (e: T) => Date,
42
+ getEnd: (e: T) => Date,
43
+ ): T[][] {
44
+ const sorted = [...events].sort(
45
+ (a, b) => getStart(a).getTime() - getStart(b).getTime(),
46
+ );
47
+ const groups: T[][] = [];
48
+
49
+ for (const event of sorted) {
50
+ let placed = false;
51
+ const eStart = getStart(event);
52
+ const eEnd = getEnd(event);
53
+
54
+ for (const group of groups) {
55
+ const overlaps = group.some((g) => {
56
+ const gStart = getStart(g);
57
+ const gEnd = getEnd(g);
58
+ return (
59
+ (eStart >= gStart && eStart < gEnd) ||
60
+ (eEnd > gStart && eEnd <= gEnd) ||
61
+ (eStart <= gStart && eEnd >= gEnd)
62
+ );
63
+ });
64
+
65
+ if (overlaps) {
66
+ group.push(event);
67
+ placed = true;
68
+ break;
69
+ }
70
+ }
71
+
72
+ if (!placed) {
73
+ groups.push([event]);
74
+ }
75
+ }
76
+
77
+ return groups;
78
+ }
79
+
80
+ export function CalendarTimeline<T>(props: CalendarTimelineProps<T>) {
81
+ const {
82
+ date,
83
+ startHour = 0,
84
+ endHour = 24,
85
+ getStart,
86
+ getEnd,
87
+ keyExtractor,
88
+ renderEvent,
89
+ style,
90
+ } = props;
91
+ const variantStyles = TimelineVariants[props.variant || "default"]();
92
+
93
+ const hours = useMemo(() => {
94
+ const arr: number[] = [];
95
+ for (let i = startHour; i < endHour; i++) {
96
+ arr.push(i);
97
+ }
98
+ return arr;
99
+ }, [startHour, endHour]);
100
+
101
+ const allEvents = props.events ?? [];
102
+
103
+ const dayEvents = useMemo(() => {
104
+ return allEvents.filter((event) => isDateSameDay(getStart(event), date));
105
+ }, [allEvents, date, getStart]);
106
+
107
+ const eventGroups = useMemo(
108
+ () => groupOverlappingEvents(dayEvents, getStart, getEnd),
109
+ [dayEvents, getStart, getEnd],
110
+ );
111
+
112
+ const now = new Date();
113
+ const isToday = isDateSameDay(now, date);
114
+ const currentTimePosition = isToday
115
+ ? ((getMinutesFromStartOfDay(now) - startHour * 60) / 60) * HOUR_HEIGHT
116
+ : null;
117
+
118
+ return (
119
+ <ScrollView
120
+ style={[variantStyles.container, style]}
121
+ showsVerticalScrollIndicator
122
+ >
123
+ <View style={variantStyles.timeline}>
124
+ {/* Time column */}
125
+ <View style={variantStyles.timeColumn}>
126
+ {hours.map((hour) => (
127
+ <View key={hour} style={variantStyles.timeSlot}>
128
+ <Text style={variantStyles.timeText}>{formatHour(hour)}</Text>
129
+ </View>
130
+ ))}
131
+ </View>
132
+
133
+ {/* Events column */}
134
+ <View style={variantStyles.eventsColumn}>
135
+ {hours.map((hour) => (
136
+ <View key={hour} style={variantStyles.hourLine} />
137
+ ))}
138
+
139
+ {/* Current time indicator */}
140
+ {currentTimePosition != null && currentTimePosition >= 0 && (
141
+ <View
142
+ style={{
143
+ position: "absolute",
144
+ left: 0,
145
+ right: 0,
146
+ top: currentTimePosition,
147
+ flexDirection: "row",
148
+ alignItems: "center",
149
+ zIndex: 1000,
150
+ }}
151
+ >
152
+ <View style={variantStyles.currentTimeDot} />
153
+ <View style={variantStyles.currentTimeLineBar} />
154
+ </View>
155
+ )}
156
+
157
+ {/* Events */}
158
+ {eventGroups.map((group) =>
159
+ group.map((event) => {
160
+ const startMinutes = getMinutesFromStartOfDay(getStart(event));
161
+ let endMinutes = getMinutesFromStartOfDay(getEnd(event));
162
+ // Handle midnight (0:00) or end times on the next day
163
+ if (endMinutes <= startMinutes) {
164
+ endMinutes = endHour * 60;
165
+ }
166
+ const duration = endMinutes - startMinutes;
167
+
168
+ const top =
169
+ ((startMinutes - startHour * 60) / 60) * HOUR_HEIGHT + 1;
170
+ const height = (duration / 60) * HOUR_HEIGHT - 3;
171
+
172
+ const indexInGroup = group.indexOf(event);
173
+ const totalInGroup = group.length;
174
+ const eventWidth = `${100 / totalInGroup - 1}%`;
175
+ const left = `${(100 / totalInGroup) * indexInGroup}%`;
176
+
177
+ const layout: TimelineEventLayout = {
178
+ top,
179
+ height: Math.max(height, 20),
180
+ left,
181
+ width: eventWidth,
182
+ };
183
+
184
+ return (
185
+ <View
186
+ key={keyExtractor(event)}
187
+ style={{
188
+ position: "absolute",
189
+ top: layout.top,
190
+ height: layout.height,
191
+ left: layout.left as unknown as number,
192
+ width: layout.width as unknown as number,
193
+ }}
194
+ >
195
+ {renderEvent(event, layout)}
196
+ </View>
197
+ );
198
+ }),
199
+ )}
200
+ </View>
201
+ </View>
202
+ </ScrollView>
203
+ );
204
+ }
@@ -0,0 +1,6 @@
1
+ export { CalendarTimeline } from "./calendar-timeline";
2
+ export type {
3
+ CalendarTimelineProps,
4
+ TimelineEventLayout,
5
+ } from "./calendar-timeline";
6
+ export type { TimelineStyles } from "./types";
@@ -0,0 +1,13 @@
1
+ import type { StyleProp, TextStyle, ViewStyle } from "react-native";
2
+
3
+ export interface TimelineStyles {
4
+ container?: StyleProp<ViewStyle>;
5
+ timeline?: StyleProp<ViewStyle>;
6
+ timeColumn?: StyleProp<ViewStyle>;
7
+ timeSlot?: StyleProp<ViewStyle>;
8
+ timeText?: StyleProp<TextStyle>;
9
+ eventsColumn?: StyleProp<ViewStyle>;
10
+ hourLine?: StyleProp<ViewStyle>;
11
+ currentTimeDot?: StyleProp<ViewStyle>;
12
+ currentTimeLineBar?: StyleProp<ViewStyle>;
13
+ }