wf-react-day-picker 0.0.1-security → 2.653.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.

Potentially problematic release.


This version of wf-react-day-picker might be problematic. Click here for more details.

@@ -0,0 +1,601 @@
1
+ import React, {Component} from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ import Caption from './Caption';
5
+ import Navbar from './Navbar';
6
+ import Month from './Month';
7
+ import Weekday from './Weekday';
8
+
9
+ import * as Helpers from './Helpers';
10
+ import * as DateUtils from './DateUtils';
11
+ import * as LocaleUtils from './LocaleUtils';
12
+ import * as ModifiersUtils from './ModifiersUtils';
13
+ import classNames from './classNames';
14
+
15
+ import {ENTER, SPACE, LEFT, UP, DOWN, RIGHT} from './keys';
16
+
17
+ export class DayPicker extends Component {
18
+ static VERSION = '7.1.8';
19
+
20
+ static propTypes = {
21
+ // Rendering months
22
+ initialMonth: PropTypes.instanceOf(Date),
23
+ month: PropTypes.instanceOf(Date),
24
+ numberOfMonths: PropTypes.number,
25
+ fromMonth: PropTypes.instanceOf(Date),
26
+ toMonth: PropTypes.instanceOf(Date),
27
+ canChangeMonth: PropTypes.bool,
28
+ reverseMonths: PropTypes.bool,
29
+ pagedNavigation: PropTypes.bool,
30
+ todayButton: PropTypes.string,
31
+ showWeekNumbers: PropTypes.bool,
32
+ showWeekDays: PropTypes.bool,
33
+
34
+ // Modifiers
35
+ selectedDays: PropTypes.oneOfType([
36
+ PropTypes.object,
37
+ PropTypes.func,
38
+ PropTypes.array,
39
+ ]),
40
+ disabledDays: PropTypes.oneOfType([
41
+ PropTypes.object,
42
+ PropTypes.func,
43
+ PropTypes.array,
44
+ ]),
45
+
46
+ modifiers: PropTypes.object,
47
+ modifiersStyles: PropTypes.object,
48
+
49
+ // Localization
50
+ dir: PropTypes.string,
51
+ firstDayOfWeek: PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6]),
52
+ labels: PropTypes.shape({
53
+ nextMonth: PropTypes.node.isRequired,
54
+ previousMonth: PropTypes.node.isRequired,
55
+ }),
56
+ locale: PropTypes.string,
57
+ localeUtils: PropTypes.shape({
58
+ formatMonthTitle: PropTypes.func,
59
+ formatWeekdayShort: PropTypes.func,
60
+ formatWeekdayLong: PropTypes.func,
61
+ getFirstDayOfWeek: PropTypes.func,
62
+ }),
63
+ months: PropTypes.arrayOf(PropTypes.node),
64
+ weekdaysLong: PropTypes.arrayOf(PropTypes.node),
65
+ weekdaysShort: PropTypes.arrayOf(PropTypes.node),
66
+
67
+ // Customization
68
+ showOutsideDays: PropTypes.bool,
69
+ enableOutsideDaysClick: PropTypes.bool,
70
+ fixedWeeks: PropTypes.bool,
71
+
72
+ // CSS and HTML
73
+ classNames: PropTypes.shape({
74
+ body: PropTypes.string,
75
+ container: PropTypes.string,
76
+ day: PropTypes.string.isRequired,
77
+ disabled: PropTypes.string.isRequired,
78
+ footer: PropTypes.string,
79
+ interactionDisabled: PropTypes.string,
80
+ months: PropTypes.string,
81
+ month: PropTypes.string,
82
+ navBar: PropTypes.string,
83
+ outside: PropTypes.string.isRequired,
84
+ selected: PropTypes.string.isRequired,
85
+ today: PropTypes.string.isRequired,
86
+ todayButton: PropTypes.string,
87
+ week: PropTypes.string,
88
+ wrapper: PropTypes.string,
89
+ }),
90
+ className: PropTypes.string,
91
+ containerProps: PropTypes.object,
92
+ tabIndex: PropTypes.number,
93
+
94
+ // Custom elements
95
+ renderDay: PropTypes.func,
96
+ renderWeek: PropTypes.func,
97
+ weekdayElement: PropTypes.oneOfType([
98
+ PropTypes.element,
99
+ PropTypes.func,
100
+ PropTypes.instanceOf(Component),
101
+ ]),
102
+ navbarElement: PropTypes.oneOfType([
103
+ PropTypes.element,
104
+ PropTypes.func,
105
+ PropTypes.instanceOf(Component),
106
+ ]),
107
+ captionElement: PropTypes.oneOfType([
108
+ PropTypes.element,
109
+ PropTypes.func,
110
+ PropTypes.instanceOf(Component),
111
+ ]),
112
+
113
+ // Events
114
+ onBlur: PropTypes.func,
115
+ onFocus: PropTypes.func,
116
+ onKeyDown: PropTypes.func,
117
+ onDayClick: PropTypes.func,
118
+ onDayKeyDown: PropTypes.func,
119
+ onDayMouseEnter: PropTypes.func,
120
+ onDayMouseLeave: PropTypes.func,
121
+ onDayMouseDown: PropTypes.func,
122
+ onDayMouseUp: PropTypes.func,
123
+ onDayTouchStart: PropTypes.func,
124
+ onDayTouchEnd: PropTypes.func,
125
+ onDayFocus: PropTypes.func,
126
+ onMonthChange: PropTypes.func,
127
+ onCaptionClick: PropTypes.func,
128
+ onWeekClick: PropTypes.func,
129
+ onTodayButtonClick: PropTypes.func,
130
+ };
131
+
132
+ static defaultProps = {
133
+ classNames,
134
+ tabIndex: 0,
135
+ initialMonth: new Date(),
136
+ numberOfMonths: 1,
137
+ labels: {
138
+ previousMonth: 'Previous Month',
139
+ nextMonth: 'Next Month',
140
+ },
141
+ locale: 'en',
142
+ localeUtils: LocaleUtils,
143
+ showOutsideDays: false,
144
+ enableOutsideDaysClick: true,
145
+ fixedWeeks: false,
146
+ canChangeMonth: true,
147
+ reverseMonths: false,
148
+ pagedNavigation: false,
149
+ showWeekNumbers: false,
150
+ showWeekDays: true,
151
+ renderDay: (day) => day.getDate(),
152
+ renderWeek: (weekNumber) => weekNumber,
153
+ weekdayElement: <Weekday />,
154
+ navbarElement: <Navbar classNames={classNames} />,
155
+ captionElement: <Caption classNames={classNames} />,
156
+ };
157
+
158
+ constructor(props) {
159
+ super(props);
160
+
161
+ const currentMonth = this.getCurrentMonthFromProps(props);
162
+ this.state = {currentMonth};
163
+ }
164
+
165
+ componentDidUpdate(prevProps) {
166
+ // Changing the `month` props means changing the current displayed month
167
+ if (
168
+ prevProps.month !== this.props.month &&
169
+ !DateUtils.isSameMonth(prevProps.month, this.props.month)
170
+ ) {
171
+ const currentMonth = this.getCurrentMonthFromProps(this.props);
172
+ // eslint-disable-next-line react/no-did-update-set-state
173
+ this.setState({currentMonth});
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Return the month to be shown in the calendar based on the component props.
179
+ *
180
+ * @param {Object} props
181
+ * @returns Date
182
+ * @memberof DayPicker
183
+ * @private
184
+ */
185
+ getCurrentMonthFromProps(props) {
186
+ const initialMonth = Helpers.startOfMonth(
187
+ props.month || props.initialMonth
188
+ );
189
+ let currentMonth = initialMonth;
190
+
191
+ if (props.pagedNavigation && props.numberOfMonths > 1 && props.fromMonth) {
192
+ const diffInMonths = Helpers.getMonthsDiff(props.fromMonth, currentMonth);
193
+ currentMonth = DateUtils.addMonths(
194
+ props.fromMonth,
195
+ Math.floor(diffInMonths / props.numberOfMonths) * props.numberOfMonths
196
+ );
197
+ } else if (
198
+ props.toMonth &&
199
+ props.numberOfMonths > 1 &&
200
+ Helpers.getMonthsDiff(currentMonth, props.toMonth) <= 0
201
+ ) {
202
+ currentMonth = DateUtils.addMonths(
203
+ props.toMonth,
204
+ 1 - this.props.numberOfMonths
205
+ );
206
+ }
207
+ return currentMonth;
208
+ }
209
+
210
+ getNextNavigableMonth() {
211
+ return DateUtils.addMonths(
212
+ this.state.currentMonth,
213
+ this.props.numberOfMonths
214
+ );
215
+ }
216
+
217
+ getPreviousNavigableMonth() {
218
+ return DateUtils.addMonths(this.state.currentMonth, -1);
219
+ }
220
+
221
+ dayPicker = null;
222
+
223
+ allowPreviousMonth() {
224
+ const previousMonth = DateUtils.addMonths(this.state.currentMonth, -1);
225
+ return this.allowMonth(previousMonth);
226
+ }
227
+
228
+ allowNextMonth() {
229
+ const nextMonth = DateUtils.addMonths(
230
+ this.state.currentMonth,
231
+ this.props.numberOfMonths
232
+ );
233
+ return this.allowMonth(nextMonth);
234
+ }
235
+
236
+ allowMonth(d) {
237
+ const {fromMonth, toMonth, canChangeMonth} = this.props;
238
+ if (
239
+ !canChangeMonth ||
240
+ (fromMonth && Helpers.getMonthsDiff(fromMonth, d) < 0) ||
241
+ (toMonth && Helpers.getMonthsDiff(toMonth, d) > 0)
242
+ ) {
243
+ return false;
244
+ }
245
+ return true;
246
+ }
247
+
248
+ allowYearChange() {
249
+ return this.props.canChangeMonth;
250
+ }
251
+
252
+ showMonth(d, callback) {
253
+ if (!this.allowMonth(d)) {
254
+ return;
255
+ }
256
+ this.setState({currentMonth: Helpers.startOfMonth(d)}, () => {
257
+ if (callback) {
258
+ callback();
259
+ }
260
+ if (this.props.onMonthChange) {
261
+ this.props.onMonthChange(this.state.currentMonth);
262
+ }
263
+ });
264
+ }
265
+
266
+ showNextMonth = (callback) => {
267
+ if (!this.allowNextMonth()) {
268
+ return;
269
+ }
270
+ const deltaMonths = this.props.pagedNavigation
271
+ ? this.props.numberOfMonths
272
+ : 1;
273
+ const nextMonth = DateUtils.addMonths(this.state.currentMonth, deltaMonths);
274
+ this.showMonth(nextMonth, callback);
275
+ };
276
+
277
+ showPreviousMonth = (callback) => {
278
+ if (!this.allowPreviousMonth()) {
279
+ return;
280
+ }
281
+ const deltaMonths = this.props.pagedNavigation
282
+ ? this.props.numberOfMonths
283
+ : 1;
284
+ const previousMonth = DateUtils.addMonths(
285
+ this.state.currentMonth,
286
+ -deltaMonths
287
+ );
288
+ this.showMonth(previousMonth, callback);
289
+ };
290
+
291
+ showNextYear() {
292
+ if (!this.allowYearChange()) {
293
+ return;
294
+ }
295
+ const nextMonth = DateUtils.addMonths(this.state.currentMonth, 12);
296
+ this.showMonth(nextMonth);
297
+ }
298
+
299
+ showPreviousYear() {
300
+ if (!this.allowYearChange()) {
301
+ return;
302
+ }
303
+ const nextMonth = DateUtils.addMonths(this.state.currentMonth, -12);
304
+ this.showMonth(nextMonth);
305
+ }
306
+
307
+ focusFirstDayOfMonth() {
308
+ Helpers.getDayNodes(this.dayPicker, this.props.classNames)[0].focus();
309
+ }
310
+
311
+ focusLastDayOfMonth() {
312
+ const dayNodes = Helpers.getDayNodes(this.dayPicker, this.props.classNames);
313
+ dayNodes[dayNodes.length - 1].focus();
314
+ }
315
+
316
+ focusPreviousDay(dayNode) {
317
+ const dayNodes = Helpers.getDayNodes(this.dayPicker, this.props.classNames);
318
+ const dayNodeIndex = Helpers.nodeListToArray(dayNodes).indexOf(dayNode);
319
+ if (dayNodeIndex === -1) return;
320
+ if (dayNodeIndex === 0) {
321
+ this.showPreviousMonth(() => this.focusLastDayOfMonth());
322
+ } else {
323
+ dayNodes[dayNodeIndex - 1].focus();
324
+ }
325
+ }
326
+
327
+ focusNextDay(dayNode) {
328
+ const dayNodes = Helpers.getDayNodes(this.dayPicker, this.props.classNames);
329
+ const dayNodeIndex = Helpers.nodeListToArray(dayNodes).indexOf(dayNode);
330
+ if (dayNodeIndex === -1) return;
331
+ if (dayNodeIndex === dayNodes.length - 1) {
332
+ this.showNextMonth(() => this.focusFirstDayOfMonth());
333
+ } else {
334
+ dayNodes[dayNodeIndex + 1].focus();
335
+ }
336
+ }
337
+
338
+ focusNextWeek(dayNode) {
339
+ const dayNodes = Helpers.getDayNodes(this.dayPicker, this.props.classNames);
340
+ const dayNodeIndex = Helpers.nodeListToArray(dayNodes).indexOf(dayNode);
341
+ const isInLastWeekOfMonth = dayNodeIndex > dayNodes.length - 8;
342
+
343
+ if (isInLastWeekOfMonth) {
344
+ this.showNextMonth(() => {
345
+ const daysAfterIndex = dayNodes.length - dayNodeIndex;
346
+ const nextMonthDayNodeIndex = 7 - daysAfterIndex;
347
+ Helpers.getDayNodes(this.dayPicker, this.props.classNames)[
348
+ nextMonthDayNodeIndex
349
+ ].focus();
350
+ });
351
+ } else {
352
+ dayNodes[dayNodeIndex + 7].focus();
353
+ }
354
+ }
355
+
356
+ focusPreviousWeek(dayNode) {
357
+ const dayNodes = Helpers.getDayNodes(this.dayPicker, this.props.classNames);
358
+ const dayNodeIndex = Helpers.nodeListToArray(dayNodes).indexOf(dayNode);
359
+ const isInFirstWeekOfMonth = dayNodeIndex <= 6;
360
+
361
+ if (isInFirstWeekOfMonth) {
362
+ this.showPreviousMonth(() => {
363
+ const previousMonthDayNodes = Helpers.getDayNodes(
364
+ this.dayPicker,
365
+ this.props.classNames
366
+ );
367
+ const startOfLastWeekOfMonth = previousMonthDayNodes.length - 7;
368
+ const previousMonthDayNodeIndex = startOfLastWeekOfMonth + dayNodeIndex;
369
+ previousMonthDayNodes[previousMonthDayNodeIndex].focus();
370
+ });
371
+ } else {
372
+ dayNodes[dayNodeIndex - 7].focus();
373
+ }
374
+ }
375
+
376
+ // Event handlers
377
+
378
+ handleKeyDown = (e) => {
379
+ e.persist();
380
+
381
+ switch (e.keyCode) {
382
+ case LEFT:
383
+ this.showPreviousMonth();
384
+ break;
385
+ case RIGHT:
386
+ this.showNextMonth();
387
+ break;
388
+ case UP:
389
+ this.showPreviousYear();
390
+ break;
391
+ case DOWN:
392
+ this.showNextYear();
393
+ break;
394
+ default:
395
+ break;
396
+ }
397
+
398
+ if (this.props.onKeyDown) {
399
+ this.props.onKeyDown(e);
400
+ }
401
+ };
402
+
403
+ handleDayKeyDown = (day, modifiers, e) => {
404
+ e.persist();
405
+ switch (e.keyCode) {
406
+ case LEFT:
407
+ Helpers.cancelEvent(e);
408
+ this.focusPreviousDay(e.target);
409
+ break;
410
+ case RIGHT:
411
+ Helpers.cancelEvent(e);
412
+ this.focusNextDay(e.target);
413
+ break;
414
+ case UP:
415
+ Helpers.cancelEvent(e);
416
+ this.focusPreviousWeek(e.target);
417
+ break;
418
+ case DOWN:
419
+ Helpers.cancelEvent(e);
420
+ this.focusNextWeek(e.target);
421
+ break;
422
+ case ENTER:
423
+ case SPACE:
424
+ Helpers.cancelEvent(e);
425
+ if (this.props.onDayClick) {
426
+ this.handleDayClick(day, modifiers, e);
427
+ }
428
+ break;
429
+ default:
430
+ break;
431
+ }
432
+ if (this.props.onDayKeyDown) {
433
+ this.props.onDayKeyDown(day, modifiers, e);
434
+ }
435
+ };
436
+
437
+ handleDayClick = (day, modifiers, e) => {
438
+ e.persist();
439
+ if (
440
+ modifiers[this.props.classNames.outside] &&
441
+ this.props.enableOutsideDaysClick
442
+ ) {
443
+ this.handleOutsideDayClick(day);
444
+ }
445
+ if (this.props.onDayClick) {
446
+ this.props.onDayClick(day, modifiers, e);
447
+ }
448
+ };
449
+
450
+ handleOutsideDayClick(day) {
451
+ const {currentMonth} = this.state;
452
+ const {numberOfMonths} = this.props;
453
+ const diffInMonths = Helpers.getMonthsDiff(currentMonth, day);
454
+ if (diffInMonths > 0 && diffInMonths >= numberOfMonths) {
455
+ this.showNextMonth();
456
+ } else if (diffInMonths < 0) {
457
+ this.showPreviousMonth();
458
+ }
459
+ }
460
+
461
+ handleTodayButtonClick = (e) => {
462
+ const today = new Date();
463
+ const month = new Date(today.getFullYear(), today.getMonth());
464
+ this.showMonth(month);
465
+ e.target.blur();
466
+ if (this.props.onTodayButtonClick) {
467
+ e.persist();
468
+ this.props.onTodayButtonClick(
469
+ new Date(today.getFullYear(), today.getMonth(), today.getDate()),
470
+ ModifiersUtils.getModifiersForDay(today, this.props.modifiers),
471
+ e
472
+ );
473
+ }
474
+ };
475
+
476
+ renderNavbar() {
477
+ const {
478
+ labels,
479
+ locale,
480
+ localeUtils,
481
+ canChangeMonth,
482
+ navbarElement,
483
+ ...attributes
484
+ } = this.props;
485
+
486
+ if (!canChangeMonth) return null;
487
+
488
+ const props = {
489
+ month: this.state.currentMonth,
490
+ classNames: this.props.classNames,
491
+ className: this.props.classNames.navBar,
492
+ nextMonth: this.getNextNavigableMonth(),
493
+ previousMonth: this.getPreviousNavigableMonth(),
494
+ showPreviousButton: this.allowPreviousMonth(),
495
+ showNextButton: this.allowNextMonth(),
496
+ onNextClick: this.showNextMonth,
497
+ onPreviousClick: this.showPreviousMonth,
498
+ dir: attributes.dir,
499
+ labels,
500
+ locale,
501
+ localeUtils,
502
+ };
503
+ return React.isValidElement(navbarElement)
504
+ ? React.cloneElement(navbarElement, props)
505
+ : React.createElement(navbarElement, props);
506
+ }
507
+
508
+ renderMonths() {
509
+ const months = [];
510
+ const firstDayOfWeek = Helpers.getFirstDayOfWeekFromProps(this.props);
511
+ for (let i = 0; i < this.props.numberOfMonths; i += 1) {
512
+ const month = DateUtils.addMonths(this.state.currentMonth, i);
513
+ months.push(
514
+ <Month
515
+ key={i}
516
+ {...this.props}
517
+ month={month}
518
+ firstDayOfWeek={firstDayOfWeek}
519
+ onDayKeyDown={this.handleDayKeyDown}
520
+ onDayClick={this.handleDayClick}
521
+ />
522
+ );
523
+ }
524
+
525
+ if (this.props.reverseMonths) {
526
+ months.reverse();
527
+ }
528
+ return months;
529
+ }
530
+
531
+ renderFooter() {
532
+ if (this.props.todayButton) {
533
+ return (
534
+ <div className={this.props.classNames.footer}>
535
+ {this.renderTodayButton()}
536
+ </div>
537
+ );
538
+ }
539
+ return null;
540
+ }
541
+
542
+ renderTodayButton() {
543
+ return (
544
+ <button
545
+ type="button"
546
+ tabIndex={0}
547
+ className={this.props.classNames.todayButton}
548
+ aria-label={this.props.todayButton}
549
+ onClick={this.handleTodayButtonClick}
550
+ >
551
+ {this.props.todayButton}
552
+ </button>
553
+ );
554
+ }
555
+
556
+ render() {
557
+ let className = this.props.classNames.container;
558
+
559
+ if (!this.props.onDayClick) {
560
+ className = `${className} ${this.props.classNames.interactionDisabled}`;
561
+ }
562
+ if (this.props.className) {
563
+ className = `${className} ${this.props.className}`;
564
+ }
565
+ return (
566
+ <div
567
+ {...this.props.containerProps}
568
+ className={className}
569
+ ref={(el) => (this.dayPicker = el)}
570
+ lang={this.props.locale}
571
+ >
572
+ <div
573
+ className={this.props.classNames.wrapper}
574
+ tabIndex={
575
+ this.props.canChangeMonth &&
576
+ typeof this.props.tabIndex !== 'undefined'
577
+ ? this.props.tabIndex
578
+ : -1
579
+ }
580
+ onKeyDown={this.handleKeyDown}
581
+ onFocus={this.props.onFocus}
582
+ onBlur={this.props.onBlur}
583
+ >
584
+ {this.renderNavbar()}
585
+ <div className={this.props.classNames.months}>
586
+ {this.renderMonths()}
587
+ </div>
588
+ {this.renderFooter()}
589
+ </div>
590
+ </div>
591
+ );
592
+ }
593
+ }
594
+
595
+ DayPicker.DateUtils = DateUtils;
596
+ DayPicker.LocaleUtils = LocaleUtils;
597
+ DayPicker.ModifiersUtils = ModifiersUtils;
598
+
599
+ export {DateUtils, LocaleUtils, ModifiersUtils};
600
+
601
+ export default DayPicker;