@coinbase/cds-mobile 8.53.1 → 8.55.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/CHANGELOG.md +20 -0
- package/README.md +5 -2
- package/dts/buttons/IconButton.d.ts +23 -1
- package/dts/buttons/IconButton.d.ts.map +1 -1
- package/dts/controls/InputIconButton.d.ts +22 -1
- package/dts/controls/InputIconButton.d.ts.map +1 -1
- package/dts/dates/Calendar.d.ts +170 -0
- package/dts/dates/Calendar.d.ts.map +1 -0
- package/dts/dates/DateInput.d.ts +2 -2
- package/dts/dates/DateInput.d.ts.map +1 -1
- package/dts/dates/DatePicker.d.ts +136 -67
- package/dts/dates/DatePicker.d.ts.map +1 -1
- package/dts/overlays/drawer/Drawer.d.ts +12 -0
- package/dts/overlays/drawer/Drawer.d.ts.map +1 -1
- package/dts/overlays/drawer/useDrawerSpacing.d.ts +4 -1
- package/dts/overlays/drawer/useDrawerSpacing.d.ts.map +1 -1
- package/dts/overlays/tooltip/Tooltip.d.ts +9 -1
- package/dts/overlays/tooltip/Tooltip.d.ts.map +1 -1
- package/dts/overlays/tray/Tray.d.ts +3 -0
- package/dts/overlays/tray/Tray.d.ts.map +1 -1
- package/dts/sticky-footer/StickyFooter.d.ts.map +1 -1
- package/esm/buttons/IconButton.js +4 -3
- package/esm/controls/InputIconButton.js +4 -3
- package/esm/dates/Calendar.js +346 -0
- package/esm/dates/DateInput.js +3 -1
- package/esm/dates/DatePicker.js +116 -39
- package/esm/dates/__stories__/Calendar.stories.js +360 -0
- package/esm/dates/__stories__/DatePicker.stories.js +51 -25
- package/esm/overlays/__stories__/TrayAction.stories.js +20 -21
- package/esm/overlays/__stories__/TrayInformational.stories.js +40 -43
- package/esm/overlays/__stories__/TrayMessaging.stories.js +36 -37
- package/esm/overlays/__stories__/TrayPromotional.stories.js +51 -74
- package/esm/overlays/__stories__/TrayRedesign.stories.js +5 -12
- package/esm/overlays/__stories__/Trays.js +1 -0
- package/esm/overlays/drawer/Drawer.js +9 -13
- package/esm/overlays/drawer/useDrawerSpacing.js +11 -8
- package/esm/overlays/tooltip/Tooltip.js +7 -2
- package/esm/overlays/tray/Tray.js +5 -0
- package/esm/sticky-footer/StickyFooter.js +4 -2
- package/esm/sticky-footer/__stories__/StickyFooterWithTray.stories.js +37 -42
- package/package.json +2 -4
package/esm/dates/DatePicker.js
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
|
-
const _excluded = ["date", "onChangeDate", "error", "onErrorDate", "required", "disabled", "seedDate", "minDate", "maxDate", "requiredError", "invalidDateError", "disabledDateError", "label", "accessibilityLabel", "accessibilityLabelledBy", "calendarIconButtonAccessibilityLabel", "dateInputStyle", "compact", "variant", "helperText", "width", "onOpen", "onClose", "onConfirm", "onCancel", "onChange"];
|
|
1
|
+
const _excluded = ["date", "styles", "highlightedDates", "highlightedDateAccessibilityHint", "nextArrowAccessibilityLabel", "previousArrowAccessibilityLabel", "disabledDates", "onChangeDate", "error", "onErrorDate", "required", "disabled", "seedDate", "minDate", "maxDate", "requiredError", "invalidDateError", "disabledDateError", "label", "accessibilityHint", "accessibilityLabel", "accessibilityLabelledBy", "calendarIconButtonAccessibilityLabel", "openCalendarAccessibilityLabel", "closeCalendarAccessibilityLabel", "dateInputStyle", "compact", "variant", "confirmText", "confirmButtonAccessibilityHint", "helperText", "width", "onOpen", "onClose", "onConfirm", "onCancel", "onChange"];
|
|
2
2
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
3
3
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
4
4
|
import { forwardRef, memo, useCallback, useMemo, useRef, useState } from 'react';
|
|
5
|
-
import
|
|
5
|
+
import { Button } from '../buttons/Button';
|
|
6
6
|
import { InputIconButton } from '../controls/InputIconButton';
|
|
7
7
|
import { Box, VStack } from '../layout';
|
|
8
|
+
import { Tray } from '../overlays/tray/Tray';
|
|
9
|
+
import { StickyFooter } from '../sticky-footer/StickyFooter';
|
|
10
|
+
import { Calendar } from './Calendar';
|
|
8
11
|
import { DateInput } from './DateInput';
|
|
9
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
13
|
export const DatePicker = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) => {
|
|
11
14
|
let {
|
|
12
15
|
date,
|
|
16
|
+
styles,
|
|
17
|
+
highlightedDates,
|
|
18
|
+
highlightedDateAccessibilityHint,
|
|
19
|
+
nextArrowAccessibilityLabel,
|
|
20
|
+
previousArrowAccessibilityLabel,
|
|
21
|
+
disabledDates,
|
|
13
22
|
onChangeDate,
|
|
14
23
|
error,
|
|
15
24
|
onErrorDate,
|
|
@@ -22,12 +31,17 @@ export const DatePicker = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref)
|
|
|
22
31
|
invalidDateError = 'Please enter a valid date',
|
|
23
32
|
disabledDateError = 'Date unavailable',
|
|
24
33
|
label,
|
|
34
|
+
accessibilityHint = 'Enter date or select from calendar using the calendar button.',
|
|
25
35
|
accessibilityLabel,
|
|
26
36
|
accessibilityLabelledBy,
|
|
27
37
|
calendarIconButtonAccessibilityLabel,
|
|
38
|
+
openCalendarAccessibilityLabel = 'Open calendar',
|
|
39
|
+
closeCalendarAccessibilityLabel = 'Close calendar without selecting a date',
|
|
28
40
|
dateInputStyle,
|
|
29
41
|
compact,
|
|
30
42
|
variant,
|
|
43
|
+
confirmText = 'Confirm',
|
|
44
|
+
confirmButtonAccessibilityHint,
|
|
31
45
|
helperText,
|
|
32
46
|
width = '100%',
|
|
33
47
|
onOpen,
|
|
@@ -37,61 +51,78 @@ export const DatePicker = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref)
|
|
|
37
51
|
onChange
|
|
38
52
|
} = _ref,
|
|
39
53
|
props = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
40
|
-
const [
|
|
54
|
+
const [showPicker, setShowPicker] = useState(false);
|
|
55
|
+
const [calendarSelectedDate, setCalendarSelectedDate] = useState(null);
|
|
41
56
|
const dateInputRef = useRef(null);
|
|
42
|
-
const
|
|
43
|
-
|
|
57
|
+
const calendarButtonRef = useRef(null);
|
|
58
|
+
const calendarRef = useRef(null);
|
|
59
|
+
const closedByConfirmRef = useRef(false);
|
|
44
60
|
/**
|
|
45
61
|
* Be careful to preserve the correct event orders
|
|
46
|
-
* 1. Selecting a date with the
|
|
47
|
-
* 2. Closing the
|
|
62
|
+
* 1. Selecting a date with the picker: onOpen -> onConfirm -> onChangeDate -> onErrorDate -> onClose
|
|
63
|
+
* 2. Closing the picker without selecting a date: onOpen -> onCancel -> onClose
|
|
48
64
|
* 3. Typing a date in a blank DateInput: onChange -> onChange -> ... -> onChangeDate -> onErrorDate
|
|
49
65
|
* 4. Typing a date in a DateInput that already had a date: onChange -> onChangeDate -> onChange -> onChange -> ... -> onChangeDate -> onErrorDate
|
|
50
66
|
*/
|
|
51
67
|
|
|
52
|
-
const
|
|
68
|
+
const handleOpenPicker = useCallback(() => {
|
|
53
69
|
onOpen == null || onOpen();
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}, [onClose]);
|
|
60
|
-
const handleConfirmNativePicker = useCallback(date => {
|
|
61
|
-
var _dateInputRef$current;
|
|
70
|
+
setCalendarSelectedDate(date); // Initialize with current date
|
|
71
|
+
setShowPicker(true);
|
|
72
|
+
}, [onOpen, date]);
|
|
73
|
+
const handleConfirmPicker = useCallback(selectedDate => {
|
|
74
|
+
closedByConfirmRef.current = true;
|
|
62
75
|
onConfirm == null || onConfirm();
|
|
63
|
-
onChangeDate(
|
|
64
|
-
if (error && error.type !== 'custom')
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}, [onChangeDate, onConfirm, error, onErrorDate
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
onChangeDate(selectedDate);
|
|
77
|
+
if (error && error.type !== 'custom') {
|
|
78
|
+
onErrorDate(null);
|
|
79
|
+
}
|
|
80
|
+
}, [onChangeDate, onConfirm, error, onErrorDate]);
|
|
81
|
+
const handleTrayCloseComplete = useCallback(() => {
|
|
82
|
+
if (!closedByConfirmRef.current) {
|
|
83
|
+
onCancel == null || onCancel();
|
|
84
|
+
setCalendarSelectedDate(null);
|
|
85
|
+
}
|
|
86
|
+
onClose == null || onClose();
|
|
87
|
+
setShowPicker(false);
|
|
88
|
+
closedByConfirmRef.current = false;
|
|
89
|
+
}, [onCancel, onClose]);
|
|
90
|
+
const handleCalendarDatePress = useCallback(selectedDate => {
|
|
91
|
+
// Update local state, user must press confirm button
|
|
92
|
+
setCalendarSelectedDate(selectedDate);
|
|
93
|
+
}, []);
|
|
94
|
+
const handleModalShow = useCallback(() => {
|
|
95
|
+
var _calendarRef$current;
|
|
96
|
+
(_calendarRef$current = calendarRef.current) == null || _calendarRef$current.focusInitialDate();
|
|
97
|
+
}, []);
|
|
72
98
|
const dateInputCalendarButton = useMemo(() => /*#__PURE__*/_jsx(VStack, {
|
|
99
|
+
accessible: true,
|
|
73
100
|
paddingEnd: 0.5,
|
|
74
101
|
children: /*#__PURE__*/_jsx(InputIconButton, {
|
|
102
|
+
ref: calendarButtonRef,
|
|
75
103
|
disableInheritFocusStyle: true,
|
|
76
104
|
transparent: true,
|
|
77
|
-
accessibilityLabel: calendarIconButtonAccessibilityLabel != null ? calendarIconButtonAccessibilityLabel :
|
|
105
|
+
accessibilityLabel: calendarIconButtonAccessibilityLabel != null ? calendarIconButtonAccessibilityLabel : openCalendarAccessibilityLabel,
|
|
106
|
+
disabled: disabled,
|
|
78
107
|
name: "calendarEmpty",
|
|
79
|
-
onPress:
|
|
108
|
+
onPress: handleOpenPicker,
|
|
80
109
|
variant: "secondary"
|
|
81
110
|
})
|
|
82
|
-
}), [
|
|
111
|
+
}), [handleOpenPicker, openCalendarAccessibilityLabel, calendarIconButtonAccessibilityLabel, disabled]);
|
|
83
112
|
return /*#__PURE__*/_jsxs(Box, {
|
|
84
113
|
ref: ref,
|
|
85
114
|
width: width,
|
|
86
115
|
children: [/*#__PURE__*/_jsx(DateInput, _extends({
|
|
87
116
|
ref: dateInputRef
|
|
88
117
|
}, props, {
|
|
118
|
+
accessibilityHint: accessibilityHint,
|
|
89
119
|
accessibilityLabel: accessibilityLabel,
|
|
90
120
|
accessibilityLabelledBy: accessibilityLabelledBy,
|
|
91
121
|
compact: compact,
|
|
92
122
|
date: date,
|
|
93
123
|
disabled: disabled,
|
|
94
124
|
disabledDateError: disabledDateError,
|
|
125
|
+
disabledDates: disabledDates,
|
|
95
126
|
end: dateInputCalendarButton,
|
|
96
127
|
error: error,
|
|
97
128
|
helperText: helperText,
|
|
@@ -104,17 +135,63 @@ export const DatePicker = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref)
|
|
|
104
135
|
onErrorDate: onErrorDate,
|
|
105
136
|
required: required,
|
|
106
137
|
requiredError: requiredError,
|
|
107
|
-
style: dateInputStyle,
|
|
138
|
+
style: [dateInputStyle, styles == null ? void 0 : styles.dateInput],
|
|
108
139
|
variant: variant
|
|
109
|
-
})),
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
140
|
+
})), showPicker && /*#__PURE__*/_jsx(Tray, {
|
|
141
|
+
accessibilityRole: "none",
|
|
142
|
+
footer: _ref2 => {
|
|
143
|
+
let {
|
|
144
|
+
handleClose
|
|
145
|
+
} = _ref2;
|
|
146
|
+
return /*#__PURE__*/_jsx(StickyFooter, {
|
|
147
|
+
paddingTop: 3,
|
|
148
|
+
paddingX: 3,
|
|
149
|
+
role: "none",
|
|
150
|
+
children: /*#__PURE__*/_jsx(Button, {
|
|
151
|
+
block: true,
|
|
152
|
+
compact: true,
|
|
153
|
+
accessibilityHint: confirmButtonAccessibilityHint,
|
|
154
|
+
disabled: disabled || !calendarSelectedDate,
|
|
155
|
+
onPress: () => {
|
|
156
|
+
if (calendarSelectedDate) {
|
|
157
|
+
handleConfirmPicker(calendarSelectedDate);
|
|
158
|
+
handleClose();
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
children: confirmText
|
|
162
|
+
})
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
handleBarAccessibilityLabel: closeCalendarAccessibilityLabel,
|
|
166
|
+
handleBarVariant: "inside",
|
|
167
|
+
onCloseComplete: handleTrayCloseComplete,
|
|
168
|
+
onOpenComplete: handleModalShow,
|
|
169
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
170
|
+
ref: calendarRef,
|
|
171
|
+
disabled: disabled,
|
|
172
|
+
disabledDateError: disabledDateError,
|
|
173
|
+
disabledDates: disabledDates,
|
|
174
|
+
highlightedDateAccessibilityHint: highlightedDateAccessibilityHint,
|
|
175
|
+
highlightedDates: highlightedDates,
|
|
176
|
+
maxDate: maxDate,
|
|
177
|
+
minDate: minDate,
|
|
178
|
+
nextArrowAccessibilityLabel: nextArrowAccessibilityLabel,
|
|
179
|
+
onPressDate: handleCalendarDatePress,
|
|
180
|
+
paddingBottom: 2,
|
|
181
|
+
paddingX: 3,
|
|
182
|
+
previousArrowAccessibilityLabel: previousArrowAccessibilityLabel,
|
|
183
|
+
seedDate: seedDate,
|
|
184
|
+
selectedDate: calendarSelectedDate,
|
|
185
|
+
styles: {
|
|
186
|
+
root: styles == null ? void 0 : styles.calendar,
|
|
187
|
+
header: styles == null ? void 0 : styles.calendarHeader,
|
|
188
|
+
title: styles == null ? void 0 : styles.calendarTitle,
|
|
189
|
+
navigation: styles == null ? void 0 : styles.calendarNavigation,
|
|
190
|
+
content: styles == null ? void 0 : styles.calendarContent,
|
|
191
|
+
day: styles == null ? void 0 : styles.calendarDay
|
|
192
|
+
}
|
|
193
|
+
})
|
|
118
194
|
})]
|
|
119
195
|
});
|
|
120
|
-
}));
|
|
196
|
+
}));
|
|
197
|
+
DatePicker.displayName = 'DatePicker';
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { useLocale } from '@coinbase/cds-common/system/LocaleProvider';
|
|
3
|
+
import { Accordion, AccordionItem } from '../../accordion';
|
|
4
|
+
import { Button } from '../../buttons/Button';
|
|
5
|
+
import { Chip } from '../../chips';
|
|
6
|
+
import { Example, ExampleScreen } from '../../examples/ExampleScreen';
|
|
7
|
+
import { useTheme } from '../../hooks/useTheme';
|
|
8
|
+
import { Icon } from '../../icons';
|
|
9
|
+
import { Box } from '../../layout';
|
|
10
|
+
import { AnimatedCaret } from '../../motion/AnimatedCaret';
|
|
11
|
+
import { Tray } from '../../overlays/tray/Tray';
|
|
12
|
+
import { Calendar } from '../Calendar';
|
|
13
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
+
const today = new Date(new Date().setHours(0, 0, 0, 0));
|
|
15
|
+
const nextMonth15th = new Date(today.getFullYear(), today.getMonth() + 1, 15);
|
|
16
|
+
const lastMonth15th = new Date(today.getFullYear(), today.getMonth() - 1, 15);
|
|
17
|
+
const nextWeek = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 7);
|
|
18
|
+
const yesterday = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 1);
|
|
19
|
+
const tomorrow = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);
|
|
20
|
+
const twoDaysAgo = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 2);
|
|
21
|
+
|
|
22
|
+
// Generate all weekend date ranges for a wide range (10 years before and after)
|
|
23
|
+
const getWeekendDates = centerDate => {
|
|
24
|
+
const weekends = [];
|
|
25
|
+
|
|
26
|
+
// Cover 10 years before and after to ensure all weekends are disabled
|
|
27
|
+
const startDate = new Date(centerDate.getFullYear() - 10, 0, 1);
|
|
28
|
+
const endDate = new Date(centerDate.getFullYear() + 10, 11, 31);
|
|
29
|
+
|
|
30
|
+
// Find the first Saturday in the range
|
|
31
|
+
const currentDate = new Date(startDate);
|
|
32
|
+
const dayOfWeek = currentDate.getDay();
|
|
33
|
+
const daysUntilSaturday = dayOfWeek === 6 ? 0 : (6 - dayOfWeek + 7) % 7;
|
|
34
|
+
currentDate.setDate(currentDate.getDate() + daysUntilSaturday);
|
|
35
|
+
|
|
36
|
+
// Iterate through weekends, jumping 7 days at a time
|
|
37
|
+
while (currentDate <= endDate) {
|
|
38
|
+
const saturday = new Date(currentDate);
|
|
39
|
+
const sunday = new Date(currentDate);
|
|
40
|
+
sunday.setDate(sunday.getDate() + 1);
|
|
41
|
+
|
|
42
|
+
// Add the weekend as a date range tuple
|
|
43
|
+
weekends.push([saturday, sunday]);
|
|
44
|
+
|
|
45
|
+
// Jump to next Saturday (7 days later)
|
|
46
|
+
currentDate.setDate(currentDate.getDate() + 7);
|
|
47
|
+
}
|
|
48
|
+
return weekends;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Compute weekends once at module level
|
|
52
|
+
const disabledWeekend = getWeekendDates(today);
|
|
53
|
+
const DATE_ACCORDION_ITEM_KEY = 'date';
|
|
54
|
+
const formatDateLabel = (date, locale) => {
|
|
55
|
+
if (!date) {
|
|
56
|
+
return 'Select date';
|
|
57
|
+
}
|
|
58
|
+
return date.toLocaleDateString(locale, {
|
|
59
|
+
month: 'short',
|
|
60
|
+
day: 'numeric',
|
|
61
|
+
year: 'numeric'
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
const CalendarTrayExample = /*#__PURE__*/memo(function CalendarTrayExample(_ref) {
|
|
65
|
+
let {
|
|
66
|
+
renderTrigger
|
|
67
|
+
} = _ref;
|
|
68
|
+
const {
|
|
69
|
+
locale
|
|
70
|
+
} = useLocale();
|
|
71
|
+
const [date, setDate] = useState(null);
|
|
72
|
+
const [showPicker, setShowPicker] = useState(false);
|
|
73
|
+
const [calendarSelectedDate, setCalendarSelectedDate] = useState(null);
|
|
74
|
+
const calendarRef = useRef(null);
|
|
75
|
+
const handleOpenPicker = useCallback(() => {
|
|
76
|
+
setCalendarSelectedDate(date);
|
|
77
|
+
setShowPicker(true);
|
|
78
|
+
}, [date]);
|
|
79
|
+
const handleClosePicker = useCallback(() => {
|
|
80
|
+
setShowPicker(false);
|
|
81
|
+
}, []);
|
|
82
|
+
const handleCancelPicker = useCallback(() => {
|
|
83
|
+
setCalendarSelectedDate(null);
|
|
84
|
+
handleClosePicker();
|
|
85
|
+
}, [handleClosePicker]);
|
|
86
|
+
const handleCalendarDatePress = useCallback(selectedDate => {
|
|
87
|
+
setCalendarSelectedDate(selectedDate);
|
|
88
|
+
}, []);
|
|
89
|
+
const handleModalShow = useCallback(() => {
|
|
90
|
+
var _calendarRef$current;
|
|
91
|
+
(_calendarRef$current = calendarRef.current) == null || _calendarRef$current.focusInitialDate();
|
|
92
|
+
}, []);
|
|
93
|
+
const handleConfirmCalendar = useCallback(() => {
|
|
94
|
+
if (calendarSelectedDate) {
|
|
95
|
+
setDate(calendarSelectedDate);
|
|
96
|
+
handleClosePicker();
|
|
97
|
+
}
|
|
98
|
+
}, [calendarSelectedDate, handleClosePicker]);
|
|
99
|
+
const trayFooter = useMemo(() => /*#__PURE__*/_jsx(Box, {
|
|
100
|
+
paddingTop: 3,
|
|
101
|
+
paddingX: 3,
|
|
102
|
+
children: /*#__PURE__*/_jsx(Button, {
|
|
103
|
+
block: true,
|
|
104
|
+
compact: true,
|
|
105
|
+
accessibilityHint: !calendarSelectedDate ? 'Select a date first' : undefined,
|
|
106
|
+
accessibilityLabel: "Confirm date selection",
|
|
107
|
+
disabled: !calendarSelectedDate,
|
|
108
|
+
onPress: handleConfirmCalendar,
|
|
109
|
+
children: "Confirm"
|
|
110
|
+
})
|
|
111
|
+
}), [calendarSelectedDate, handleConfirmCalendar]);
|
|
112
|
+
const formattedLabel = formatDateLabel(date, locale);
|
|
113
|
+
const triggerProps = useMemo(() => ({
|
|
114
|
+
formattedLabel,
|
|
115
|
+
onOpen: handleOpenPicker,
|
|
116
|
+
showPicker
|
|
117
|
+
}), [formattedLabel, handleOpenPicker, showPicker]);
|
|
118
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
119
|
+
children: [renderTrigger(triggerProps), showPicker && /*#__PURE__*/_jsx(Tray, {
|
|
120
|
+
accessibilityRole: "none",
|
|
121
|
+
footer: trayFooter,
|
|
122
|
+
handleBarAccessibilityLabel: "Close calendar",
|
|
123
|
+
handleBarVariant: "inside",
|
|
124
|
+
onCloseComplete: handleCancelPicker,
|
|
125
|
+
onOpenComplete: handleModalShow,
|
|
126
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
127
|
+
ref: calendarRef,
|
|
128
|
+
onPressDate: handleCalendarDatePress,
|
|
129
|
+
paddingBottom: 2,
|
|
130
|
+
paddingX: 2,
|
|
131
|
+
selectedDate: calendarSelectedDate
|
|
132
|
+
})
|
|
133
|
+
})]
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
const CalendarChipWithTrayExample = () => {
|
|
137
|
+
const renderTrigger = useCallback(_ref2 => {
|
|
138
|
+
let {
|
|
139
|
+
formattedLabel,
|
|
140
|
+
onOpen,
|
|
141
|
+
showPicker
|
|
142
|
+
} = _ref2;
|
|
143
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
144
|
+
alignSelf: "flex-start",
|
|
145
|
+
children: /*#__PURE__*/_jsx(Chip, {
|
|
146
|
+
compact: true,
|
|
147
|
+
accessibilityLabel: formattedLabel,
|
|
148
|
+
end: /*#__PURE__*/_jsx(AnimatedCaret, {
|
|
149
|
+
active: true,
|
|
150
|
+
color: "fg",
|
|
151
|
+
rotate: showPicker ? 0 : 180,
|
|
152
|
+
size: "xs"
|
|
153
|
+
}),
|
|
154
|
+
onPress: onOpen,
|
|
155
|
+
children: formattedLabel
|
|
156
|
+
})
|
|
157
|
+
});
|
|
158
|
+
}, []);
|
|
159
|
+
return /*#__PURE__*/_jsx(CalendarTrayExample, {
|
|
160
|
+
renderTrigger: renderTrigger
|
|
161
|
+
});
|
|
162
|
+
};
|
|
163
|
+
const CalendarChipWithTrayButtonExample = () => {
|
|
164
|
+
const renderTrigger = useCallback(_ref3 => {
|
|
165
|
+
let {
|
|
166
|
+
formattedLabel,
|
|
167
|
+
onOpen
|
|
168
|
+
} = _ref3;
|
|
169
|
+
return /*#__PURE__*/_jsx(Button, {
|
|
170
|
+
compact: true,
|
|
171
|
+
accessibilityLabel: formattedLabel,
|
|
172
|
+
onPress: onOpen,
|
|
173
|
+
children: formattedLabel
|
|
174
|
+
});
|
|
175
|
+
}, []);
|
|
176
|
+
return /*#__PURE__*/_jsx(CalendarTrayExample, {
|
|
177
|
+
renderTrigger: renderTrigger
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
const CalendarAccordionExample = () => {
|
|
181
|
+
const {
|
|
182
|
+
locale
|
|
183
|
+
} = useLocale();
|
|
184
|
+
const [date, setDate] = useState(null);
|
|
185
|
+
const [activeKey, setActiveKey] = useState(null);
|
|
186
|
+
const expanded = activeKey === DATE_ACCORDION_ITEM_KEY;
|
|
187
|
+
const calendarRef = useRef(null);
|
|
188
|
+
const handleDatePress = useCallback(selectedDate => {
|
|
189
|
+
setDate(selectedDate);
|
|
190
|
+
setActiveKey(null);
|
|
191
|
+
}, []);
|
|
192
|
+
useEffect(() => {
|
|
193
|
+
if (expanded) {
|
|
194
|
+
const id = requestAnimationFrame(() => {
|
|
195
|
+
var _calendarRef$current2;
|
|
196
|
+
(_calendarRef$current2 = calendarRef.current) == null || _calendarRef$current2.focusInitialDate();
|
|
197
|
+
});
|
|
198
|
+
return () => cancelAnimationFrame(id);
|
|
199
|
+
}
|
|
200
|
+
}, [expanded]);
|
|
201
|
+
return /*#__PURE__*/_jsx(Accordion, {
|
|
202
|
+
activeKey: activeKey,
|
|
203
|
+
setActiveKey: setActiveKey,
|
|
204
|
+
children: /*#__PURE__*/_jsx(AccordionItem, {
|
|
205
|
+
itemKey: DATE_ACCORDION_ITEM_KEY,
|
|
206
|
+
media: /*#__PURE__*/_jsx(Icon, {
|
|
207
|
+
color: "fg",
|
|
208
|
+
name: "calendarEmpty"
|
|
209
|
+
}),
|
|
210
|
+
subtitle: formatDateLabel(date, locale),
|
|
211
|
+
title: "Date",
|
|
212
|
+
children: expanded ? /*#__PURE__*/_jsx(Calendar, {
|
|
213
|
+
ref: calendarRef,
|
|
214
|
+
onPressDate: handleDatePress,
|
|
215
|
+
selectedDate: date
|
|
216
|
+
}) : null
|
|
217
|
+
})
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
const CalendarScreen = () => {
|
|
221
|
+
const [basicDate, setBasicDate] = useState(today);
|
|
222
|
+
const [noSelectionDate, setNoSelectionDate] = useState(null);
|
|
223
|
+
const [seedDateDate, setSeedDateDate] = useState(null);
|
|
224
|
+
const [minMaxDate, setMinMaxDate] = useState(today);
|
|
225
|
+
const [futureDatesDate, setFutureDatesDate] = useState(null);
|
|
226
|
+
const [highlightedDate, setHighlightedDate] = useState(today);
|
|
227
|
+
const [disabledDatesDate, setDisabledDatesDate] = useState(null);
|
|
228
|
+
const [rangeDate, setRangeDate] = useState(today);
|
|
229
|
+
const [hiddenControlsDate, setHiddenControlsDate] = useState(today);
|
|
230
|
+
const highlightedRange = [yesterday, nextWeek];
|
|
231
|
+
const firstDayOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
|
|
232
|
+
const lastDayOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0);
|
|
233
|
+
const {
|
|
234
|
+
color
|
|
235
|
+
} = useTheme();
|
|
236
|
+
return /*#__PURE__*/_jsxs(ExampleScreen, {
|
|
237
|
+
children: [/*#__PURE__*/_jsx(Example, {
|
|
238
|
+
title: "Basic",
|
|
239
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
240
|
+
onPressDate: setBasicDate,
|
|
241
|
+
selectedDate: basicDate
|
|
242
|
+
})
|
|
243
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
244
|
+
title: "No selection",
|
|
245
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
246
|
+
onPressDate: setNoSelectionDate,
|
|
247
|
+
selectedDate: noSelectionDate
|
|
248
|
+
})
|
|
249
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
250
|
+
title: "With seedDate (different month)",
|
|
251
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
252
|
+
onPressDate: setSeedDateDate,
|
|
253
|
+
seedDate: nextMonth15th,
|
|
254
|
+
selectedDate: seedDateDate
|
|
255
|
+
})
|
|
256
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
257
|
+
title: "With min/max dates",
|
|
258
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
259
|
+
disabledDateError: "Date is outside allowed range",
|
|
260
|
+
maxDate: nextMonth15th,
|
|
261
|
+
minDate: lastMonth15th,
|
|
262
|
+
onPressDate: setMinMaxDate,
|
|
263
|
+
selectedDate: minMaxDate
|
|
264
|
+
})
|
|
265
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
266
|
+
title: "Future dates only",
|
|
267
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
268
|
+
disabledDateError: "Past dates are not available",
|
|
269
|
+
minDate: today,
|
|
270
|
+
onPressDate: setFutureDatesDate,
|
|
271
|
+
selectedDate: futureDatesDate
|
|
272
|
+
})
|
|
273
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
274
|
+
title: "With highlighted dates",
|
|
275
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
276
|
+
highlightedDates: [yesterday, today, nextWeek],
|
|
277
|
+
onPressDate: setHighlightedDate,
|
|
278
|
+
selectedDate: highlightedDate
|
|
279
|
+
})
|
|
280
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
281
|
+
title: "With disabled dates",
|
|
282
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
283
|
+
disabledDateError: "Weekends are not available",
|
|
284
|
+
disabledDates: disabledWeekend,
|
|
285
|
+
onPressDate: setDisabledDatesDate,
|
|
286
|
+
seedDate: today,
|
|
287
|
+
selectedDate: disabledDatesDate
|
|
288
|
+
})
|
|
289
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
290
|
+
title: "With date range",
|
|
291
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
292
|
+
highlightedDates: [highlightedRange],
|
|
293
|
+
onPressDate: setRangeDate,
|
|
294
|
+
selectedDate: rangeDate
|
|
295
|
+
})
|
|
296
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
297
|
+
title: "Hidden controls",
|
|
298
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
299
|
+
hideControls: true,
|
|
300
|
+
maxDate: lastDayOfMonth,
|
|
301
|
+
minDate: firstDayOfMonth,
|
|
302
|
+
onPressDate: setHiddenControlsDate,
|
|
303
|
+
selectedDate: hiddenControlsDate
|
|
304
|
+
})
|
|
305
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
306
|
+
title: "Disabled",
|
|
307
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
308
|
+
disabled: true,
|
|
309
|
+
selectedDate: today
|
|
310
|
+
})
|
|
311
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
312
|
+
title: "Slot styling",
|
|
313
|
+
children: /*#__PURE__*/_jsx(Calendar, {
|
|
314
|
+
disabledDateError: "Date unavailable",
|
|
315
|
+
disabledDates: [twoDaysAgo],
|
|
316
|
+
highlightedDates: [tomorrow],
|
|
317
|
+
maxDate: nextMonth15th,
|
|
318
|
+
minDate: lastMonth15th,
|
|
319
|
+
onPressDate: setBasicDate,
|
|
320
|
+
selectedDate: basicDate,
|
|
321
|
+
styles: {
|
|
322
|
+
root: {
|
|
323
|
+
borderColor: color.bgLineHeavy,
|
|
324
|
+
borderRadius: 16,
|
|
325
|
+
borderWidth: 1,
|
|
326
|
+
padding: 12
|
|
327
|
+
},
|
|
328
|
+
header: {
|
|
329
|
+
backgroundColor: color.bgPositiveWash,
|
|
330
|
+
borderRadius: 16,
|
|
331
|
+
paddingBottom: 0
|
|
332
|
+
},
|
|
333
|
+
content: {
|
|
334
|
+
paddingVertical: 8
|
|
335
|
+
},
|
|
336
|
+
day: {
|
|
337
|
+
borderColor: color.bgNegative,
|
|
338
|
+
borderWidth: 1
|
|
339
|
+
},
|
|
340
|
+
navigation: {
|
|
341
|
+
borderColor: color.bgLineHeavy,
|
|
342
|
+
borderRadius: 8,
|
|
343
|
+
borderStyle: 'dashed',
|
|
344
|
+
borderWidth: 1
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
})
|
|
348
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
349
|
+
title: "With tray (Chip trigger)",
|
|
350
|
+
children: /*#__PURE__*/_jsx(CalendarChipWithTrayExample, {})
|
|
351
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
352
|
+
title: "With tray (Button trigger)",
|
|
353
|
+
children: /*#__PURE__*/_jsx(CalendarChipWithTrayButtonExample, {})
|
|
354
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
355
|
+
title: "With Accordion (select to collapse)",
|
|
356
|
+
children: /*#__PURE__*/_jsx(CalendarAccordionExample, {})
|
|
357
|
+
})]
|
|
358
|
+
});
|
|
359
|
+
};
|
|
360
|
+
export default CalendarScreen;
|