@dreamstack-us/kaal 0.0.2 → 0.0.3
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/README.md +165 -0
- package/lib/module/components/CalendarGrid/CalendarGrid.js +80 -18
- package/lib/module/components/CalendarGrid/CalendarGrid.js.map +1 -1
- package/lib/module/components/CalendarGrid/CalendarGrid.web.js +80 -18
- package/lib/module/components/CalendarGrid/CalendarGrid.web.js.map +1 -1
- package/lib/module/components/CalendarGrid/DayCell.js +17 -5
- package/lib/module/components/CalendarGrid/DayCell.js.map +1 -1
- package/lib/module/components/CalendarGrid/DayCell.web.js +17 -5
- package/lib/module/components/CalendarGrid/DayCell.web.js.map +1 -1
- package/lib/module/components/DatePicker/DatePicker.android.js +42 -19
- package/lib/module/components/DatePicker/DatePicker.android.js.map +1 -1
- package/lib/module/components/DatePicker/DatePicker.ios.js +44 -21
- package/lib/module/components/DatePicker/DatePicker.ios.js.map +1 -1
- package/lib/module/components/DatePicker/DatePicker.js.map +1 -1
- package/lib/module/components/DatePicker/DatePicker.web.js +40 -16
- package/lib/module/components/DatePicker/DatePicker.web.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/components/CalendarGrid/CalendarGrid.d.ts +19 -7
- package/lib/typescript/components/CalendarGrid/CalendarGrid.d.ts.map +1 -1
- package/lib/typescript/components/CalendarGrid/CalendarGrid.web.d.ts +19 -7
- package/lib/typescript/components/CalendarGrid/CalendarGrid.web.d.ts.map +1 -1
- package/lib/typescript/components/CalendarGrid/DayCell.d.ts +3 -0
- package/lib/typescript/components/CalendarGrid/DayCell.d.ts.map +1 -1
- package/lib/typescript/components/CalendarGrid/DayCell.web.d.ts +3 -0
- package/lib/typescript/components/CalendarGrid/DayCell.web.d.ts.map +1 -1
- package/lib/typescript/components/DatePicker/DatePicker.android.d.ts.map +1 -1
- package/lib/typescript/components/DatePicker/DatePicker.d.ts +20 -8
- package/lib/typescript/components/DatePicker/DatePicker.d.ts.map +1 -1
- package/lib/typescript/components/DatePicker/DatePicker.ios.d.ts.map +1 -1
- package/lib/typescript/components/DatePicker/DatePicker.web.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/types/datepicker.d.ts +37 -3
- package/lib/typescript/types/datepicker.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/CalendarGrid/CalendarGrid.tsx +216 -122
- package/src/components/CalendarGrid/CalendarGrid.web.tsx +227 -136
- package/src/components/CalendarGrid/DayCell.tsx +48 -6
- package/src/components/CalendarGrid/DayCell.web.tsx +48 -6
- package/src/components/DatePicker/DatePicker.android.tsx +39 -21
- package/src/components/DatePicker/DatePicker.ios.tsx +42 -24
- package/src/components/DatePicker/DatePicker.tsx +28 -8
- package/src/components/DatePicker/DatePicker.web.tsx +40 -16
- package/src/index.ts +2 -0
- package/src/types/datepicker.ts +43 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePicker.ios.d.ts","sourceRoot":"","sources":["../../../../src/components/DatePicker/DatePicker.ios.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"DatePicker.ios.d.ts","sourceRoot":"","sources":["../../../../src/components/DatePicker/DatePicker.ios.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAKxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAgCxD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAgEpD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePicker.web.d.ts","sourceRoot":"","sources":["../../../../src/components/DatePicker/DatePicker.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,
|
|
1
|
+
{"version":3,"file":"DatePicker.web.d.ts","sourceRoot":"","sources":["../../../../src/components/DatePicker/DatePicker.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAExD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA6DpD,CAAC"}
|
|
@@ -7,7 +7,7 @@ export { useTimePicker, to12Hour, to24Hour, formatTime, snapToInterval, } from '
|
|
|
7
7
|
export { toISODateString, toISODateTimeString, parseISODate, parseISODateTime, fromISODateString, fromISODateTimeString, getDateRange, isDateInRange, getUserTimezone, addDays, addMonths, compareDates, isSameDay, isSameMonth, getMonthDays, getFirstDayOfMonth, getLastDayOfMonth, getDayOfWeek, formatMonth, formatWeekday, formatYearMonth, today, } from './utils';
|
|
8
8
|
export { isoDateSchema, isoDateTimeSchema, dateRangeSchema, datePickerValueSchema, dateSchema, temporalDateSchema, } from './utils';
|
|
9
9
|
export type { DatePickerValue, DateRange } from './utils';
|
|
10
|
-
export type { DatePickerMode, DatePickerTheme, DatePickerVariant, DatePickerProps, DatePickerThemeOverrides, } from './types';
|
|
10
|
+
export type { DatePickerMode, DatePickerTheme, DatePickerVariant, DatePickerSelectionMode, DatePickerProps, DatePickerThemeOverrides, DateRange as DatePickerDateRange, } from './types';
|
|
11
11
|
export type { TimePeriod, ClockMode, Time12Hour, MinuteInterval, TimePickerTheme, TimePickerThemeOverrides, } from './types';
|
|
12
12
|
export { ThemeOverrideProvider, useDatePickerOverrides, useTimePickerOverrides, useThemeOverrides, } from './context/ThemeOverrideContext';
|
|
13
13
|
export type { ThemeOverrideContextValue } from './context/ThemeOverrideContext';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EACL,UAAU,EACV,eAAe,EACf,SAAS,EACT,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,SAAS,GACf,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EACL,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,OAAO,EACP,SAAS,EACT,YAAY,EACZ,SAAS,EACT,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,aAAa,EACb,eAAe,EACf,KAAK,GACN,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC1D,YAAY,EACV,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,wBAAwB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EACL,UAAU,EACV,eAAe,EACf,SAAS,EACT,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,SAAS,GACf,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EACL,aAAa,EACb,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,OAAO,EACP,SAAS,EACT,YAAY,EACZ,SAAS,EACT,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,aAAa,EACb,eAAe,EACf,KAAK,GACN,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC1D,YAAY,EACV,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,wBAAwB,EACxB,SAAS,IAAI,mBAAmB,GACjC,MAAM,SAAS,CAAC;AAGjB,YAAY,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,cAAc,EACd,eAAe,EACf,wBAAwB,GACzB,MAAM,SAAS,CAAC;AAGjB,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
export type DatePickerMode = 'date' | 'time' | 'datetime';
|
|
2
2
|
export type DatePickerTheme = 'native' | 'ios' | 'android' | 'custom';
|
|
3
3
|
export type DatePickerVariant = 'wheel' | 'calendar' | 'compact';
|
|
4
|
+
export type DatePickerSelectionMode = 'single' | 'range';
|
|
5
|
+
export interface DateRange {
|
|
6
|
+
startDate: Date;
|
|
7
|
+
endDate: Date | null;
|
|
8
|
+
}
|
|
4
9
|
/**
|
|
5
10
|
* Theme overrides for DatePicker components.
|
|
6
11
|
* These allow customizing colors without matching Kaal's internal theme structure.
|
|
@@ -30,10 +35,15 @@ export interface DatePickerThemeOverrides {
|
|
|
30
35
|
cellBorderRadius?: number;
|
|
31
36
|
/** Padding for calendar container */
|
|
32
37
|
padding?: number;
|
|
38
|
+
/** Background color for dates in range (between start and end) */
|
|
39
|
+
cellInRangeColor?: string;
|
|
40
|
+
/** Text color for dates in range */
|
|
41
|
+
textInRangeColor?: string;
|
|
33
42
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Base props shared between single and range selection modes
|
|
45
|
+
*/
|
|
46
|
+
interface DatePickerBaseProps {
|
|
37
47
|
mode?: DatePickerMode;
|
|
38
48
|
theme?: DatePickerTheme;
|
|
39
49
|
variant?: DatePickerVariant;
|
|
@@ -53,4 +63,28 @@ export interface DatePickerProps {
|
|
|
53
63
|
/** Custom theme overrides for styling without matching Kaal's theme structure */
|
|
54
64
|
themeOverrides?: DatePickerThemeOverrides;
|
|
55
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Props for single date selection mode (default)
|
|
68
|
+
*/
|
|
69
|
+
interface DatePickerSingleProps extends DatePickerBaseProps {
|
|
70
|
+
selectionMode?: 'single';
|
|
71
|
+
value: Date;
|
|
72
|
+
onChange: (date: Date) => void;
|
|
73
|
+
startDate?: never;
|
|
74
|
+
endDate?: never;
|
|
75
|
+
onRangeChange?: never;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Props for range selection mode
|
|
79
|
+
*/
|
|
80
|
+
interface DatePickerRangeProps extends DatePickerBaseProps {
|
|
81
|
+
selectionMode: 'range';
|
|
82
|
+
startDate: Date | null;
|
|
83
|
+
endDate: Date | null;
|
|
84
|
+
onRangeChange: (range: DateRange) => void;
|
|
85
|
+
value?: never;
|
|
86
|
+
onChange?: never;
|
|
87
|
+
}
|
|
88
|
+
export type DatePickerProps = DatePickerSingleProps | DatePickerRangeProps;
|
|
89
|
+
export {};
|
|
56
90
|
//# sourceMappingURL=datepicker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"datepicker.d.ts","sourceRoot":"","sources":["../../../src/types/datepicker.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEtE,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;AAEjE;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IAEvC,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oCAAoC;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iCAAiC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"datepicker.d.ts","sourceRoot":"","sources":["../../../src/types/datepicker.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;AAE1D,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEtE,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAC;AAEjE,MAAM,MAAM,uBAAuB,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,IAAI,CAAC;IAChB,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IAEvC,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oCAAoC;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iCAAiC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,2CAA2C;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,UAAU,mBAAmB;IAC3B,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,aAAa,CAAC,EAAE,IAAI,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACrB,iFAAiF;IACjF,cAAc,CAAC,EAAE,wBAAwB,CAAC;CAC3C;AAED;;GAEG;AACH,UAAU,qBAAsB,SAAQ,mBAAmB;IACzD,aAAa,CAAC,EAAE,QAAQ,CAAC;IACzB,KAAK,EAAE,IAAI,CAAC;IACZ,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAE/B,SAAS,CAAC,EAAE,KAAK,CAAC;IAClB,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,aAAa,CAAC,EAAE,KAAK,CAAC;CACvB;AAED;;GAEG;AACH,UAAU,oBAAqB,SAAQ,mBAAmB;IACxD,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAE1C,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,MAAM,MAAM,eAAe,GAAG,qBAAqB,GAAG,oBAAoB,CAAC"}
|
package/package.json
CHANGED
|
@@ -14,9 +14,9 @@ import {
|
|
|
14
14
|
import { styles } from './CalendarGrid.styles';
|
|
15
15
|
import { DayCell } from './DayCell';
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
import type { DateRange } from '../../types/datepicker';
|
|
18
|
+
|
|
19
|
+
interface CalendarGridBaseProps {
|
|
20
20
|
minDate?: Date;
|
|
21
21
|
maxDate?: Date;
|
|
22
22
|
disabledDates?: Date[];
|
|
@@ -24,14 +24,30 @@ interface CalendarGridProps {
|
|
|
24
24
|
/**
|
|
25
25
|
* First day of the week: 0 = Sunday, 1 = Monday
|
|
26
26
|
* @default 0 (Sunday)
|
|
27
|
-
*
|
|
28
|
-
* TODO: This is a temporary solution. In the future, we need to add full
|
|
29
|
-
* locale support to handle different calendar formats, layouts, and
|
|
30
|
-
* localized day/month names across different regions.
|
|
31
27
|
*/
|
|
32
28
|
weekStartsOn?: 0 | 1;
|
|
33
29
|
}
|
|
34
30
|
|
|
31
|
+
interface CalendarGridSingleProps extends CalendarGridBaseProps {
|
|
32
|
+
selectionMode?: 'single';
|
|
33
|
+
value: Date;
|
|
34
|
+
onChange: (date: Date) => void;
|
|
35
|
+
startDate?: never;
|
|
36
|
+
endDate?: never;
|
|
37
|
+
onRangeChange?: never;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface CalendarGridRangeProps extends CalendarGridBaseProps {
|
|
41
|
+
selectionMode: 'range';
|
|
42
|
+
startDate: Date | null;
|
|
43
|
+
endDate: Date | null;
|
|
44
|
+
onRangeChange: (range: DateRange) => void;
|
|
45
|
+
value?: never;
|
|
46
|
+
onChange?: never;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type CalendarGridProps = CalendarGridSingleProps | CalendarGridRangeProps;
|
|
50
|
+
|
|
35
51
|
const CELL_SIZE = 44;
|
|
36
52
|
|
|
37
53
|
// Week day labels starting from Sunday
|
|
@@ -100,138 +116,216 @@ const generateMonthDays = (
|
|
|
100
116
|
return days;
|
|
101
117
|
};
|
|
102
118
|
|
|
103
|
-
export const CalendarGrid: React.FC<CalendarGridProps> = memo(
|
|
104
|
-
|
|
105
|
-
value,
|
|
106
|
-
onChange,
|
|
119
|
+
export const CalendarGrid: React.FC<CalendarGridProps> = memo((props) => {
|
|
120
|
+
const {
|
|
107
121
|
minDate,
|
|
108
122
|
maxDate,
|
|
109
123
|
disabledDates,
|
|
110
124
|
themeMode,
|
|
111
125
|
weekStartsOn = 0,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
126
|
+
selectionMode = 'single',
|
|
127
|
+
} = props;
|
|
128
|
+
|
|
129
|
+
// Extract mode-specific props
|
|
130
|
+
const singleValue = selectionMode === 'single' ? props.value : null;
|
|
131
|
+
const singleOnChange = selectionMode === 'single' ? props.onChange : null;
|
|
132
|
+
const rangeStart = selectionMode === 'range' ? props.startDate : null;
|
|
133
|
+
const rangeEnd = selectionMode === 'range' ? props.endDate : null;
|
|
134
|
+
const rangeOnChange = selectionMode === 'range' ? props.onRangeChange : null;
|
|
135
|
+
|
|
136
|
+
const overrides = useDatePickerOverrides();
|
|
137
|
+
const [currentMonth, setCurrentMonth] = React.useState(() =>
|
|
138
|
+
getFirstDayOfMonth(singleValue ?? rangeStart ?? new Date()),
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
const days = useMemo(
|
|
142
|
+
() => generateMonthDays(currentMonth, weekStartsOn),
|
|
143
|
+
[currentMonth, weekStartsOn],
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const weekDays =
|
|
147
|
+
weekStartsOn === 0 ? WEEK_DAYS_SUNDAY_START : WEEK_DAYS_MONDAY_START;
|
|
148
|
+
|
|
149
|
+
const todayDate = useMemo(() => today(), []);
|
|
150
|
+
|
|
151
|
+
const isDisabled = useCallback(
|
|
152
|
+
(date: Date | null): boolean => {
|
|
153
|
+
if (!date) return true;
|
|
154
|
+
if (minDate && compareDates(date, minDate) < 0) return true;
|
|
155
|
+
if (maxDate && compareDates(date, maxDate) > 0) return true;
|
|
156
|
+
if (disabledDates?.some((d) => isSameDay(date, d))) return true;
|
|
157
|
+
return false;
|
|
158
|
+
},
|
|
159
|
+
[minDate, maxDate, disabledDates],
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const navigateMonth = useCallback((direction: 1 | -1) => {
|
|
163
|
+
setCurrentMonth((prev) => addMonths(prev, direction));
|
|
164
|
+
}, []);
|
|
165
|
+
|
|
166
|
+
// Handle date press for both single and range modes
|
|
167
|
+
const handleDatePress = useCallback(
|
|
168
|
+
(date: Date) => {
|
|
169
|
+
if (selectionMode === 'single' && singleOnChange) {
|
|
170
|
+
singleOnChange(date);
|
|
171
|
+
} else if (selectionMode === 'range' && rangeOnChange) {
|
|
172
|
+
// Range selection logic:
|
|
173
|
+
// 1. If no start date, set start date
|
|
174
|
+
// 2. If start date but no end date, set end date (if after start)
|
|
175
|
+
// 3. If both dates exist, reset to new start date
|
|
176
|
+
if (!rangeStart || (rangeStart && rangeEnd)) {
|
|
177
|
+
rangeOnChange({ startDate: date, endDate: null });
|
|
178
|
+
} else {
|
|
179
|
+
// Have start but no end
|
|
180
|
+
if (compareDates(date, rangeStart) < 0) {
|
|
181
|
+
// Clicked before start - make this the new start
|
|
182
|
+
rangeOnChange({ startDate: date, endDate: null });
|
|
183
|
+
} else if (isSameDay(date, rangeStart)) {
|
|
184
|
+
// Clicked same day - clear selection
|
|
185
|
+
rangeOnChange({ startDate: date, endDate: null });
|
|
186
|
+
} else {
|
|
187
|
+
// Clicked after start - set as end date
|
|
188
|
+
rangeOnChange({ startDate: rangeStart, endDate: date });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
[selectionMode, singleOnChange, rangeOnChange, rangeStart, rangeEnd],
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
// Check if date is in range (between start and end)
|
|
197
|
+
const isDateInRange = useCallback(
|
|
198
|
+
(date: Date | null): boolean => {
|
|
199
|
+
if (!date || selectionMode !== 'range' || !rangeStart || !rangeEnd) {
|
|
134
200
|
return false;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
201
|
+
}
|
|
202
|
+
return (
|
|
203
|
+
compareDates(date, rangeStart) > 0 && compareDates(date, rangeEnd) < 0
|
|
204
|
+
);
|
|
205
|
+
},
|
|
206
|
+
[selectionMode, rangeStart, rangeEnd],
|
|
207
|
+
);
|
|
138
208
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
209
|
+
const renderDay = useCallback(
|
|
210
|
+
({ item }: { item: Date | null }) => {
|
|
211
|
+
const isRangeStart =
|
|
212
|
+
selectionMode === 'range' && item && rangeStart
|
|
213
|
+
? isSameDay(item, rangeStart)
|
|
214
|
+
: false;
|
|
215
|
+
const isRangeEnd =
|
|
216
|
+
selectionMode === 'range' && item && rangeEnd
|
|
217
|
+
? isSameDay(item, rangeEnd)
|
|
218
|
+
: false;
|
|
219
|
+
const isSelected =
|
|
220
|
+
selectionMode === 'single' && item && singleValue
|
|
221
|
+
? isSameDay(item, singleValue)
|
|
222
|
+
: false;
|
|
142
223
|
|
|
143
|
-
|
|
144
|
-
({ item }: { item: Date | null }) => (
|
|
224
|
+
return (
|
|
145
225
|
<DayCell
|
|
146
226
|
date={item}
|
|
147
|
-
isSelected={
|
|
227
|
+
isSelected={isSelected}
|
|
148
228
|
isToday={item ? isSameDay(item, todayDate) : false}
|
|
149
229
|
isDisabled={isDisabled(item)}
|
|
150
230
|
isWeekend={
|
|
151
231
|
item ? getDayOfWeek(item) === 0 || getDayOfWeek(item) === 6 : false
|
|
152
232
|
}
|
|
153
|
-
|
|
233
|
+
isRangeStart={isRangeStart}
|
|
234
|
+
isRangeEnd={isRangeEnd}
|
|
235
|
+
isInRange={isDateInRange(item)}
|
|
236
|
+
onPress={
|
|
237
|
+
item && !isDisabled(item) ? () => handleDatePress(item) : undefined
|
|
238
|
+
}
|
|
154
239
|
/>
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
240
|
+
);
|
|
241
|
+
},
|
|
242
|
+
[
|
|
243
|
+
selectionMode,
|
|
244
|
+
singleValue,
|
|
245
|
+
rangeStart,
|
|
246
|
+
rangeEnd,
|
|
247
|
+
todayDate,
|
|
248
|
+
isDisabled,
|
|
249
|
+
isDateInRange,
|
|
250
|
+
handleDatePress,
|
|
251
|
+
],
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
const keyExtractor = useCallback(
|
|
255
|
+
(item: Date | null, index: number) =>
|
|
256
|
+
item?.toISOString() ?? `empty-${index}`,
|
|
257
|
+
[],
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
const getItemLayout = useCallback(
|
|
261
|
+
(_data: ArrayLike<Date | null> | null | undefined, index: number) => ({
|
|
262
|
+
length: CELL_SIZE,
|
|
263
|
+
offset: CELL_SIZE * Math.floor(index / 7),
|
|
264
|
+
index,
|
|
265
|
+
}),
|
|
266
|
+
[],
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
// Build override styles from themeOverrides
|
|
270
|
+
const containerStyle = useMemo(
|
|
271
|
+
() => ({
|
|
272
|
+
backgroundColor: overrides?.backgroundColor ?? '#1E1E1E',
|
|
273
|
+
borderRadius: overrides?.borderRadius ?? 16,
|
|
274
|
+
padding: overrides?.padding ?? 16,
|
|
275
|
+
}),
|
|
276
|
+
[overrides],
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const navTextStyle = useMemo(
|
|
280
|
+
() => ({
|
|
281
|
+
color: overrides?.primaryColor ?? '#4DA6FF',
|
|
282
|
+
}),
|
|
283
|
+
[overrides],
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
const monthTitleStyle = useMemo(
|
|
287
|
+
() => ({
|
|
288
|
+
color: overrides?.textColor ?? '#FFFFFF',
|
|
289
|
+
}),
|
|
290
|
+
[overrides],
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
return (
|
|
294
|
+
<View style={[styles.container, containerStyle]}>
|
|
295
|
+
<View style={styles.header}>
|
|
296
|
+
<Pressable onPress={() => navigateMonth(-1)} style={styles.navButton}>
|
|
297
|
+
<Text style={[styles.navText, navTextStyle]}>‹</Text>
|
|
298
|
+
</Pressable>
|
|
299
|
+
<Text style={[styles.monthTitle, monthTitleStyle]}>
|
|
300
|
+
{formatYearMonth(currentMonth)}
|
|
301
|
+
</Text>
|
|
302
|
+
<Pressable onPress={() => navigateMonth(1)} style={styles.navButton}>
|
|
303
|
+
<Text style={[styles.navText, navTextStyle]}>›</Text>
|
|
304
|
+
</Pressable>
|
|
305
|
+
</View>
|
|
306
|
+
|
|
307
|
+
<View style={styles.weekDays}>
|
|
308
|
+
{weekDays.map((day) => (
|
|
309
|
+
<Text key={day} style={styles.weekDayText}>
|
|
310
|
+
{day}
|
|
206
311
|
</Text>
|
|
207
|
-
|
|
208
|
-
<Text style={[styles.navText, navTextStyle]}>›</Text>
|
|
209
|
-
</Pressable>
|
|
210
|
-
</View>
|
|
211
|
-
|
|
212
|
-
<View style={styles.weekDays}>
|
|
213
|
-
{weekDays.map((day) => (
|
|
214
|
-
<Text key={day} style={styles.weekDayText}>
|
|
215
|
-
{day}
|
|
216
|
-
</Text>
|
|
217
|
-
))}
|
|
218
|
-
</View>
|
|
219
|
-
|
|
220
|
-
<FlatList
|
|
221
|
-
data={days}
|
|
222
|
-
renderItem={renderDay}
|
|
223
|
-
keyExtractor={keyExtractor}
|
|
224
|
-
getItemLayout={getItemLayout}
|
|
225
|
-
numColumns={7}
|
|
226
|
-
scrollEnabled={false}
|
|
227
|
-
removeClippedSubviews={true}
|
|
228
|
-
maxToRenderPerBatch={14}
|
|
229
|
-
windowSize={3}
|
|
230
|
-
initialNumToRender={42}
|
|
231
|
-
/>
|
|
312
|
+
))}
|
|
232
313
|
</View>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
314
|
+
|
|
315
|
+
<FlatList
|
|
316
|
+
data={days}
|
|
317
|
+
renderItem={renderDay}
|
|
318
|
+
keyExtractor={keyExtractor}
|
|
319
|
+
getItemLayout={getItemLayout}
|
|
320
|
+
numColumns={7}
|
|
321
|
+
scrollEnabled={false}
|
|
322
|
+
removeClippedSubviews={true}
|
|
323
|
+
maxToRenderPerBatch={14}
|
|
324
|
+
windowSize={3}
|
|
325
|
+
initialNumToRender={42}
|
|
326
|
+
/>
|
|
327
|
+
</View>
|
|
328
|
+
);
|
|
329
|
+
});
|
|
236
330
|
|
|
237
331
|
CalendarGrid.displayName = 'CalendarGrid';
|