@lazerlen/legend-calendar 1.1.1 → 1.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazerlen/legend-calendar",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "private": false,
5
5
  "description": "A better calendar for React Native.",
6
6
  "repository": {
@@ -36,7 +36,7 @@ const styles = StyleSheet.create({
36
36
  export type DayState = "idle" | "active" | "today" | "disabled";
37
37
 
38
38
  interface DayTheme {
39
- container: Omit<ViewStyle, "borderRadius">;
39
+ container: ViewStyle;
40
40
  content: TextStyle;
41
41
  }
42
42
  type CalendarItemDayTheme = Record<
@@ -57,7 +57,7 @@ const buildBaseStyles = (theme: BaseTheme): CalendarItemDayTheme => {
57
57
  };
58
58
 
59
59
  return {
60
- active: ({ isPressed, isHovered, isStartOfRange, isEndOfRange }) => {
60
+ active: ({ isPressed, isHovered }) => {
61
61
  const baseStyles: DayTheme & { container: ViewStyle } =
62
62
  isPressed || isHovered
63
63
  ? {
@@ -81,18 +81,6 @@ const buildBaseStyles = (theme: BaseTheme): CalendarItemDayTheme => {
81
81
  },
82
82
  };
83
83
 
84
- baseStyles.container.borderRadius = 0;
85
- if (isStartOfRange) {
86
- baseStyles.container.borderTopLeftRadius = 16;
87
- baseStyles.container.borderBottomLeftRadius = 16;
88
- }
89
- if (isEndOfRange) {
90
- baseStyles.container.borderTopRightRadius = 16;
91
- baseStyles.container.borderBottomRightRadius = 16;
92
- }
93
- if (!isStartOfRange && !isEndOfRange) {
94
- baseStyles.container.borderRadius = 0;
95
- }
96
84
  return baseStyles;
97
85
  },
98
86
  disabled: () => ({
@@ -206,12 +194,74 @@ export const CalendarItemDay = memo(function CalendarItemDay({
206
194
  isStartOfRange: metadata.isStartOfRange ?? false,
207
195
  };
208
196
  const { container } = baseStyles[metadata.state](params);
209
- return {
197
+ const baseThemeContainer = theme?.base?.({ ...metadata, isPressed })
198
+ .container as ViewStyle | undefined;
199
+ const stateThemeContainer = theme?.[metadata.state]?.({
200
+ ...metadata,
201
+ isPressed,
202
+ }).container as ViewStyle | undefined;
203
+ const mergedContainer: ViewStyle = {
210
204
  ...container,
211
205
  height,
212
- ...theme?.base?.({ ...metadata, isPressed }).container,
213
- ...theme?.[metadata.state]?.({ ...metadata, isPressed }).container,
206
+ ...baseThemeContainer,
207
+ ...stateThemeContainer,
214
208
  };
209
+ if (metadata.state === "active") {
210
+ const hasCustomRadius =
211
+ baseThemeContainer?.borderRadius !== undefined ||
212
+ baseThemeContainer?.borderTopLeftRadius !== undefined ||
213
+ baseThemeContainer?.borderBottomLeftRadius !== undefined ||
214
+ baseThemeContainer?.borderTopRightRadius !== undefined ||
215
+ baseThemeContainer?.borderBottomRightRadius !== undefined ||
216
+ stateThemeContainer?.borderRadius !== undefined ||
217
+ stateThemeContainer?.borderTopLeftRadius !== undefined ||
218
+ stateThemeContainer?.borderBottomLeftRadius !== undefined ||
219
+ stateThemeContainer?.borderTopRightRadius !== undefined ||
220
+ stateThemeContainer?.borderBottomRightRadius !== undefined;
221
+
222
+ if (!hasCustomRadius) {
223
+ const defaultRadius = styles.baseContainer.borderRadius ?? 0;
224
+ mergedContainer.borderRadius = 0;
225
+ if (metadata.isStartOfRange) {
226
+ mergedContainer.borderTopLeftRadius = defaultRadius;
227
+ mergedContainer.borderBottomLeftRadius = defaultRadius;
228
+ }
229
+ if (metadata.isEndOfRange) {
230
+ mergedContainer.borderTopRightRadius = defaultRadius;
231
+ mergedContainer.borderBottomRightRadius = defaultRadius;
232
+ }
233
+ if (!metadata.isStartOfRange && !metadata.isEndOfRange) {
234
+ mergedContainer.borderRadius = 0;
235
+ }
236
+ } else if (mergedContainer.borderRadius !== undefined) {
237
+ const radius = mergedContainer.borderRadius;
238
+ if (
239
+ metadata.isStartOfRange &&
240
+ mergedContainer.borderTopLeftRadius === undefined
241
+ ) {
242
+ mergedContainer.borderTopLeftRadius = radius;
243
+ }
244
+ if (
245
+ metadata.isStartOfRange &&
246
+ mergedContainer.borderBottomLeftRadius === undefined
247
+ ) {
248
+ mergedContainer.borderBottomLeftRadius = radius;
249
+ }
250
+ if (
251
+ metadata.isEndOfRange &&
252
+ mergedContainer.borderTopRightRadius === undefined
253
+ ) {
254
+ mergedContainer.borderTopRightRadius = radius;
255
+ }
256
+ if (
257
+ metadata.isEndOfRange &&
258
+ mergedContainer.borderBottomRightRadius === undefined
259
+ ) {
260
+ mergedContainer.borderBottomRightRadius = radius;
261
+ }
262
+ }
263
+ }
264
+ return mergedContainer;
215
265
  }}
216
266
  >
217
267
  {({ pressed: isPressed, hovered: isHovered, focused: isFocused }) => {
@@ -250,7 +300,7 @@ export const CalendarItemDay = memo(function CalendarItemDay({
250
300
  interface CalendarItemDayContainerTheme {
251
301
  /** An empty view that acts as a spacer between each day. The spacing is
252
302
  * controlled by the `daySpacing` prop. */
253
- spacer?: ViewStyle;
303
+ spacer?: ViewStyle | ((params: CalendarDayMetadata) => ViewStyle);
254
304
  /** An absolute positioned filler to join the active days together in a single
255
305
  * complete range. */
256
306
  activeDayFiller?: ViewStyle | ((params: CalendarDayMetadata) => ViewStyle);
@@ -285,12 +335,16 @@ export const CalendarItemDayContainer = memo(function CalendarItemDayContainer({
285
335
  metadata,
286
336
  }: CalendarItemDayContainerProps) {
287
337
  const baseTheme = useTheme();
338
+ const spacerTheme =
339
+ typeof theme?.spacer === "function" && metadata
340
+ ? theme.spacer(metadata)
341
+ : theme?.spacer;
288
342
  const spacerStyles: ViewStyle = {
289
343
  position: "relative",
290
344
  marginLeft: isStartOfWeek ? 0 : daySpacing,
291
345
  flex: 1,
292
346
  height: dayHeight,
293
- ...theme?.spacer,
347
+ ...(spacerTheme ?? {}),
294
348
  };
295
349
 
296
350
  const activeDayFiller: ViewStyle | null = !shouldShowActiveDayFiller
@@ -3,7 +3,7 @@ import {
3
3
  type LegendListProps,
4
4
  type LegendListRef,
5
5
  } from "@legendapp/list/react-native";
6
- import { memo, useEffect, useImperativeHandle, useRef } from "react";
6
+ import { useEffect, useImperativeHandle, useRef } from "react";
7
7
  import { StyleSheet, View } from "react-native";
8
8
 
9
9
  import type { CalendarProps } from "@/components/Calendar";
@@ -106,7 +106,7 @@ export interface CalendarListRef {
106
106
  scrollToOffset: (offset: number, animated: boolean) => void;
107
107
  }
108
108
 
109
- export const CalendarList = memo(function CalendarList({
109
+ export function CalendarList({
110
110
  ref,
111
111
  ...props
112
112
  }: CalendarListProps & { ref?: React.Ref<CalendarListRef> }) {
@@ -292,21 +292,40 @@ export const CalendarList = memo(function CalendarList({
292
292
 
293
293
  const calendarContainerStyle = { paddingBottom: calendarSpacing };
294
294
 
295
+ const getFixedItemSize = (item: CalendarMonthEnhanced) => {
296
+ return getHeightForMonth({
297
+ calendarMonth: item,
298
+ calendarSpacing,
299
+ calendarDayHeight,
300
+ calendarMonthHeaderHeight,
301
+ calendarRowVerticalSpacing,
302
+ calendarWeekHeaderHeight,
303
+ calendarAdditionalHeight,
304
+ });
305
+ };
306
+
295
307
  const handleRenderItem = ({ item }: { item: CalendarMonthEnhanced }) => (
296
308
  <View style={calendarContainerStyle}>
297
309
  <Calendar calendarMonthId={item.id} {...item.calendarProps} />
298
310
  </View>
299
311
  );
300
312
 
313
+ // Uncertain why but passing this as a no op resolved blanking issues after adding
314
+ // getFixedItemSize + recycleItems
315
+ const handleViewableItemsChanged = () => {};
316
+
301
317
  return (
302
318
  <LegendList
303
319
  data={monthListWithCalendarProps}
320
+ drawDistance={560}
304
321
  estimatedItemSize={273}
322
+ getFixedItemSize={getFixedItemSize}
305
323
  initialScrollIndex={initialMonthIndex}
306
324
  keyExtractor={keyExtractor}
307
325
  maintainVisibleContentPosition
308
326
  onEndReached={handleOnEndReached}
309
327
  onStartReached={handleOnStartReached}
328
+ onViewableItemsChanged={handleViewableItemsChanged}
310
329
  recycleItems
311
330
  ref={legendListRef}
312
331
  renderItem={handleRenderItem}
@@ -315,7 +334,7 @@ export const CalendarList = memo(function CalendarList({
315
334
  {...flatListProps}
316
335
  />
317
336
  );
318
- });
337
+ }
319
338
 
320
339
  const styles = StyleSheet.create({
321
340
  container: {