@super-calendar/native 2.1.5 → 2.3.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/{DefaultMonthEvent-C-BiOsXb.d.mts → DefaultMonthEvent-BW6qy50X.d.ts} +62 -8
- package/dist/{DefaultMonthEvent-CcZLyfps.d.ts → DefaultMonthEvent-BbCMc60z.d.mts} +62 -8
- package/dist/{MonthList-BKlLes2B.mjs → MonthList-BidXJMfm.mjs} +98 -32
- package/dist/{MonthList-ege6HsEP.js → MonthList-CFXm7BK_.js} +102 -30
- package/dist/index.d.mts +110 -6
- package/dist/index.d.ts +110 -6
- package/dist/index.js +480 -113
- package/dist/index.mjs +476 -116
- package/dist/picker.d.mts +1 -1
- package/dist/picker.d.ts +1 -1
- package/dist/picker.js +1 -1
- package/dist/picker.mjs +1 -1
- package/package.json +2 -2
- package/src/components/Agenda.tsx +2 -2
- package/src/components/AllDayLane.tsx +11 -2
- package/src/components/Calendar.tsx +37 -3
- package/src/components/DefaultEvent.tsx +68 -47
- package/src/components/DefaultMonthEvent.tsx +11 -8
- package/src/components/MonthList.tsx +15 -2
- package/src/components/MonthPager.tsx +18 -10
- package/src/components/MonthView.tsx +39 -10
- package/src/components/ResourceTimeline.tsx +441 -0
- package/src/components/TimeGrid.tsx +54 -17
- package/src/index.tsx +10 -0
- package/src/theme.ts +74 -4
- package/src/types.ts +9 -0
- package/src/utils/withEventAccessibilityLabel.tsx +30 -0
|
@@ -63,8 +63,11 @@ import {
|
|
|
63
63
|
snapDeltaMinutes,
|
|
64
64
|
} from "@super-calendar/core";
|
|
65
65
|
import { formatHour, layoutDayEvents, type PositionedEvent } from "@super-calendar/core";
|
|
66
|
+
import type { EventAccessibilityLabeler } from "@super-calendar/core";
|
|
67
|
+
import { type WeekdayFormat, weekdayFormatToken } from "@super-calendar/core";
|
|
66
68
|
import { useWebGridZoom } from "../utils/useWebGridZoom";
|
|
67
69
|
import { useWebPagerKeys } from "../utils/useWebPagerKeys";
|
|
70
|
+
import { withEventAccessibilityLabel } from "../utils/withEventAccessibilityLabel";
|
|
68
71
|
import { AllDayLane } from "./AllDayLane";
|
|
69
72
|
|
|
70
73
|
// Horizontal swipe paging doesn't translate to web; there we disable it and page
|
|
@@ -370,7 +373,9 @@ function AnimatedEventBox<T>({
|
|
|
370
373
|
!draggable && onLongPress ? () => onLongPress(positioned.event) : undefined;
|
|
371
374
|
|
|
372
375
|
const box = (
|
|
373
|
-
<Animated.View
|
|
376
|
+
<Animated.View
|
|
377
|
+
style={[styles.eventBox, { left, width }, boxStyle, theme.containers.timeGridEvent]}
|
|
378
|
+
>
|
|
374
379
|
<RenderEventComponent
|
|
375
380
|
event={positioned.event}
|
|
376
381
|
mode={mode}
|
|
@@ -493,6 +498,7 @@ type NowIndicatorProps = {
|
|
|
493
498
|
};
|
|
494
499
|
|
|
495
500
|
const NowIndicator = ({ cellHeight, nowHours, minHour, left, width, color }: NowIndicatorProps) => {
|
|
501
|
+
const theme = useCalendarTheme();
|
|
496
502
|
const animatedStyle = useAnimatedStyle(
|
|
497
503
|
() => ({ top: (nowHours - minHour) * cellHeight.value }),
|
|
498
504
|
[nowHours, minHour],
|
|
@@ -505,6 +511,7 @@ const NowIndicator = ({ cellHeight, nowHours, minHour, left, width, color }: Now
|
|
|
505
511
|
styles.nonInteractive,
|
|
506
512
|
{ left, width, backgroundColor: color },
|
|
507
513
|
animatedStyle,
|
|
514
|
+
theme.containers.nowIndicator,
|
|
508
515
|
]}
|
|
509
516
|
/>
|
|
510
517
|
);
|
|
@@ -1179,7 +1186,15 @@ export type TimeGridProps<T> = {
|
|
|
1179
1186
|
/** Initial per-hour row height in px; seeds scroll/zoom without reading the shared value during render. */
|
|
1180
1187
|
hourHeight?: number;
|
|
1181
1188
|
weekStartsOn: WeekStartsOn;
|
|
1189
|
+
/** Column-header weekday label width: `narrow` ("M"), `short` ("Mon", default), or `long` ("Monday"). */
|
|
1190
|
+
weekdayFormat?: WeekdayFormat;
|
|
1182
1191
|
renderEvent: RenderEvent<T>;
|
|
1192
|
+
/**
|
|
1193
|
+
* Override the screen-reader label for each event. Receives the event and a
|
|
1194
|
+
* `{ mode, isAllDay, ampm }` context; return the full text to announce. Defaults
|
|
1195
|
+
* to the built-in title-and-time label.
|
|
1196
|
+
*/
|
|
1197
|
+
eventAccessibilityLabel?: EventAccessibilityLabeler<T>;
|
|
1183
1198
|
keyExtractor: EventKeyExtractor<T>;
|
|
1184
1199
|
scrollOffsetMinutes?: number;
|
|
1185
1200
|
hourColumnWidth?: number;
|
|
@@ -1258,7 +1273,9 @@ function TimeGridInner<T>({
|
|
|
1258
1273
|
cellHeight,
|
|
1259
1274
|
hourHeight = DEFAULT_HOUR_HEIGHT,
|
|
1260
1275
|
weekStartsOn,
|
|
1276
|
+
weekdayFormat = "short",
|
|
1261
1277
|
renderEvent,
|
|
1278
|
+
eventAccessibilityLabel,
|
|
1262
1279
|
keyExtractor,
|
|
1263
1280
|
scrollOffsetMinutes = 0,
|
|
1264
1281
|
hourColumnWidth: hourColumnWidthProp = DEFAULT_HOUR_COLUMN_WIDTH,
|
|
@@ -1304,6 +1321,14 @@ function TimeGridInner<T>({
|
|
|
1304
1321
|
// Collapse the hour gutter to zero when hours are hidden.
|
|
1305
1322
|
const hourColumnWidth = hideHours ? 0 : hourColumnWidthProp;
|
|
1306
1323
|
|
|
1324
|
+
// Inject a consumer's `eventAccessibilityLabel` override into every event once,
|
|
1325
|
+
// so the timed columns and the all-day lane share it without threading a prop
|
|
1326
|
+
// through each. Passes the grid's `ampm` so the label can match the clock.
|
|
1327
|
+
const labeledRenderEvent = useMemo(
|
|
1328
|
+
() => withEventAccessibilityLabel(renderEvent, eventAccessibilityLabel, ampm),
|
|
1329
|
+
[renderEvent, eventAccessibilityLabel, ampm],
|
|
1330
|
+
);
|
|
1331
|
+
|
|
1307
1332
|
const { width, height } = useWindowDimensions();
|
|
1308
1333
|
const listRef = useRef<LegendListRef>(null);
|
|
1309
1334
|
// The grid's outer view; on web its ref resolves to the DOM node we attach the
|
|
@@ -1590,7 +1615,7 @@ function TimeGridInner<T>({
|
|
|
1590
1615
|
minHourHeight={minHourHeight}
|
|
1591
1616
|
maxHourHeight={maxHourHeight}
|
|
1592
1617
|
showNowIndicator={showNowIndicator}
|
|
1593
|
-
renderEvent={
|
|
1618
|
+
renderEvent={labeledRenderEvent}
|
|
1594
1619
|
keyExtractor={keyExtractor}
|
|
1595
1620
|
snapMinutes={Math.max(1, dragStepMinutes)}
|
|
1596
1621
|
showDragHandle={showDragHandle}
|
|
@@ -1634,7 +1659,7 @@ function TimeGridInner<T>({
|
|
|
1634
1659
|
minHourHeight,
|
|
1635
1660
|
maxHourHeight,
|
|
1636
1661
|
showNowIndicator,
|
|
1637
|
-
|
|
1662
|
+
labeledRenderEvent,
|
|
1638
1663
|
keyExtractor,
|
|
1639
1664
|
dragStepMinutes,
|
|
1640
1665
|
showDragHandle,
|
|
@@ -1667,6 +1692,7 @@ function TimeGridInner<T>({
|
|
|
1667
1692
|
hourColumnWidth={hourColumnWidth}
|
|
1668
1693
|
showWeekNumber={showWeekNumber}
|
|
1669
1694
|
weekNumberPrefix={weekNumberPrefix}
|
|
1695
|
+
weekdayFormat={weekdayFormat}
|
|
1670
1696
|
locale={locale}
|
|
1671
1697
|
activeDate={activeDate}
|
|
1672
1698
|
onPressDateHeader={onPressDateHeader}
|
|
@@ -1747,6 +1773,7 @@ type DefaultHeaderProps = {
|
|
|
1747
1773
|
hourColumnWidth: number;
|
|
1748
1774
|
showWeekNumber?: boolean;
|
|
1749
1775
|
weekNumberPrefix?: string;
|
|
1776
|
+
weekdayFormat?: WeekdayFormat;
|
|
1750
1777
|
locale?: Locale;
|
|
1751
1778
|
activeDate?: Date;
|
|
1752
1779
|
onPressDateHeader?: (date: Date) => void;
|
|
@@ -1759,6 +1786,7 @@ const DefaultHeader = ({
|
|
|
1759
1786
|
hourColumnWidth,
|
|
1760
1787
|
showWeekNumber,
|
|
1761
1788
|
weekNumberPrefix = "W",
|
|
1789
|
+
weekdayFormat,
|
|
1762
1790
|
locale,
|
|
1763
1791
|
activeDate,
|
|
1764
1792
|
onPressDateHeader,
|
|
@@ -1785,6 +1813,7 @@ const DefaultHeader = ({
|
|
|
1785
1813
|
day={day}
|
|
1786
1814
|
mode={mode}
|
|
1787
1815
|
width={dayWidth}
|
|
1816
|
+
weekdayFormat={weekdayFormat}
|
|
1788
1817
|
locale={locale}
|
|
1789
1818
|
activeDate={activeDate}
|
|
1790
1819
|
onPressDateHeader={onPressDateHeader}
|
|
@@ -1798,12 +1827,20 @@ type DayHeaderProps = {
|
|
|
1798
1827
|
day: Date;
|
|
1799
1828
|
mode: CalendarMode;
|
|
1800
1829
|
width: number;
|
|
1830
|
+
weekdayFormat?: WeekdayFormat;
|
|
1801
1831
|
locale?: Locale;
|
|
1802
1832
|
activeDate?: Date;
|
|
1803
1833
|
onPressDateHeader?: (date: Date) => void;
|
|
1804
1834
|
};
|
|
1805
1835
|
|
|
1806
|
-
const DayHeader = ({
|
|
1836
|
+
const DayHeader = ({
|
|
1837
|
+
day,
|
|
1838
|
+
width,
|
|
1839
|
+
weekdayFormat = "short",
|
|
1840
|
+
locale,
|
|
1841
|
+
activeDate,
|
|
1842
|
+
onPressDateHeader,
|
|
1843
|
+
}: DayHeaderProps) => {
|
|
1807
1844
|
const theme = useCalendarTheme();
|
|
1808
1845
|
const isToday = getIsToday(day);
|
|
1809
1846
|
// Highlight the chosen `activeDate` when supplied, else the real today.
|
|
@@ -1811,28 +1848,36 @@ const DayHeader = ({ day, width, locale, activeDate, onPressDateHeader }: DayHea
|
|
|
1811
1848
|
|
|
1812
1849
|
return (
|
|
1813
1850
|
<Pressable
|
|
1814
|
-
style={[styles.dayHeader, { width }]}
|
|
1851
|
+
style={[styles.dayHeader, { width }, theme.containers.columnHeader]}
|
|
1815
1852
|
onPress={onPressDateHeader ? () => onPressDateHeader(day) : undefined}
|
|
1816
1853
|
disabled={!onPressDateHeader}
|
|
1817
1854
|
accessibilityRole={onPressDateHeader ? "button" : undefined}
|
|
1855
|
+
// A pressable header announces the full date it opens; a static one lets
|
|
1856
|
+
// the child labels speak for themselves.
|
|
1857
|
+
accessibilityLabel={onPressDateHeader ? format(day, "EEEE d MMMM", { locale }) : undefined}
|
|
1818
1858
|
>
|
|
1819
1859
|
{/* Mirrors the dom renderer's header: the muted weekday label sits above the
|
|
1820
|
-
day number, and the number's circle fills for today / the active date.
|
|
1860
|
+
day number, and the number's circle fills for today / the active date.
|
|
1861
|
+
Theme text merges after the muted colour so a themed colour wins. */}
|
|
1821
1862
|
<Text
|
|
1822
|
-
style={[
|
|
1863
|
+
style={[{ color: theme.colors.textMuted }, theme.text.columnHeaderWeekday]}
|
|
1823
1864
|
allowFontScaling={false}
|
|
1824
1865
|
>
|
|
1825
|
-
{format(day,
|
|
1866
|
+
{format(day, weekdayFormatToken(weekdayFormat), { locale })}
|
|
1826
1867
|
</Text>
|
|
1827
1868
|
<View
|
|
1869
|
+
testID="column-header-badge"
|
|
1828
1870
|
style={[
|
|
1829
1871
|
styles.dayHeaderBadge,
|
|
1872
|
+
theme.containers.columnHeaderBadge,
|
|
1830
1873
|
isHighlighted && { backgroundColor: theme.colors.todayBackground },
|
|
1831
1874
|
]}
|
|
1832
1875
|
>
|
|
1833
1876
|
<Text
|
|
1834
1877
|
style={[
|
|
1835
|
-
|
|
1878
|
+
theme.text.dayNumber,
|
|
1879
|
+
// The state colour stays last so a themed dayNumber can't break the
|
|
1880
|
+
// today/active contrast.
|
|
1836
1881
|
{ color: isHighlighted ? theme.colors.todayText : theme.colors.text },
|
|
1837
1882
|
]}
|
|
1838
1883
|
allowFontScaling={false}
|
|
@@ -1872,10 +1917,6 @@ const styles = StyleSheet.create({
|
|
|
1872
1917
|
gap: 2,
|
|
1873
1918
|
paddingVertical: 6,
|
|
1874
1919
|
},
|
|
1875
|
-
dayHeaderWeekday: {
|
|
1876
|
-
fontSize: 11,
|
|
1877
|
-
fontWeight: "600",
|
|
1878
|
-
},
|
|
1879
1920
|
dayHeaderBadge: {
|
|
1880
1921
|
// A fixed circle so the today/active fill never shifts the header's height.
|
|
1881
1922
|
width: 28,
|
|
@@ -1884,10 +1925,6 @@ const styles = StyleSheet.create({
|
|
|
1884
1925
|
justifyContent: "center",
|
|
1885
1926
|
alignItems: "center",
|
|
1886
1927
|
},
|
|
1887
|
-
dayHeaderNumber: {
|
|
1888
|
-
fontSize: 15,
|
|
1889
|
-
fontWeight: "600",
|
|
1890
|
-
},
|
|
1891
1928
|
content: {
|
|
1892
1929
|
width: "100%",
|
|
1893
1930
|
position: "relative",
|
package/src/index.tsx
CHANGED
|
@@ -35,6 +35,12 @@ export {
|
|
|
35
35
|
} from "./components/TimeGrid";
|
|
36
36
|
export { DefaultEvent } from "./components/DefaultEvent";
|
|
37
37
|
export { DefaultMonthEvent } from "./components/DefaultMonthEvent";
|
|
38
|
+
export {
|
|
39
|
+
ResourceTimeline,
|
|
40
|
+
type ResourceTimelineProps,
|
|
41
|
+
type Resource,
|
|
42
|
+
type ResourceEventArgs,
|
|
43
|
+
} from "./components/ResourceTimeline";
|
|
38
44
|
export {
|
|
39
45
|
type CalendarTheme,
|
|
40
46
|
type PartialCalendarTheme,
|
|
@@ -48,6 +54,8 @@ export type {
|
|
|
48
54
|
BusinessHours,
|
|
49
55
|
CalendarEvent,
|
|
50
56
|
CalendarMode,
|
|
57
|
+
EventAccessibilityLabelContext,
|
|
58
|
+
EventAccessibilityLabeler,
|
|
51
59
|
EventKeyExtractor,
|
|
52
60
|
ICalendarEvent,
|
|
53
61
|
RecurrenceFrequency,
|
|
@@ -55,6 +63,7 @@ export type {
|
|
|
55
63
|
RenderEvent,
|
|
56
64
|
RenderEventArgs,
|
|
57
65
|
TimeGridMode,
|
|
66
|
+
WeekdayFormat,
|
|
58
67
|
WeekStartsOn,
|
|
59
68
|
} from "./types";
|
|
60
69
|
export {
|
|
@@ -77,6 +86,7 @@ export {
|
|
|
77
86
|
type MonthGridWeekday,
|
|
78
87
|
type UseMonthGridOptions,
|
|
79
88
|
useMonthGrid,
|
|
89
|
+
weekdayFormatToken,
|
|
80
90
|
} from "@super-calendar/core";
|
|
81
91
|
export { expandRecurringEvents } from "@super-calendar/core";
|
|
82
92
|
export { eventsInTimeZone, toZonedTime } from "@super-calendar/core";
|
package/src/theme.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type CalendarColors, darkColors, lightColors } from "@super-calendar/core";
|
|
2
2
|
import { type Context, createContext, useContext } from "react";
|
|
3
|
-
import type { TextStyle } from "react-native";
|
|
3
|
+
import type { TextStyle, ViewStyle } from "react-native";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* The full set of colours, text styles and metrics the calendar paints with.
|
|
@@ -12,10 +12,14 @@ export interface CalendarTheme {
|
|
|
12
12
|
colors: CalendarColors;
|
|
13
13
|
/** Text styles for the calendar's labels and the built-in event box. */
|
|
14
14
|
text: {
|
|
15
|
-
/**
|
|
15
|
+
/** The day number in a time-grid (week/day) column header. */
|
|
16
16
|
dayNumber: TextStyle;
|
|
17
|
-
/**
|
|
17
|
+
/** The weekday label ("Mon") in a time-grid column header. */
|
|
18
|
+
columnHeaderWeekday: TextStyle;
|
|
19
|
+
/** Short weekday label ("Mon") in the month grid's header row. */
|
|
18
20
|
weekday: TextStyle;
|
|
21
|
+
/** The "MMMM yyyy" month title above the month grid. */
|
|
22
|
+
monthTitle: TextStyle;
|
|
19
23
|
/** Date number inside a month cell. */
|
|
20
24
|
dateCell: TextStyle;
|
|
21
25
|
/** Hour labels down the left of the time grid. */
|
|
@@ -25,6 +29,46 @@ export interface CalendarTheme {
|
|
|
25
29
|
/** Title inside the built-in default event box. */
|
|
26
30
|
eventTitle: TextStyle;
|
|
27
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* Per-part `ViewStyle` overrides for the renderer's container elements, the
|
|
34
|
+
* React Native counterpart of the web renderer's per-slot classes. Each is
|
|
35
|
+
* merged onto the built-in style, so you override only what you set. (Rolling
|
|
36
|
+
* out across the views; more slots as they land.)
|
|
37
|
+
*/
|
|
38
|
+
containers: {
|
|
39
|
+
/** The month view's outer container (title + weekday header + grid). */
|
|
40
|
+
monthContainer: ViewStyle;
|
|
41
|
+
/** The weekday-label header row above a month grid. */
|
|
42
|
+
weekdayHeader: ViewStyle;
|
|
43
|
+
/** Each week (row of 7 day cells) in the month grid. */
|
|
44
|
+
weekRow: ViewStyle;
|
|
45
|
+
/** Each day cell in the month grid. */
|
|
46
|
+
dayCell: ViewStyle;
|
|
47
|
+
/** The date badge (the circle) inside a month day cell. */
|
|
48
|
+
dayBadge: ViewStyle;
|
|
49
|
+
/** An event chip inside a month day cell. */
|
|
50
|
+
monthEvent: ViewStyle;
|
|
51
|
+
/** Each day's column header in the time grid. */
|
|
52
|
+
columnHeader: ViewStyle;
|
|
53
|
+
/** The day-number badge (the circle) inside a time-grid column header. */
|
|
54
|
+
columnHeaderBadge: ViewStyle;
|
|
55
|
+
/** A timed event's positioned box in the time grid (and resource timeline). */
|
|
56
|
+
timeGridEvent: ViewStyle;
|
|
57
|
+
/** The current-time indicator line. */
|
|
58
|
+
nowIndicator: ViewStyle;
|
|
59
|
+
/** Each resource row in the resource timeline. */
|
|
60
|
+
resourceRow: ViewStyle;
|
|
61
|
+
/** The left-hand resource-label cell in the resource timeline. */
|
|
62
|
+
resourceLabel: ViewStyle;
|
|
63
|
+
/** The schedule/agenda list's outer container. */
|
|
64
|
+
agendaList: ViewStyle;
|
|
65
|
+
/** Each event row in the agenda list. */
|
|
66
|
+
agendaRow: ViewStyle;
|
|
67
|
+
/** The all-day lane above the time grid. */
|
|
68
|
+
allDayLane: ViewStyle;
|
|
69
|
+
/** Each day's column within the all-day lane. */
|
|
70
|
+
allDayColumn: ViewStyle;
|
|
71
|
+
};
|
|
28
72
|
/** Corner radius of the today badge. Use a large value for a circle. */
|
|
29
73
|
todayBadgeRadius: number;
|
|
30
74
|
/**
|
|
@@ -38,8 +82,13 @@ export interface CalendarTheme {
|
|
|
38
82
|
export const defaultTheme: CalendarTheme = {
|
|
39
83
|
colors: lightColors,
|
|
40
84
|
text: {
|
|
41
|
-
|
|
85
|
+
// Match the header's shipped look: these two previously lived as hardcoded
|
|
86
|
+
// styles in the time-grid header, so honouring the theme changes nothing
|
|
87
|
+
// until a consumer overrides them.
|
|
88
|
+
dayNumber: { fontSize: 15, fontWeight: "600" },
|
|
89
|
+
columnHeaderWeekday: { fontSize: 11, fontWeight: "600" },
|
|
42
90
|
weekday: { fontSize: 13, fontWeight: "700" },
|
|
91
|
+
monthTitle: { fontSize: 17, fontWeight: "700" },
|
|
43
92
|
dateCell: { fontSize: 13, fontWeight: "700" },
|
|
44
93
|
hourLabel: { fontSize: 10 },
|
|
45
94
|
more: { fontSize: 11, fontWeight: "700" },
|
|
@@ -47,6 +96,24 @@ export const defaultTheme: CalendarTheme = {
|
|
|
47
96
|
// whole number of lines (clipping on a line boundary, never mid-line).
|
|
48
97
|
eventTitle: { fontSize: 12, fontWeight: "700", lineHeight: 16 },
|
|
49
98
|
},
|
|
99
|
+
containers: {
|
|
100
|
+
monthContainer: {},
|
|
101
|
+
weekdayHeader: {},
|
|
102
|
+
weekRow: {},
|
|
103
|
+
dayCell: {},
|
|
104
|
+
dayBadge: {},
|
|
105
|
+
monthEvent: {},
|
|
106
|
+
columnHeader: {},
|
|
107
|
+
columnHeaderBadge: {},
|
|
108
|
+
timeGridEvent: {},
|
|
109
|
+
nowIndicator: {},
|
|
110
|
+
resourceRow: {},
|
|
111
|
+
resourceLabel: {},
|
|
112
|
+
agendaList: {},
|
|
113
|
+
agendaRow: {},
|
|
114
|
+
allDayLane: {},
|
|
115
|
+
allDayColumn: {},
|
|
116
|
+
},
|
|
50
117
|
todayBadgeRadius: 999,
|
|
51
118
|
rangeBandHeight: 22,
|
|
52
119
|
};
|
|
@@ -59,6 +126,7 @@ export const defaultTheme: CalendarTheme = {
|
|
|
59
126
|
export const darkTheme: CalendarTheme = {
|
|
60
127
|
colors: darkColors,
|
|
61
128
|
text: defaultTheme.text,
|
|
129
|
+
containers: defaultTheme.containers,
|
|
62
130
|
todayBadgeRadius: defaultTheme.todayBadgeRadius,
|
|
63
131
|
rangeBandHeight: defaultTheme.rangeBandHeight,
|
|
64
132
|
};
|
|
@@ -69,6 +137,7 @@ export function mergeTheme(theme?: PartialCalendarTheme): CalendarTheme {
|
|
|
69
137
|
return {
|
|
70
138
|
colors: { ...defaultTheme.colors, ...theme.colors },
|
|
71
139
|
text: { ...defaultTheme.text, ...theme.text },
|
|
140
|
+
containers: { ...defaultTheme.containers, ...theme.containers },
|
|
72
141
|
todayBadgeRadius: theme.todayBadgeRadius ?? defaultTheme.todayBadgeRadius,
|
|
73
142
|
rangeBandHeight: theme.rangeBandHeight ?? defaultTheme.rangeBandHeight,
|
|
74
143
|
};
|
|
@@ -82,6 +151,7 @@ export function mergeTheme(theme?: PartialCalendarTheme): CalendarTheme {
|
|
|
82
151
|
export type PartialCalendarTheme = {
|
|
83
152
|
colors?: Partial<CalendarTheme["colors"]>;
|
|
84
153
|
text?: Partial<CalendarTheme["text"]>;
|
|
154
|
+
containers?: Partial<CalendarTheme["containers"]>;
|
|
85
155
|
todayBadgeRadius?: number;
|
|
86
156
|
rangeBandHeight?: number;
|
|
87
157
|
};
|
package/src/types.ts
CHANGED
|
@@ -9,11 +9,14 @@ export type {
|
|
|
9
9
|
BusinessHours,
|
|
10
10
|
CalendarEvent,
|
|
11
11
|
CalendarMode,
|
|
12
|
+
EventAccessibilityLabelContext,
|
|
13
|
+
EventAccessibilityLabeler,
|
|
12
14
|
EventKeyExtractor,
|
|
13
15
|
ICalendarEvent,
|
|
14
16
|
RecurrenceFrequency,
|
|
15
17
|
RecurrenceRule,
|
|
16
18
|
TimeGridMode,
|
|
19
|
+
WeekdayFormat,
|
|
17
20
|
WeekStartsOn,
|
|
18
21
|
} from "@super-calendar/core";
|
|
19
22
|
|
|
@@ -53,6 +56,12 @@ export type RenderEventArgs<T = unknown> = {
|
|
|
53
56
|
allDayLabel?: string;
|
|
54
57
|
/** Per-event style resolved from `eventCellStyle`; the built-in renderer merges it onto the box. */
|
|
55
58
|
cellStyle?: StyleProp<ViewStyle>;
|
|
59
|
+
/**
|
|
60
|
+
* Screen-reader label to announce for the event, injected by a consumer's
|
|
61
|
+
* `eventAccessibilityLabel` override. The built-in renderers use it in place of
|
|
62
|
+
* their default label; `undefined` falls back to that default.
|
|
63
|
+
*/
|
|
64
|
+
accessibilityLabel?: string;
|
|
56
65
|
onPress: () => void;
|
|
57
66
|
/** Wired when the consumer passes `onLongPressEvent`; otherwise undefined. */
|
|
58
67
|
onLongPress?: () => void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { EventAccessibilityLabeler } from "@super-calendar/core";
|
|
2
|
+
import type { RenderEvent, RenderEventArgs } from "../types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Wrap an event renderer so it injects a consumer's `eventAccessibilityLabel`
|
|
6
|
+
* override into `RenderEventArgs.accessibilityLabel`. The built-in renderers use
|
|
7
|
+
* that string in place of their default label, and custom renderers can read it
|
|
8
|
+
* too. Returns the renderer unchanged when no override is set, so the common path
|
|
9
|
+
* pays nothing.
|
|
10
|
+
*/
|
|
11
|
+
export function withEventAccessibilityLabel<T>(
|
|
12
|
+
renderEvent: RenderEvent<T>,
|
|
13
|
+
labeler: EventAccessibilityLabeler<T> | undefined,
|
|
14
|
+
ampm: boolean,
|
|
15
|
+
): RenderEvent<T> {
|
|
16
|
+
if (!labeler) return renderEvent;
|
|
17
|
+
const Base = renderEvent;
|
|
18
|
+
return function LabeledEvent(props: RenderEventArgs<T>) {
|
|
19
|
+
return (
|
|
20
|
+
<Base
|
|
21
|
+
{...props}
|
|
22
|
+
accessibilityLabel={labeler(props.event, {
|
|
23
|
+
mode: props.mode,
|
|
24
|
+
isAllDay: props.isAllDay ?? false,
|
|
25
|
+
ampm,
|
|
26
|
+
})}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
}
|