Skip to content

Commit ba4124d

Browse files
authored
DateTimePicker - start deprecation of moment props (#2625)
1 parent c113114 commit ba4124d

File tree

6 files changed

+144
-59
lines changed

6 files changed

+144
-59
lines changed

demo/src/screens/componentScreens/DateTimePickerScreen.tsx

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
11
import React, {Component} from 'react';
22
import {ScrollView} from 'react-native';
3-
import {DateTimePicker, DateTimePickerProps, View, Text} from 'react-native-ui-lib'; // eslint-disable-line
3+
import moment from 'moment';
4+
import * as LightDate from 'light-date';
5+
import {DateTimePicker, DateTimePickerProps, DateTimePickerMode, View, Text, Switch} from 'react-native-ui-lib';
6+
7+
interface State {
8+
mode: DateTimePickerMode;
9+
dateTimeFormatter: 'moment' | 'light-date';
10+
}
11+
12+
export default class DateTimePickerScreen extends Component<{}, State> {
13+
constructor(props: any) {
14+
super(props);
15+
this.state = {
16+
mode: 'time',
17+
dateTimeFormatter: 'moment'
18+
};
19+
}
420

5-
export default class DateTimePickerScreen extends Component {
621
getCustomInputValue = (value?: string) => {
722
if (!value) {
823
return 'Default';
@@ -21,7 +36,27 @@ export default class DateTimePickerScreen extends Component {
2136
);
2237
};
2338

39+
toggleTimeOrDate = () => {
40+
this.setState({mode: this.state.mode === 'time' ? 'date' : 'time'});
41+
};
42+
43+
toggleFormatter = () => {
44+
this.setState({dateTimeFormatter: this.state.dateTimeFormatter === 'moment' ? 'light-date' : 'moment'});
45+
};
46+
47+
getFormatter = (): DateTimePickerProps['dateTimeFormatter'] => {
48+
const {dateTimeFormatter} = this.state;
49+
if (dateTimeFormatter === 'moment') {
50+
return (value: Date, mode: DateTimePickerMode) =>
51+
moment(value).format(mode === 'date' ? 'MMM D, YYYY' : 'h:mm A');
52+
} else {
53+
return (value: Date, mode: DateTimePickerMode) =>
54+
LightDate.format(value, mode === 'date' ? '{mm}-{dd}-{yyyy}' : '{HH}:{mm}');
55+
}
56+
};
57+
2458
render() {
59+
const {mode, dateTimeFormatter} = this.state;
2560
return (
2661
<ScrollView>
2762
<View padding-page>
@@ -31,15 +66,13 @@ export default class DateTimePickerScreen extends Component {
3166
containerStyle={{marginVertical: 20}}
3267
label={'Date'}
3368
placeholder={'Select a date'}
34-
// dateFormat={'MMM D, YYYY'}
3569
// value={new Date('October 13, 2014')}
3670
/>
3771
<DateTimePicker
3872
migrateTextField
3973
mode={'time'}
4074
label={'Time'}
4175
placeholder={'Select time'}
42-
// timeFormat={'h:mm A'}
4376
// value={new Date('2015-03-25T12:00:00-06:30')}
4477
/>
4578

@@ -64,13 +97,22 @@ export default class DateTimePickerScreen extends Component {
6497
<Text text60R marginT-40>
6598
Custom Input
6699
</Text>
100+
<View row marginV-20 centerV spread>
101+
<View row>
102+
<Text text80>{mode}</Text>
103+
<Switch value={mode === 'time'} onValueChange={this.toggleTimeOrDate} marginL-10/>
104+
</View>
105+
<View row>
106+
<Text text80>{dateTimeFormatter}</Text>
107+
<Switch value={dateTimeFormatter === 'moment'} onValueChange={this.toggleFormatter} marginL-10/>
108+
</View>
109+
</View>
67110
<DateTimePicker
68111
migrateTextField
69112
containerStyle={{marginVertical: 20}}
70-
label={'Date'}
71-
placeholder={'Select a date'}
72113
renderInput={this.renderCustomInput}
73-
dateFormat={'MMM D, YYYY'}
114+
mode={mode}
115+
dateTimeFormatter={this.getFormatter()}
74116
// value={new Date('2015-03-25T12:00:00-06:30')}
75117
/>
76118
</View>

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@
4949
"prop-types": "^15.5.10",
5050
"react-freeze": "^1.0.0",
5151
"react-native-redash": "^12.0.3",
52-
"wix-react-native-text-size": "~1.0.0",
5352
"semver": "^5.5.0",
5453
"tinycolor2": "^1.4.2",
55-
"url-parse": "^1.2.0"
54+
"url-parse": "^1.2.0",
55+
"wix-react-native-text-size": "~1.0.0"
5656
},
5757
"devDependencies": {
5858
"@babel/cli": "^7.16.8",
@@ -66,7 +66,6 @@
6666
"@formatjs/intl-locale": "^3.0.3",
6767
"@formatjs/intl-numberformat": "^8.0.4",
6868
"@formatjs/intl-pluralrules": "^5.0.3",
69-
"react-native-mmkv": "2.6.1",
7069
"@react-native-community/blur": "4.3.0",
7170
"@react-native-community/datetimepicker": "^3.4.6",
7271
"@react-native-community/netinfo": "^5.6.2",
@@ -96,6 +95,7 @@
9695
"eslint-plugin-uilib": "file:./eslint-rules",
9796
"gh-pages": "^1.1.0",
9897
"jest": "^29.2.1",
98+
"light-date": "^1.2.0",
9999
"metro-react-native-babel-preset": "0.73.7",
100100
"mocha": "^5.0.0",
101101
"moment": "^2.24.0",
@@ -110,6 +110,7 @@
110110
"react-native-gesture-handler": "2.9.0",
111111
"react-native-haptic-feedback": "^1.11.0",
112112
"react-native-linear-gradient": "2.6.2",
113+
"react-native-mmkv": "2.6.1",
113114
"react-native-navigation": "7.32.1",
114115
"react-native-reanimated": "3.1.0",
115116
"react-native-shimmer-placeholder": "^2.0.6",

src/components/dateTimePicker/dateTimePicker.api.json

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@
2525
{"name": "editable", "type": "boolean", "description": "Should this input be editable or disabled"},
2626
{"name": "minimumDate", "type": "Date", "description": "The minimum date or time value to use"},
2727
{"name": "maximumDate", "type": "Date", "description": "The maximum date or time value to use"},
28-
{"name": "dateFormat", "type": "string", "description": "The date format for the text display"},
29-
{"name": "dateFormatter", "type": "() => Date", "description": "A callback function to format date"},
30-
{"name": "timeFormat", "type": "string", "description": "The time format for the text display"},
31-
{"name": "timeFormatter", "type": "() => Date", "description": "A callback function to format time"},
28+
{
29+
"name": "dateTimeFormatter",
30+
"type": "(value: Date, mode: DateTimePickerMode) => string",
31+
"description": "A callback function to format the time or date"
32+
},
3233
{
3334
"name": "locale",
3435
"type": "string",
@@ -62,7 +63,5 @@
6263
"description": "Override system theme variant (dark or light mode) used by the date picker"
6364
}
6465
],
65-
"snippet": [
66-
"<DateTimePicker title={'Select time'$1} placeholder={'Placeholder'$2} mode={'time'$3}/>"
67-
]
66+
"snippet": ["<DateTimePicker title={'Select time'$1} placeholder={'Placeholder'$2} mode={'time'$3}/>"]
6867
}

src/components/dateTimePicker/index.tsx

Lines changed: 20 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import React, {
99
ForwardedRef
1010
} from 'react';
1111
import {StyleProp, StyleSheet, ViewStyle} from 'react-native';
12-
import {DateTimePickerPackage as RNDateTimePicker, MomentPackage as moment} from '../../optionalDependencies';
12+
import {DateTimePickerPackage as RNDateTimePicker} from '../../optionalDependencies';
1313
import {useDidUpdate} from '../../hooks';
1414
import {Colors} from '../../style';
1515
import Assets from '../../assets';
@@ -20,17 +20,15 @@ import View from '../view';
2020
import Button from '../button';
2121
import ExpandableOverlay, {ExpandableOverlayMethods, RenderCustomOverlayProps} from '../../incubator/expandableOverlay';
2222
import type {TextFieldProps, TextFieldMethods} from '../../incubator/TextField';
23+
import useOldApi, {OldApiProps} from './useOldApi';
2324

24-
const MODES = {
25-
DATE: 'date',
26-
TIME: 'time'
27-
};
25+
export type DateTimePickerMode = 'date' | 'time';
2826

29-
export type DateTimePickerProps = Omit<TextFieldProps, 'value' | 'onChange'> & {
27+
export type DateTimePickerProps = OldApiProps & Omit<TextFieldProps, 'value' | 'onChange'> & {
3028
/**
3129
* The type of picker to display ('date' or 'time')
3230
*/
33-
mode?: 'date' | 'time';
31+
mode?: DateTimePickerMode;
3432
/**
3533
* The initial value to set the picker to. Defaults to device's date / time
3634
*/
@@ -52,21 +50,11 @@ export type DateTimePickerProps = Omit<TextFieldProps, 'value' | 'onChange'> & {
5250
*/
5351
maximumDate?: Date;
5452
/**
55-
* The date format for the text display
56-
*/
57-
dateFormat?: string;
58-
/**
59-
* A callback function to format date
53+
* A callback function to format the time or date
54+
* @param mode the type of the picker ('date' or 'time')
55+
* @returns the formatted string to display
6056
*/
61-
dateFormatter?: (date: Date) => string;
62-
/**
63-
* The time format for the text display
64-
*/
65-
timeFormat?: string;
66-
/**
67-
* A callback function to format time
68-
*/
69-
timeFormatter?: (date: Date) => string;
57+
dateTimeFormatter?: (value: Date, mode: DateTimePickerMode) => string;
7058
/**
7159
* Allows changing of the locale of the component (iOS only)
7260
*/
@@ -126,11 +114,12 @@ const DateTimePicker = forwardRef((props: DateTimePickerPropsInternal, ref: Forw
126114
value: propsValue,
127115
renderInput,
128116
editable,
129-
mode = MODES.DATE,
117+
mode = 'date',
130118
dateFormat,
131119
timeFormat,
132120
dateFormatter,
133121
timeFormatter,
122+
dateTimeFormatter,
134123
minimumDate,
135124
maximumDate,
136125
locale,
@@ -161,16 +150,11 @@ const DateTimePicker = forwardRef((props: DateTimePickerPropsInternal, ref: Forw
161150

162151
useEffect(() => {
163152
if (!RNDateTimePicker) {
153+
// eslint-disable-next-line max-len
164154
console.error(`RNUILib DateTimePicker component requires installing "@react-native-community/datetimepicker" dependency`);
165155
}
166156
}, []);
167157

168-
useEffect(() => {
169-
if (!moment && (dateFormat || timeFormat)) {
170-
console.error(`RNUILib DateTimePicker component with date/time format requires installing "moment" dependency`);
171-
}
172-
}, [dateFormat, timeFormat]);
173-
174158
useDidUpdate(() => {
175159
setValue(propsValue);
176160
}, [propsValue]);
@@ -193,21 +177,16 @@ const DateTimePicker = forwardRef((props: DateTimePickerPropsInternal, ref: Forw
193177
};
194178
}, [dialogProps, testID]);
195179

180+
const {getStringValue: getStringValueOld} = useOldApi({dateFormat, dateFormatter, timeFormat, timeFormatter});
181+
196182
const getStringValue = () => {
197183
if (value) {
198-
switch (mode) {
199-
case MODES.DATE:
200-
return dateFormatter
201-
? dateFormatter(value)
202-
: dateFormat && moment
203-
? moment(value).format(dateFormat)
204-
: value.toLocaleDateString();
205-
case MODES.TIME:
206-
return timeFormatter
207-
? timeFormatter(value)
208-
: timeFormat && moment
209-
? moment(value).format(timeFormat)
210-
: value.toLocaleTimeString();
184+
if (dateTimeFormatter) {
185+
return dateTimeFormatter(value, mode);
186+
} else {
187+
return getStringValueOld(value, mode);
188+
// TODO: once we remove the old implementation, add the following:
189+
// return mode === 'time' ? value.toLocaleTimeString() : value.toLocaleDateString();
211190
}
212191
}
213192
};
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// TODO: delete whole file in v8
2+
import {useEffect} from 'react';
3+
import {MomentPackage as moment} from '../../optionalDependencies';
4+
5+
export interface OldApiProps {
6+
/**
7+
* @deprecated
8+
* The date format for the text display
9+
*/
10+
dateFormat?: string;
11+
/**
12+
* @deprecated
13+
* A callback function to format date
14+
*/
15+
dateFormatter?: (date: Date) => string;
16+
/**
17+
* @deprecated
18+
* The time format for the text display
19+
*/
20+
timeFormat?: string;
21+
/**
22+
* @deprecated
23+
* A callback function to format time
24+
*/
25+
timeFormatter?: (date: Date) => string;
26+
}
27+
28+
// This file will be deleted in the next major version,
29+
// duplicating these here will make this less complicated
30+
// than removing the duplication
31+
type Mode = 'date' | 'time';
32+
33+
const useOldApi = (props: OldApiProps) => {
34+
const {dateFormat, dateFormatter, timeFormat, timeFormatter} = props;
35+
36+
useEffect(() => {
37+
if (!moment && (dateFormat || timeFormat)) {
38+
console.error(`RNUILib DateTimePicker component with date/time format requires installing "moment" dependency`);
39+
}
40+
}, [dateFormat, timeFormat]);
41+
42+
const getStringValue = (value: Date, mode: Mode) => {
43+
if (value) {
44+
switch (mode) {
45+
case 'date':
46+
return dateFormatter
47+
? dateFormatter(value)
48+
: dateFormat && moment
49+
? moment(value).format(dateFormat)
50+
: value.toLocaleDateString();
51+
case 'time':
52+
return timeFormatter
53+
? timeFormatter(value)
54+
: timeFormat && moment
55+
? moment(value).format(timeFormat)
56+
: value.toLocaleTimeString();
57+
}
58+
}
59+
};
60+
61+
return {getStringValue};
62+
};
63+
64+
export default useOldApi;

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export {default as ColorSliderGroup, ColorSliderGroupProps} from './components/s
6868
export {default as ColorSwatch, ColorSwatchProps} from './components/colorSwatch';
6969
export {default as ConnectionStatusBar, ConnectionStatusBarProps} from './components/connectionStatusBar';
7070
export {default as Dash, DashProps} from './components/dash';
71-
export {default as DateTimePicker, DateTimePickerProps} from './components/dateTimePicker';
71+
export {default as DateTimePicker, DateTimePickerProps, DateTimePickerMode} from './components/dateTimePicker';
7272
export {default as Dialog, DialogProps, DialogDirections, DialogDirectionsEnum} from './components/dialog';
7373
export {default as Drawer, DrawerProps, DrawerItemProps} from './components/drawer';
7474
export {default as ExpandableSection, ExpandableSectionProps} from './components/expandableSection';

0 commit comments

Comments
 (0)