@lafarmer28/densitycalendarnative 0.1.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 (90) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +37 -0
  3. package/lib/module/components/density-calendar/context/ks-density-calendar-context.js +5 -0
  4. package/lib/module/components/density-calendar/context/ks-density-calendar-context.js.map +1 -0
  5. package/lib/module/components/density-calendar/context/ks-density-calendar-provider.js +68 -0
  6. package/lib/module/components/density-calendar/context/ks-density-calendar-provider.js.map +1 -0
  7. package/lib/module/components/density-calendar/context/use-ks-density-calendar-context.js +12 -0
  8. package/lib/module/components/density-calendar/context/use-ks-density-calendar-context.js.map +1 -0
  9. package/lib/module/components/density-calendar/day-view/day-navigation.js +172 -0
  10. package/lib/module/components/density-calendar/day-view/day-navigation.js.map +1 -0
  11. package/lib/module/components/density-calendar/day-view/ks-density-calendar-day-view.js +183 -0
  12. package/lib/module/components/density-calendar/day-view/ks-density-calendar-day-view.js.map +1 -0
  13. package/lib/module/components/density-calendar/ks-density-calendar-root.js +201 -0
  14. package/lib/module/components/density-calendar/ks-density-calendar-root.js.map +1 -0
  15. package/lib/module/components/density-calendar/ks-density-calendar.js +24 -0
  16. package/lib/module/components/density-calendar/ks-density-calendar.js.map +1 -0
  17. package/lib/module/components/density-calendar/ks-error-popup/ks-error-tooltip.js +74 -0
  18. package/lib/module/components/density-calendar/ks-error-popup/ks-error-tooltip.js.map +1 -0
  19. package/lib/module/components/density-calendar/ks-slider/ks-slider.js +174 -0
  20. package/lib/module/components/density-calendar/ks-slider/ks-slider.js.map +1 -0
  21. package/lib/module/components/density-calendar/ks-toggler/ks-toggler.js +72 -0
  22. package/lib/module/components/density-calendar/ks-toggler/ks-toggler.js.map +1 -0
  23. package/lib/module/components/density-calendar/month-view/days-of-week.js +51 -0
  24. package/lib/module/components/density-calendar/month-view/days-of-week.js.map +1 -0
  25. package/lib/module/components/density-calendar/month-view/ks-density-calendar-month-view.js +212 -0
  26. package/lib/module/components/density-calendar/month-view/ks-density-calendar-month-view.js.map +1 -0
  27. package/lib/module/components/density-calendar/month-view/top-navigation.js +118 -0
  28. package/lib/module/components/density-calendar/month-view/top-navigation.js.map +1 -0
  29. package/lib/module/components/density-calendar/utility-functions.js +50 -0
  30. package/lib/module/components/density-calendar/utility-functions.js.map +1 -0
  31. package/lib/module/components/density-calendar/week-view/ks-density-calendar-week-view.js +152 -0
  32. package/lib/module/components/density-calendar/week-view/ks-density-calendar-week-view.js.map +1 -0
  33. package/lib/module/components/density-calendar/week-view/top.js +53 -0
  34. package/lib/module/components/density-calendar/week-view/top.js.map +1 -0
  35. package/lib/module/index.js +4 -0
  36. package/lib/module/index.js.map +1 -0
  37. package/lib/module/package.json +1 -0
  38. package/lib/typescript/package.json +1 -0
  39. package/lib/typescript/src/components/density-calendar/context/ks-density-calendar-context.d.ts +17 -0
  40. package/lib/typescript/src/components/density-calendar/context/ks-density-calendar-context.d.ts.map +1 -0
  41. package/lib/typescript/src/components/density-calendar/context/ks-density-calendar-provider.d.ts +19 -0
  42. package/lib/typescript/src/components/density-calendar/context/ks-density-calendar-provider.d.ts.map +1 -0
  43. package/lib/typescript/src/components/density-calendar/context/use-ks-density-calendar-context.d.ts +2 -0
  44. package/lib/typescript/src/components/density-calendar/context/use-ks-density-calendar-context.d.ts.map +1 -0
  45. package/lib/typescript/src/components/density-calendar/day-view/day-navigation.d.ts +17 -0
  46. package/lib/typescript/src/components/density-calendar/day-view/day-navigation.d.ts.map +1 -0
  47. package/lib/typescript/src/components/density-calendar/day-view/ks-density-calendar-day-view.d.ts +21 -0
  48. package/lib/typescript/src/components/density-calendar/day-view/ks-density-calendar-day-view.d.ts.map +1 -0
  49. package/lib/typescript/src/components/density-calendar/ks-density-calendar-root.d.ts +14 -0
  50. package/lib/typescript/src/components/density-calendar/ks-density-calendar-root.d.ts.map +1 -0
  51. package/lib/typescript/src/components/density-calendar/ks-density-calendar.d.ts +43 -0
  52. package/lib/typescript/src/components/density-calendar/ks-density-calendar.d.ts.map +1 -0
  53. package/lib/typescript/src/components/density-calendar/ks-error-popup/ks-error-tooltip.d.ts +8 -0
  54. package/lib/typescript/src/components/density-calendar/ks-error-popup/ks-error-tooltip.d.ts.map +1 -0
  55. package/lib/typescript/src/components/density-calendar/ks-slider/ks-slider.d.ts +8 -0
  56. package/lib/typescript/src/components/density-calendar/ks-slider/ks-slider.d.ts.map +1 -0
  57. package/lib/typescript/src/components/density-calendar/ks-toggler/ks-toggler.d.ts +3 -0
  58. package/lib/typescript/src/components/density-calendar/ks-toggler/ks-toggler.d.ts.map +1 -0
  59. package/lib/typescript/src/components/density-calendar/month-view/days-of-week.d.ts +3 -0
  60. package/lib/typescript/src/components/density-calendar/month-view/days-of-week.d.ts.map +1 -0
  61. package/lib/typescript/src/components/density-calendar/month-view/ks-density-calendar-month-view.d.ts +17 -0
  62. package/lib/typescript/src/components/density-calendar/month-view/ks-density-calendar-month-view.d.ts.map +1 -0
  63. package/lib/typescript/src/components/density-calendar/month-view/top-navigation.d.ts +11 -0
  64. package/lib/typescript/src/components/density-calendar/month-view/top-navigation.d.ts.map +1 -0
  65. package/lib/typescript/src/components/density-calendar/utility-functions.d.ts +9 -0
  66. package/lib/typescript/src/components/density-calendar/utility-functions.d.ts.map +1 -0
  67. package/lib/typescript/src/components/density-calendar/week-view/ks-density-calendar-week-view.d.ts +12 -0
  68. package/lib/typescript/src/components/density-calendar/week-view/ks-density-calendar-week-view.d.ts.map +1 -0
  69. package/lib/typescript/src/components/density-calendar/week-view/top.d.ts +6 -0
  70. package/lib/typescript/src/components/density-calendar/week-view/top.d.ts.map +1 -0
  71. package/lib/typescript/src/index.d.ts +2 -0
  72. package/lib/typescript/src/index.d.ts.map +1 -0
  73. package/package.json +166 -0
  74. package/src/components/density-calendar/context/ks-density-calendar-context.tsx +23 -0
  75. package/src/components/density-calendar/context/ks-density-calendar-provider.tsx +96 -0
  76. package/src/components/density-calendar/context/use-ks-density-calendar-context.tsx +15 -0
  77. package/src/components/density-calendar/day-view/day-navigation.tsx +199 -0
  78. package/src/components/density-calendar/day-view/ks-density-calendar-day-view.tsx +245 -0
  79. package/src/components/density-calendar/ks-density-calendar-root.tsx +215 -0
  80. package/src/components/density-calendar/ks-density-calendar.tsx +74 -0
  81. package/src/components/density-calendar/ks-error-popup/ks-error-tooltip.tsx +71 -0
  82. package/src/components/density-calendar/ks-slider/ks-slider.tsx +185 -0
  83. package/src/components/density-calendar/ks-toggler/ks-toggler.tsx +69 -0
  84. package/src/components/density-calendar/month-view/days-of-week.tsx +47 -0
  85. package/src/components/density-calendar/month-view/ks-density-calendar-month-view.tsx +289 -0
  86. package/src/components/density-calendar/month-view/top-navigation.tsx +137 -0
  87. package/src/components/density-calendar/utility-functions.ts +67 -0
  88. package/src/components/density-calendar/week-view/ks-density-calendar-week-view.tsx +189 -0
  89. package/src/components/density-calendar/week-view/top.tsx +54 -0
  90. package/src/index.tsx +1 -0
@@ -0,0 +1,289 @@
1
+ import { useMemo } from 'react';
2
+ import {
3
+ StyleSheet,
4
+ View,
5
+ Text,
6
+ Pressable,
7
+ ScrollView,
8
+ useWindowDimensions,
9
+ DimensionValue,
10
+ } from 'react-native';
11
+ import {
12
+ format,
13
+ subDays,
14
+ addDays,
15
+ startOfMonth,
16
+ endOfMonth,
17
+ getDaysInMonth,
18
+ eachDayOfInterval,
19
+ isToday,
20
+ isSameMonth,
21
+ } from 'date-fns';
22
+
23
+ import KSSlider from '../ks-slider/ks-slider';
24
+ import { useKSDensityCalendar } from '../context/use-ks-density-calendar-context';
25
+ import {
26
+ type KSDensityCalendarEventType,
27
+ type ThemeKeyProps,
28
+ } from '../ks-density-calendar';
29
+ import { getColorForPercentage, type UsedNames } from '../utility-functions';
30
+ import DaysOfWeek from './days-of-week';
31
+ import TopNavigation from './top-navigation';
32
+ import { type SVGProps } from '../ks-density-calendar-root';
33
+
34
+ type KSDensityCalendarMonthProps = {
35
+ displayDate: Date;
36
+ toDayHandler: (dt: Date) => void;
37
+ multScheduleData: KSDensityCalendarEventType[];
38
+ handlePrevious: () => void;
39
+ handleNext: () => void;
40
+ handleToday: () => void;
41
+ calendarDisplay: string;
42
+ themeKeys: ThemeKeyProps['themeKeys'];
43
+ } & SVGProps;
44
+
45
+ export const GetDaysOfMonthWithinIntersection = (
46
+ displayDateStart: Date,
47
+ displayDateEnd: Date,
48
+ start: Date,
49
+ end: Date
50
+ ) => {
51
+ const s = start < displayDateStart ? displayDateStart : start;
52
+ const e = end > displayDateEnd ? displayDateEnd : end;
53
+ try {
54
+ const daysWithinInterval = eachDayOfInterval({ start: s, end: e });
55
+ return daysWithinInterval.map((dt: Date) => dt.getDate());
56
+ } catch {
57
+ return [];
58
+ }
59
+ };
60
+
61
+ export const CalcDayPercents = (
62
+ dt: Date,
63
+ data: KSDensityCalendarEventType[]
64
+ ) => {
65
+ const daysInMonth = getDaysInMonth(dt);
66
+ const ret = new Array(daysInMonth).fill(0);
67
+ const usedNames: UsedNames = {};
68
+ const displayDateStart = startOfMonth(dt);
69
+ const displayDateEnd = endOfMonth(dt);
70
+
71
+ data.forEach((item) => {
72
+ if (item.start > displayDateEnd || item.end < displayDateStart) return;
73
+
74
+ const intersection = GetDaysOfMonthWithinIntersection(
75
+ displayDateStart,
76
+ displayDateEnd,
77
+ item.start,
78
+ item.end
79
+ );
80
+
81
+ intersection.forEach((day) => {
82
+ if (!usedNames[item.name]) {
83
+ usedNames[item.name] = new Array(daysInMonth).fill(0);
84
+ }
85
+
86
+ const nameSchedule = usedNames[item.name];
87
+
88
+ if (nameSchedule && nameSchedule[day - 1] === 0) {
89
+ nameSchedule[day - 1] = 1;
90
+ ret[day - 1] += 1;
91
+ }
92
+ });
93
+ });
94
+
95
+ const totalNames = Object.keys(usedNames).length;
96
+ if (totalNames > 0) {
97
+ for (let j = 0; j < ret.length; j++) {
98
+ ret[j] = Math.round((ret[j] / totalNames) * 100);
99
+ }
100
+ }
101
+ return ret;
102
+ };
103
+
104
+ const KSDensityCalendarMonthView = ({
105
+ displayDate,
106
+ toDayHandler,
107
+ multScheduleData,
108
+ handlePrevious,
109
+ handleNext,
110
+ handleToday,
111
+ calendarDisplay,
112
+ themeKeys,
113
+ svgIconColor,
114
+ svgIconSize,
115
+ svgIconUnactiveColor,
116
+ }: KSDensityCalendarMonthProps) => {
117
+ const { state } = useKSDensityCalendar();
118
+ const { toggleKSSlider, minVal, maxVal } = state;
119
+ const { height, width: windowWidth } = useWindowDimensions();
120
+ const isLandscape = windowWidth > height;
121
+
122
+ const firstDayOfMonth = startOfMonth(displayDate);
123
+ const firstDayOfWeek = firstDayOfMonth.getDay();
124
+
125
+ const percentsForDayOfMonth = useMemo(
126
+ () => CalcDayPercents(displayDate, multScheduleData),
127
+ [displayDate, multScheduleData]
128
+ );
129
+
130
+ const cells = Array.from({ length: 42 }, (_, index) => {
131
+ let date: Date;
132
+ if (index < firstDayOfWeek) {
133
+ date = subDays(firstDayOfMonth, firstDayOfWeek - index);
134
+ } else {
135
+ date = addDays(firstDayOfMonth, index - firstDayOfWeek);
136
+ }
137
+
138
+ const isCurrentMonth = isSameMonth(date, displayDate);
139
+ const rawPercent = isCurrentMonth
140
+ ? percentsForDayOfMonth[date.getDate() - 1]
141
+ : 0;
142
+
143
+ const percentValue =
144
+ (minVal === 0 && maxVal === 100) ||
145
+ (rawPercent >= minVal && rawPercent <= maxVal)
146
+ ? rawPercent
147
+ : 0;
148
+
149
+ const color = getColorForPercentage(percentValue);
150
+ const barWidth =
151
+ percentValue <= 33 ? '30%' : percentValue <= 66 ? '50%' : '80%';
152
+ const barHeight = percentValue > 0 ? `${percentValue}%` : '0%';
153
+
154
+ const cellStyle = [
155
+ styles.dateCell,
156
+ {
157
+ borderColor: isCurrentMonth
158
+ ? themeKeys.secondaryColor
159
+ : themeKeys.secondaryColorPnt3,
160
+ height: isLandscape ? height * 0.12 : height * 0.08,
161
+ },
162
+ ];
163
+
164
+ const textStyle = isToday(date)
165
+ ? isCurrentMonth
166
+ ? styles.todayCurrentMonth
167
+ : styles.todayNonCurrentMonth
168
+ : isCurrentMonth
169
+ ? { color: themeKeys.secondaryColor }
170
+ : { color: themeKeys.secondaryColorPnt3 };
171
+
172
+ return (
173
+ <Pressable
174
+ key={index}
175
+ style={cellStyle}
176
+ onPress={() => isCurrentMonth && percentValue > 0 && toDayHandler(date)}
177
+ >
178
+ <View style={styles.cellHeader}>
179
+ <Text style={[styles.dateText, textStyle]}>{format(date, 'd')}</Text>
180
+ </View>
181
+
182
+ {isCurrentMonth && (
183
+ <View style={styles.percentageContainer}>
184
+ {percentValue > 0 && (
185
+ <Text
186
+ style={[
187
+ styles.percentLabel,
188
+ { color: themeKeys.secondaryColor },
189
+ ]}
190
+ >
191
+ {percentValue}%
192
+ </Text>
193
+ )}
194
+ <View style={styles.barTrack}>
195
+ <View
196
+ style={[
197
+ styles.percentageBar,
198
+ {
199
+ backgroundColor: color,
200
+ // Cast both as DimensionValue to satisfy TypeScript
201
+ width: barWidth as DimensionValue,
202
+ height: barHeight as DimensionValue,
203
+ },
204
+ ]}
205
+ />
206
+ </View>
207
+ </View>
208
+ )}
209
+ </Pressable>
210
+ );
211
+ });
212
+
213
+ return (
214
+ <View style={styles.container}>
215
+ <TopNavigation
216
+ handlePrevious={handlePrevious}
217
+ handleNext={handleNext}
218
+ handleToday={handleToday}
219
+ displayDate={displayDate}
220
+ themeKeys={themeKeys}
221
+ svgIconColor={svgIconColor}
222
+ svgIconSize={svgIconSize}
223
+ svgIconUnactiveColor={svgIconUnactiveColor}
224
+ />
225
+ <DaysOfWeek />
226
+ <ScrollView contentContainerStyle={styles.monthGrid}>{cells}</ScrollView>
227
+ {toggleKSSlider && (
228
+ <View style={styles.sliderWrapper}>
229
+ <KSSlider calendarDisplay={calendarDisplay} themeKeys={themeKeys} />
230
+ </View>
231
+ )}
232
+ </View>
233
+ );
234
+ };
235
+
236
+ const styles = StyleSheet.create({
237
+ container: {
238
+ flex: 1,
239
+ width: '100%',
240
+ },
241
+ monthGrid: {
242
+ flexDirection: 'row',
243
+ flexWrap: 'wrap',
244
+ paddingHorizontal: 8,
245
+ },
246
+ dateCell: {
247
+ width: '14.28%',
248
+ borderWidth: 0.5,
249
+ padding: 2,
250
+ justifyContent: 'space-between',
251
+ },
252
+ cellHeader: {
253
+ alignSelf: 'flex-start',
254
+ },
255
+ dateText: {
256
+ fontSize: 12,
257
+ },
258
+ todayCurrentMonth: {
259
+ color: 'rgba(137, 28, 28, 1)',
260
+ fontWeight: 'bold',
261
+ },
262
+ todayNonCurrentMonth: {
263
+ color: 'rgba(137, 28, 28, 0.4)',
264
+ },
265
+ percentageContainer: {
266
+ flex: 1,
267
+ justifyContent: 'flex-end',
268
+ alignItems: 'center',
269
+ },
270
+ percentLabel: {
271
+ fontSize: 8,
272
+ marginBottom: 2,
273
+ },
274
+ barTrack: {
275
+ width: '100%',
276
+ height: '60%',
277
+ justifyContent: 'flex-end',
278
+ alignItems: 'center',
279
+ },
280
+ percentageBar: {
281
+ borderRadius: 4,
282
+ },
283
+ sliderWrapper: {
284
+ paddingBottom: 20,
285
+ paddingHorizontal: 10,
286
+ },
287
+ });
288
+
289
+ export default KSDensityCalendarMonthView;
@@ -0,0 +1,137 @@
1
+ import { StyleSheet, View, Text, Pressable } from 'react-native';
2
+ import { MaterialIcons, MaterialCommunityIcons } from '@expo/vector-icons';
3
+ import { format } from 'date-fns';
4
+ import KSToggler from '../ks-toggler/ks-toggler';
5
+ import { type ThemeKeyProps } from '../ks-density-calendar';
6
+ import { type SVGProps } from '../ks-density-calendar-root';
7
+
8
+ type TopNavigationProps = {
9
+ handlePrevious: () => void;
10
+ displayDate: Date;
11
+ handleNext: () => void;
12
+ handleToday: () => void;
13
+ } & ThemeKeyProps &
14
+ SVGProps;
15
+
16
+ const TopNavigation = ({
17
+ handlePrevious,
18
+ displayDate,
19
+ handleNext,
20
+ handleToday,
21
+ svgIconColor,
22
+ svgIconSize,
23
+ svgIconUnactiveColor,
24
+ }: TopNavigationProps) => {
25
+ return (
26
+ <View style={styles.container}>
27
+ <View style={styles.headerRow}>
28
+ <Pressable
29
+ onPress={handlePrevious}
30
+ style={({ pressed }) => [
31
+ styles.iconButton,
32
+ pressed && styles.pressed,
33
+ ]}
34
+ >
35
+ <MaterialIcons
36
+ name="chevron-left"
37
+ size={svgIconSize + 10}
38
+ color={svgIconColor}
39
+ />
40
+ </Pressable>
41
+
42
+ <Text style={styles.titleText}>{format(displayDate, 'MMMM yyyy')}</Text>
43
+
44
+ <Pressable
45
+ onPress={handleNext}
46
+ style={({ pressed }) => [
47
+ styles.iconButton,
48
+ pressed && styles.pressed,
49
+ ]}
50
+ >
51
+ <MaterialIcons
52
+ name="chevron-right"
53
+ size={svgIconSize + 10}
54
+ color={svgIconColor}
55
+ />
56
+ </Pressable>
57
+ </View>
58
+
59
+ <View style={styles.controlsRow}>
60
+ <View style={styles.togglerContainer}>
61
+ <MaterialCommunityIcons
62
+ name="minus"
63
+ size={svgIconSize}
64
+ color={svgIconUnactiveColor || svgIconColor}
65
+ />
66
+ <View style={styles.togglerWrapper}>
67
+ <KSToggler />
68
+ </View>
69
+ <MaterialCommunityIcons
70
+ name="plus"
71
+ size={svgIconSize}
72
+ color={svgIconUnactiveColor || svgIconColor}
73
+ />
74
+ </View>
75
+
76
+ <Pressable
77
+ onPress={handleToday}
78
+ style={({ pressed }) => [
79
+ styles.iconButton,
80
+ pressed && styles.pressed,
81
+ ]}
82
+ >
83
+ <MaterialCommunityIcons
84
+ name="calendar-today"
85
+ size={svgIconSize}
86
+ color={svgIconColor}
87
+ />
88
+ </Pressable>
89
+ </View>
90
+ </View>
91
+ );
92
+ };
93
+
94
+ const styles = StyleSheet.create({
95
+ container: {
96
+ width: '100%',
97
+ paddingHorizontal: 8,
98
+ paddingVertical: 12,
99
+ },
100
+ headerRow: {
101
+ flexDirection: 'row',
102
+ alignItems: 'center',
103
+ justifyContent: 'center',
104
+ width: '100%',
105
+ marginBottom: 10,
106
+ },
107
+ titleText: {
108
+ fontSize: 24,
109
+ fontWeight: '600',
110
+ textAlign: 'center',
111
+ minWidth: '50%',
112
+ },
113
+ controlsRow: {
114
+ flexDirection: 'row',
115
+ alignItems: 'center',
116
+ justifyContent: 'center',
117
+ width: '100%',
118
+ },
119
+ togglerContainer: {
120
+ flexDirection: 'row',
121
+ alignItems: 'center',
122
+ marginRight: 15,
123
+ },
124
+ togglerWrapper: {
125
+ marginHorizontal: 8,
126
+ },
127
+ iconButton: {
128
+ padding: 6,
129
+ justifyContent: 'center',
130
+ alignItems: 'center',
131
+ },
132
+ pressed: {
133
+ opacity: 0.6,
134
+ },
135
+ });
136
+
137
+ export default TopNavigation;
@@ -0,0 +1,67 @@
1
+ import { eachDayOfInterval } from 'date-fns';
2
+ import type { KSDensityCalendarEventType } from './ks-density-calendar';
3
+
4
+ export interface UsedNames {
5
+ [name: string]: number[];
6
+ }
7
+
8
+ export const firstDateOfWeek: Date = new Date(2023, 0, 1);
9
+
10
+ const colorList: string[] = Array.from({ length: 100 }, (_, i) => {
11
+ const step = i + 1;
12
+ const r = 51 + Math.floor(step * 2.04);
13
+ const a = ((step - 1) / 99) * 0.5 + 0.5;
14
+ return `rgba(${r}, 0, 0, ${a.toFixed(1)})`;
15
+ });
16
+
17
+ export const getColorForPercentage = (percentage: number): string => {
18
+ if (percentage <= 0) return 'transparent';
19
+ const index = Math.min(Math.max(percentage - 1, 0), 99);
20
+ return colorList[index] || 'transparent';
21
+ };
22
+
23
+ export const getDaysOfWeekWithinIntersection = (
24
+ start: Date,
25
+ end: Date
26
+ ): number[] => {
27
+ const daysWithinInterval = eachDayOfInterval({ start, end });
28
+ return daysWithinInterval.map((dt) => dt.getDay());
29
+ };
30
+
31
+ export const calcWeekPercents = (
32
+ data: KSDensityCalendarEventType[]
33
+ ): number[] => {
34
+ const ret = new Array(7).fill(0);
35
+ const usedNames: UsedNames = {};
36
+
37
+ for (const item of data) {
38
+ if (!item) continue;
39
+
40
+ const daysOfWeekWithinIntersection = getDaysOfWeekWithinIntersection(
41
+ item.start,
42
+ item.end
43
+ );
44
+
45
+ daysOfWeekWithinIntersection.forEach((itemDayOfWeek) => {
46
+ if (!usedNames[item.name]) {
47
+ usedNames[item.name] = new Array(7).fill(0);
48
+ }
49
+
50
+ const currentNameData = usedNames[item.name]!;
51
+
52
+ if (currentNameData[itemDayOfWeek] === 0) {
53
+ currentNameData[itemDayOfWeek] = 1;
54
+ ret[itemDayOfWeek] += 1;
55
+ }
56
+ });
57
+ }
58
+
59
+ const totalNames = Object.keys(usedNames).length;
60
+ if (totalNames > 0) {
61
+ for (let j = 0; j < ret.length; j++) {
62
+ ret[j] = Math.round((ret[j] / totalNames) * 100);
63
+ }
64
+ }
65
+
66
+ return ret;
67
+ };
@@ -0,0 +1,189 @@
1
+ import {
2
+ StyleSheet,
3
+ View,
4
+ Text,
5
+ Pressable,
6
+ ViewStyle,
7
+ DimensionValue,
8
+ } from 'react-native';
9
+ import {
10
+ type KSDensityCalendarEventType,
11
+ type ThemeKeyProps,
12
+ } from '../ks-density-calendar';
13
+ import { type KSOptionalProps } from '../ks-density-calendar';
14
+ import { type SVGProps } from '../ks-density-calendar-root';
15
+ import { useKSDensityCalendar } from '../context/use-ks-density-calendar-context';
16
+ import {
17
+ getColorForPercentage,
18
+ firstDateOfWeek,
19
+ calcWeekPercents,
20
+ } from '../utility-functions';
21
+ import Top from './top';
22
+ import KSSlider from '../ks-slider/ks-slider';
23
+
24
+ type KSDensityCalendarWeekProps = {
25
+ displayDate: Date;
26
+ toDayHandler: (dt: Date) => void;
27
+ multScheduleData: KSDensityCalendarEventType[];
28
+ calendarDisplay: string;
29
+ } & KSOptionalProps &
30
+ ThemeKeyProps &
31
+ SVGProps;
32
+
33
+ const KSDensityCalendarWeekView = ({
34
+ toDayHandler,
35
+ multScheduleData,
36
+ calendarDisplay,
37
+ themeKeys,
38
+ svgIconColor,
39
+ svgIconSize,
40
+ svgIconUnactiveColor,
41
+ }: KSDensityCalendarWeekProps) => {
42
+ const { daysOfWeek, state } = useKSDensityCalendar();
43
+
44
+ const percentsForDaysOfWeek: number[] = calcWeekPercents(multScheduleData);
45
+
46
+ return (
47
+ <View
48
+ style={[styles.container, !state.toggleKSSlider && styles.paddingBottom]}
49
+ >
50
+ <Top
51
+ themeKeys={themeKeys}
52
+ svgIconColor={svgIconColor}
53
+ svgIconSize={svgIconSize}
54
+ svgIconUnactiveColor={svgIconUnactiveColor}
55
+ />
56
+
57
+ <View style={styles.daysHeader}>
58
+ {Array.from({ length: 7 }, (_, index) => (
59
+ <View key={daysOfWeek[index] || index} style={styles.headerCell}>
60
+ <Text style={styles.headerText}>{daysOfWeek[index]}</Text>
61
+ </View>
62
+ ))}
63
+ </View>
64
+
65
+ <View style={styles.graphContainer}>
66
+ {percentsForDaysOfWeek.map((percentValue, index) => {
67
+ const showValue =
68
+ state.minVal === 0 && state.maxVal === 100
69
+ ? percentValue
70
+ : state.minVal <= percentValue && percentValue <= state.maxVal
71
+ ? percentValue
72
+ : 0;
73
+
74
+ const color = getColorForPercentage(percentValue);
75
+ const barWidth =
76
+ percentValue <= 33 ? '25%' : percentValue <= 66 ? '45%' : '65%';
77
+
78
+ const barStyle: ViewStyle = {
79
+ // Assign the type here
80
+ height: `${showValue}%` as DimensionValue, // Assert as DimensionValue
81
+ width: barWidth as DimensionValue, // Assert as DimensionValue
82
+ backgroundColor: showValue > 0 ? color : 'transparent',
83
+ borderTopLeftRadius: 10,
84
+ borderTopRightRadius: 10,
85
+ opacity: 0.6,
86
+ shadowColor: '#000',
87
+ shadowOffset: { width: 1, height: 0 },
88
+ shadowOpacity: showValue > 0 ? 0.3 : 0,
89
+ shadowRadius: 1,
90
+ };
91
+
92
+ const handlePress = () => {
93
+ if (showValue > 0) {
94
+ const dateValue = new Date(firstDateOfWeek);
95
+ dateValue.setDate(1 + index - firstDateOfWeek.getDay());
96
+ toDayHandler(dateValue);
97
+ }
98
+ };
99
+
100
+ return (
101
+ <Pressable
102
+ key={index}
103
+ onPress={handlePress}
104
+ style={[
105
+ styles.weekSegment,
106
+ index === 0 && styles.roundedLeft,
107
+ index === 6 && styles.roundedRight,
108
+ index === 6 && styles.borderRight,
109
+ ]}
110
+ >
111
+ <Text style={styles.percentText}>
112
+ {showValue > 0 ? `${showValue}%` : ''}
113
+ </Text>
114
+ <View style={barStyle} />
115
+ </Pressable>
116
+ );
117
+ })}
118
+ </View>
119
+
120
+ {state.toggleKSSlider && (
121
+ <View style={styles.sliderWrapper}>
122
+ <KSSlider calendarDisplay={calendarDisplay} themeKeys={themeKeys} />
123
+ </View>
124
+ )}
125
+ </View>
126
+ );
127
+ };
128
+
129
+ const styles = StyleSheet.create({
130
+ container: {
131
+ flex: 1,
132
+ width: '100%',
133
+ paddingHorizontal: 8,
134
+ },
135
+ paddingBottom: {
136
+ paddingBottom: 8,
137
+ },
138
+ daysHeader: {
139
+ flexDirection: 'row',
140
+ justifyContent: 'space-between',
141
+ width: '100%',
142
+ paddingVertical: 10,
143
+ },
144
+ headerCell: {
145
+ flex: 1,
146
+ alignItems: 'center',
147
+ },
148
+ headerText: {
149
+ fontSize: 14,
150
+ fontWeight: '500',
151
+ },
152
+ graphContainer: {
153
+ flex: 1,
154
+ flexDirection: 'row',
155
+ width: '100%',
156
+ alignItems: 'flex-end',
157
+ },
158
+ weekSegment: {
159
+ flex: 1,
160
+ height: '100%',
161
+ justifyContent: 'flex-end',
162
+ alignItems: 'center',
163
+ borderTopWidth: 1,
164
+ borderBottomWidth: 1,
165
+ borderLeftWidth: 1,
166
+ borderColor: 'rgba(254, 243, 200, 0.5)',
167
+ },
168
+ percentText: {
169
+ fontSize: 10,
170
+ marginBottom: 4,
171
+ },
172
+ roundedLeft: {
173
+ borderTopLeftRadius: 10,
174
+ borderBottomLeftRadius: 10,
175
+ },
176
+ roundedRight: {
177
+ borderTopRightRadius: 10,
178
+ borderBottomRightRadius: 10,
179
+ },
180
+ borderRight: {
181
+ borderRightWidth: 1,
182
+ },
183
+ sliderWrapper: {
184
+ width: '100%',
185
+ paddingVertical: 10,
186
+ },
187
+ });
188
+
189
+ export default KSDensityCalendarWeekView;