DatePickerIOS.ios.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /**
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. * @format
  8. * @flow strict-local
  9. */
  10. // This is a controlled component version of RCTDatePickerIOS.
  11. 'use strict';
  12. import RCTDatePickerNativeComponent, {
  13. Commands as DatePickerCommands,
  14. } from './RCTDatePickerNativeComponent';
  15. const React = require('react');
  16. const StyleSheet = require('../../StyleSheet/StyleSheet');
  17. const View = require('../View/View');
  18. const invariant = require('invariant');
  19. import type {SyntheticEvent} from '../../Types/CoreEventTypes';
  20. import type {ViewProps} from '../View/ViewPropTypes';
  21. type Event = SyntheticEvent<
  22. $ReadOnly<{|
  23. timestamp: number,
  24. |}>,
  25. >;
  26. type Props = $ReadOnly<{|
  27. ...ViewProps,
  28. /**
  29. * The currently selected date.
  30. */
  31. date?: ?Date,
  32. /**
  33. * Provides an initial value that will change when the user starts selecting
  34. * a date. It is useful for simple use-cases where you do not want to deal
  35. * with listening to events and updating the date prop to keep the
  36. * controlled state in sync. The controlled state has known bugs which
  37. * causes it to go out of sync with native. The initialDate prop is intended
  38. * to allow you to have native be source of truth.
  39. */
  40. initialDate?: ?Date,
  41. /**
  42. * The date picker locale.
  43. */
  44. locale?: ?string,
  45. /**
  46. * Maximum date.
  47. *
  48. * Restricts the range of possible date/time values.
  49. */
  50. maximumDate?: ?Date,
  51. /**
  52. * Minimum date.
  53. *
  54. * Restricts the range of possible date/time values.
  55. */
  56. minimumDate?: ?Date,
  57. /**
  58. * The interval at which minutes can be selected.
  59. */
  60. minuteInterval?: ?(1 | 2 | 3 | 4 | 5 | 6 | 10 | 12 | 15 | 20 | 30),
  61. /**
  62. * The date picker mode.
  63. */
  64. mode?: ?('date' | 'time' | 'datetime'),
  65. /**
  66. * Date change handler.
  67. *
  68. * This is called when the user changes the date or time in the UI.
  69. * The first and only argument is an Event. For getting the date the picker
  70. * was changed to, use onDateChange instead.
  71. */
  72. onChange?: ?(event: Event) => void,
  73. /**
  74. * Date change handler.
  75. *
  76. * This is called when the user changes the date or time in the UI.
  77. * The first and only argument is a Date object representing the new
  78. * date and time.
  79. */
  80. onDateChange: (date: Date) => void,
  81. /**
  82. * Timezone offset in minutes.
  83. *
  84. * By default, the date picker will use the device's timezone. With this
  85. * parameter, it is possible to force a certain timezone offset. For
  86. * instance, to show times in Pacific Standard Time, pass -7 * 60.
  87. */
  88. timeZoneOffsetInMinutes?: ?number,
  89. |}>;
  90. /**
  91. * Use `DatePickerIOS` to render a date/time picker (selector) on iOS. This is
  92. * a controlled component, so you must hook in to the `onDateChange` callback
  93. * and update the `date` prop in order for the component to update, otherwise
  94. * the user's change will be reverted immediately to reflect `props.date` as the
  95. * source of truth.
  96. */
  97. class DatePickerIOS extends React.Component<Props> {
  98. static DefaultProps: {|mode: $TEMPORARY$string<'datetime'>|} = {
  99. mode: 'datetime',
  100. };
  101. _picker: ?React.ElementRef<typeof RCTDatePickerNativeComponent> = null;
  102. componentDidUpdate() {
  103. if (this.props.date) {
  104. const propsTimeStamp = this.props.date.getTime();
  105. if (this._picker) {
  106. DatePickerCommands.setNativeDate(this._picker, propsTimeStamp);
  107. }
  108. }
  109. }
  110. _onChange = (event: Event) => {
  111. const nativeTimeStamp = event.nativeEvent.timestamp;
  112. this.props.onDateChange &&
  113. this.props.onDateChange(new Date(nativeTimeStamp));
  114. this.props.onChange && this.props.onChange(event);
  115. this.forceUpdate();
  116. };
  117. render(): React.Node {
  118. const props = this.props;
  119. invariant(
  120. props.date || props.initialDate,
  121. 'A selected date or initial date should be specified.',
  122. );
  123. return (
  124. <View style={props.style}>
  125. <RCTDatePickerNativeComponent
  126. testID={props.testID}
  127. ref={picker => {
  128. this._picker = picker;
  129. }}
  130. style={styles.datePickerIOS}
  131. date={
  132. props.date
  133. ? props.date.getTime()
  134. : props.initialDate
  135. ? props.initialDate.getTime()
  136. : undefined
  137. }
  138. locale={
  139. props.locale != null && props.locale !== ''
  140. ? props.locale
  141. : undefined
  142. }
  143. maximumDate={
  144. props.maximumDate ? props.maximumDate.getTime() : undefined
  145. }
  146. minimumDate={
  147. props.minimumDate ? props.minimumDate.getTime() : undefined
  148. }
  149. mode={props.mode}
  150. minuteInterval={props.minuteInterval}
  151. timeZoneOffsetInMinutes={props.timeZoneOffsetInMinutes}
  152. onChange={this._onChange}
  153. onStartShouldSetResponder={() => true}
  154. onResponderTerminationRequest={() => false}
  155. />
  156. </View>
  157. );
  158. }
  159. }
  160. const styles = StyleSheet.create({
  161. datePickerIOS: {
  162. height: 216,
  163. },
  164. });
  165. module.exports = DatePickerIOS;