@khanacademy/wonder-blocks-birthday-picker 1.1.0 → 1.2.2

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 CHANGED
@@ -1,5 +1,32 @@
1
1
  # @khanacademy/wonder-blocks-birthday-picker
2
2
 
3
+ ## 1.2.2
4
+
5
+ ### Patch Changes
6
+
7
+ - @khanacademy/wonder-blocks-dropdown@2.6.7
8
+
9
+ ## 1.2.1
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [246a921d]
14
+ - @khanacademy/wonder-blocks-core@4.3.0
15
+ - @khanacademy/wonder-blocks-dropdown@2.6.6
16
+ - @khanacademy/wonder-blocks-icon@1.2.26
17
+ - @khanacademy/wonder-blocks-layout@1.4.8
18
+ - @khanacademy/wonder-blocks-typography@1.1.30
19
+
20
+ ## 1.2.0
21
+
22
+ ### Minor Changes
23
+
24
+ - 5536d12e: Add `monthYearOnly` prop to hide the `day` field from the UI. Passes the first day of the selected month for this case.
25
+
26
+ ### Patch Changes
27
+
28
+ - @khanacademy/wonder-blocks-dropdown@2.6.5
29
+
3
30
  ## 1.1.0
4
31
 
5
32
  ### Minor Changes
package/dist/es/index.js CHANGED
@@ -18,7 +18,12 @@ const defaultLabels = Object.freeze({
18
18
  month: "Month",
19
19
  year: "Year",
20
20
  day: "Day"
21
- });
21
+ }); // Default minWidth value when we include the full DOB.
22
+
23
+ const FIELD_MIN_WIDTH_FULL = 110; // Alternative minWidth value when we hide the day field.
24
+ // See: https://www.figma.com/file/uJZi9ZvuEz5N8GJ3HqKFAa/(2021)-Account-records?node-id=20%3A398
25
+
26
+ const FIELD_MIN_WIDTH_MONTH_YEAR = 167;
22
27
  /**
23
28
  * Birthday Picker. Similar to a datepicker, but specifically for birthdates.
24
29
  * We don't want to show a calendar in this case as it can be quite tedious to
@@ -127,11 +132,12 @@ class BirthdayPicker extends React.Component {
127
132
 
128
133
  getStateFromDefault() {
129
134
  const {
130
- defaultValue
135
+ defaultValue,
136
+ monthYearOnly
131
137
  } = this.props;
132
138
  const initialState = {
133
139
  month: null,
134
- day: null,
140
+ day: monthYearOnly ? "1" : null,
135
141
  year: null,
136
142
  error: null
137
143
  }; // merge custom labels with the default ones
@@ -191,34 +197,45 @@ class BirthdayPicker extends React.Component {
191
197
  }, error)));
192
198
  }
193
199
 
194
- render() {
200
+ renderMonth() {
195
201
  const {
196
- disabled
202
+ disabled,
203
+ monthYearOnly
197
204
  } = this.props;
198
205
  const {
199
- month,
200
- day,
201
- year
206
+ month
202
207
  } = this.state;
203
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
204
- testId: "birthday-picker",
205
- style: {
206
- flexDirection: "row"
207
- }
208
- }, /*#__PURE__*/React.createElement(SingleSelect, {
208
+ const minWidth = monthYearOnly ? FIELD_MIN_WIDTH_MONTH_YEAR : FIELD_MIN_WIDTH_FULL;
209
+ return /*#__PURE__*/React.createElement(SingleSelect, {
209
210
  disabled: disabled,
210
211
  placeholder: this.labels.month,
211
212
  onChange: this.handleMonthChange,
212
213
  selectedValue: month,
213
214
  style: {
214
- minWidth: 110
215
+ minWidth
215
216
  },
216
217
  testId: "birthday-picker-month"
217
218
  }, moment.monthsShort().map((month, i) => /*#__PURE__*/React.createElement(OptionItem, {
218
219
  key: month,
219
220
  label: month,
220
221
  value: String(i)
221
- }))), /*#__PURE__*/React.createElement(Strut, {
222
+ })));
223
+ }
224
+
225
+ maybeRenderDay() {
226
+ const {
227
+ disabled,
228
+ monthYearOnly
229
+ } = this.props;
230
+ const {
231
+ day
232
+ } = this.state; // Hide the day field if the month/year only mode is enabled.
233
+
234
+ if (monthYearOnly) {
235
+ return null;
236
+ }
237
+
238
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Strut, {
222
239
  size: Spacing.xSmall_8
223
240
  }), /*#__PURE__*/React.createElement(SingleSelect, {
224
241
  disabled: disabled,
@@ -233,22 +250,43 @@ class BirthdayPicker extends React.Component {
233
250
  key: String(day + 1),
234
251
  label: String(day + 1),
235
252
  value: String(day + 1)
236
- }))), /*#__PURE__*/React.createElement(Strut, {
237
- size: Spacing.xSmall_8
238
- }), /*#__PURE__*/React.createElement(SingleSelect, {
253
+ }))));
254
+ }
255
+
256
+ renderYear() {
257
+ const {
258
+ disabled,
259
+ monthYearOnly
260
+ } = this.props;
261
+ const {
262
+ year
263
+ } = this.state;
264
+ const minWidth = monthYearOnly ? FIELD_MIN_WIDTH_MONTH_YEAR : FIELD_MIN_WIDTH_FULL;
265
+ return /*#__PURE__*/React.createElement(SingleSelect, {
239
266
  disabled: disabled,
240
267
  placeholder: this.labels.year,
241
268
  onChange: this.handleYearChange,
242
269
  selectedValue: year,
243
270
  style: {
244
- minWidth: 110
271
+ minWidth
245
272
  },
246
273
  testId: "birthday-picker-year"
247
274
  }, Array.from(Array(120)).map((_, yearOffset) => /*#__PURE__*/React.createElement(OptionItem, {
248
275
  key: String(CUR_YEAR - yearOffset),
249
276
  label: String(CUR_YEAR - yearOffset),
250
277
  value: String(CUR_YEAR - yearOffset)
251
- })))), this.maybeRenderError());
278
+ })));
279
+ }
280
+
281
+ render() {
282
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(View, {
283
+ testId: "birthday-picker",
284
+ style: {
285
+ flexDirection: "row"
286
+ }
287
+ }, this.renderMonth(), this.maybeRenderDay(), /*#__PURE__*/React.createElement(Strut, {
288
+ size: Spacing.xSmall_8
289
+ }), this.renderYear()), this.maybeRenderError());
252
290
  }
253
291
 
254
292
  }
package/dist/index.js CHANGED
@@ -176,7 +176,12 @@ const defaultLabels = Object.freeze({
176
176
  month: "Month",
177
177
  year: "Year",
178
178
  day: "Day"
179
- });
179
+ }); // Default minWidth value when we include the full DOB.
180
+
181
+ const FIELD_MIN_WIDTH_FULL = 110; // Alternative minWidth value when we hide the day field.
182
+ // See: https://www.figma.com/file/uJZi9ZvuEz5N8GJ3HqKFAa/(2021)-Account-records?node-id=20%3A398
183
+
184
+ const FIELD_MIN_WIDTH_MONTH_YEAR = 167;
180
185
  /**
181
186
  * Birthday Picker. Similar to a datepicker, but specifically for birthdates.
182
187
  * We don't want to show a calendar in this case as it can be quite tedious to
@@ -285,11 +290,12 @@ class BirthdayPicker extends react__WEBPACK_IMPORTED_MODULE_1__["Component"] {
285
290
 
286
291
  getStateFromDefault() {
287
292
  const {
288
- defaultValue
293
+ defaultValue,
294
+ monthYearOnly
289
295
  } = this.props;
290
296
  const initialState = {
291
297
  month: null,
292
- day: null,
298
+ day: monthYearOnly ? "1" : null,
293
299
  year: null,
294
300
  error: null
295
301
  }; // merge custom labels with the default ones
@@ -351,34 +357,45 @@ class BirthdayPicker extends react__WEBPACK_IMPORTED_MODULE_1__["Component"] {
351
357
  }, error)));
352
358
  }
353
359
 
354
- render() {
360
+ renderMonth() {
355
361
  const {
356
- disabled
362
+ disabled,
363
+ monthYearOnly
357
364
  } = this.props;
358
365
  const {
359
- month,
360
- day,
361
- year
366
+ month
362
367
  } = this.state;
363
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](react__WEBPACK_IMPORTED_MODULE_1__["Fragment"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__["View"], {
364
- testId: "birthday-picker",
365
- style: {
366
- flexDirection: "row"
367
- }
368
- }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_dropdown__WEBPACK_IMPORTED_MODULE_8__["SingleSelect"], {
368
+ const minWidth = monthYearOnly ? FIELD_MIN_WIDTH_MONTH_YEAR : FIELD_MIN_WIDTH_FULL;
369
+ return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_dropdown__WEBPACK_IMPORTED_MODULE_8__["SingleSelect"], {
369
370
  disabled: disabled,
370
371
  placeholder: this.labels.month,
371
372
  onChange: this.handleMonthChange,
372
373
  selectedValue: month,
373
374
  style: {
374
- minWidth: 110
375
+ minWidth
375
376
  },
376
377
  testId: "birthday-picker-month"
377
378
  }, moment__WEBPACK_IMPORTED_MODULE_0___default.a.monthsShort().map((month, i) => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_dropdown__WEBPACK_IMPORTED_MODULE_8__["OptionItem"], {
378
379
  key: month,
379
380
  label: month,
380
381
  value: String(i)
381
- }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_layout__WEBPACK_IMPORTED_MODULE_3__["Strut"], {
382
+ })));
383
+ }
384
+
385
+ maybeRenderDay() {
386
+ const {
387
+ disabled,
388
+ monthYearOnly
389
+ } = this.props;
390
+ const {
391
+ day
392
+ } = this.state; // Hide the day field if the month/year only mode is enabled.
393
+
394
+ if (monthYearOnly) {
395
+ return null;
396
+ }
397
+
398
+ return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](react__WEBPACK_IMPORTED_MODULE_1__["Fragment"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_layout__WEBPACK_IMPORTED_MODULE_3__["Strut"], {
382
399
  size: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.xSmall_8
383
400
  }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_dropdown__WEBPACK_IMPORTED_MODULE_8__["SingleSelect"], {
384
401
  disabled: disabled,
@@ -393,22 +410,43 @@ class BirthdayPicker extends react__WEBPACK_IMPORTED_MODULE_1__["Component"] {
393
410
  key: String(day + 1),
394
411
  label: String(day + 1),
395
412
  value: String(day + 1)
396
- }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_layout__WEBPACK_IMPORTED_MODULE_3__["Strut"], {
397
- size: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.xSmall_8
398
- }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_dropdown__WEBPACK_IMPORTED_MODULE_8__["SingleSelect"], {
413
+ }))));
414
+ }
415
+
416
+ renderYear() {
417
+ const {
418
+ disabled,
419
+ monthYearOnly
420
+ } = this.props;
421
+ const {
422
+ year
423
+ } = this.state;
424
+ const minWidth = monthYearOnly ? FIELD_MIN_WIDTH_MONTH_YEAR : FIELD_MIN_WIDTH_FULL;
425
+ return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_dropdown__WEBPACK_IMPORTED_MODULE_8__["SingleSelect"], {
399
426
  disabled: disabled,
400
427
  placeholder: this.labels.year,
401
428
  onChange: this.handleYearChange,
402
429
  selectedValue: year,
403
430
  style: {
404
- minWidth: 110
431
+ minWidth
405
432
  },
406
433
  testId: "birthday-picker-year"
407
434
  }, Array.from(Array(120)).map((_, yearOffset) => /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_dropdown__WEBPACK_IMPORTED_MODULE_8__["OptionItem"], {
408
435
  key: String(CUR_YEAR - yearOffset),
409
436
  label: String(CUR_YEAR - yearOffset),
410
437
  value: String(CUR_YEAR - yearOffset)
411
- })))), this.maybeRenderError());
438
+ })));
439
+ }
440
+
441
+ render() {
442
+ return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](react__WEBPACK_IMPORTED_MODULE_1__["Fragment"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_2__["View"], {
443
+ testId: "birthday-picker",
444
+ style: {
445
+ flexDirection: "row"
446
+ }
447
+ }, this.renderMonth(), this.maybeRenderDay(), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__["createElement"](_khanacademy_wonder_blocks_layout__WEBPACK_IMPORTED_MODULE_3__["Strut"], {
448
+ size: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_4___default.a.xSmall_8
449
+ }), this.renderYear()), this.maybeRenderError());
412
450
  }
413
451
 
414
452
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-birthday-picker",
3
- "version": "1.1.0",
3
+ "version": "1.2.2",
4
4
  "design": "v1",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -15,12 +15,12 @@
15
15
  "dependencies": {
16
16
  "@babel/runtime": "^7.16.3",
17
17
  "@khanacademy/wonder-blocks-color": "^1.1.20",
18
- "@khanacademy/wonder-blocks-core": "^4.2.0",
19
- "@khanacademy/wonder-blocks-dropdown": "^2.6.4",
20
- "@khanacademy/wonder-blocks-icon": "^1.2.24",
21
- "@khanacademy/wonder-blocks-layout": "^1.4.6",
18
+ "@khanacademy/wonder-blocks-core": "^4.3.0",
19
+ "@khanacademy/wonder-blocks-dropdown": "^2.6.7",
20
+ "@khanacademy/wonder-blocks-icon": "^1.2.26",
21
+ "@khanacademy/wonder-blocks-layout": "^1.4.8",
22
22
  "@khanacademy/wonder-blocks-spacing": "^3.0.5",
23
- "@khanacademy/wonder-blocks-typography": "^1.1.28"
23
+ "@khanacademy/wonder-blocks-typography": "^1.1.30"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "aphrodite": "^1.2.5",
@@ -119,3 +119,21 @@ DisabledBirthdayPicker.parameters = {
119
119
  "A BirthdayPicker can be disabled by passing the `disabled` prop. This will disable all the dropdown controls and prevent them from being interacted with.",
120
120
  },
121
121
  };
122
+
123
+ export const BirthdayPickerWithYearAndMonthOnly: StoryComponentType =
124
+ Template.bind({});
125
+
126
+ BirthdayPickerWithYearAndMonthOnly.args = {
127
+ monthYearOnly: true,
128
+ onChange: (date: ?string) => {
129
+ // eslint-disable-next-line no-console
130
+ console.log("Date selected: ", date);
131
+ },
132
+ };
133
+
134
+ BirthdayPickerWithYearAndMonthOnly.parameters = {
135
+ docs: {
136
+ storyDescription:
137
+ "A BirthdayPicker can be configured to only show the year and month dropdowns. This can be useful when we want to display and collect a birthday that doesn't require the full DOB for privacy reasons.",
138
+ },
139
+ };
@@ -34,6 +34,18 @@ describe("BirthdayPicker", () => {
34
34
  expect(yearPicker).toHaveTextContent("Year");
35
35
  });
36
36
 
37
+ it("renders without the day field if monthYearOnly is set", () => {
38
+ // Arrange
39
+
40
+ // Act
41
+ render(<BirthdayPicker monthYearOnly={true} onChange={() => {}} />);
42
+
43
+ const dayPicker = screen.queryByTestId("birthday-picker-day");
44
+
45
+ // Assert
46
+ expect(dayPicker).not.toBeInTheDocument();
47
+ });
48
+
37
49
  it("renders with a valid default value", () => {
38
50
  // Arrange
39
51
  const date = moment(today);
@@ -169,9 +181,9 @@ describe("BirthdayPicker", () => {
169
181
  // Arrange
170
182
  const onChange = jest.fn();
171
183
 
172
- // Act
173
184
  render(<BirthdayPicker onChange={onChange} />);
174
185
 
186
+ // Act
175
187
  userEvent.click(screen.getByTestId("birthday-picker-month"));
176
188
  const monthOption = await screen.findByRole("option", {
177
189
  name: "Jul",
@@ -258,7 +270,6 @@ describe("BirthdayPicker", () => {
258
270
  // Arrange
259
271
  const onChange = jest.fn();
260
272
 
261
- // Act
262
273
  render(
263
274
  <BirthdayPicker
264
275
  defaultValue="2017-07-17"
@@ -266,6 +277,7 @@ describe("BirthdayPicker", () => {
266
277
  />,
267
278
  );
268
279
 
280
+ // Act
269
281
  userEvent.click(screen.getByTestId("birthday-picker-month"));
270
282
  const monthOption = await screen.findByRole("option", {
271
283
  name: "Aug",
@@ -327,7 +339,6 @@ describe("BirthdayPicker", () => {
327
339
  // Arrange
328
340
  const onChange = jest.fn();
329
341
 
330
- // Act
331
342
  render(
332
343
  <BirthdayPicker
333
344
  defaultValue="2021-02-31"
@@ -335,6 +346,7 @@ describe("BirthdayPicker", () => {
335
346
  />,
336
347
  );
337
348
 
349
+ // Act
338
350
  userEvent.click(screen.getByTestId("birthday-picker-year"));
339
351
  const yearOption = await screen.findByRole("option", {
340
352
  name: "2020",
@@ -346,6 +358,68 @@ describe("BirthdayPicker", () => {
346
358
  // Assert
347
359
  expect(onChange).toHaveBeenCalledTimes(1);
348
360
  });
361
+
362
+ it("onChange triggers the first day of the month when monthYearOnly is set", async () => {
363
+ // Arrange
364
+ const onChange = jest.fn();
365
+
366
+ render(<BirthdayPicker monthYearOnly={true} onChange={onChange} />);
367
+
368
+ // Act
369
+ userEvent.click(screen.getByTestId("birthday-picker-month"));
370
+ const monthOption = await screen.findByRole("option", {
371
+ name: "Aug",
372
+ });
373
+ userEvent.click(monthOption, undefined, {
374
+ skipPointerEventsCheck: true,
375
+ });
376
+
377
+ userEvent.click(screen.getByTestId("birthday-picker-year"));
378
+ const yearOption = await screen.findByRole("option", {
379
+ name: "2018",
380
+ });
381
+ userEvent.click(yearOption, undefined, {
382
+ skipPointerEventsCheck: true,
383
+ });
384
+
385
+ // Assert
386
+ // Verify that we passed the first day of the month
387
+ expect(onChange).toHaveBeenCalledWith("2018-08-01");
388
+ });
389
+
390
+ it("onChange triggers the passed-in day intact when defaultValue and monthYearOnly are set", async () => {
391
+ // Arrange
392
+ const onChange = jest.fn();
393
+
394
+ render(
395
+ <BirthdayPicker
396
+ defaultValue="2017-07-17"
397
+ monthYearOnly={true}
398
+ onChange={onChange}
399
+ />,
400
+ );
401
+
402
+ // Act
403
+ userEvent.click(screen.getByTestId("birthday-picker-month"));
404
+ const monthOption = await screen.findByRole("option", {
405
+ name: "Aug",
406
+ });
407
+ userEvent.click(monthOption, undefined, {
408
+ skipPointerEventsCheck: true,
409
+ });
410
+
411
+ userEvent.click(screen.getByTestId("birthday-picker-year"));
412
+ const yearOption = await screen.findByRole("option", {
413
+ name: "2018",
414
+ });
415
+ userEvent.click(yearOption, undefined, {
416
+ skipPointerEventsCheck: true,
417
+ });
418
+
419
+ // Assert
420
+ // Verify that we passed the same day originally passed in.
421
+ expect(onChange).toHaveBeenCalledWith("2018-08-17");
422
+ });
349
423
  });
350
424
 
351
425
  describe("labels", () => {
@@ -49,6 +49,16 @@ type Props = {|
49
49
  */
50
50
  labels?: Labels,
51
51
 
52
+ /**
53
+ * Whether we want to hide the day field.
54
+ *
55
+ * **NOTE:** We will set the day to the _first_ day of the _selected_ month
56
+ * if the day field is hidden. Please make sure to modify the passed date
57
+ * value to fit different needs (e.g. if you want to set the _first_ day of
58
+ * the _following_ month instead).
59
+ */
60
+ monthYearOnly?: boolean,
61
+
52
62
  /**
53
63
  * Listen for changes to the birthdate. Could be a string in the YYYY-MM-DD
54
64
  * format or `null`.
@@ -87,6 +97,13 @@ export const defaultLabels: Labels = Object.freeze({
87
97
  day: "Day",
88
98
  });
89
99
 
100
+ // Default minWidth value when we include the full DOB.
101
+ const FIELD_MIN_WIDTH_FULL = 110;
102
+
103
+ // Alternative minWidth value when we hide the day field.
104
+ // See: https://www.figma.com/file/uJZi9ZvuEz5N8GJ3HqKFAa/(2021)-Account-records?node-id=20%3A398
105
+ const FIELD_MIN_WIDTH_MONTH_YEAR = 167;
106
+
90
107
  /**
91
108
  * Birthday Picker. Similar to a datepicker, but specifically for birthdates.
92
109
  * We don't want to show a calendar in this case as it can be quite tedious to
@@ -134,10 +151,10 @@ export default class BirthdayPicker extends React.Component<Props, State> {
134
151
  * Calculates the initial state values based on the default value.
135
152
  */
136
153
  getStateFromDefault(): State {
137
- const {defaultValue} = this.props;
154
+ const {defaultValue, monthYearOnly} = this.props;
138
155
  const initialState: State = {
139
156
  month: null,
140
- day: null,
157
+ day: monthYearOnly ? "1" : null,
141
158
  year: null,
142
159
  error: null,
143
160
  };
@@ -252,63 +269,99 @@ export default class BirthdayPicker extends React.Component<Props, State> {
252
269
  );
253
270
  }
254
271
 
255
- render(): React.Element<any> {
256
- const {disabled} = this.props;
257
- const {month, day, year} = this.state;
272
+ renderMonth(): React.Node {
273
+ const {disabled, monthYearOnly} = this.props;
274
+ const {month} = this.state;
275
+ const minWidth = monthYearOnly
276
+ ? FIELD_MIN_WIDTH_MONTH_YEAR
277
+ : FIELD_MIN_WIDTH_FULL;
278
+
279
+ return (
280
+ <SingleSelect
281
+ disabled={disabled}
282
+ placeholder={this.labels.month}
283
+ onChange={this.handleMonthChange}
284
+ selectedValue={month}
285
+ style={{minWidth}}
286
+ testId="birthday-picker-month"
287
+ >
288
+ {moment.monthsShort().map((month, i) => (
289
+ <OptionItem key={month} label={month} value={String(i)} />
290
+ ))}
291
+ </SingleSelect>
292
+ );
293
+ }
294
+
295
+ maybeRenderDay(): ?React.Node {
296
+ const {disabled, monthYearOnly} = this.props;
297
+ const {day} = this.state;
298
+
299
+ // Hide the day field if the month/year only mode is enabled.
300
+ if (monthYearOnly) {
301
+ return null;
302
+ }
258
303
 
304
+ return (
305
+ <>
306
+ <Strut size={Spacing.xSmall_8} />
307
+ <SingleSelect
308
+ disabled={disabled}
309
+ placeholder={this.labels.day}
310
+ onChange={this.handleDayChange}
311
+ selectedValue={day}
312
+ style={{minWidth: 100}}
313
+ testId="birthday-picker-day"
314
+ >
315
+ {Array.from(Array(31)).map((_, day) => (
316
+ <OptionItem
317
+ key={String(day + 1)}
318
+ label={String(day + 1)}
319
+ value={String(day + 1)}
320
+ />
321
+ ))}
322
+ </SingleSelect>
323
+ </>
324
+ );
325
+ }
326
+
327
+ renderYear(): React.Node {
328
+ const {disabled, monthYearOnly} = this.props;
329
+ const {year} = this.state;
330
+ const minWidth = monthYearOnly
331
+ ? FIELD_MIN_WIDTH_MONTH_YEAR
332
+ : FIELD_MIN_WIDTH_FULL;
333
+
334
+ return (
335
+ <SingleSelect
336
+ disabled={disabled}
337
+ placeholder={this.labels.year}
338
+ onChange={this.handleYearChange}
339
+ selectedValue={year}
340
+ style={{minWidth}}
341
+ testId="birthday-picker-year"
342
+ >
343
+ {Array.from(Array(120)).map((_, yearOffset) => (
344
+ <OptionItem
345
+ key={String(CUR_YEAR - yearOffset)}
346
+ label={String(CUR_YEAR - yearOffset)}
347
+ value={String(CUR_YEAR - yearOffset)}
348
+ />
349
+ ))}
350
+ </SingleSelect>
351
+ );
352
+ }
353
+
354
+ render(): React.Element<any> {
259
355
  return (
260
356
  <>
261
357
  <View testId="birthday-picker" style={{flexDirection: "row"}}>
262
- <SingleSelect
263
- disabled={disabled}
264
- placeholder={this.labels.month}
265
- onChange={this.handleMonthChange}
266
- selectedValue={month}
267
- style={{minWidth: 110}}
268
- testId="birthday-picker-month"
269
- >
270
- {moment.monthsShort().map((month, i) => (
271
- <OptionItem
272
- key={month}
273
- label={month}
274
- value={String(i)}
275
- />
276
- ))}
277
- </SingleSelect>
278
- <Strut size={Spacing.xSmall_8} />
279
- <SingleSelect
280
- disabled={disabled}
281
- placeholder={this.labels.day}
282
- onChange={this.handleDayChange}
283
- selectedValue={day}
284
- style={{minWidth: 100}}
285
- testId="birthday-picker-day"
286
- >
287
- {Array.from(Array(31)).map((_, day) => (
288
- <OptionItem
289
- key={String(day + 1)}
290
- label={String(day + 1)}
291
- value={String(day + 1)}
292
- />
293
- ))}
294
- </SingleSelect>
358
+ {this.renderMonth()}
359
+
360
+ {this.maybeRenderDay()}
361
+
295
362
  <Strut size={Spacing.xSmall_8} />
296
- <SingleSelect
297
- disabled={disabled}
298
- placeholder={this.labels.year}
299
- onChange={this.handleYearChange}
300
- selectedValue={year}
301
- style={{minWidth: 110}}
302
- testId="birthday-picker-year"
303
- >
304
- {Array.from(Array(120)).map((_, yearOffset) => (
305
- <OptionItem
306
- key={String(CUR_YEAR - yearOffset)}
307
- label={String(CUR_YEAR - yearOffset)}
308
- value={String(CUR_YEAR - yearOffset)}
309
- />
310
- ))}
311
- </SingleSelect>
363
+
364
+ {this.renderYear()}
312
365
  </View>
313
366
  {this.maybeRenderError()}
314
367
  </>