react-native-month-day-picker 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +269 -0
- package/lib/commonjs/BirthdayPicker.js +177 -0
- package/lib/commonjs/BirthdayPicker.js.map +1 -0
- package/lib/commonjs/BirthdayPickerModal.js +176 -0
- package/lib/commonjs/BirthdayPickerModal.js.map +1 -0
- package/lib/commonjs/constants.js +80 -0
- package/lib/commonjs/constants.js.map +1 -0
- package/lib/commonjs/hooks/useBirthdayPicker.js +90 -0
- package/lib/commonjs/hooks/useBirthdayPicker.js.map +1 -0
- package/lib/commonjs/index.js +89 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/types.js +6 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/utils/dateUtils.js +103 -0
- package/lib/commonjs/utils/dateUtils.js.map +1 -0
- package/lib/commonjs/utils/localeUtils.js +90 -0
- package/lib/commonjs/utils/localeUtils.js.map +1 -0
- package/lib/module/BirthdayPicker.js +169 -0
- package/lib/module/BirthdayPicker.js.map +1 -0
- package/lib/module/BirthdayPickerModal.js +169 -0
- package/lib/module/BirthdayPickerModal.js.map +1 -0
- package/lib/module/constants.js +74 -0
- package/lib/module/constants.js.map +1 -0
- package/lib/module/hooks/useBirthdayPicker.js +84 -0
- package/lib/module/hooks/useBirthdayPicker.js.map +1 -0
- package/lib/module/index.js +16 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/dateUtils.js +92 -0
- package/lib/module/utils/dateUtils.js.map +1 -0
- package/lib/module/utils/localeUtils.js +81 -0
- package/lib/module/utils/localeUtils.js.map +1 -0
- package/lib/typescript/BirthdayPicker.d.ts +25 -0
- package/lib/typescript/BirthdayPicker.d.ts.map +1 -0
- package/lib/typescript/BirthdayPickerModal.d.ts +24 -0
- package/lib/typescript/BirthdayPickerModal.d.ts.map +1 -0
- package/lib/typescript/constants.d.ts +39 -0
- package/lib/typescript/constants.d.ts.map +1 -0
- package/lib/typescript/hooks/useBirthdayPicker.d.ts +17 -0
- package/lib/typescript/hooks/useBirthdayPicker.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +8 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +160 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/lib/typescript/utils/dateUtils.d.ts +43 -0
- package/lib/typescript/utils/dateUtils.d.ts.map +1 -0
- package/lib/typescript/utils/localeUtils.d.ts +28 -0
- package/lib/typescript/utils/localeUtils.d.ts.map +1 -0
- package/package.json +137 -0
- package/src/BirthdayPicker.tsx +210 -0
- package/src/BirthdayPickerModal.tsx +192 -0
- package/src/constants.ts +64 -0
- package/src/hooks/useBirthdayPicker.ts +106 -0
- package/src/index.ts +31 -0
- package/src/types.ts +189 -0
- package/src/utils/dateUtils.ts +101 -0
- package/src/utils/localeUtils.ts +99 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { Modal, View, Text, TouchableOpacity, StyleSheet, SafeAreaView, Platform } from 'react-native';
|
|
3
|
+
import { BirthdayPicker } from './BirthdayPicker';
|
|
4
|
+
import { DEFAULT_BIRTHDAY_VALUE } from './constants';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A modal wrapper for BirthdayPicker that provides confirm/cancel functionality.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* const [visible, setVisible] = useState(false);
|
|
12
|
+
* const [birthday, setBirthday] = useState({ month: 1, day: 1 });
|
|
13
|
+
*
|
|
14
|
+
* <BirthdayPickerModal
|
|
15
|
+
* visible={visible}
|
|
16
|
+
* value={birthday}
|
|
17
|
+
* onConfirm={(value) => {
|
|
18
|
+
* setBirthday(value);
|
|
19
|
+
* setVisible(false);
|
|
20
|
+
* }}
|
|
21
|
+
* onCancel={() => setVisible(false)}
|
|
22
|
+
* />
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function BirthdayPickerModal({
|
|
26
|
+
visible,
|
|
27
|
+
onConfirm,
|
|
28
|
+
onCancel,
|
|
29
|
+
value: externalValue,
|
|
30
|
+
defaultValue = DEFAULT_BIRTHDAY_VALUE,
|
|
31
|
+
title = 'Select Birthday',
|
|
32
|
+
confirmText = 'Confirm',
|
|
33
|
+
cancelText = 'Cancel',
|
|
34
|
+
animationType = 'slide',
|
|
35
|
+
locale,
|
|
36
|
+
monthFormat,
|
|
37
|
+
allowLeapDay,
|
|
38
|
+
disabled,
|
|
39
|
+
testID,
|
|
40
|
+
itemHeight,
|
|
41
|
+
visibleItems,
|
|
42
|
+
monthAccessibilityLabel,
|
|
43
|
+
dayAccessibilityLabel
|
|
44
|
+
}) {
|
|
45
|
+
// Internal state to track the selection while modal is open
|
|
46
|
+
const [internalValue, setInternalValue] = useState(() => externalValue ?? defaultValue);
|
|
47
|
+
|
|
48
|
+
// Reset internal value when modal opens or external value changes
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (visible) {
|
|
51
|
+
setInternalValue(externalValue ?? defaultValue);
|
|
52
|
+
}
|
|
53
|
+
}, [visible, externalValue, defaultValue]);
|
|
54
|
+
|
|
55
|
+
// Handle value changes from the picker
|
|
56
|
+
const handleChange = useCallback(newValue => {
|
|
57
|
+
setInternalValue(newValue);
|
|
58
|
+
}, []);
|
|
59
|
+
|
|
60
|
+
// Handle confirm button press
|
|
61
|
+
const handleConfirm = useCallback(() => {
|
|
62
|
+
onConfirm(internalValue);
|
|
63
|
+
}, [onConfirm, internalValue]);
|
|
64
|
+
|
|
65
|
+
// Handle cancel button press
|
|
66
|
+
const handleCancel = useCallback(() => {
|
|
67
|
+
onCancel();
|
|
68
|
+
}, [onCancel]);
|
|
69
|
+
return /*#__PURE__*/React.createElement(Modal, {
|
|
70
|
+
visible: visible,
|
|
71
|
+
transparent: true,
|
|
72
|
+
animationType: animationType,
|
|
73
|
+
onRequestClose: handleCancel,
|
|
74
|
+
testID: testID
|
|
75
|
+
}, /*#__PURE__*/React.createElement(View, {
|
|
76
|
+
style: styles.overlay
|
|
77
|
+
}, /*#__PURE__*/React.createElement(SafeAreaView, {
|
|
78
|
+
style: styles.safeArea
|
|
79
|
+
}, /*#__PURE__*/React.createElement(View, {
|
|
80
|
+
style: styles.container
|
|
81
|
+
}, /*#__PURE__*/React.createElement(View, {
|
|
82
|
+
style: styles.header
|
|
83
|
+
}, /*#__PURE__*/React.createElement(TouchableOpacity, {
|
|
84
|
+
onPress: handleCancel,
|
|
85
|
+
style: styles.headerButton,
|
|
86
|
+
accessibilityRole: "button",
|
|
87
|
+
accessibilityLabel: cancelText,
|
|
88
|
+
testID: testID ? `${testID}-cancel` : undefined
|
|
89
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
90
|
+
style: styles.cancelText
|
|
91
|
+
}, cancelText)), /*#__PURE__*/React.createElement(Text, {
|
|
92
|
+
style: styles.title
|
|
93
|
+
}, title), /*#__PURE__*/React.createElement(TouchableOpacity, {
|
|
94
|
+
onPress: handleConfirm,
|
|
95
|
+
style: styles.headerButton,
|
|
96
|
+
accessibilityRole: "button",
|
|
97
|
+
accessibilityLabel: confirmText,
|
|
98
|
+
testID: testID ? `${testID}-confirm` : undefined
|
|
99
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
100
|
+
style: styles.confirmText
|
|
101
|
+
}, confirmText))), /*#__PURE__*/React.createElement(View, {
|
|
102
|
+
style: styles.pickerWrapper
|
|
103
|
+
}, /*#__PURE__*/React.createElement(BirthdayPicker, {
|
|
104
|
+
value: internalValue,
|
|
105
|
+
onChange: handleChange,
|
|
106
|
+
locale: locale,
|
|
107
|
+
monthFormat: monthFormat,
|
|
108
|
+
allowLeapDay: allowLeapDay,
|
|
109
|
+
disabled: disabled,
|
|
110
|
+
itemHeight: itemHeight,
|
|
111
|
+
visibleItems: visibleItems,
|
|
112
|
+
monthAccessibilityLabel: monthAccessibilityLabel,
|
|
113
|
+
dayAccessibilityLabel: dayAccessibilityLabel,
|
|
114
|
+
testID: testID ? `${testID}-picker` : undefined
|
|
115
|
+
}))))));
|
|
116
|
+
}
|
|
117
|
+
const styles = StyleSheet.create({
|
|
118
|
+
overlay: {
|
|
119
|
+
flex: 1,
|
|
120
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
121
|
+
justifyContent: 'flex-end'
|
|
122
|
+
},
|
|
123
|
+
safeArea: {
|
|
124
|
+
backgroundColor: 'white',
|
|
125
|
+
borderTopLeftRadius: 16,
|
|
126
|
+
borderTopRightRadius: 16,
|
|
127
|
+
overflow: 'hidden'
|
|
128
|
+
},
|
|
129
|
+
container: {
|
|
130
|
+
backgroundColor: 'white',
|
|
131
|
+
paddingBottom: Platform.OS === 'android' ? 16 : 0
|
|
132
|
+
},
|
|
133
|
+
header: {
|
|
134
|
+
flexDirection: 'row',
|
|
135
|
+
alignItems: 'center',
|
|
136
|
+
justifyContent: 'space-between',
|
|
137
|
+
paddingHorizontal: 16,
|
|
138
|
+
paddingVertical: 12,
|
|
139
|
+
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
140
|
+
borderBottomColor: '#ccc'
|
|
141
|
+
},
|
|
142
|
+
headerButton: {
|
|
143
|
+
paddingVertical: 8,
|
|
144
|
+
paddingHorizontal: 4,
|
|
145
|
+
minWidth: 60
|
|
146
|
+
},
|
|
147
|
+
title: {
|
|
148
|
+
fontSize: 17,
|
|
149
|
+
fontWeight: '600',
|
|
150
|
+
color: '#000',
|
|
151
|
+
textAlign: 'center',
|
|
152
|
+
flex: 1
|
|
153
|
+
},
|
|
154
|
+
cancelText: {
|
|
155
|
+
fontSize: 17,
|
|
156
|
+
color: '#007AFF'
|
|
157
|
+
},
|
|
158
|
+
confirmText: {
|
|
159
|
+
fontSize: 17,
|
|
160
|
+
fontWeight: '600',
|
|
161
|
+
color: '#007AFF',
|
|
162
|
+
textAlign: 'right'
|
|
163
|
+
},
|
|
164
|
+
pickerWrapper: {
|
|
165
|
+
paddingVertical: 16
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
export default BirthdayPickerModal;
|
|
169
|
+
//# sourceMappingURL=BirthdayPickerModal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useState","useEffect","useCallback","Modal","View","Text","TouchableOpacity","StyleSheet","SafeAreaView","Platform","BirthdayPicker","DEFAULT_BIRTHDAY_VALUE","BirthdayPickerModal","visible","onConfirm","onCancel","value","externalValue","defaultValue","title","confirmText","cancelText","animationType","locale","monthFormat","allowLeapDay","disabled","testID","itemHeight","visibleItems","monthAccessibilityLabel","dayAccessibilityLabel","internalValue","setInternalValue","handleChange","newValue","handleConfirm","handleCancel","createElement","transparent","onRequestClose","style","styles","overlay","safeArea","container","header","onPress","headerButton","accessibilityRole","accessibilityLabel","undefined","pickerWrapper","onChange","create","flex","backgroundColor","justifyContent","borderTopLeftRadius","borderTopRightRadius","overflow","paddingBottom","OS","flexDirection","alignItems","paddingHorizontal","paddingVertical","borderBottomWidth","hairlineWidth","borderBottomColor","minWidth","fontSize","fontWeight","color","textAlign"],"sourceRoot":"../../src","sources":["BirthdayPickerModal.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default birthday value (January 1st)
|
|
3
|
+
*/
|
|
4
|
+
export const DEFAULT_BIRTHDAY_VALUE = {
|
|
5
|
+
month: 1,
|
|
6
|
+
day: 1
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Default locale for month formatting
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_LOCALE = 'en-US';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Default month format
|
|
16
|
+
*/
|
|
17
|
+
export const DEFAULT_MONTH_FORMAT = 'long';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Default item height in pixels
|
|
21
|
+
*/
|
|
22
|
+
export const DEFAULT_ITEM_HEIGHT = 40;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Default number of visible items
|
|
26
|
+
*/
|
|
27
|
+
export const DEFAULT_VISIBLE_ITEMS = 5;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Days in each month (1-indexed, index 0 is unused)
|
|
31
|
+
* February is set to 28, leap day handling is separate
|
|
32
|
+
*/
|
|
33
|
+
export const DAYS_IN_MONTH = [0,
|
|
34
|
+
// Index 0 unused
|
|
35
|
+
31,
|
|
36
|
+
// January
|
|
37
|
+
28,
|
|
38
|
+
// February (leap day handled separately)
|
|
39
|
+
31,
|
|
40
|
+
// March
|
|
41
|
+
30,
|
|
42
|
+
// April
|
|
43
|
+
31,
|
|
44
|
+
// May
|
|
45
|
+
30,
|
|
46
|
+
// June
|
|
47
|
+
31,
|
|
48
|
+
// July
|
|
49
|
+
31,
|
|
50
|
+
// August
|
|
51
|
+
30,
|
|
52
|
+
// September
|
|
53
|
+
31,
|
|
54
|
+
// October
|
|
55
|
+
30,
|
|
56
|
+
// November
|
|
57
|
+
31 // December
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Number of months in a year
|
|
62
|
+
*/
|
|
63
|
+
export const MONTHS_IN_YEAR = 12;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* February month number
|
|
67
|
+
*/
|
|
68
|
+
export const FEBRUARY = 2;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Leap day (Feb 29)
|
|
72
|
+
*/
|
|
73
|
+
export const LEAP_DAY = 29;
|
|
74
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["DEFAULT_BIRTHDAY_VALUE","month","day","DEFAULT_LOCALE","DEFAULT_MONTH_FORMAT","DEFAULT_ITEM_HEIGHT","DEFAULT_VISIBLE_ITEMS","DAYS_IN_MONTH","MONTHS_IN_YEAR","FEBRUARY","LEAP_DAY"],"sourceRoot":"../../src","sources":["constants.ts"],"mappings":"AAEA;AACA;AACA;AACA,OAAO,MAAMA,sBAAqC,GAAG;EACnDC,KAAK,EAAE,CAAC;EACRC,GAAG,EAAE;AACP,CAAC;;AAED;AACA;AACA;AACA,OAAO,MAAMC,cAAc,GAAG,OAAO;;AAErC;AACA;AACA;AACA,OAAO,MAAMC,oBAAiC,GAAG,MAAM;;AAEvD;AACA;AACA;AACA,OAAO,MAAMC,mBAAmB,GAAG,EAAE;;AAErC;AACA;AACA;AACA,OAAO,MAAMC,qBAAqB,GAAG,CAAC;;AAEtC;AACA;AACA;AACA;AACA,OAAO,MAAMC,aAAgC,GAAG,CAC9C,CAAC;AAAE;AACH,EAAE;AAAE;AACJ,EAAE;AAAE;AACJ,EAAE;AAAE;AACJ,EAAE;AAAE;AACJ,EAAE;AAAE;AACJ,EAAE;AAAE;AACJ,EAAE;AAAE;AACJ,EAAE;AAAE;AACJ,EAAE;AAAE;AACJ,EAAE;AAAE;AACJ,EAAE;AAAE;AACJ,EAAE,CAAE;AAAA,CACL;;AAED;AACA;AACA;AACA,OAAO,MAAMC,cAAc,GAAG,EAAE;;AAEhC;AACA;AACA;AACA,OAAO,MAAMC,QAAQ,GAAG,CAAC;;AAEzB;AACA;AACA;AACA,OAAO,MAAMC,QAAQ,GAAG,EAAE","ignoreList":[]}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { useState, useCallback, useMemo } from 'react';
|
|
2
|
+
import { DEFAULT_BIRTHDAY_VALUE } from '../constants';
|
|
3
|
+
import { getDaysInMonth, clampDay, isValidBirthday, normalizeBirthday } from '../utils/dateUtils';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Hook for managing birthday picker state
|
|
7
|
+
*
|
|
8
|
+
* @param options - Configuration options
|
|
9
|
+
* @returns State and handlers for birthday picker
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const { value, setMonth, setDay, daysInMonth } = useBirthdayPicker({
|
|
14
|
+
* initialValue: { month: 6, day: 15 },
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export function useBirthdayPicker(options = {}) {
|
|
19
|
+
const {
|
|
20
|
+
initialValue = DEFAULT_BIRTHDAY_VALUE,
|
|
21
|
+
allowLeapDay = true
|
|
22
|
+
} = options;
|
|
23
|
+
|
|
24
|
+
// Normalize the initial value
|
|
25
|
+
const normalizedInitial = useMemo(() => normalizeBirthday(initialValue, allowLeapDay),
|
|
26
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
27
|
+
[] // Only compute once on mount
|
|
28
|
+
);
|
|
29
|
+
const [value, setValueInternal] = useState(normalizedInitial);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Set the month, clamping the day if necessary
|
|
33
|
+
*/
|
|
34
|
+
const setMonth = useCallback(month => {
|
|
35
|
+
setValueInternal(prev => {
|
|
36
|
+
const clampedMonth = Math.max(1, Math.min(month, 12));
|
|
37
|
+
const clampedDay = clampDay(prev.day, clampedMonth, allowLeapDay);
|
|
38
|
+
return {
|
|
39
|
+
month: clampedMonth,
|
|
40
|
+
day: clampedDay
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
}, [allowLeapDay]);
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Set the day, clamping to valid range for current month
|
|
47
|
+
*/
|
|
48
|
+
const setDay = useCallback(day => {
|
|
49
|
+
setValueInternal(prev => {
|
|
50
|
+
const clampedDay = clampDay(day, prev.month, allowLeapDay);
|
|
51
|
+
return {
|
|
52
|
+
...prev,
|
|
53
|
+
day: clampedDay
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
}, [allowLeapDay]);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Set the entire value, normalizing both month and day
|
|
60
|
+
*/
|
|
61
|
+
const setValue = useCallback(newValue => {
|
|
62
|
+
setValueInternal(normalizeBirthday(newValue, allowLeapDay));
|
|
63
|
+
}, [allowLeapDay]);
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Number of days in the currently selected month
|
|
67
|
+
*/
|
|
68
|
+
const daysInMonth = useMemo(() => getDaysInMonth(value.month, allowLeapDay), [value.month, allowLeapDay]);
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Whether the current value is valid
|
|
72
|
+
*/
|
|
73
|
+
const isValid = useMemo(() => isValidBirthday(value, allowLeapDay), [value, allowLeapDay]);
|
|
74
|
+
return {
|
|
75
|
+
value,
|
|
76
|
+
setMonth,
|
|
77
|
+
setDay,
|
|
78
|
+
setValue,
|
|
79
|
+
daysInMonth,
|
|
80
|
+
isValid
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export default useBirthdayPicker;
|
|
84
|
+
//# sourceMappingURL=useBirthdayPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useState","useCallback","useMemo","DEFAULT_BIRTHDAY_VALUE","getDaysInMonth","clampDay","isValidBirthday","normalizeBirthday","useBirthdayPicker","options","initialValue","allowLeapDay","normalizedInitial","value","setValueInternal","setMonth","month","prev","clampedMonth","Math","max","min","clampedDay","day","setDay","setValue","newValue","daysInMonth","isValid"],"sourceRoot":"../../../src","sources":["hooks/useBirthdayPicker.ts"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,WAAW,EAAEC,OAAO,QAAQ,OAAO;AAMtD,SAASC,sBAAsB,QAAQ,cAAc;AACrD,SACEC,cAAc,EACdC,QAAQ,EACRC,eAAe,EACfC,iBAAiB,QACZ,oBAAoB;;AAE3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,iBAAiBA,CAC/BC,OAAiC,GAAG,CAAC,CAAC,EACb;EACzB,MAAM;IAAEC,YAAY,GAAGP,sBAAsB;IAAEQ,YAAY,GAAG;EAAK,CAAC,GAClEF,OAAO;;EAET;EACA,MAAMG,iBAAiB,GAAGV,OAAO,CAC/B,MAAMK,iBAAiB,CAACG,YAAY,EAAEC,YAAY,CAAC;EACnD;EACA,EAAE,CAAC;EACL,CAAC;EAED,MAAM,CAACE,KAAK,EAAEC,gBAAgB,CAAC,GAAGd,QAAQ,CAAgBY,iBAAiB,CAAC;;EAE5E;AACF;AACA;EACE,MAAMG,QAAQ,GAAGd,WAAW,CACzBe,KAAa,IAAK;IACjBF,gBAAgB,CAAEG,IAAI,IAAK;MACzB,MAAMC,YAAY,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAED,IAAI,CAACE,GAAG,CAACL,KAAK,EAAE,EAAE,CAAC,CAAC;MACrD,MAAMM,UAAU,GAAGjB,QAAQ,CAACY,IAAI,CAACM,GAAG,EAAEL,YAAY,EAAEP,YAAY,CAAC;MACjE,OAAO;QAAEK,KAAK,EAAEE,YAAY;QAAEK,GAAG,EAAED;MAAW,CAAC;IACjD,CAAC,CAAC;EACJ,CAAC,EACD,CAACX,YAAY,CACf,CAAC;;EAED;AACF;AACA;EACE,MAAMa,MAAM,GAAGvB,WAAW,CACvBsB,GAAW,IAAK;IACfT,gBAAgB,CAAEG,IAAI,IAAK;MACzB,MAAMK,UAAU,GAAGjB,QAAQ,CAACkB,GAAG,EAAEN,IAAI,CAACD,KAAK,EAAEL,YAAY,CAAC;MAC1D,OAAO;QAAE,GAAGM,IAAI;QAAEM,GAAG,EAAED;MAAW,CAAC;IACrC,CAAC,CAAC;EACJ,CAAC,EACD,CAACX,YAAY,CACf,CAAC;;EAED;AACF;AACA;EACE,MAAMc,QAAQ,GAAGxB,WAAW,CACzByB,QAAuB,IAAK;IAC3BZ,gBAAgB,CAACP,iBAAiB,CAACmB,QAAQ,EAAEf,YAAY,CAAC,CAAC;EAC7D,CAAC,EACD,CAACA,YAAY,CACf,CAAC;;EAED;AACF;AACA;EACE,MAAMgB,WAAW,GAAGzB,OAAO,CACzB,MAAME,cAAc,CAACS,KAAK,CAACG,KAAK,EAAEL,YAAY,CAAC,EAC/C,CAACE,KAAK,CAACG,KAAK,EAAEL,YAAY,CAC5B,CAAC;;EAED;AACF;AACA;EACE,MAAMiB,OAAO,GAAG1B,OAAO,CACrB,MAAMI,eAAe,CAACO,KAAK,EAAEF,YAAY,CAAC,EAC1C,CAACE,KAAK,EAAEF,YAAY,CACtB,CAAC;EAED,OAAO;IACLE,KAAK;IACLE,QAAQ;IACRS,MAAM;IACNC,QAAQ;IACRE,WAAW;IACXC;EACF,CAAC;AACH;AAEA,eAAepB,iBAAiB","ignoreList":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Main components
|
|
2
|
+
export { BirthdayPicker } from './BirthdayPicker';
|
|
3
|
+
export { BirthdayPickerModal } from './BirthdayPickerModal';
|
|
4
|
+
|
|
5
|
+
// Hook
|
|
6
|
+
export { useBirthdayPicker } from './hooks/useBirthdayPicker';
|
|
7
|
+
|
|
8
|
+
// Types
|
|
9
|
+
|
|
10
|
+
// Utilities (for advanced usage)
|
|
11
|
+
export { getDaysInMonth, clampDay, isValidBirthday, getDaysArray, getMonthsArray, normalizeBirthday } from './utils/dateUtils';
|
|
12
|
+
export { getMonthNames, formatMonth, formatDay } from './utils/localeUtils';
|
|
13
|
+
|
|
14
|
+
// Default export
|
|
15
|
+
export { BirthdayPicker as default } from './BirthdayPicker';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["BirthdayPicker","BirthdayPickerModal","useBirthdayPicker","getDaysInMonth","clampDay","isValidBirthday","getDaysArray","getMonthsArray","normalizeBirthday","getMonthNames","formatMonth","formatDay","default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AAAA;AACA,SAASA,cAAc,QAAQ,kBAAkB;AACjD,SAASC,mBAAmB,QAAQ,uBAAuB;;AAE3D;AACA,SAASC,iBAAiB,QAAQ,2BAA2B;;AAE7D;;AAUA;AACA,SACEC,cAAc,EACdC,QAAQ,EACRC,eAAe,EACfC,YAAY,EACZC,cAAc,EACdC,iBAAiB,QACZ,mBAAmB;AAE1B,SAASC,aAAa,EAAEC,WAAW,EAAEC,SAAS,QAAQ,qBAAqB;;AAE3E;AACA,SAASX,cAAc,IAAIY,OAAO,QAAQ,kBAAkB","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { DAYS_IN_MONTH, FEBRUARY, LEAP_DAY, MONTHS_IN_YEAR } from '../constants';
|
|
2
|
+
/**
|
|
3
|
+
* Get the number of days in a given month
|
|
4
|
+
* @param month - Month (1-12)
|
|
5
|
+
* @param allowLeapDay - Whether to allow Feb 29
|
|
6
|
+
* @returns Number of days in the month
|
|
7
|
+
*/
|
|
8
|
+
export function getDaysInMonth(month, allowLeapDay = true) {
|
|
9
|
+
if (month < 1 || month > MONTHS_IN_YEAR) {
|
|
10
|
+
throw new Error(`Invalid month: ${month}. Must be between 1 and 12.`);
|
|
11
|
+
}
|
|
12
|
+
if (month === FEBRUARY && allowLeapDay) {
|
|
13
|
+
return LEAP_DAY;
|
|
14
|
+
}
|
|
15
|
+
return DAYS_IN_MONTH[month];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Clamp a day value to be valid for a given month
|
|
20
|
+
* @param day - Day to clamp
|
|
21
|
+
* @param month - Month (1-12)
|
|
22
|
+
* @param allowLeapDay - Whether to allow Feb 29
|
|
23
|
+
* @returns Clamped day value
|
|
24
|
+
*/
|
|
25
|
+
export function clampDay(day, month, allowLeapDay = true) {
|
|
26
|
+
const maxDays = getDaysInMonth(month, allowLeapDay);
|
|
27
|
+
return Math.max(1, Math.min(day, maxDays));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Check if a birthday value is valid
|
|
32
|
+
* @param value - Birthday value to validate
|
|
33
|
+
* @param allowLeapDay - Whether to allow Feb 29
|
|
34
|
+
* @returns Whether the value is valid
|
|
35
|
+
*/
|
|
36
|
+
export function isValidBirthday(value, allowLeapDay = true) {
|
|
37
|
+
const {
|
|
38
|
+
month,
|
|
39
|
+
day
|
|
40
|
+
} = value;
|
|
41
|
+
|
|
42
|
+
// Check month range
|
|
43
|
+
if (month < 1 || month > MONTHS_IN_YEAR) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Check day range
|
|
48
|
+
const maxDays = getDaysInMonth(month, allowLeapDay);
|
|
49
|
+
if (day < 1 || day > maxDays) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Generate an array of day numbers for a given month
|
|
57
|
+
* @param month - Month (1-12)
|
|
58
|
+
* @param allowLeapDay - Whether to allow Feb 29
|
|
59
|
+
* @returns Array of day numbers [1, 2, 3, ..., n]
|
|
60
|
+
*/
|
|
61
|
+
export function getDaysArray(month, allowLeapDay = true) {
|
|
62
|
+
const maxDays = getDaysInMonth(month, allowLeapDay);
|
|
63
|
+
return Array.from({
|
|
64
|
+
length: maxDays
|
|
65
|
+
}, (_, i) => i + 1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Generate an array of month numbers
|
|
70
|
+
* @returns Array of month numbers [1, 2, 3, ..., 12]
|
|
71
|
+
*/
|
|
72
|
+
export function getMonthsArray() {
|
|
73
|
+
return Array.from({
|
|
74
|
+
length: MONTHS_IN_YEAR
|
|
75
|
+
}, (_, i) => i + 1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Normalize a birthday value to ensure it's valid
|
|
80
|
+
* @param value - Birthday value to normalize
|
|
81
|
+
* @param allowLeapDay - Whether to allow Feb 29
|
|
82
|
+
* @returns Normalized birthday value
|
|
83
|
+
*/
|
|
84
|
+
export function normalizeBirthday(value, allowLeapDay = true) {
|
|
85
|
+
const month = Math.max(1, Math.min(value.month, MONTHS_IN_YEAR));
|
|
86
|
+
const day = clampDay(value.day, month, allowLeapDay);
|
|
87
|
+
return {
|
|
88
|
+
month,
|
|
89
|
+
day
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=dateUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["DAYS_IN_MONTH","FEBRUARY","LEAP_DAY","MONTHS_IN_YEAR","getDaysInMonth","month","allowLeapDay","Error","clampDay","day","maxDays","Math","max","min","isValidBirthday","value","getDaysArray","Array","from","length","_","i","getMonthsArray","normalizeBirthday"],"sourceRoot":"../../../src","sources":["utils/dateUtils.ts"],"mappings":"AAAA,SACEA,aAAa,EACbC,QAAQ,EACRC,QAAQ,EACRC,cAAc,QACT,cAAc;AAGrB;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAACC,KAAa,EAAEC,YAAY,GAAG,IAAI,EAAU;EACzE,IAAID,KAAK,GAAG,CAAC,IAAIA,KAAK,GAAGF,cAAc,EAAE;IACvC,MAAM,IAAII,KAAK,CAAC,kBAAkBF,KAAK,6BAA6B,CAAC;EACvE;EAEA,IAAIA,KAAK,KAAKJ,QAAQ,IAAIK,YAAY,EAAE;IACtC,OAAOJ,QAAQ;EACjB;EAEA,OAAOF,aAAa,CAACK,KAAK,CAAC;AAC7B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASG,QAAQA,CACtBC,GAAW,EACXJ,KAAa,EACbC,YAAY,GAAG,IAAI,EACX;EACR,MAAMI,OAAO,GAAGN,cAAc,CAACC,KAAK,EAAEC,YAAY,CAAC;EACnD,OAAOK,IAAI,CAACC,GAAG,CAAC,CAAC,EAAED,IAAI,CAACE,GAAG,CAACJ,GAAG,EAAEC,OAAO,CAAC,CAAC;AAC5C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,eAAeA,CAC7BC,KAAoB,EACpBT,YAAY,GAAG,IAAI,EACV;EACT,MAAM;IAAED,KAAK;IAAEI;EAAI,CAAC,GAAGM,KAAK;;EAE5B;EACA,IAAIV,KAAK,GAAG,CAAC,IAAIA,KAAK,GAAGF,cAAc,EAAE;IACvC,OAAO,KAAK;EACd;;EAEA;EACA,MAAMO,OAAO,GAAGN,cAAc,CAACC,KAAK,EAAEC,YAAY,CAAC;EACnD,IAAIG,GAAG,GAAG,CAAC,IAAIA,GAAG,GAAGC,OAAO,EAAE;IAC5B,OAAO,KAAK;EACd;EAEA,OAAO,IAAI;AACb;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASM,YAAYA,CAACX,KAAa,EAAEC,YAAY,GAAG,IAAI,EAAY;EACzE,MAAMI,OAAO,GAAGN,cAAc,CAACC,KAAK,EAAEC,YAAY,CAAC;EACnD,OAAOW,KAAK,CAACC,IAAI,CAAC;IAAEC,MAAM,EAAET;EAAQ,CAAC,EAAE,CAACU,CAAC,EAAEC,CAAC,KAAKA,CAAC,GAAG,CAAC,CAAC;AACzD;;AAEA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAAA,EAAa;EACzC,OAAOL,KAAK,CAACC,IAAI,CAAC;IAAEC,MAAM,EAAEhB;EAAe,CAAC,EAAE,CAACiB,CAAC,EAAEC,CAAC,KAAKA,CAAC,GAAG,CAAC,CAAC;AAChE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,iBAAiBA,CAC/BR,KAAoB,EACpBT,YAAY,GAAG,IAAI,EACJ;EACf,MAAMD,KAAK,GAAGM,IAAI,CAACC,GAAG,CAAC,CAAC,EAAED,IAAI,CAACE,GAAG,CAACE,KAAK,CAACV,KAAK,EAAEF,cAAc,CAAC,CAAC;EAChE,MAAMM,GAAG,GAAGD,QAAQ,CAACO,KAAK,CAACN,GAAG,EAAEJ,KAAK,EAAEC,YAAY,CAAC;EACpD,OAAO;IAAED,KAAK;IAAEI;EAAI,CAAC;AACvB","ignoreList":[]}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { MONTHS_IN_YEAR, DEFAULT_LOCALE, DEFAULT_MONTH_FORMAT } from '../constants';
|
|
2
|
+
/**
|
|
3
|
+
* Cache for month names to avoid repeated Intl.DateTimeFormat calls
|
|
4
|
+
*/
|
|
5
|
+
const monthNamesCache = new Map();
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generate a cache key for month names
|
|
9
|
+
*/
|
|
10
|
+
function getCacheKey(locale, format) {
|
|
11
|
+
return `${locale}-${format}`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get month names for a given locale and format
|
|
16
|
+
* @param locale - BCP 47 locale string (e.g., 'en-US', 'ja-JP')
|
|
17
|
+
* @param format - Format for month names ('long', 'short', 'numeric')
|
|
18
|
+
* @returns Array of month names/numbers (1-indexed, index 0 is empty string)
|
|
19
|
+
*/
|
|
20
|
+
export function getMonthNames(locale = DEFAULT_LOCALE, format = DEFAULT_MONTH_FORMAT) {
|
|
21
|
+
const cacheKey = getCacheKey(locale, format);
|
|
22
|
+
|
|
23
|
+
// Return cached result if available
|
|
24
|
+
if (monthNamesCache.has(cacheKey)) {
|
|
25
|
+
return monthNamesCache.get(cacheKey);
|
|
26
|
+
}
|
|
27
|
+
const names = [''];
|
|
28
|
+
if (format === 'numeric') {
|
|
29
|
+
// For numeric format, just use month numbers
|
|
30
|
+
for (let i = 1; i <= MONTHS_IN_YEAR; i++) {
|
|
31
|
+
names.push(String(i));
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
// Use Intl.DateTimeFormat for localized month names
|
|
35
|
+
const formatter = new Intl.DateTimeFormat(locale, {
|
|
36
|
+
month: format
|
|
37
|
+
});
|
|
38
|
+
for (let i = 0; i < MONTHS_IN_YEAR; i++) {
|
|
39
|
+
// Create a date in month i (0-indexed for Date constructor)
|
|
40
|
+
const date = new Date(2024, i, 1);
|
|
41
|
+
names.push(formatter.format(date));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Cache the result
|
|
46
|
+
monthNamesCache.set(cacheKey, names);
|
|
47
|
+
return names;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Format a single month number to a localized string
|
|
52
|
+
* @param month - Month number (1-12)
|
|
53
|
+
* @param locale - BCP 47 locale string
|
|
54
|
+
* @param format - Format for month name
|
|
55
|
+
* @returns Formatted month name
|
|
56
|
+
*/
|
|
57
|
+
export function formatMonth(month, locale = DEFAULT_LOCALE, format = DEFAULT_MONTH_FORMAT) {
|
|
58
|
+
if (month < 1 || month > MONTHS_IN_YEAR) {
|
|
59
|
+
throw new Error(`Invalid month: ${month}. Must be between 1 and 12.`);
|
|
60
|
+
}
|
|
61
|
+
const names = getMonthNames(locale, format);
|
|
62
|
+
return names[month];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Format a day number with optional locale-specific formatting
|
|
67
|
+
* @param day - Day number (1-31)
|
|
68
|
+
* @param locale - BCP 47 locale string (currently unused, for future i18n)
|
|
69
|
+
* @returns Formatted day string
|
|
70
|
+
*/
|
|
71
|
+
export function formatDay(day, locale = DEFAULT_LOCALE) {
|
|
72
|
+
return new Intl.NumberFormat(locale).format(day);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Clear the month names cache (useful for testing)
|
|
77
|
+
*/
|
|
78
|
+
export function clearMonthNamesCache() {
|
|
79
|
+
monthNamesCache.clear();
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=localeUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["MONTHS_IN_YEAR","DEFAULT_LOCALE","DEFAULT_MONTH_FORMAT","monthNamesCache","Map","getCacheKey","locale","format","getMonthNames","cacheKey","has","get","names","i","push","String","formatter","Intl","DateTimeFormat","month","date","Date","set","formatMonth","Error","formatDay","day","NumberFormat","clearMonthNamesCache","clear"],"sourceRoot":"../../../src","sources":["utils/localeUtils.ts"],"mappings":"AAAA,SACEA,cAAc,EACdC,cAAc,EACdC,oBAAoB,QACf,cAAc;AAGrB;AACA;AACA;AACA,MAAMC,eAAe,GAAG,IAAIC,GAAG,CAAmB,CAAC;;AAEnD;AACA;AACA;AACA,SAASC,WAAWA,CAACC,MAAc,EAAEC,MAAmB,EAAU;EAChE,OAAO,GAAGD,MAAM,IAAIC,MAAM,EAAE;AAC9B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,aAAaA,CAC3BF,MAAc,GAAGL,cAAc,EAC/BM,MAAmB,GAAGL,oBAAoB,EAChC;EACV,MAAMO,QAAQ,GAAGJ,WAAW,CAACC,MAAM,EAAEC,MAAM,CAAC;;EAE5C;EACA,IAAIJ,eAAe,CAACO,GAAG,CAACD,QAAQ,CAAC,EAAE;IACjC,OAAON,eAAe,CAACQ,GAAG,CAACF,QAAQ,CAAC;EACtC;EAEA,MAAMG,KAAe,GAAG,CAAC,EAAE,CAAC;EAE5B,IAAIL,MAAM,KAAK,SAAS,EAAE;IACxB;IACA,KAAK,IAAIM,CAAC,GAAG,CAAC,EAAEA,CAAC,IAAIb,cAAc,EAAEa,CAAC,EAAE,EAAE;MACxCD,KAAK,CAACE,IAAI,CAACC,MAAM,CAACF,CAAC,CAAC,CAAC;IACvB;EACF,CAAC,MAAM;IACL;IACA,MAAMG,SAAS,GAAG,IAAIC,IAAI,CAACC,cAAc,CAACZ,MAAM,EAAE;MAAEa,KAAK,EAAEZ;IAAO,CAAC,CAAC;IAEpE,KAAK,IAAIM,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGb,cAAc,EAAEa,CAAC,EAAE,EAAE;MACvC;MACA,MAAMO,IAAI,GAAG,IAAIC,IAAI,CAAC,IAAI,EAAER,CAAC,EAAE,CAAC,CAAC;MACjCD,KAAK,CAACE,IAAI,CAACE,SAAS,CAACT,MAAM,CAACa,IAAI,CAAC,CAAC;IACpC;EACF;;EAEA;EACAjB,eAAe,CAACmB,GAAG,CAACb,QAAQ,EAAEG,KAAK,CAAC;EAEpC,OAAOA,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASW,WAAWA,CACzBJ,KAAa,EACbb,MAAc,GAAGL,cAAc,EAC/BM,MAAmB,GAAGL,oBAAoB,EAClC;EACR,IAAIiB,KAAK,GAAG,CAAC,IAAIA,KAAK,GAAGnB,cAAc,EAAE;IACvC,MAAM,IAAIwB,KAAK,CAAC,kBAAkBL,KAAK,6BAA6B,CAAC;EACvE;EAEA,MAAMP,KAAK,GAAGJ,aAAa,CAACF,MAAM,EAAEC,MAAM,CAAC;EAC3C,OAAOK,KAAK,CAACO,KAAK,CAAC;AACrB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASM,SAASA,CACvBC,GAAW,EACXpB,MAAc,GAAGL,cAAc,EACvB;EACR,OAAO,IAAIgB,IAAI,CAACU,YAAY,CAACrB,MAAM,CAAC,CAACC,MAAM,CAACmB,GAAG,CAAC;AAClD;;AAEA;AACA;AACA;AACA,OAAO,SAASE,oBAAoBA,CAAA,EAAS;EAC3CzB,eAAe,CAAC0B,KAAK,CAAC,CAAC;AACzB","ignoreList":[]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { BirthdayPickerProps } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* A birthday picker component that allows selecting month and day.
|
|
5
|
+
* Does not include year for privacy-friendly birthday selection.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* // Uncontrolled mode
|
|
10
|
+
* <BirthdayPicker
|
|
11
|
+
* defaultValue={{ month: 6, day: 15 }}
|
|
12
|
+
* onChange={(value) => console.log(value)}
|
|
13
|
+
* />
|
|
14
|
+
*
|
|
15
|
+
* // Controlled mode
|
|
16
|
+
* const [birthday, setBirthday] = useState({ month: 1, day: 1 });
|
|
17
|
+
* <BirthdayPicker
|
|
18
|
+
* value={birthday}
|
|
19
|
+
* onChange={setBirthday}
|
|
20
|
+
* />
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function BirthdayPicker({ value: controlledValue, defaultValue, onChange, locale, monthFormat, allowLeapDay, disabled, testID, style, itemHeight, visibleItems, monthAccessibilityLabel, dayAccessibilityLabel, }: BirthdayPickerProps): React.ReactElement;
|
|
24
|
+
export default BirthdayPicker;
|
|
25
|
+
//# sourceMappingURL=BirthdayPicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BirthdayPicker.d.ts","sourceRoot":"","sources":["../../src/BirthdayPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkD,MAAM,OAAO,CAAC;AAGvE,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AAwBlE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EAAE,eAAe,EACtB,YAAqC,EACrC,QAAQ,EACR,MAAuB,EACvB,WAAkC,EAClC,YAAmB,EACnB,QAAgB,EAChB,MAAM,EACN,KAAK,EACL,UAAgC,EAChC,YAAoC,EACpC,uBAAwC,EACxC,qBAAoC,GACrC,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,CAuI1C;AAaD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { BirthdayPickerModalProps } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* A modal wrapper for BirthdayPicker that provides confirm/cancel functionality.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* const [visible, setVisible] = useState(false);
|
|
9
|
+
* const [birthday, setBirthday] = useState({ month: 1, day: 1 });
|
|
10
|
+
*
|
|
11
|
+
* <BirthdayPickerModal
|
|
12
|
+
* visible={visible}
|
|
13
|
+
* value={birthday}
|
|
14
|
+
* onConfirm={(value) => {
|
|
15
|
+
* setBirthday(value);
|
|
16
|
+
* setVisible(false);
|
|
17
|
+
* }}
|
|
18
|
+
* onCancel={() => setVisible(false)}
|
|
19
|
+
* />
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function BirthdayPickerModal({ visible, onConfirm, onCancel, value: externalValue, defaultValue, title, confirmText, cancelText, animationType, locale, monthFormat, allowLeapDay, disabled, testID, itemHeight, visibleItems, monthAccessibilityLabel, dayAccessibilityLabel, }: BirthdayPickerModalProps): React.ReactElement;
|
|
23
|
+
export default BirthdayPickerModal;
|
|
24
|
+
//# sourceMappingURL=BirthdayPickerModal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BirthdayPickerModal.d.ts","sourceRoot":"","sources":["../../src/BirthdayPickerModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAWhE,OAAO,KAAK,EAAE,wBAAwB,EAAiB,MAAM,SAAS,CAAC;AAGvE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,SAAS,EACT,QAAQ,EACR,KAAK,EAAE,aAAa,EACpB,YAAqC,EACrC,KAAyB,EACzB,WAAuB,EACvB,UAAqB,EACrB,aAAuB,EACvB,MAAM,EACN,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,UAAU,EACV,YAAY,EACZ,uBAAuB,EACvB,qBAAqB,GACtB,EAAE,wBAAwB,GAAG,KAAK,CAAC,YAAY,CAqF/C;AAsDD,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { BirthdayValue, MonthFormat } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Default birthday value (January 1st)
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_BIRTHDAY_VALUE: BirthdayValue;
|
|
6
|
+
/**
|
|
7
|
+
* Default locale for month formatting
|
|
8
|
+
*/
|
|
9
|
+
export declare const DEFAULT_LOCALE = "en-US";
|
|
10
|
+
/**
|
|
11
|
+
* Default month format
|
|
12
|
+
*/
|
|
13
|
+
export declare const DEFAULT_MONTH_FORMAT: MonthFormat;
|
|
14
|
+
/**
|
|
15
|
+
* Default item height in pixels
|
|
16
|
+
*/
|
|
17
|
+
export declare const DEFAULT_ITEM_HEIGHT = 40;
|
|
18
|
+
/**
|
|
19
|
+
* Default number of visible items
|
|
20
|
+
*/
|
|
21
|
+
export declare const DEFAULT_VISIBLE_ITEMS = 5;
|
|
22
|
+
/**
|
|
23
|
+
* Days in each month (1-indexed, index 0 is unused)
|
|
24
|
+
* February is set to 28, leap day handling is separate
|
|
25
|
+
*/
|
|
26
|
+
export declare const DAYS_IN_MONTH: readonly number[];
|
|
27
|
+
/**
|
|
28
|
+
* Number of months in a year
|
|
29
|
+
*/
|
|
30
|
+
export declare const MONTHS_IN_YEAR = 12;
|
|
31
|
+
/**
|
|
32
|
+
* February month number
|
|
33
|
+
*/
|
|
34
|
+
export declare const FEBRUARY = 2;
|
|
35
|
+
/**
|
|
36
|
+
* Leap day (Feb 29)
|
|
37
|
+
*/
|
|
38
|
+
export declare const LEAP_DAY = 29;
|
|
39
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE1D;;GAEG;AACH,eAAO,MAAM,sBAAsB,EAAE,aAGpC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAoB,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;GAEG;AACH,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAc1C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC;;GAEG;AACH,eAAO,MAAM,QAAQ,IAAI,CAAC;AAE1B;;GAEG;AACH,eAAO,MAAM,QAAQ,KAAK,CAAC"}
|