@super-calendar/native 2.5.0 → 2.6.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/dist/index.d.mts CHANGED
@@ -4,6 +4,53 @@ import { ComponentType, ReactElement } from "react";
4
4
  import { SharedValue, useSharedValue } from "react-native-reanimated";
5
5
  import { CalendarEvent as CalendarEvent$1, DateRange, DateSelectionConstraints, DaySelectionState, EventAccessibilityLabeler as EventAccessibilityLabeler$1, ICalEvent, MonthGrid, MonthGridDay, MonthGridWeek, MonthGridWeekday, PositionedEvent, ToICalendarOptions, UseDateRangeOptions, UseMonthGridOptions, WeekdayFormat as WeekdayFormat$1, buildMonthGrid, buildMonthWeeks, daySelectionState, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, minutesIntoDay, nextDateRange, parseICalendar, toICalendar, toZonedTime, useDateRange, useMonthGrid, weekdayFormatToken } from "@super-calendar/core";
6
6
  import { StyleProp, ViewStyle } from "react-native";
7
+ //#region src/components/YearView.d.ts
8
+ /**
9
+ * The styleable parts of {@link YearView}. `dayText` and `eventDot` are the
10
+ * text/marker inside a day cell (React Native text colour doesn't inherit).
11
+ */
12
+ type YearViewSlot = "grid" | "month" | "monthTitle" | "weekdays" | "weekday" | "week" | "day" | "dayText" | "eventDot";
13
+ /** Props for {@link YearView}, the twelve mini-month year grid. */
14
+ type YearViewProps<T = unknown> = SlotStyleProps<YearViewSlot> & {
15
+ /** Any date inside the year to render. */
16
+ date: Date;
17
+ /** Days holding at least one event get a dot. Omit for a plain year. */
18
+ events?: CalendarEvent<T>[];
19
+ weekStartsOn: WeekStartsOn;
20
+ locale?: Locale;
21
+ /** Highlight this date instead of the real "today". */
22
+ activeDate?: Date;
23
+ /**
24
+ * Smallest width a mini month may take before the grid drops a column
25
+ * (default 150). The grid fits 2–4 columns from the measured width.
26
+ */
27
+ minMonthWidth?: number;
28
+ /** Tap a day cell (e.g. to drill into the day or month view). */
29
+ onPressDay?: (date: Date) => void;
30
+ /** Tap a month's title (e.g. to jump to that month's view). */
31
+ onPressMonth?: (month: Date) => void;
32
+ };
33
+ declare function YearViewInner<T>({ date, events, weekStartsOn, locale, activeDate, minMonthWidth, onPressDay, onPressMonth, classNames, styles: styleOverrides }: YearViewProps<T>): ReactElement;
34
+ /**
35
+ * A year at a glance: the twelve months as compact mini grids, with today
36
+ * highlighted and a dot under days that hold events. Tap a day or a month
37
+ * title to drill into a denser view. It's the view `Calendar` renders for
38
+ * `mode="year"`.
39
+ *
40
+ * @example
41
+ * ```tsx
42
+ * import { YearView } from "@super-calendar/native";
43
+ *
44
+ * <YearView
45
+ * date={new Date()}
46
+ * events={events}
47
+ * weekStartsOn={1}
48
+ * onPressDay={(day) => console.log(day)}
49
+ * />
50
+ * ```
51
+ */
52
+ declare const YearView: typeof YearViewInner;
53
+ //#endregion
7
54
  //#region src/components/Agenda.d.ts
8
55
  /**
9
56
  * The styleable parts of {@link Agenda}. Mirrors the dom renderer's slot names;
@@ -182,7 +229,7 @@ declare const TimeGrid: typeof TimeGridInner;
182
229
  * month pager, the grid slots reach the time grid, and the agenda slots reach
183
230
  * the schedule view; slots for views that aren't rendered are ignored.
184
231
  */
185
- type CalendarSlot = MonthViewSlot | TimeGridSlot | AgendaSlot;
232
+ type CalendarSlot = MonthViewSlot | TimeGridSlot | AgendaSlot | YearViewSlot;
186
233
  /** Props for the {@link Calendar} component. */
187
234
  type CalendarProps<T> = SlotStyleProps<CalendarSlot> & {
188
235
  events: CalendarEvent<T>[];
@@ -217,8 +264,10 @@ type CalendarProps<T> = SlotStyleProps<CalendarSlot> & {
217
264
  * drag-to-move and drag-to-resize working while hiding the visible indicator.
218
265
  */
219
266
  showDragHandle?: boolean;
220
- /** Tap a day cell (month mode) — e.g. drill into the day view. */
267
+ /** Tap a day cell (month and year modes) — e.g. drill into the day view. */
221
268
  onPressDay?: (date: Date) => void;
269
+ /** Tap a month's title in the year view — e.g. jump to that month. */
270
+ onPressMonth?: (month: Date) => void;
222
271
  /** Long-press a day cell (month mode). */
223
272
  onLongPressDay?: (date: Date) => void;
224
273
  /** Tap the "+N more" overflow label in a month cell. */
@@ -397,7 +446,7 @@ type CalendarProps<T> = SlotStyleProps<CalendarSlot> & {
397
446
  * }
398
447
  * ```
399
448
  */
400
- declare function Calendar<T>({ events, mode, date, onChangeDate, onChangeDateRange, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, dragStepMinutes, showDragHandle, onPressDay, onLongPressDay, onPressMore, onPressCell, resetPageOnPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, maxVisibleEventCount, sortedMonthView, moreLabel, showAdjacentMonths, disableMonthEventCellPress, weekStartsOn, weekdayFormat, numberOfDays, weekEndsOn, renderEvent, eventAccessibilityLabel, eventCellStyle, calendarCellStyle, businessHours, keyExtractor, theme, cellHeight: cellHeightProp, hourHeight, minHourHeight, maxHourHeight, hourColumnWidth, hideHours, timeslots, showAllDayEventCell, showWeekNumber, weekNumberPrefix, hourComponent, showSixWeeks, swipeEnabled, showVerticalScrollIndicator, verticalScrollEnabled, headerComponent, minHour, maxHour, ampm, showTime, ellipsizeTitle, allDayLabel, scrollOffsetMinutes, showNowIndicator, locale, timeZone, activeDate, isRTL, freeSwipe, renderTimeGridHeader, renderHeaderForMonthView, renderCustomDateForMonth, itemSeparatorComponent, classNames, styles: styleOverrides }: CalendarProps<T>): ReactElement;
449
+ declare function Calendar<T>({ events, mode, date, onChangeDate, onChangeDateRange, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, dragStepMinutes, showDragHandle, onPressDay, onPressMonth, onLongPressDay, onPressMore, onPressCell, resetPageOnPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, maxVisibleEventCount, sortedMonthView, moreLabel, showAdjacentMonths, disableMonthEventCellPress, weekStartsOn, weekdayFormat, numberOfDays, weekEndsOn, renderEvent, eventAccessibilityLabel, eventCellStyle, calendarCellStyle, businessHours, keyExtractor, theme, cellHeight: cellHeightProp, hourHeight, minHourHeight, maxHourHeight, hourColumnWidth, hideHours, timeslots, showAllDayEventCell, showWeekNumber, weekNumberPrefix, hourComponent, showSixWeeks, swipeEnabled, showVerticalScrollIndicator, verticalScrollEnabled, headerComponent, minHour, maxHour, ampm, showTime, ellipsizeTitle, allDayLabel, scrollOffsetMinutes, showNowIndicator, locale, timeZone, activeDate, isRTL, freeSwipe, renderTimeGridHeader, renderHeaderForMonthView, renderCustomDateForMonth, itemSeparatorComponent, classNames, styles: styleOverrides }: CalendarProps<T>): ReactElement;
401
450
  //#endregion
402
451
  //#region src/components/DefaultEvent.d.ts
403
452
  /**
@@ -520,4 +569,4 @@ interface ResourceTimelineProps<T = unknown> {
520
569
  */
521
570
  declare function ResourceTimeline<T = unknown>({ date, orientation, resources, events, resourceId, startHour, endHour, hourWidth, hourHeight, rowHeight, labelWidth, ampm, renderEvent, onPressEvent, onLongPressEvent, onDragEvent, onPressCell, onLongPressCell, onCreateEvent, businessHours, dragStepMinutes }: ResourceTimelineProps<T>): ReactElement;
522
571
  //#endregion
523
- export { Agenda, type AgendaProps, type AgendaSlot, type BusinessHours, Calendar, type CalendarEvent, type CalendarMode, type CalendarProps, type CalendarSlot, type CalendarTheme, CalendarThemeProvider, DEFAULT_HOUR_HEIGHT, type DateRange, type DateSelectionConstraints, type DaySelectionState, DefaultEvent, DefaultMonthEvent, type EventAccessibilityLabelContext, type EventAccessibilityLabeler, type EventDragHandler, type EventDragStartHandler, type EventKeyExtractor, type HourRenderer, type ICalEvent, type ICalendarEvent, type MonthGrid, type MonthGridDay, type MonthGridWeek, type MonthGridWeekday, MonthList, type MonthListProps, type MonthListSlot, MonthPager, type MonthPagerProps, MonthView, type MonthViewProps, type MonthViewSlot, type PartialCalendarTheme, type PositionedEvent, type RecurrenceFrequency, type RecurrenceRule, type RenderEvent, type RenderEventArgs, type ResolvedSlot, type Resource, type ResourceEventArgs, ResourceTimeline, type ResourceTimelineProps, type SlotDefault, type SlotStyleProps, TimeGrid, type TimeGridMode, type TimeGridProps, type TimeGridSlot, type ToICalendarOptions, type UseDateRangeOptions, type UseMonthGridOptions, type WeekStartsOn, type WeekdayFormat, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, mergeTheme, minutesIntoDay, nextDateRange, parseICalendar, toICalendar, toZonedTime, useCalendarTheme, useDateRange, useMonthGrid, weekdayFormatToken };
572
+ export { Agenda, type AgendaProps, type AgendaSlot, type BusinessHours, Calendar, type CalendarEvent, type CalendarMode, type CalendarProps, type CalendarSlot, type CalendarTheme, CalendarThemeProvider, DEFAULT_HOUR_HEIGHT, type DateRange, type DateSelectionConstraints, type DaySelectionState, DefaultEvent, DefaultMonthEvent, type EventAccessibilityLabelContext, type EventAccessibilityLabeler, type EventDragHandler, type EventDragStartHandler, type EventKeyExtractor, type HourRenderer, type ICalEvent, type ICalendarEvent, type MonthGrid, type MonthGridDay, type MonthGridWeek, type MonthGridWeekday, MonthList, type MonthListProps, type MonthListSlot, MonthPager, type MonthPagerProps, MonthView, type MonthViewProps, type MonthViewSlot, type PartialCalendarTheme, type PositionedEvent, type RecurrenceFrequency, type RecurrenceRule, type RenderEvent, type RenderEventArgs, type ResolvedSlot, type Resource, type ResourceEventArgs, ResourceTimeline, type ResourceTimelineProps, type SlotDefault, type SlotStyleProps, TimeGrid, type TimeGridMode, type TimeGridProps, type TimeGridSlot, type ToICalendarOptions, type UseDateRangeOptions, type UseMonthGridOptions, type WeekStartsOn, type WeekdayFormat, YearView, type YearViewProps, type YearViewSlot, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, mergeTheme, minutesIntoDay, nextDateRange, parseICalendar, toICalendar, toZonedTime, useCalendarTheme, useDateRange, useMonthGrid, weekdayFormatToken };
package/dist/index.d.ts CHANGED
@@ -4,6 +4,53 @@ import { ComponentType, ReactElement } from "react";
4
4
  import { StyleProp, ViewStyle } from "react-native";
5
5
  import { SharedValue, useSharedValue } from "react-native-reanimated";
6
6
  import { CalendarEvent as CalendarEvent$1, DateRange, DateSelectionConstraints, DaySelectionState, EventAccessibilityLabeler as EventAccessibilityLabeler$1, ICalEvent, MonthGrid, MonthGridDay, MonthGridWeek, MonthGridWeekday, PositionedEvent, ToICalendarOptions, UseDateRangeOptions, UseMonthGridOptions, WeekdayFormat as WeekdayFormat$1, buildMonthGrid, buildMonthWeeks, daySelectionState, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, minutesIntoDay, nextDateRange, parseICalendar, toICalendar, toZonedTime, useDateRange, useMonthGrid, weekdayFormatToken } from "@super-calendar/core";
7
+ //#region src/components/YearView.d.ts
8
+ /**
9
+ * The styleable parts of {@link YearView}. `dayText` and `eventDot` are the
10
+ * text/marker inside a day cell (React Native text colour doesn't inherit).
11
+ */
12
+ type YearViewSlot = "grid" | "month" | "monthTitle" | "weekdays" | "weekday" | "week" | "day" | "dayText" | "eventDot";
13
+ /** Props for {@link YearView}, the twelve mini-month year grid. */
14
+ type YearViewProps<T = unknown> = SlotStyleProps<YearViewSlot> & {
15
+ /** Any date inside the year to render. */
16
+ date: Date;
17
+ /** Days holding at least one event get a dot. Omit for a plain year. */
18
+ events?: CalendarEvent<T>[];
19
+ weekStartsOn: WeekStartsOn;
20
+ locale?: Locale;
21
+ /** Highlight this date instead of the real "today". */
22
+ activeDate?: Date;
23
+ /**
24
+ * Smallest width a mini month may take before the grid drops a column
25
+ * (default 150). The grid fits 2–4 columns from the measured width.
26
+ */
27
+ minMonthWidth?: number;
28
+ /** Tap a day cell (e.g. to drill into the day or month view). */
29
+ onPressDay?: (date: Date) => void;
30
+ /** Tap a month's title (e.g. to jump to that month's view). */
31
+ onPressMonth?: (month: Date) => void;
32
+ };
33
+ declare function YearViewInner<T>({ date, events, weekStartsOn, locale, activeDate, minMonthWidth, onPressDay, onPressMonth, classNames, styles: styleOverrides }: YearViewProps<T>): ReactElement;
34
+ /**
35
+ * A year at a glance: the twelve months as compact mini grids, with today
36
+ * highlighted and a dot under days that hold events. Tap a day or a month
37
+ * title to drill into a denser view. It's the view `Calendar` renders for
38
+ * `mode="year"`.
39
+ *
40
+ * @example
41
+ * ```tsx
42
+ * import { YearView } from "@super-calendar/native";
43
+ *
44
+ * <YearView
45
+ * date={new Date()}
46
+ * events={events}
47
+ * weekStartsOn={1}
48
+ * onPressDay={(day) => console.log(day)}
49
+ * />
50
+ * ```
51
+ */
52
+ declare const YearView: typeof YearViewInner;
53
+ //#endregion
7
54
  //#region src/components/Agenda.d.ts
8
55
  /**
9
56
  * The styleable parts of {@link Agenda}. Mirrors the dom renderer's slot names;
@@ -182,7 +229,7 @@ declare const TimeGrid: typeof TimeGridInner;
182
229
  * month pager, the grid slots reach the time grid, and the agenda slots reach
183
230
  * the schedule view; slots for views that aren't rendered are ignored.
184
231
  */
185
- type CalendarSlot = MonthViewSlot | TimeGridSlot | AgendaSlot;
232
+ type CalendarSlot = MonthViewSlot | TimeGridSlot | AgendaSlot | YearViewSlot;
186
233
  /** Props for the {@link Calendar} component. */
187
234
  type CalendarProps<T> = SlotStyleProps<CalendarSlot> & {
188
235
  events: CalendarEvent<T>[];
@@ -217,8 +264,10 @@ type CalendarProps<T> = SlotStyleProps<CalendarSlot> & {
217
264
  * drag-to-move and drag-to-resize working while hiding the visible indicator.
218
265
  */
219
266
  showDragHandle?: boolean;
220
- /** Tap a day cell (month mode) — e.g. drill into the day view. */
267
+ /** Tap a day cell (month and year modes) — e.g. drill into the day view. */
221
268
  onPressDay?: (date: Date) => void;
269
+ /** Tap a month's title in the year view — e.g. jump to that month. */
270
+ onPressMonth?: (month: Date) => void;
222
271
  /** Long-press a day cell (month mode). */
223
272
  onLongPressDay?: (date: Date) => void;
224
273
  /** Tap the "+N more" overflow label in a month cell. */
@@ -397,7 +446,7 @@ type CalendarProps<T> = SlotStyleProps<CalendarSlot> & {
397
446
  * }
398
447
  * ```
399
448
  */
400
- declare function Calendar<T>({ events, mode, date, onChangeDate, onChangeDateRange, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, dragStepMinutes, showDragHandle, onPressDay, onLongPressDay, onPressMore, onPressCell, resetPageOnPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, maxVisibleEventCount, sortedMonthView, moreLabel, showAdjacentMonths, disableMonthEventCellPress, weekStartsOn, weekdayFormat, numberOfDays, weekEndsOn, renderEvent, eventAccessibilityLabel, eventCellStyle, calendarCellStyle, businessHours, keyExtractor, theme, cellHeight: cellHeightProp, hourHeight, minHourHeight, maxHourHeight, hourColumnWidth, hideHours, timeslots, showAllDayEventCell, showWeekNumber, weekNumberPrefix, hourComponent, showSixWeeks, swipeEnabled, showVerticalScrollIndicator, verticalScrollEnabled, headerComponent, minHour, maxHour, ampm, showTime, ellipsizeTitle, allDayLabel, scrollOffsetMinutes, showNowIndicator, locale, timeZone, activeDate, isRTL, freeSwipe, renderTimeGridHeader, renderHeaderForMonthView, renderCustomDateForMonth, itemSeparatorComponent, classNames, styles: styleOverrides }: CalendarProps<T>): ReactElement;
449
+ declare function Calendar<T>({ events, mode, date, onChangeDate, onChangeDateRange, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, dragStepMinutes, showDragHandle, onPressDay, onPressMonth, onLongPressDay, onPressMore, onPressCell, resetPageOnPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, maxVisibleEventCount, sortedMonthView, moreLabel, showAdjacentMonths, disableMonthEventCellPress, weekStartsOn, weekdayFormat, numberOfDays, weekEndsOn, renderEvent, eventAccessibilityLabel, eventCellStyle, calendarCellStyle, businessHours, keyExtractor, theme, cellHeight: cellHeightProp, hourHeight, minHourHeight, maxHourHeight, hourColumnWidth, hideHours, timeslots, showAllDayEventCell, showWeekNumber, weekNumberPrefix, hourComponent, showSixWeeks, swipeEnabled, showVerticalScrollIndicator, verticalScrollEnabled, headerComponent, minHour, maxHour, ampm, showTime, ellipsizeTitle, allDayLabel, scrollOffsetMinutes, showNowIndicator, locale, timeZone, activeDate, isRTL, freeSwipe, renderTimeGridHeader, renderHeaderForMonthView, renderCustomDateForMonth, itemSeparatorComponent, classNames, styles: styleOverrides }: CalendarProps<T>): ReactElement;
401
450
  //#endregion
402
451
  //#region src/components/DefaultEvent.d.ts
403
452
  /**
@@ -520,4 +569,4 @@ interface ResourceTimelineProps<T = unknown> {
520
569
  */
521
570
  declare function ResourceTimeline<T = unknown>({ date, orientation, resources, events, resourceId, startHour, endHour, hourWidth, hourHeight, rowHeight, labelWidth, ampm, renderEvent, onPressEvent, onLongPressEvent, onDragEvent, onPressCell, onLongPressCell, onCreateEvent, businessHours, dragStepMinutes }: ResourceTimelineProps<T>): ReactElement;
522
571
  //#endregion
523
- export { Agenda, type AgendaProps, type AgendaSlot, type BusinessHours, Calendar, type CalendarEvent, type CalendarMode, type CalendarProps, type CalendarSlot, type CalendarTheme, CalendarThemeProvider, DEFAULT_HOUR_HEIGHT, type DateRange, type DateSelectionConstraints, type DaySelectionState, DefaultEvent, DefaultMonthEvent, type EventAccessibilityLabelContext, type EventAccessibilityLabeler, type EventDragHandler, type EventDragStartHandler, type EventKeyExtractor, type HourRenderer, type ICalEvent, type ICalendarEvent, type MonthGrid, type MonthGridDay, type MonthGridWeek, type MonthGridWeekday, MonthList, type MonthListProps, type MonthListSlot, MonthPager, type MonthPagerProps, MonthView, type MonthViewProps, type MonthViewSlot, type PartialCalendarTheme, type PositionedEvent, type RecurrenceFrequency, type RecurrenceRule, type RenderEvent, type RenderEventArgs, type ResolvedSlot, type Resource, type ResourceEventArgs, ResourceTimeline, type ResourceTimelineProps, type SlotDefault, type SlotStyleProps, TimeGrid, type TimeGridMode, type TimeGridProps, type TimeGridSlot, type ToICalendarOptions, type UseDateRangeOptions, type UseMonthGridOptions, type WeekStartsOn, type WeekdayFormat, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, mergeTheme, minutesIntoDay, nextDateRange, parseICalendar, toICalendar, toZonedTime, useCalendarTheme, useDateRange, useMonthGrid, weekdayFormatToken };
572
+ export { Agenda, type AgendaProps, type AgendaSlot, type BusinessHours, Calendar, type CalendarEvent, type CalendarMode, type CalendarProps, type CalendarSlot, type CalendarTheme, CalendarThemeProvider, DEFAULT_HOUR_HEIGHT, type DateRange, type DateSelectionConstraints, type DaySelectionState, DefaultEvent, DefaultMonthEvent, type EventAccessibilityLabelContext, type EventAccessibilityLabeler, type EventDragHandler, type EventDragStartHandler, type EventKeyExtractor, type HourRenderer, type ICalEvent, type ICalendarEvent, type MonthGrid, type MonthGridDay, type MonthGridWeek, type MonthGridWeekday, MonthList, type MonthListProps, type MonthListSlot, MonthPager, type MonthPagerProps, MonthView, type MonthViewProps, type MonthViewSlot, type PartialCalendarTheme, type PositionedEvent, type RecurrenceFrequency, type RecurrenceRule, type RenderEvent, type RenderEventArgs, type ResolvedSlot, type Resource, type ResourceEventArgs, ResourceTimeline, type ResourceTimelineProps, type SlotDefault, type SlotStyleProps, TimeGrid, type TimeGridMode, type TimeGridProps, type TimeGridSlot, type ToICalendarOptions, type UseDateRangeOptions, type UseMonthGridOptions, type WeekStartsOn, type WeekdayFormat, YearView, type YearViewProps, type YearViewSlot, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, mergeTheme, minutesIntoDay, nextDateRange, parseICalendar, toICalendar, toZonedTime, useCalendarTheme, useDateRange, useMonthGrid, weekdayFormatToken };
package/dist/index.js CHANGED
@@ -21,16 +21,179 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  enumerable: true
22
22
  }) : target, mod));
23
23
  //#endregion
24
- const require_MonthList = require("./MonthList-Aczb2RSY.js");
24
+ const require_MonthList = require("./MonthList-Gu6p64fE.js");
25
25
  let date_fns = require("date-fns");
26
26
  let react = require("react");
27
27
  let react_native_reanimated = require("react-native-reanimated");
28
28
  react_native_reanimated = __toESM(react_native_reanimated);
29
29
  let _super_calendar_core = require("@super-calendar/core");
30
- let _legendapp_list_react_native = require("@legendapp/list/react-native");
31
30
  let react_native = require("react-native");
32
31
  let react_jsx_runtime = require("react/jsx-runtime");
32
+ let _legendapp_list_react_native = require("@legendapp/list/react-native");
33
33
  let react_native_gesture_handler = require("react-native-gesture-handler");
34
+ //#region src/components/YearView.tsx
35
+ const FALLBACK_COLUMNS = 3;
36
+ function YearViewInner({ date, events, weekStartsOn, locale, activeDate, minMonthWidth = 150, onPressDay, onPressMonth, classNames, styles: styleOverrides }) {
37
+ const theme = require_MonthList.useCalendarTheme();
38
+ const slot = require_MonthList.createSlots({
39
+ classNames,
40
+ styles: styleOverrides
41
+ });
42
+ const [columns, setColumns] = (0, react.useState)(FALLBACK_COLUMNS);
43
+ const handleLayout = (event) => {
44
+ const width = event.nativeEvent.layout.width;
45
+ if (width <= 0) return;
46
+ setColumns(Math.max(2, Math.min(4, Math.floor(width / minMonthWidth))));
47
+ };
48
+ const months = (0, react.useMemo)(() => (0, _super_calendar_core.getYearMonths)(date), [date]);
49
+ const weekdayLabels = (0, react.useMemo)(() => (0, _super_calendar_core.getWeekDays)(date, weekStartsOn).map((d) => (0, date_fns.format)(d, (0, _super_calendar_core.weekdayFormatToken)("narrow"), { locale })), [
50
+ date,
51
+ weekStartsOn,
52
+ locale
53
+ ]);
54
+ const eventDays = (0, react.useMemo)(() => new Set(events && events.length > 0 ? (0, _super_calendar_core.groupEventsByDay)(events).keys() : []), [events]);
55
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.ScrollView, {
56
+ onLayout: handleLayout,
57
+ showsVerticalScrollIndicator: true,
58
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
59
+ ...slot("grid", { base: styles$5.grid }),
60
+ children: months.map((month) => {
61
+ const weeks = (0, _super_calendar_core.buildMonthWeeks)(month, weekStartsOn);
62
+ const title = (0, date_fns.format)(month, "MMMM", { locale });
63
+ const monthLabel = (0, date_fns.format)(month, "MMMM yyyy", { locale });
64
+ const titleText = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
65
+ ...slot("monthTitle", {
66
+ base: styles$5.monthTitle,
67
+ themed: [styles$5.monthTitleText, { color: theme.colors.todayBackground }]
68
+ }),
69
+ allowFontScaling: false,
70
+ children: title
71
+ });
72
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_native.View, {
73
+ ...slot("month", { base: [styles$5.month, { width: `${100 / columns}%` }] }),
74
+ children: [
75
+ onPressMonth ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
76
+ onPress: () => onPressMonth(month),
77
+ accessibilityRole: "button",
78
+ accessibilityLabel: monthLabel,
79
+ children: titleText
80
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
81
+ accessible: true,
82
+ accessibilityRole: "header",
83
+ accessibilityLabel: monthLabel,
84
+ children: titleText
85
+ }),
86
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
87
+ ...slot("weekdays", { base: styles$5.weekdays }),
88
+ accessibilityElementsHidden: true,
89
+ importantForAccessibility: "no-hide-descendants",
90
+ children: weekdayLabels.map((label, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
91
+ ...slot("weekday", {
92
+ base: styles$5.weekday,
93
+ themed: [styles$5.weekdayText, { color: theme.colors.textMuted }]
94
+ }),
95
+ allowFontScaling: false,
96
+ children: label
97
+ }, i))
98
+ }),
99
+ weeks.map((week) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
100
+ ...slot("week", { base: styles$5.week }),
101
+ children: week.map((day) => {
102
+ if (day.getMonth() !== month.getMonth()) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { style: styles$5.day }, day.toISOString());
103
+ const isHighlighted = activeDate ? (0, _super_calendar_core.isSameCalendarDay)(day, activeDate) : (0, _super_calendar_core.getIsToday)(day);
104
+ const hasEvents = eventDays.has((0, date_fns.startOfDay)(day).toISOString());
105
+ const label = `${(0, date_fns.format)(day, "EEEE, d LLLL yyyy", { locale })}${(0, _super_calendar_core.getIsToday)(day) ? ", today" : ""}${hasEvents ? ", has events" : ""}`;
106
+ const daySlot = slot("day", {
107
+ base: styles$5.day,
108
+ themed: isHighlighted ? {
109
+ backgroundColor: theme.colors.todayBackground,
110
+ borderRadius: theme.todayBadgeRadius
111
+ } : void 0
112
+ });
113
+ const content = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
114
+ ...slot("dayText", { themed: [styles$5.dayText, { color: isHighlighted ? theme.colors.todayText : theme.colors.text }] }),
115
+ allowFontScaling: false,
116
+ children: day.getDate()
117
+ }), hasEvents ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, { ...slot("eventDot", {
118
+ base: styles$5.eventDot,
119
+ themed: { backgroundColor: isHighlighted ? theme.colors.todayText : theme.colors.todayBackground }
120
+ }) }) : null] });
121
+ return onPressDay ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Pressable, {
122
+ onPress: () => onPressDay(day),
123
+ accessibilityRole: "button",
124
+ accessibilityLabel: label,
125
+ ...daySlot,
126
+ children: content
127
+ }, day.toISOString()) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
128
+ accessible: true,
129
+ accessibilityLabel: label,
130
+ ...daySlot,
131
+ children: content
132
+ }, day.toISOString());
133
+ })
134
+ }, week[0].toISOString()))
135
+ ]
136
+ }, month.toISOString());
137
+ })
138
+ })
139
+ });
140
+ }
141
+ /**
142
+ * A year at a glance: the twelve months as compact mini grids, with today
143
+ * highlighted and a dot under days that hold events. Tap a day or a month
144
+ * title to drill into a denser view. It's the view `Calendar` renders for
145
+ * `mode="year"`.
146
+ *
147
+ * @example
148
+ * ```tsx
149
+ * import { YearView } from "@super-calendar/native";
150
+ *
151
+ * <YearView
152
+ * date={new Date()}
153
+ * events={events}
154
+ * weekStartsOn={1}
155
+ * onPressDay={(day) => console.log(day)}
156
+ * />
157
+ * ```
158
+ */
159
+ const YearView = (0, react.memo)(YearViewInner);
160
+ const styles$5 = react_native.StyleSheet.create({
161
+ grid: {
162
+ flexDirection: "row",
163
+ flexWrap: "wrap"
164
+ },
165
+ month: { padding: 8 },
166
+ monthTitle: { paddingBottom: 4 },
167
+ monthTitleText: {
168
+ fontSize: 13,
169
+ fontWeight: "700"
170
+ },
171
+ weekdays: { flexDirection: "row" },
172
+ weekday: {
173
+ flex: 1,
174
+ textAlign: "center"
175
+ },
176
+ weekdayText: {
177
+ fontSize: 9,
178
+ fontWeight: "600"
179
+ },
180
+ week: { flexDirection: "row" },
181
+ day: {
182
+ flex: 1,
183
+ aspectRatio: 1,
184
+ alignItems: "center",
185
+ justifyContent: "center"
186
+ },
187
+ dayText: { fontSize: 11 },
188
+ eventDot: {
189
+ position: "absolute",
190
+ bottom: 1,
191
+ width: 3,
192
+ height: 3,
193
+ borderRadius: 2
194
+ }
195
+ });
196
+ //#endregion
34
197
  //#region src/components/Agenda.tsx
35
198
  /**
36
199
  * A vertical, day-grouped list of events (no time grid). Events are sorted by
@@ -1589,11 +1752,13 @@ const styles$1 = react_native.StyleSheet.create({
1589
1752
  const defaultKeyExtractor = (event) => `${event.start.toISOString()}|${event.end.toISOString()}|${event.title ?? ""}`;
1590
1753
  function visibleRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1591
1754
  if (mode === "month") return [(0, date_fns.startOfWeek)((0, date_fns.startOfMonth)(date), { weekStartsOn }), (0, date_fns.endOfWeek)((0, date_fns.endOfMonth)(date), { weekStartsOn })];
1755
+ if (mode === "year") return [(0, date_fns.startOfWeek)((0, date_fns.startOfYear)(date), { weekStartsOn }), (0, date_fns.endOfWeek)((0, date_fns.endOfYear)(date), { weekStartsOn })];
1592
1756
  const days = (0, _super_calendar_core.getViewDays)(mode, date, weekStartsOn, numberOfDays, false, weekEndsOn);
1593
1757
  return [(0, date_fns.startOfDay)(days[0]), (0, date_fns.endOfDay)(days[days.length - 1])];
1594
1758
  }
1595
1759
  function expansionRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1596
1760
  if (mode === "month") return [(0, date_fns.startOfWeek)((0, date_fns.startOfMonth)((0, date_fns.addMonths)(date, -1)), { weekStartsOn }), (0, date_fns.addWeeks)((0, date_fns.endOfWeek)((0, date_fns.endOfMonth)((0, date_fns.addMonths)(date, 1)), { weekStartsOn }), 1)];
1761
+ if (mode === "year") return [(0, date_fns.startOfWeek)((0, date_fns.startOfYear)(date), { weekStartsOn }), (0, date_fns.endOfWeek)((0, date_fns.endOfYear)(date), { weekStartsOn })];
1597
1762
  if (mode === "schedule") return [(0, date_fns.startOfDay)(date), (0, date_fns.endOfDay)((0, date_fns.addMonths)(date, 3))];
1598
1763
  const days = (0, _super_calendar_core.getViewDays)(mode, date, weekStartsOn, numberOfDays, false, weekEndsOn);
1599
1764
  const span = days.length;
@@ -1625,7 +1790,7 @@ function expansionRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1625
1790
  * }
1626
1791
  * ```
1627
1792
  */
1628
- function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, dragStepMinutes, showDragHandle, onPressDay, onLongPressDay, onPressMore, onPressCell, resetPageOnPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, maxVisibleEventCount, sortedMonthView, moreLabel, showAdjacentMonths, disableMonthEventCellPress, weekStartsOn = 0, weekdayFormat, numberOfDays, weekEndsOn, renderEvent = DefaultEvent, eventAccessibilityLabel, eventCellStyle, calendarCellStyle, businessHours, keyExtractor = defaultKeyExtractor, theme, cellHeight: cellHeightProp, hourHeight = 48, minHourHeight, maxHourHeight, hourColumnWidth, hideHours, timeslots, showAllDayEventCell, showWeekNumber, weekNumberPrefix, hourComponent, showSixWeeks, swipeEnabled, showVerticalScrollIndicator, verticalScrollEnabled, headerComponent, minHour, maxHour, ampm, showTime, ellipsizeTitle, allDayLabel, scrollOffsetMinutes, showNowIndicator, locale, timeZone, activeDate, isRTL, freeSwipe, renderTimeGridHeader, renderHeaderForMonthView, renderCustomDateForMonth, itemSeparatorComponent, classNames, styles: styleOverrides }) {
1793
+ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, dragStepMinutes, showDragHandle, onPressDay, onPressMonth, onLongPressDay, onPressMore, onPressCell, resetPageOnPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, maxVisibleEventCount, sortedMonthView, moreLabel, showAdjacentMonths, disableMonthEventCellPress, weekStartsOn = 0, weekdayFormat, numberOfDays, weekEndsOn, renderEvent = DefaultEvent, eventAccessibilityLabel, eventCellStyle, calendarCellStyle, businessHours, keyExtractor = defaultKeyExtractor, theme, cellHeight: cellHeightProp, hourHeight = 48, minHourHeight, maxHourHeight, hourColumnWidth, hideHours, timeslots, showAllDayEventCell, showWeekNumber, weekNumberPrefix, hourComponent, showSixWeeks, swipeEnabled, showVerticalScrollIndicator, verticalScrollEnabled, headerComponent, minHour, maxHour, ampm, showTime, ellipsizeTitle, allDayLabel, scrollOffsetMinutes, showNowIndicator, locale, timeZone, activeDate, isRTL, freeSwipe, renderTimeGridHeader, renderHeaderForMonthView, renderCustomDateForMonth, itemSeparatorComponent, classNames, styles: styleOverrides }) {
1629
1794
  const mergedTheme = (0, react.useMemo)(() => require_MonthList.mergeTheme(theme), [theme]);
1630
1795
  const internalCellHeight = (0, react_native_reanimated.useSharedValue)(hourHeight);
1631
1796
  const cellHeight = cellHeightProp ?? internalCellHeight;
@@ -1726,6 +1891,16 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1726
1891
  swipeEnabled,
1727
1892
  classNames,
1728
1893
  styles: styleOverrides
1894
+ }) : mode === "year" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(YearView, {
1895
+ date,
1896
+ events: displayEvents,
1897
+ weekStartsOn,
1898
+ locale,
1899
+ activeDate,
1900
+ onPressDay,
1901
+ onPressMonth,
1902
+ classNames,
1903
+ styles: styleOverrides
1729
1904
  }) : mode === "schedule" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Agenda, {
1730
1905
  events: displayEvents,
1731
1906
  locale,
@@ -2506,6 +2681,7 @@ exports.MonthPager = require_MonthList.MonthPager;
2506
2681
  exports.MonthView = require_MonthList.MonthView;
2507
2682
  exports.ResourceTimeline = ResourceTimeline;
2508
2683
  exports.TimeGrid = TimeGrid;
2684
+ exports.YearView = YearView;
2509
2685
  Object.defineProperty(exports, "buildMonthGrid", {
2510
2686
  enumerable: true,
2511
2687
  get: function() {
package/dist/index.mjs CHANGED
@@ -1,12 +1,175 @@
1
- import { a as withEventAccessibilityLabel, c as createSlots, d as darkTheme, f as defaultTheme, i as MonthView, l as useSlots, m as useCalendarTheme, n as DefaultMonthEvent, o as useWebPagerKeys, p as mergeTheme, r as MonthPager, s as SlotStylesProvider, t as MonthList, u as CalendarThemeProvider } from "./MonthList-zPLklHAY.mjs";
2
- import { addDays, addMonths, addWeeks, differenceInCalendarDays, endOfDay, endOfMonth, endOfWeek, format, getHours, getISOWeek, getMinutes, isSameDay, startOfDay, startOfMonth, startOfWeek } from "date-fns";
1
+ import { a as withEventAccessibilityLabel, c as createSlots, d as darkTheme, f as defaultTheme, i as MonthView, l as useSlots, m as useCalendarTheme, n as DefaultMonthEvent, o as useWebPagerKeys, p as mergeTheme, r as MonthPager, s as SlotStylesProvider, t as MonthList, u as CalendarThemeProvider } from "./MonthList-CMzYn9T0.mjs";
2
+ import { addDays, addMonths, addWeeks, differenceInCalendarDays, endOfDay, endOfMonth, endOfWeek, endOfYear, format, getHours, getISOWeek, getMinutes, isSameDay, startOfDay, startOfMonth, startOfWeek, startOfYear } from "date-fns";
3
3
  import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
4
4
  import Animated, { runOnJS, scrollTo, useAnimatedReaction, useAnimatedRef, useAnimatedScrollHandler, useAnimatedStyle, useDerivedValue, useReducedMotion, useSharedValue } from "react-native-reanimated";
5
- import { buildMonthGrid, buildMonthWeeks, cellRangeFromDrag, closedHourBands, daySelectionState, eventAccessibilityLabel, eventChipLayout, eventTimeLabel, eventsInTimeZone, eventsInTimeZone as eventsInTimeZone$1, expandRecurringEvents, expandRecurringEvents as expandRecurringEvents$1, formatHour, getIsToday, getIsToday as getIsToday$1, getViewDays, getViewDays as getViewDays$1, getWeekDays, isAllDayEvent, isAllDayEvent as isAllDayEvent$1, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isSameCalendarDay as isSameCalendarDay$1, isWeekend, isWeekend as isWeekend$1, isWithinDateRange, layoutDayEvents, layoutDayEvents as layoutDayEvents$1, minutesIntoDay, nextDateRange, parseICalendar, resolveDraggedBounds, snapDeltaMinutes, titleEllipsizeMode, titleNumberOfLines, toICalendar, toZonedTime, useDateRange, useMonthGrid, viewDayCount, weekdayFormatToken, weekdayFormatToken as weekdayFormatToken$1 } from "@super-calendar/core";
6
- import { LegendList } from "@legendapp/list/react-native";
5
+ import { buildMonthGrid, buildMonthWeeks, buildMonthWeeks as buildMonthWeeks$1, cellRangeFromDrag, closedHourBands, daySelectionState, eventAccessibilityLabel, eventChipLayout, eventTimeLabel, eventsInTimeZone, eventsInTimeZone as eventsInTimeZone$1, expandRecurringEvents, expandRecurringEvents as expandRecurringEvents$1, formatHour, getIsToday, getIsToday as getIsToday$1, getViewDays, getViewDays as getViewDays$1, getWeekDays, getWeekDays as getWeekDays$1, getYearMonths, groupEventsByDay, isAllDayEvent, isAllDayEvent as isAllDayEvent$1, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isSameCalendarDay as isSameCalendarDay$1, isWeekend, isWeekend as isWeekend$1, isWithinDateRange, layoutDayEvents, layoutDayEvents as layoutDayEvents$1, minutesIntoDay, nextDateRange, parseICalendar, resolveDraggedBounds, snapDeltaMinutes, titleEllipsizeMode, titleNumberOfLines, toICalendar, toZonedTime, useDateRange, useMonthGrid, viewDayCount, weekdayFormatToken, weekdayFormatToken as weekdayFormatToken$1 } from "@super-calendar/core";
7
6
  import { Platform, Pressable, ScrollView, StyleSheet, Text, TouchableOpacity, View, useWindowDimensions } from "react-native";
8
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ import { LegendList } from "@legendapp/list/react-native";
9
9
  import { Gesture, GestureDetector } from "react-native-gesture-handler";
10
+ //#region src/components/YearView.tsx
11
+ const FALLBACK_COLUMNS = 3;
12
+ function YearViewInner({ date, events, weekStartsOn, locale, activeDate, minMonthWidth = 150, onPressDay, onPressMonth, classNames, styles: styleOverrides }) {
13
+ const theme = useCalendarTheme();
14
+ const slot = createSlots({
15
+ classNames,
16
+ styles: styleOverrides
17
+ });
18
+ const [columns, setColumns] = useState(FALLBACK_COLUMNS);
19
+ const handleLayout = (event) => {
20
+ const width = event.nativeEvent.layout.width;
21
+ if (width <= 0) return;
22
+ setColumns(Math.max(2, Math.min(4, Math.floor(width / minMonthWidth))));
23
+ };
24
+ const months = useMemo(() => getYearMonths(date), [date]);
25
+ const weekdayLabels = useMemo(() => getWeekDays$1(date, weekStartsOn).map((d) => format(d, weekdayFormatToken$1("narrow"), { locale })), [
26
+ date,
27
+ weekStartsOn,
28
+ locale
29
+ ]);
30
+ const eventDays = useMemo(() => new Set(events && events.length > 0 ? groupEventsByDay(events).keys() : []), [events]);
31
+ return /* @__PURE__ */ jsx(ScrollView, {
32
+ onLayout: handleLayout,
33
+ showsVerticalScrollIndicator: true,
34
+ children: /* @__PURE__ */ jsx(View, {
35
+ ...slot("grid", { base: styles$5.grid }),
36
+ children: months.map((month) => {
37
+ const weeks = buildMonthWeeks$1(month, weekStartsOn);
38
+ const title = format(month, "MMMM", { locale });
39
+ const monthLabel = format(month, "MMMM yyyy", { locale });
40
+ const titleText = /* @__PURE__ */ jsx(Text, {
41
+ ...slot("monthTitle", {
42
+ base: styles$5.monthTitle,
43
+ themed: [styles$5.monthTitleText, { color: theme.colors.todayBackground }]
44
+ }),
45
+ allowFontScaling: false,
46
+ children: title
47
+ });
48
+ return /* @__PURE__ */ jsxs(View, {
49
+ ...slot("month", { base: [styles$5.month, { width: `${100 / columns}%` }] }),
50
+ children: [
51
+ onPressMonth ? /* @__PURE__ */ jsx(Pressable, {
52
+ onPress: () => onPressMonth(month),
53
+ accessibilityRole: "button",
54
+ accessibilityLabel: monthLabel,
55
+ children: titleText
56
+ }) : /* @__PURE__ */ jsx(View, {
57
+ accessible: true,
58
+ accessibilityRole: "header",
59
+ accessibilityLabel: monthLabel,
60
+ children: titleText
61
+ }),
62
+ /* @__PURE__ */ jsx(View, {
63
+ ...slot("weekdays", { base: styles$5.weekdays }),
64
+ accessibilityElementsHidden: true,
65
+ importantForAccessibility: "no-hide-descendants",
66
+ children: weekdayLabels.map((label, i) => /* @__PURE__ */ jsx(Text, {
67
+ ...slot("weekday", {
68
+ base: styles$5.weekday,
69
+ themed: [styles$5.weekdayText, { color: theme.colors.textMuted }]
70
+ }),
71
+ allowFontScaling: false,
72
+ children: label
73
+ }, i))
74
+ }),
75
+ weeks.map((week) => /* @__PURE__ */ jsx(View, {
76
+ ...slot("week", { base: styles$5.week }),
77
+ children: week.map((day) => {
78
+ if (day.getMonth() !== month.getMonth()) return /* @__PURE__ */ jsx(View, { style: styles$5.day }, day.toISOString());
79
+ const isHighlighted = activeDate ? isSameCalendarDay$1(day, activeDate) : getIsToday$1(day);
80
+ const hasEvents = eventDays.has(startOfDay(day).toISOString());
81
+ const label = `${format(day, "EEEE, d LLLL yyyy", { locale })}${getIsToday$1(day) ? ", today" : ""}${hasEvents ? ", has events" : ""}`;
82
+ const daySlot = slot("day", {
83
+ base: styles$5.day,
84
+ themed: isHighlighted ? {
85
+ backgroundColor: theme.colors.todayBackground,
86
+ borderRadius: theme.todayBadgeRadius
87
+ } : void 0
88
+ });
89
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Text, {
90
+ ...slot("dayText", { themed: [styles$5.dayText, { color: isHighlighted ? theme.colors.todayText : theme.colors.text }] }),
91
+ allowFontScaling: false,
92
+ children: day.getDate()
93
+ }), hasEvents ? /* @__PURE__ */ jsx(View, { ...slot("eventDot", {
94
+ base: styles$5.eventDot,
95
+ themed: { backgroundColor: isHighlighted ? theme.colors.todayText : theme.colors.todayBackground }
96
+ }) }) : null] });
97
+ return onPressDay ? /* @__PURE__ */ jsx(Pressable, {
98
+ onPress: () => onPressDay(day),
99
+ accessibilityRole: "button",
100
+ accessibilityLabel: label,
101
+ ...daySlot,
102
+ children: content
103
+ }, day.toISOString()) : /* @__PURE__ */ jsx(View, {
104
+ accessible: true,
105
+ accessibilityLabel: label,
106
+ ...daySlot,
107
+ children: content
108
+ }, day.toISOString());
109
+ })
110
+ }, week[0].toISOString()))
111
+ ]
112
+ }, month.toISOString());
113
+ })
114
+ })
115
+ });
116
+ }
117
+ /**
118
+ * A year at a glance: the twelve months as compact mini grids, with today
119
+ * highlighted and a dot under days that hold events. Tap a day or a month
120
+ * title to drill into a denser view. It's the view `Calendar` renders for
121
+ * `mode="year"`.
122
+ *
123
+ * @example
124
+ * ```tsx
125
+ * import { YearView } from "@super-calendar/native";
126
+ *
127
+ * <YearView
128
+ * date={new Date()}
129
+ * events={events}
130
+ * weekStartsOn={1}
131
+ * onPressDay={(day) => console.log(day)}
132
+ * />
133
+ * ```
134
+ */
135
+ const YearView = memo(YearViewInner);
136
+ const styles$5 = StyleSheet.create({
137
+ grid: {
138
+ flexDirection: "row",
139
+ flexWrap: "wrap"
140
+ },
141
+ month: { padding: 8 },
142
+ monthTitle: { paddingBottom: 4 },
143
+ monthTitleText: {
144
+ fontSize: 13,
145
+ fontWeight: "700"
146
+ },
147
+ weekdays: { flexDirection: "row" },
148
+ weekday: {
149
+ flex: 1,
150
+ textAlign: "center"
151
+ },
152
+ weekdayText: {
153
+ fontSize: 9,
154
+ fontWeight: "600"
155
+ },
156
+ week: { flexDirection: "row" },
157
+ day: {
158
+ flex: 1,
159
+ aspectRatio: 1,
160
+ alignItems: "center",
161
+ justifyContent: "center"
162
+ },
163
+ dayText: { fontSize: 11 },
164
+ eventDot: {
165
+ position: "absolute",
166
+ bottom: 1,
167
+ width: 3,
168
+ height: 3,
169
+ borderRadius: 2
170
+ }
171
+ });
172
+ //#endregion
10
173
  //#region src/components/Agenda.tsx
11
174
  /**
12
175
  * A vertical, day-grouped list of events (no time grid). Events are sorted by
@@ -1565,11 +1728,13 @@ const styles$1 = StyleSheet.create({
1565
1728
  const defaultKeyExtractor = (event) => `${event.start.toISOString()}|${event.end.toISOString()}|${event.title ?? ""}`;
1566
1729
  function visibleRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1567
1730
  if (mode === "month") return [startOfWeek(startOfMonth(date), { weekStartsOn }), endOfWeek(endOfMonth(date), { weekStartsOn })];
1731
+ if (mode === "year") return [startOfWeek(startOfYear(date), { weekStartsOn }), endOfWeek(endOfYear(date), { weekStartsOn })];
1568
1732
  const days = getViewDays$1(mode, date, weekStartsOn, numberOfDays, false, weekEndsOn);
1569
1733
  return [startOfDay(days[0]), endOfDay(days[days.length - 1])];
1570
1734
  }
1571
1735
  function expansionRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1572
1736
  if (mode === "month") return [startOfWeek(startOfMonth(addMonths(date, -1)), { weekStartsOn }), addWeeks(endOfWeek(endOfMonth(addMonths(date, 1)), { weekStartsOn }), 1)];
1737
+ if (mode === "year") return [startOfWeek(startOfYear(date), { weekStartsOn }), endOfWeek(endOfYear(date), { weekStartsOn })];
1573
1738
  if (mode === "schedule") return [startOfDay(date), endOfDay(addMonths(date, 3))];
1574
1739
  const days = getViewDays$1(mode, date, weekStartsOn, numberOfDays, false, weekEndsOn);
1575
1740
  const span = days.length;
@@ -1601,7 +1766,7 @@ function expansionRange(mode, date, weekStartsOn, numberOfDays, weekEndsOn) {
1601
1766
  * }
1602
1767
  * ```
1603
1768
  */
1604
- function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, dragStepMinutes, showDragHandle, onPressDay, onLongPressDay, onPressMore, onPressCell, resetPageOnPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, maxVisibleEventCount, sortedMonthView, moreLabel, showAdjacentMonths, disableMonthEventCellPress, weekStartsOn = 0, weekdayFormat, numberOfDays, weekEndsOn, renderEvent = DefaultEvent, eventAccessibilityLabel, eventCellStyle, calendarCellStyle, businessHours, keyExtractor = defaultKeyExtractor, theme, cellHeight: cellHeightProp, hourHeight = 48, minHourHeight, maxHourHeight, hourColumnWidth, hideHours, timeslots, showAllDayEventCell, showWeekNumber, weekNumberPrefix, hourComponent, showSixWeeks, swipeEnabled, showVerticalScrollIndicator, verticalScrollEnabled, headerComponent, minHour, maxHour, ampm, showTime, ellipsizeTitle, allDayLabel, scrollOffsetMinutes, showNowIndicator, locale, timeZone, activeDate, isRTL, freeSwipe, renderTimeGridHeader, renderHeaderForMonthView, renderCustomDateForMonth, itemSeparatorComponent, classNames, styles: styleOverrides }) {
1769
+ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPressEvent, onLongPressEvent, onDragEvent, onDragStart, dragStepMinutes, showDragHandle, onPressDay, onPressMonth, onLongPressDay, onPressMore, onPressCell, resetPageOnPressCell, onLongPressCell, onCreateEvent, onPressDateHeader, maxVisibleEventCount, sortedMonthView, moreLabel, showAdjacentMonths, disableMonthEventCellPress, weekStartsOn = 0, weekdayFormat, numberOfDays, weekEndsOn, renderEvent = DefaultEvent, eventAccessibilityLabel, eventCellStyle, calendarCellStyle, businessHours, keyExtractor = defaultKeyExtractor, theme, cellHeight: cellHeightProp, hourHeight = 48, minHourHeight, maxHourHeight, hourColumnWidth, hideHours, timeslots, showAllDayEventCell, showWeekNumber, weekNumberPrefix, hourComponent, showSixWeeks, swipeEnabled, showVerticalScrollIndicator, verticalScrollEnabled, headerComponent, minHour, maxHour, ampm, showTime, ellipsizeTitle, allDayLabel, scrollOffsetMinutes, showNowIndicator, locale, timeZone, activeDate, isRTL, freeSwipe, renderTimeGridHeader, renderHeaderForMonthView, renderCustomDateForMonth, itemSeparatorComponent, classNames, styles: styleOverrides }) {
1605
1770
  const mergedTheme = useMemo(() => mergeTheme(theme), [theme]);
1606
1771
  const internalCellHeight = useSharedValue(hourHeight);
1607
1772
  const cellHeight = cellHeightProp ?? internalCellHeight;
@@ -1702,6 +1867,16 @@ function Calendar({ events, mode, date, onChangeDate, onChangeDateRange, onPress
1702
1867
  swipeEnabled,
1703
1868
  classNames,
1704
1869
  styles: styleOverrides
1870
+ }) : mode === "year" ? /* @__PURE__ */ jsx(YearView, {
1871
+ date,
1872
+ events: displayEvents,
1873
+ weekStartsOn,
1874
+ locale,
1875
+ activeDate,
1876
+ onPressDay,
1877
+ onPressMonth,
1878
+ classNames,
1879
+ styles: styleOverrides
1705
1880
  }) : mode === "schedule" ? /* @__PURE__ */ jsx(Agenda, {
1706
1881
  events: displayEvents,
1707
1882
  locale,
@@ -2471,4 +2646,4 @@ const styles = StyleSheet.create({
2471
2646
  }
2472
2647
  });
2473
2648
  //#endregion
2474
- export { Agenda, Calendar, CalendarThemeProvider, DEFAULT_HOUR_HEIGHT, DefaultEvent, DefaultMonthEvent, MonthList, MonthPager, MonthView, ResourceTimeline, TimeGrid, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, mergeTheme, minutesIntoDay, nextDateRange, parseICalendar, toICalendar, toZonedTime, useCalendarTheme, useDateRange, useMonthGrid, weekdayFormatToken };
2649
+ export { Agenda, Calendar, CalendarThemeProvider, DEFAULT_HOUR_HEIGHT, DefaultEvent, DefaultMonthEvent, MonthList, MonthPager, MonthView, ResourceTimeline, TimeGrid, YearView, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, eventsInTimeZone, expandRecurringEvents, getIsToday, getViewDays, getWeekDays, isAllDayEvent, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, layoutDayEvents, mergeTheme, minutesIntoDay, nextDateRange, parseICalendar, toICalendar, toZonedTime, useCalendarTheme, useDateRange, useMonthGrid, weekdayFormatToken };
package/dist/picker.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_MonthList = require("./MonthList-Aczb2RSY.js");
2
+ const require_MonthList = require("./MonthList-Gu6p64fE.js");
3
3
  let _super_calendar_core = require("@super-calendar/core");
4
4
  exports.CalendarThemeProvider = require_MonthList.CalendarThemeProvider;
5
5
  exports.DefaultMonthEvent = require_MonthList.DefaultMonthEvent;
package/dist/picker.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { d as darkTheme, f as defaultTheme, i as MonthView, m as useCalendarTheme, n as DefaultMonthEvent, p as mergeTheme, r as MonthPager, t as MonthList, u as CalendarThemeProvider } from "./MonthList-zPLklHAY.mjs";
1
+ import { d as darkTheme, f as defaultTheme, i as MonthView, m as useCalendarTheme, n as DefaultMonthEvent, p as mergeTheme, r as MonthPager, t as MonthList, u as CalendarThemeProvider } from "./MonthList-CMzYn9T0.mjs";
2
2
  import { buildMonthGrid, buildMonthWeeks, daySelectionState, getIsToday, getWeekDays, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, minutesIntoDay, nextDateRange, useDateRange, useMonthGrid } from "@super-calendar/core";
3
3
  export { CalendarThemeProvider, DefaultMonthEvent, MonthList, MonthPager, MonthView, buildMonthGrid, buildMonthWeeks, darkTheme, daySelectionState, defaultTheme, getIsToday, getWeekDays, isDateSelectable, isRangeEndpoint, isSameCalendarDay, isWeekend, isWithinDateRange, mergeTheme, minutesIntoDay, nextDateRange, useCalendarTheme, useDateRange, useMonthGrid };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@super-calendar/native",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "Gesture-driven, virtualized month / week / day calendar and date picker for React Native (and web via react-native-web).",
5
5
  "keywords": [
6
6
  "agenda",
@@ -64,7 +64,7 @@
64
64
  "access": "public"
65
65
  },
66
66
  "dependencies": {
67
- "@super-calendar/core": "2.5.0"
67
+ "@super-calendar/core": "2.6.0"
68
68
  },
69
69
  "peerDependencies": {
70
70
  "@legendapp/list": ">=3",
@@ -5,10 +5,12 @@ import {
5
5
  endOfDay,
6
6
  endOfMonth,
7
7
  endOfWeek,
8
+ endOfYear,
8
9
  type Locale,
9
10
  startOfDay,
10
11
  startOfMonth,
11
12
  startOfWeek,
13
+ startOfYear,
12
14
  } from "date-fns";
13
15
  import { type ReactElement, useCallback, useMemo } from "react";
14
16
  import type { StyleProp, ViewStyle } from "react-native";
@@ -31,6 +33,7 @@ import {
31
33
  getViewDays,
32
34
  } from "@super-calendar/core";
33
35
  import { type SlotStyleProps } from "../utils/slots";
36
+ import { YearView, type YearViewSlot } from "./YearView";
34
37
  import { Agenda, type AgendaSlot } from "./Agenda";
35
38
  import { DefaultEvent } from "./DefaultEvent";
36
39
  import { MonthPager } from "./MonthPager";
@@ -49,7 +52,7 @@ import {
49
52
  * month pager, the grid slots reach the time grid, and the agenda slots reach
50
53
  * the schedule view; slots for views that aren't rendered are ignored.
51
54
  */
52
- export type CalendarSlot = MonthViewSlot | TimeGridSlot | AgendaSlot;
55
+ export type CalendarSlot = MonthViewSlot | TimeGridSlot | AgendaSlot | YearViewSlot;
53
56
 
54
57
  /** Props for the {@link Calendar} component. */
55
58
  export type CalendarProps<T> = SlotStyleProps<CalendarSlot> & {
@@ -85,8 +88,10 @@ export type CalendarProps<T> = SlotStyleProps<CalendarSlot> & {
85
88
  * drag-to-move and drag-to-resize working while hiding the visible indicator.
86
89
  */
87
90
  showDragHandle?: boolean;
88
- /** Tap a day cell (month mode) — e.g. drill into the day view. */
91
+ /** Tap a day cell (month and year modes) — e.g. drill into the day view. */
89
92
  onPressDay?: (date: Date) => void;
93
+ /** Tap a month's title in the year view — e.g. jump to that month. */
94
+ onPressMonth?: (month: Date) => void;
90
95
  /** Long-press a day cell (month mode). */
91
96
  onLongPressDay?: (date: Date) => void;
92
97
  /** Tap the "+N more" overflow label in a month cell. */
@@ -261,6 +266,12 @@ function visibleRange(
261
266
  endOfWeek(endOfMonth(date), { weekStartsOn }),
262
267
  ];
263
268
  }
269
+ if (mode === "year") {
270
+ return [
271
+ startOfWeek(startOfYear(date), { weekStartsOn }),
272
+ endOfWeek(endOfYear(date), { weekStartsOn }),
273
+ ];
274
+ }
264
275
  const days = getViewDays(mode, date, weekStartsOn, numberOfDays, false, weekEndsOn);
265
276
  return [startOfDay(days[0]), endOfDay(days[days.length - 1])];
266
277
  }
@@ -283,6 +294,12 @@ function expansionRange(
283
294
  addWeeks(endOfWeek(endOfMonth(addMonths(date, 1)), { weekStartsOn }), 1),
284
295
  ];
285
296
  }
297
+ if (mode === "year") {
298
+ return [
299
+ startOfWeek(startOfYear(date), { weekStartsOn }),
300
+ endOfWeek(endOfYear(date), { weekStartsOn }),
301
+ ];
302
+ }
286
303
  if (mode === "schedule") {
287
304
  // The agenda lists forward from the anchor date; three months is a sensible
288
305
  // default look-ahead. Pre-expand for a different window.
@@ -332,6 +349,7 @@ export function Calendar<T>({
332
349
  dragStepMinutes,
333
350
  showDragHandle,
334
351
  onPressDay,
352
+ onPressMonth,
335
353
  onLongPressDay,
336
354
  onPressMore,
337
355
  onPressCell,
@@ -523,6 +541,18 @@ export function Calendar<T>({
523
541
  classNames={classNames}
524
542
  styles={styleOverrides}
525
543
  />
544
+ ) : mode === "year" ? (
545
+ <YearView
546
+ date={date}
547
+ events={displayEvents}
548
+ weekStartsOn={weekStartsOn}
549
+ locale={locale}
550
+ activeDate={activeDate}
551
+ onPressDay={onPressDay}
552
+ onPressMonth={onPressMonth}
553
+ classNames={classNames}
554
+ styles={styleOverrides}
555
+ />
526
556
  ) : mode === "schedule" ? (
527
557
  <Agenda
528
558
  events={displayEvents}
@@ -0,0 +1,276 @@
1
+ import { format, startOfDay, type Locale } from "date-fns";
2
+ import { memo, type ReactElement, useMemo, useState } from "react";
3
+ import {
4
+ type LayoutChangeEvent,
5
+ Pressable,
6
+ ScrollView,
7
+ StyleSheet,
8
+ Text,
9
+ View,
10
+ } from "react-native";
11
+ import { useCalendarTheme } from "../theme";
12
+ import type { CalendarEvent, WeekStartsOn } from "../types";
13
+ import { createSlots, type SlotStyleProps } from "../utils/slots";
14
+ import {
15
+ buildMonthWeeks,
16
+ getIsToday,
17
+ getWeekDays,
18
+ getYearMonths,
19
+ groupEventsByDay,
20
+ isSameCalendarDay,
21
+ weekdayFormatToken,
22
+ } from "@super-calendar/core";
23
+
24
+ /**
25
+ * The styleable parts of {@link YearView}. `dayText` and `eventDot` are the
26
+ * text/marker inside a day cell (React Native text colour doesn't inherit).
27
+ */
28
+ export type YearViewSlot =
29
+ | "grid"
30
+ | "month"
31
+ | "monthTitle"
32
+ | "weekdays"
33
+ | "weekday"
34
+ | "week"
35
+ | "day"
36
+ | "dayText"
37
+ | "eventDot";
38
+
39
+ /** Props for {@link YearView}, the twelve mini-month year grid. */
40
+ export type YearViewProps<T = unknown> = SlotStyleProps<YearViewSlot> & {
41
+ /** Any date inside the year to render. */
42
+ date: Date;
43
+ /** Days holding at least one event get a dot. Omit for a plain year. */
44
+ events?: CalendarEvent<T>[];
45
+ weekStartsOn: WeekStartsOn;
46
+ locale?: Locale;
47
+ /** Highlight this date instead of the real "today". */
48
+ activeDate?: Date;
49
+ /**
50
+ * Smallest width a mini month may take before the grid drops a column
51
+ * (default 150). The grid fits 2–4 columns from the measured width.
52
+ */
53
+ minMonthWidth?: number;
54
+ /** Tap a day cell (e.g. to drill into the day or month view). */
55
+ onPressDay?: (date: Date) => void;
56
+ /** Tap a month's title (e.g. to jump to that month's view). */
57
+ onPressMonth?: (month: Date) => void;
58
+ };
59
+
60
+ // Seed before the first layout pass so the grid renders immediately (and in
61
+ // tests, where onLayout never fires).
62
+ const FALLBACK_COLUMNS = 3;
63
+
64
+ function YearViewInner<T>({
65
+ date,
66
+ events,
67
+ weekStartsOn,
68
+ locale,
69
+ activeDate,
70
+ minMonthWidth = 150,
71
+ onPressDay,
72
+ onPressMonth,
73
+ classNames,
74
+ styles: styleOverrides,
75
+ }: YearViewProps<T>): ReactElement {
76
+ const theme = useCalendarTheme();
77
+ const slot = createSlots<YearViewSlot>({ classNames, styles: styleOverrides });
78
+
79
+ const [columns, setColumns] = useState(FALLBACK_COLUMNS);
80
+ const handleLayout = (event: LayoutChangeEvent) => {
81
+ const width = event.nativeEvent.layout.width;
82
+ if (width <= 0) return;
83
+ setColumns(Math.max(2, Math.min(4, Math.floor(width / minMonthWidth))));
84
+ };
85
+
86
+ const months = useMemo(() => getYearMonths(date), [date]);
87
+ // Weekday initials for one shared header per mini month.
88
+ const weekdayLabels = useMemo(
89
+ () =>
90
+ getWeekDays(date, weekStartsOn).map((d) =>
91
+ format(d, weekdayFormatToken("narrow"), { locale }),
92
+ ),
93
+ [date, weekStartsOn, locale],
94
+ );
95
+ // Days that hold at least one event, keyed like `groupEventsByDay`.
96
+ const eventDays = useMemo(
97
+ () => new Set(events && events.length > 0 ? groupEventsByDay(events).keys() : []),
98
+ [events],
99
+ );
100
+
101
+ return (
102
+ <ScrollView onLayout={handleLayout} showsVerticalScrollIndicator>
103
+ <View {...slot("grid", { base: styles.grid })}>
104
+ {months.map((month) => {
105
+ const weeks = buildMonthWeeks(month, weekStartsOn);
106
+ const title = format(month, "MMMM", { locale });
107
+ const monthLabel = format(month, "MMMM yyyy", { locale });
108
+ const titleText = (
109
+ <Text
110
+ {...slot("monthTitle", {
111
+ base: styles.monthTitle,
112
+ themed: [styles.monthTitleText, { color: theme.colors.todayBackground }],
113
+ })}
114
+ allowFontScaling={false}
115
+ >
116
+ {title}
117
+ </Text>
118
+ );
119
+ return (
120
+ <View
121
+ key={month.toISOString()}
122
+ {...slot("month", { base: [styles.month, { width: `${100 / columns}%` }] })}
123
+ >
124
+ {onPressMonth ? (
125
+ <Pressable
126
+ onPress={() => onPressMonth(month)}
127
+ accessibilityRole="button"
128
+ accessibilityLabel={monthLabel}
129
+ >
130
+ {titleText}
131
+ </Pressable>
132
+ ) : (
133
+ <View accessible accessibilityRole="header" accessibilityLabel={monthLabel}>
134
+ {titleText}
135
+ </View>
136
+ )}
137
+ {/* Decorative initials: repeating 84 single letters across the twelve
138
+ mini months would drown a screen reader, so hide the rows (the
139
+ day cells carry full date labels). */}
140
+ <View
141
+ {...slot("weekdays", { base: styles.weekdays })}
142
+ accessibilityElementsHidden
143
+ importantForAccessibility="no-hide-descendants"
144
+ >
145
+ {weekdayLabels.map((label, i) => (
146
+ <Text
147
+ key={i}
148
+ {...slot("weekday", {
149
+ base: styles.weekday,
150
+ themed: [styles.weekdayText, { color: theme.colors.textMuted }],
151
+ })}
152
+ allowFontScaling={false}
153
+ >
154
+ {label}
155
+ </Text>
156
+ ))}
157
+ </View>
158
+ {weeks.map((week) => (
159
+ <View key={week[0].toISOString()} {...slot("week", { base: styles.week })}>
160
+ {week.map((day) => {
161
+ // Adjacent-month days keep the grid shape but stay blank,
162
+ // like the mini months of other year views.
163
+ if (day.getMonth() !== month.getMonth()) {
164
+ return <View key={day.toISOString()} style={styles.day} />;
165
+ }
166
+ const isHighlighted = activeDate
167
+ ? isSameCalendarDay(day, activeDate)
168
+ : getIsToday(day);
169
+ const hasEvents = eventDays.has(startOfDay(day).toISOString());
170
+ const label = `${format(day, "EEEE, d LLLL yyyy", { locale })}${
171
+ getIsToday(day) ? ", today" : ""
172
+ }${hasEvents ? ", has events" : ""}`;
173
+ const daySlot = slot("day", {
174
+ base: styles.day,
175
+ themed: isHighlighted
176
+ ? {
177
+ backgroundColor: theme.colors.todayBackground,
178
+ borderRadius: theme.todayBadgeRadius,
179
+ }
180
+ : undefined,
181
+ });
182
+ const content = (
183
+ <>
184
+ <Text
185
+ {...slot("dayText", {
186
+ themed: [
187
+ styles.dayText,
188
+ {
189
+ color: isHighlighted ? theme.colors.todayText : theme.colors.text,
190
+ },
191
+ ],
192
+ })}
193
+ allowFontScaling={false}
194
+ >
195
+ {day.getDate()}
196
+ </Text>
197
+ {hasEvents ? (
198
+ <View
199
+ {...slot("eventDot", {
200
+ base: styles.eventDot,
201
+ themed: {
202
+ backgroundColor: isHighlighted
203
+ ? theme.colors.todayText
204
+ : theme.colors.todayBackground,
205
+ },
206
+ })}
207
+ />
208
+ ) : null}
209
+ </>
210
+ );
211
+ return onPressDay ? (
212
+ <Pressable
213
+ key={day.toISOString()}
214
+ onPress={() => onPressDay(day)}
215
+ accessibilityRole="button"
216
+ accessibilityLabel={label}
217
+ {...daySlot}
218
+ >
219
+ {content}
220
+ </Pressable>
221
+ ) : (
222
+ <View
223
+ key={day.toISOString()}
224
+ accessible
225
+ accessibilityLabel={label}
226
+ {...daySlot}
227
+ >
228
+ {content}
229
+ </View>
230
+ );
231
+ })}
232
+ </View>
233
+ ))}
234
+ </View>
235
+ );
236
+ })}
237
+ </View>
238
+ </ScrollView>
239
+ );
240
+ }
241
+
242
+ /**
243
+ * A year at a glance: the twelve months as compact mini grids, with today
244
+ * highlighted and a dot under days that hold events. Tap a day or a month
245
+ * title to drill into a denser view. It's the view `Calendar` renders for
246
+ * `mode="year"`.
247
+ *
248
+ * @example
249
+ * ```tsx
250
+ * import { YearView } from "@super-calendar/native";
251
+ *
252
+ * <YearView
253
+ * date={new Date()}
254
+ * events={events}
255
+ * weekStartsOn={1}
256
+ * onPressDay={(day) => console.log(day)}
257
+ * />
258
+ * ```
259
+ */
260
+ export const YearView = memo(YearViewInner) as typeof YearViewInner;
261
+
262
+ const styles = StyleSheet.create({
263
+ grid: { flexDirection: "row", flexWrap: "wrap" },
264
+ month: { padding: 8 },
265
+ // Structural layout / themed typography split per slot, so a slot class can
266
+ // replace the look without breaking the layout.
267
+ monthTitle: { paddingBottom: 4 },
268
+ monthTitleText: { fontSize: 13, fontWeight: "700" },
269
+ weekdays: { flexDirection: "row" },
270
+ weekday: { flex: 1, textAlign: "center" },
271
+ weekdayText: { fontSize: 9, fontWeight: "600" },
272
+ week: { flexDirection: "row" },
273
+ day: { flex: 1, aspectRatio: 1, alignItems: "center", justifyContent: "center" },
274
+ dayText: { fontSize: 11 },
275
+ eventDot: { position: "absolute", bottom: 1, width: 3, height: 3, borderRadius: 2 },
276
+ });
package/src/index.tsx CHANGED
@@ -23,6 +23,7 @@
23
23
  export { Calendar, type CalendarProps, type CalendarSlot } from "./components/Calendar";
24
24
  export { Agenda, type AgendaProps, type AgendaSlot } from "./components/Agenda";
25
25
  export { MonthView, type MonthViewProps, type MonthViewSlot } from "./components/MonthView";
26
+ export { YearView, type YearViewProps, type YearViewSlot } from "./components/YearView";
26
27
  export { type ResolvedSlot, type SlotDefault, type SlotStyleProps } from "./utils/slots";
27
28
  export { MonthPager, type MonthPagerProps } from "./components/MonthPager";
28
29
  export { MonthList, type MonthListProps, type MonthListSlot } from "./components/MonthList";
@@ -1,9 +1,9 @@
1
1
  import { addMonths, differenceInCalendarMonths, format, isSameMonth, startOfDay, startOfMonth } from "date-fns";
2
2
  import { createContext, createElement, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
3
3
  import { CalendarSelectionProvider, buildMonthWeeks, compareDayEvents, darkColors, dayBadgeKind, daySelectionState, eventAccessibilityLabel, eventTimeLabel, getIsToday, getWeekDays, groupEventsByDay, isAllDayEvent, isDateSelectable, isSameCalendarDay, isWeekend, lightColors, monthEventCapacity, monthVisibleCount, rangeBandKind, titleEllipsizeMode, titleNumberOfLines, useCalendarSelection, weekdayFormatToken } from "@super-calendar/core";
4
- import { LegendList } from "@legendapp/list/react-native";
5
4
  import { Platform, StyleSheet, Text, TouchableOpacity, View, useWindowDimensions } from "react-native";
6
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { LegendList } from "@legendapp/list/react-native";
7
7
  import { Gesture, GestureDetector } from "react-native-gesture-handler";
8
8
  //#region src/theme.ts
9
9
  /** The default light theme. Every key the calendar reads falls back to this. */
@@ -1,9 +1,9 @@
1
1
  let date_fns = require("date-fns");
2
2
  let react = require("react");
3
3
  let _super_calendar_core = require("@super-calendar/core");
4
- let _legendapp_list_react_native = require("@legendapp/list/react-native");
5
4
  let react_native = require("react-native");
6
5
  let react_jsx_runtime = require("react/jsx-runtime");
6
+ let _legendapp_list_react_native = require("@legendapp/list/react-native");
7
7
  let react_native_gesture_handler = require("react-native-gesture-handler");
8
8
  //#region src/theme.ts
9
9
  /** The default light theme. Every key the calendar reads falls back to this. */