@coinbase/cds-mobile 8.53.1 → 8.54.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 +10 -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 +4 -0
- package/dts/overlays/drawer/Drawer.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/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/drawer/Drawer.js +4 -2
- package/esm/overlays/tooltip/Tooltip.js +7 -2
- package/package.json +2 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../src/overlays/tooltip/Tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4E,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../../src/overlays/tooltip/Tooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4E,MAAM,OAAO,CAAC;AACjG,OAAO,EAAE,KAAK,kBAAkB,EAA4C,MAAM,cAAc,CAAC;AAKjG,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGtE,MAAM,MAAM,YAAY,GAAG,gBAAgB,GAAG;IAC5C;;OAEG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC,CAAC;AAEF,eAAO,MAAM,OAAO,yTAoBf,YAAY,6CA0JhB,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const _excluded = ["name", "active", "variant", "transparent", "compact", "background", "color", "borderColor", "iconSize", "borderWidth", "borderRadius", "feedback", "flush", "loading", "style", "accessibilityHint", "accessibilityLabel"];
|
|
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
|
-
import React, { memo, useCallback, useMemo } from 'react';
|
|
4
|
+
import React, { forwardRef, memo, useCallback, useMemo } from 'react';
|
|
5
5
|
import { ActivityIndicator } from 'react-native';
|
|
6
6
|
import { transparentVariants, variants } from '@coinbase/cds-common/tokens/button';
|
|
7
7
|
import { interactableHeight } from '@coinbase/cds-common/tokens/interactableHeight';
|
|
@@ -10,7 +10,7 @@ import { useTheme } from '../hooks/useTheme';
|
|
|
10
10
|
import { Icon } from '../icons/Icon';
|
|
11
11
|
import { Pressable } from '../system/Pressable';
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
-
export const IconButton = /*#__PURE__*/memo(function IconButton(_ref) {
|
|
13
|
+
export const IconButton = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(function IconButton(_ref, ref) {
|
|
14
14
|
let {
|
|
15
15
|
name,
|
|
16
16
|
active,
|
|
@@ -54,6 +54,7 @@ export const IconButton = /*#__PURE__*/memo(function IconButton(_ref) {
|
|
|
54
54
|
}), [minHeight]);
|
|
55
55
|
const pressableStyle = useCallback(state => [sizingStyle, typeof style === 'function' ? style(state) : style], [sizingStyle, style]);
|
|
56
56
|
return /*#__PURE__*/_jsx(Pressable, _extends({
|
|
57
|
+
ref: ref,
|
|
57
58
|
accessibilityHint: accessibilityHint,
|
|
58
59
|
accessibilityLabel: loading ? (accessibilityLabel != null ? accessibilityLabel : '') + ", loading" : accessibilityLabel,
|
|
59
60
|
background: backgroundValue,
|
|
@@ -83,5 +84,5 @@ export const IconButton = /*#__PURE__*/memo(function IconButton(_ref) {
|
|
|
83
84
|
style: sizingStyle
|
|
84
85
|
})
|
|
85
86
|
}));
|
|
86
|
-
});
|
|
87
|
+
}));
|
|
87
88
|
IconButton.displayName = 'IconButton';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const _excluded = ["disableInheritFocusStyle", "testID", "variant", "accessibilityLabel", "accessibilityHint"];
|
|
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
|
-
import React, { memo, useContext } from 'react';
|
|
4
|
+
import React, { forwardRef, memo, useContext } from 'react';
|
|
5
5
|
import { IconButton } from '../buttons/IconButton';
|
|
6
6
|
import { Box } from '../layout/Box';
|
|
7
7
|
import { TextInputFocusVariantContext } from './context';
|
|
@@ -14,7 +14,7 @@ export const variantTransformMap = {
|
|
|
14
14
|
foregroundMuted: 'foregroundMuted',
|
|
15
15
|
secondary: 'secondary'
|
|
16
16
|
};
|
|
17
|
-
export const InputIconButton = /*#__PURE__*/memo(function InputIconButton(_ref) {
|
|
17
|
+
export const InputIconButton = /*#__PURE__*/memo(/*#__PURE__*/forwardRef(function InputIconButton(_ref, ref) {
|
|
18
18
|
let {
|
|
19
19
|
disableInheritFocusStyle = false,
|
|
20
20
|
testID,
|
|
@@ -30,10 +30,11 @@ export const InputIconButton = /*#__PURE__*/memo(function InputIconButton(_ref)
|
|
|
30
30
|
paddingStart: 1,
|
|
31
31
|
testID: testID,
|
|
32
32
|
children: /*#__PURE__*/_jsx(IconButton, _extends({
|
|
33
|
+
ref: ref,
|
|
33
34
|
transparent: true,
|
|
34
35
|
accessibilityHint: accessibilityHint != null ? accessibilityHint : props.name,
|
|
35
36
|
accessibilityLabel: accessibilityLabel != null ? accessibilityLabel : props.name,
|
|
36
37
|
variant: disableInheritFocusStyle ? variant : transformedVariant
|
|
37
38
|
}, props))
|
|
38
39
|
});
|
|
39
|
-
});
|
|
40
|
+
}));
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
const _excluded = ["background", "borderRadius", "children"],
|
|
2
|
+
_excluded2 = ["selectedDate", "seedDate", "onPressDate", "disabled", "hideControls", "disabledDates", "highlightedDates", "minDate", "maxDate", "disabledDateError", "nextArrowAccessibilityLabel", "previousArrowAccessibilityLabel", "todayAccessibilityHint", "highlightedDateAccessibilityHint", "style", "styles"];
|
|
3
|
+
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); }
|
|
4
|
+
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; }
|
|
5
|
+
import { forwardRef, memo, useCallback, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
6
|
+
import { StyleSheet } from 'react-native';
|
|
7
|
+
import { generateCalendarMonth } from '@coinbase/cds-common/dates/generateCalendarMonth';
|
|
8
|
+
import { getMidnightDate } from '@coinbase/cds-common/dates/getMidnightDate';
|
|
9
|
+
import { getTimesFromDatesAndRanges } from '@coinbase/cds-common/dates/getTimesFromDatesAndRanges';
|
|
10
|
+
import { useLocale } from '@coinbase/cds-common/system/LocaleProvider';
|
|
11
|
+
import { accessibleOpacityDisabled } from '@coinbase/cds-common/tokens/interactable';
|
|
12
|
+
import { useA11y } from '../hooks/useA11y';
|
|
13
|
+
import { useScreenReaderStatus } from '../hooks/useScreenReaderStatus';
|
|
14
|
+
import { Icon } from '../icons/Icon';
|
|
15
|
+
import { Box } from '../layout/Box';
|
|
16
|
+
import { HStack } from '../layout/HStack';
|
|
17
|
+
import { VStack } from '../layout/VStack';
|
|
18
|
+
import { Tooltip } from '../overlays/tooltip/Tooltip';
|
|
19
|
+
import { Pressable } from '../system/Pressable';
|
|
20
|
+
import { Text } from '../typography/Text';
|
|
21
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
22
|
+
const CALENDAR_DAY_DIMENSION = 40;
|
|
23
|
+
|
|
24
|
+
// These could be dynamically generated, but our Calendar and DatePicker aren't localized so there's no point
|
|
25
|
+
const DAYS_OF_WEEK = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
26
|
+
const styles = StyleSheet.create({
|
|
27
|
+
pressable: {
|
|
28
|
+
alignItems: 'center',
|
|
29
|
+
justifyContent: 'center',
|
|
30
|
+
width: '100%',
|
|
31
|
+
height: '100%'
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
const CalendarPressable = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) => {
|
|
35
|
+
let {
|
|
36
|
+
background = 'transparent',
|
|
37
|
+
borderRadius = 1000,
|
|
38
|
+
children
|
|
39
|
+
} = _ref,
|
|
40
|
+
props = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
41
|
+
return /*#__PURE__*/_jsx(Pressable, _extends({
|
|
42
|
+
ref: ref,
|
|
43
|
+
background: background,
|
|
44
|
+
borderRadius: borderRadius,
|
|
45
|
+
contentStyle: styles.pressable,
|
|
46
|
+
height: CALENDAR_DAY_DIMENSION,
|
|
47
|
+
width: CALENDAR_DAY_DIMENSION
|
|
48
|
+
}, props, {
|
|
49
|
+
children: children
|
|
50
|
+
}));
|
|
51
|
+
}));
|
|
52
|
+
CalendarPressable.displayName = 'CalendarPressable';
|
|
53
|
+
const getDayAccessibilityLabel = function (date, locale) {
|
|
54
|
+
if (locale === void 0) {
|
|
55
|
+
locale = 'en-US';
|
|
56
|
+
}
|
|
57
|
+
return date.toLocaleDateString(locale, {
|
|
58
|
+
weekday: 'long',
|
|
59
|
+
day: 'numeric'
|
|
60
|
+
}) + " " + date.toLocaleDateString(locale, {
|
|
61
|
+
month: 'long',
|
|
62
|
+
year: 'numeric'
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
const CalendarDay = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref2, ref) => {
|
|
66
|
+
let {
|
|
67
|
+
date,
|
|
68
|
+
active,
|
|
69
|
+
disabled,
|
|
70
|
+
highlighted,
|
|
71
|
+
isToday,
|
|
72
|
+
isCurrentMonth,
|
|
73
|
+
onPress,
|
|
74
|
+
disabledError,
|
|
75
|
+
todayAccessibilityHint,
|
|
76
|
+
highlightedDateAccessibilityHint,
|
|
77
|
+
style
|
|
78
|
+
} = _ref2;
|
|
79
|
+
const {
|
|
80
|
+
locale
|
|
81
|
+
} = useLocale();
|
|
82
|
+
const handlePress = useCallback(() => onPress == null ? void 0 : onPress(date), [date, onPress]);
|
|
83
|
+
const accessibilityLabel = useMemo(() => getDayAccessibilityLabel(date, locale), [date, locale]);
|
|
84
|
+
const accessibilityState = useMemo(() => ({
|
|
85
|
+
disabled: !!disabled,
|
|
86
|
+
selected: !!active
|
|
87
|
+
}), [disabled, active]);
|
|
88
|
+
|
|
89
|
+
// Period between phrases gives screen readers a clear pause (e.g. "Today. Date unavailable").
|
|
90
|
+
const accessibilityHint = useMemo(() => {
|
|
91
|
+
const hints = [isToday ? todayAccessibilityHint : undefined, highlighted ? highlightedDateAccessibilityHint : undefined, disabled ? disabledError : undefined].filter(Boolean).join('. ');
|
|
92
|
+
return hints || undefined;
|
|
93
|
+
}, [disabled, highlighted, isToday, todayAccessibilityHint, highlightedDateAccessibilityHint, disabledError]);
|
|
94
|
+
const isScreenReaderEnabled = useScreenReaderStatus();
|
|
95
|
+
|
|
96
|
+
// Expose disabled to the tooltip's accessibilityState so screen readers on both platforms
|
|
97
|
+
// announce the day button as disabled. We only set disabled when a screen reader is active:
|
|
98
|
+
// on some platforms a11y disabled is equivalent to the top-level disabled prop, so always
|
|
99
|
+
// setting it would block tooltip interactivity for users not using SRs.
|
|
100
|
+
const tooltipAccessibilityState = useMemo(() => ({
|
|
101
|
+
disabled: isScreenReaderEnabled
|
|
102
|
+
}), [isScreenReaderEnabled]);
|
|
103
|
+
if (!isCurrentMonth) {
|
|
104
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
105
|
+
"aria-hidden": true,
|
|
106
|
+
height: CALENDAR_DAY_DIMENSION,
|
|
107
|
+
width: CALENDAR_DAY_DIMENSION
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const dayButton = /*#__PURE__*/_jsx(CalendarPressable, {
|
|
111
|
+
ref: ref,
|
|
112
|
+
accessibilityHint: accessibilityHint,
|
|
113
|
+
accessibilityLabel: accessibilityLabel,
|
|
114
|
+
accessibilityRole: "button",
|
|
115
|
+
accessibilityState: accessibilityState,
|
|
116
|
+
background: active && !disabled ? 'bgPrimary' : undefined,
|
|
117
|
+
borderColor: isToday ? 'bgPrimary' : undefined,
|
|
118
|
+
bordered: isToday,
|
|
119
|
+
disabled: disabled,
|
|
120
|
+
feedback: disabled ? 'none' : 'light',
|
|
121
|
+
onPress: handlePress,
|
|
122
|
+
style: style,
|
|
123
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
124
|
+
accessible: false,
|
|
125
|
+
align: "center",
|
|
126
|
+
color: active && !disabled ? 'fgInverse' : highlighted ? 'fgPrimary' : undefined,
|
|
127
|
+
font: "body",
|
|
128
|
+
children: date.getDate()
|
|
129
|
+
})
|
|
130
|
+
});
|
|
131
|
+
if (disabled) {
|
|
132
|
+
return /*#__PURE__*/_jsx(Tooltip, {
|
|
133
|
+
accessibilityHint: accessibilityHint,
|
|
134
|
+
accessibilityLabel: accessibilityLabel,
|
|
135
|
+
accessibilityState: tooltipAccessibilityState,
|
|
136
|
+
content: disabledError,
|
|
137
|
+
children: dayButton
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return dayButton;
|
|
141
|
+
}));
|
|
142
|
+
CalendarDay.displayName = 'CalendarDay';
|
|
143
|
+
export const Calendar = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref3, ref) => {
|
|
144
|
+
let {
|
|
145
|
+
selectedDate,
|
|
146
|
+
seedDate,
|
|
147
|
+
onPressDate,
|
|
148
|
+
disabled,
|
|
149
|
+
hideControls,
|
|
150
|
+
disabledDates,
|
|
151
|
+
highlightedDates,
|
|
152
|
+
minDate,
|
|
153
|
+
maxDate,
|
|
154
|
+
disabledDateError = 'Date unavailable',
|
|
155
|
+
nextArrowAccessibilityLabel = 'Go to next month',
|
|
156
|
+
previousArrowAccessibilityLabel = 'Go to previous month',
|
|
157
|
+
todayAccessibilityHint = 'Today',
|
|
158
|
+
highlightedDateAccessibilityHint = 'Highlighted',
|
|
159
|
+
style,
|
|
160
|
+
styles
|
|
161
|
+
} = _ref3,
|
|
162
|
+
props = _objectWithoutPropertiesLoose(_ref3, _excluded2);
|
|
163
|
+
const {
|
|
164
|
+
setA11yFocus,
|
|
165
|
+
announceForA11y
|
|
166
|
+
} = useA11y();
|
|
167
|
+
const today = useMemo(() => getMidnightDate(new Date()), []);
|
|
168
|
+
const todayTime = useMemo(() => today.getTime(), [today]);
|
|
169
|
+
|
|
170
|
+
// Determine default calendar seed date: use whichever comes first between maxDate and today
|
|
171
|
+
const defaultSeedDate = useMemo(() => {
|
|
172
|
+
if (selectedDate) {
|
|
173
|
+
return selectedDate;
|
|
174
|
+
}
|
|
175
|
+
if (seedDate) {
|
|
176
|
+
return seedDate;
|
|
177
|
+
}
|
|
178
|
+
if (maxDate) {
|
|
179
|
+
const maxDateTime = getMidnightDate(maxDate).getTime();
|
|
180
|
+
const todayTime = today.getTime();
|
|
181
|
+
return maxDateTime < todayTime ? maxDate : today;
|
|
182
|
+
}
|
|
183
|
+
return today;
|
|
184
|
+
}, [selectedDate, seedDate, maxDate, today]);
|
|
185
|
+
const [calendarSeedDate, setCalendarSeedDate] = useState(defaultSeedDate);
|
|
186
|
+
const initialFocusRef = useRef(null);
|
|
187
|
+
const calendarMonth = useMemo(() => generateCalendarMonth(calendarSeedDate), [calendarSeedDate]);
|
|
188
|
+
const selectedTime = useMemo(() => selectedDate ? getMidnightDate(selectedDate).getTime() : null, [selectedDate]);
|
|
189
|
+
const disabledTimes = useMemo(() => new Set(getTimesFromDatesAndRanges(disabledDates || [])), [disabledDates]);
|
|
190
|
+
const focusTargetTime = useMemo(() => selectedTime || (seedDate ? getMidnightDate(seedDate).getTime() : null) || todayTime, [selectedTime, seedDate, todayTime]);
|
|
191
|
+
useImperativeHandle(ref, () => ({
|
|
192
|
+
focusInitialDate: () => {
|
|
193
|
+
if (disabled || !initialFocusRef.current) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
setA11yFocus(initialFocusRef);
|
|
197
|
+
}
|
|
198
|
+
}), [disabled, setA11yFocus]);
|
|
199
|
+
const minTime = useMemo(() => minDate && getMidnightDate(minDate).getTime(), [minDate]);
|
|
200
|
+
const maxTime = useMemo(() => maxDate && getMidnightDate(maxDate).getTime(), [maxDate]);
|
|
201
|
+
const highlightedTimes = useMemo(() => new Set(getTimesFromDatesAndRanges(highlightedDates || [])), [highlightedDates]);
|
|
202
|
+
const handleGoNextMonth = useCallback(() => {
|
|
203
|
+
setCalendarSeedDate(s => {
|
|
204
|
+
const next = new Date(s.getFullYear(), s.getMonth() + 1, 1);
|
|
205
|
+
announceForA11y(next.toLocaleDateString('en-US', {
|
|
206
|
+
month: 'long',
|
|
207
|
+
year: 'numeric'
|
|
208
|
+
}));
|
|
209
|
+
return next;
|
|
210
|
+
});
|
|
211
|
+
}, [setCalendarSeedDate, announceForA11y]);
|
|
212
|
+
const handleGoPreviousMonth = useCallback(() => {
|
|
213
|
+
setCalendarSeedDate(s => {
|
|
214
|
+
const prev = new Date(s.getFullYear(), s.getMonth() - 1, 1);
|
|
215
|
+
announceForA11y(prev.toLocaleDateString('en-US', {
|
|
216
|
+
month: 'long',
|
|
217
|
+
year: 'numeric'
|
|
218
|
+
}));
|
|
219
|
+
return prev;
|
|
220
|
+
});
|
|
221
|
+
}, [setCalendarSeedDate, announceForA11y]);
|
|
222
|
+
const disableGoNextMonth = useMemo(() => {
|
|
223
|
+
if (disabled) {
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
const firstDateOfNextMonth = new Date(calendarSeedDate.getFullYear(), calendarSeedDate.getMonth() + 1, 1);
|
|
227
|
+
return maxTime ? maxTime < firstDateOfNextMonth.getTime() : false;
|
|
228
|
+
}, [maxTime, calendarSeedDate, disabled]);
|
|
229
|
+
const disableGoPreviousMonth = useMemo(() => {
|
|
230
|
+
if (disabled) {
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
const lastDateOfPreviousMonth = new Date(calendarSeedDate.getFullYear(), calendarSeedDate.getMonth(), 0);
|
|
234
|
+
return minTime ? minTime > lastDateOfPreviousMonth.getTime() : false;
|
|
235
|
+
}, [minTime, calendarSeedDate, disabled]);
|
|
236
|
+
|
|
237
|
+
// Split calendar month into weeks
|
|
238
|
+
const calendarWeeks = useMemo(() => {
|
|
239
|
+
const weeks = [];
|
|
240
|
+
for (let i = 0; i < calendarMonth.length; i += DAYS_OF_WEEK.length) {
|
|
241
|
+
const weekDates = calendarMonth.slice(i, i + DAYS_OF_WEEK.length);
|
|
242
|
+
weeks.push(["week-" + calendarMonth[i].getTime(), weekDates]);
|
|
243
|
+
}
|
|
244
|
+
return weeks;
|
|
245
|
+
}, [calendarMonth]);
|
|
246
|
+
const monthYearLabel = useMemo(() => calendarSeedDate.toLocaleDateString('en-US', {
|
|
247
|
+
month: 'long',
|
|
248
|
+
year: 'numeric'
|
|
249
|
+
}), [calendarSeedDate]);
|
|
250
|
+
const previousArrowAccessibilityState = useMemo(() => ({
|
|
251
|
+
disabled: !!disableGoPreviousMonth
|
|
252
|
+
}), [disableGoPreviousMonth]);
|
|
253
|
+
const nextArrowAccessibilityState = useMemo(() => ({
|
|
254
|
+
disabled: !!disableGoNextMonth
|
|
255
|
+
}), [disableGoNextMonth]);
|
|
256
|
+
return /*#__PURE__*/_jsxs(VStack, _extends({
|
|
257
|
+
opacity: disabled ? accessibleOpacityDisabled : undefined,
|
|
258
|
+
style: [style, styles == null ? void 0 : styles.root]
|
|
259
|
+
}, props, {
|
|
260
|
+
children: [/*#__PURE__*/_jsxs(HStack, {
|
|
261
|
+
alignItems: "center",
|
|
262
|
+
justifyContent: "space-between",
|
|
263
|
+
paddingBottom: 2,
|
|
264
|
+
paddingStart: 1.5,
|
|
265
|
+
style: styles == null ? void 0 : styles.header,
|
|
266
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
267
|
+
accessibilityRole: "header",
|
|
268
|
+
font: "headline",
|
|
269
|
+
style: styles == null ? void 0 : styles.title,
|
|
270
|
+
children: monthYearLabel
|
|
271
|
+
}), !hideControls && /*#__PURE__*/_jsxs(HStack, {
|
|
272
|
+
gap: 1,
|
|
273
|
+
style: styles == null ? void 0 : styles.navigation,
|
|
274
|
+
children: [/*#__PURE__*/_jsx(CalendarPressable, {
|
|
275
|
+
accessibilityLabel: previousArrowAccessibilityLabel,
|
|
276
|
+
accessibilityRole: "button",
|
|
277
|
+
accessibilityState: previousArrowAccessibilityState,
|
|
278
|
+
disabled: disableGoPreviousMonth,
|
|
279
|
+
feedback: "light",
|
|
280
|
+
onPress: disableGoPreviousMonth ? undefined : handleGoPreviousMonth,
|
|
281
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
282
|
+
color: "fg",
|
|
283
|
+
name: "backArrow",
|
|
284
|
+
size: "s"
|
|
285
|
+
})
|
|
286
|
+
}), /*#__PURE__*/_jsx(CalendarPressable, {
|
|
287
|
+
accessibilityLabel: nextArrowAccessibilityLabel,
|
|
288
|
+
accessibilityRole: "button",
|
|
289
|
+
accessibilityState: nextArrowAccessibilityState,
|
|
290
|
+
disabled: disableGoNextMonth,
|
|
291
|
+
feedback: "light",
|
|
292
|
+
onPress: disableGoNextMonth ? undefined : handleGoNextMonth,
|
|
293
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
294
|
+
color: "fg",
|
|
295
|
+
name: "forwardArrow",
|
|
296
|
+
size: "s"
|
|
297
|
+
})
|
|
298
|
+
})]
|
|
299
|
+
})]
|
|
300
|
+
}), /*#__PURE__*/_jsxs(VStack, {
|
|
301
|
+
gap: 1,
|
|
302
|
+
style: styles == null ? void 0 : styles.content,
|
|
303
|
+
children: [/*#__PURE__*/_jsx(HStack, {
|
|
304
|
+
"aria-hidden": true,
|
|
305
|
+
gap: 1,
|
|
306
|
+
justifyContent: "space-between",
|
|
307
|
+
paddingBottom: 1,
|
|
308
|
+
children: DAYS_OF_WEEK.map(day => /*#__PURE__*/_jsx(Box, {
|
|
309
|
+
alignItems: "center",
|
|
310
|
+
height: CALENDAR_DAY_DIMENSION,
|
|
311
|
+
justifyContent: "center",
|
|
312
|
+
width: CALENDAR_DAY_DIMENSION,
|
|
313
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
314
|
+
font: "body",
|
|
315
|
+
userSelect: "none",
|
|
316
|
+
children: day.charAt(0)
|
|
317
|
+
})
|
|
318
|
+
}, day))
|
|
319
|
+
}), calendarWeeks.map(_ref4 => {
|
|
320
|
+
let [weekId, week] = _ref4;
|
|
321
|
+
return /*#__PURE__*/_jsx(HStack, {
|
|
322
|
+
gap: 1,
|
|
323
|
+
justifyContent: "space-between",
|
|
324
|
+
children: week.map(date => {
|
|
325
|
+
const time = date.getTime();
|
|
326
|
+
return /*#__PURE__*/_jsx(CalendarDay, {
|
|
327
|
+
ref: time === focusTargetTime ? initialFocusRef : undefined,
|
|
328
|
+
active: time === selectedTime,
|
|
329
|
+
date: date,
|
|
330
|
+
disabled: disabled || minTime !== undefined && minTime !== null && time < minTime || maxTime !== undefined && maxTime !== null && time > maxTime || disabledTimes.has(time),
|
|
331
|
+
disabledError: disabledDateError,
|
|
332
|
+
highlighted: highlightedTimes.has(time),
|
|
333
|
+
highlightedDateAccessibilityHint: highlightedDateAccessibilityHint,
|
|
334
|
+
isCurrentMonth: date.getMonth() === calendarSeedDate.getMonth(),
|
|
335
|
+
isToday: time === todayTime,
|
|
336
|
+
onPress: onPressDate,
|
|
337
|
+
style: styles == null ? void 0 : styles.day,
|
|
338
|
+
todayAccessibilityHint: todayAccessibilityHint
|
|
339
|
+
}, time);
|
|
340
|
+
})
|
|
341
|
+
}, weekId);
|
|
342
|
+
})]
|
|
343
|
+
})]
|
|
344
|
+
}));
|
|
345
|
+
}));
|
|
346
|
+
Calendar.displayName = 'Calendar';
|
package/esm/dates/DateInput.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const _excluded = ["date", "onChangeDate", "error", "onErrorDate", "required", "separator", "minDate", "maxDate", "requiredError", "invalidDateError", "disabledDateError", "start", "end", "placeholder", "helperText", "variant", "onBlur", "onChange", "onEndEditing", "testIDMap", "style"];
|
|
1
|
+
const _excluded = ["date", "onChangeDate", "error", "onErrorDate", "required", "separator", "disabledDates", "minDate", "maxDate", "requiredError", "invalidDateError", "disabledDateError", "start", "end", "placeholder", "helperText", "variant", "onBlur", "onChange", "onEndEditing", "testIDMap", "style"];
|
|
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 React, { forwardRef, memo, useCallback, useMemo, useRef } from 'react';
|
|
@@ -16,6 +16,7 @@ export const DateInput = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =
|
|
|
16
16
|
onErrorDate,
|
|
17
17
|
required,
|
|
18
18
|
separator = '/',
|
|
19
|
+
disabledDates,
|
|
19
20
|
minDate,
|
|
20
21
|
maxDate,
|
|
21
22
|
requiredError,
|
|
@@ -53,6 +54,7 @@ export const DateInput = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =
|
|
|
53
54
|
onErrorDate,
|
|
54
55
|
intlDateFormat,
|
|
55
56
|
required,
|
|
57
|
+
disabledDates,
|
|
56
58
|
minDate,
|
|
57
59
|
maxDate,
|
|
58
60
|
requiredError,
|
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';
|