@superdispatch/dates 0.21.6 → 0.21.13

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.
Files changed (62) hide show
  1. package/.babelrc.js +5 -0
  2. package/.turbo/turbo-version.log +26 -0
  3. package/package.json +58 -32
  4. package/pkg/README.md +10 -0
  5. package/{dist-types → pkg/dist-types}/index.d.ts +237 -237
  6. package/pkg/package.json +32 -0
  7. package/playroom.ts +10 -0
  8. package/src/__tests__/index.spec.ts +48 -0
  9. package/src/base-date-picker/BaseDatePicker.tsx +145 -0
  10. package/src/calendar/Calendar.playroom.tsx +28 -0
  11. package/src/calendar/Calendar.spec.tsx +531 -0
  12. package/src/calendar/Calendar.stories.tsx +50 -0
  13. package/src/calendar/Calendar.tsx +534 -0
  14. package/src/calendar/CalendarQuickSelection.tsx +34 -0
  15. package/src/calendar/InternalCalendarComponents.tsx +79 -0
  16. package/src/date-config/DateConfig.spec.tsx +23 -0
  17. package/src/date-config/DateConfig.tsx +60 -0
  18. package/src/date-field/DateField.playroom.tsx +21 -0
  19. package/src/date-field/DateField.spec.tsx +350 -0
  20. package/src/date-field/DateField.stories.tsx +47 -0
  21. package/src/date-field/DateField.tsx +155 -0
  22. package/src/date-range-field/DateRangeField.playroom.tsx +24 -0
  23. package/src/date-range-field/DateRangeField.spec.tsx +318 -0
  24. package/src/date-range-field/DateRangeField.stories.tsx +51 -0
  25. package/src/date-range-field/DateRangeField.tsx +277 -0
  26. package/src/date-time-utils/DateTimeUtils.spec.ts +652 -0
  27. package/src/date-time-utils/DateTimeUtils.ts +339 -0
  28. package/src/date-utils/DateUtils.spec.ts +234 -0
  29. package/src/date-utils/DateUtils.ts +333 -0
  30. package/src/formatted-date/FormattedDate.spec.tsx +103 -0
  31. package/src/formatted-date/FormattedDate.ts +42 -0
  32. package/src/formatted-relative-time/FormattedRelativeTime.spec.tsx +93 -0
  33. package/src/formatted-relative-time/FormattedRelativeTime.ts +60 -0
  34. package/src/index.ts +12 -0
  35. package/src/time-field/TimeField.playroom.tsx +21 -0
  36. package/src/time-field/TimeField.stories.tsx +35 -0
  37. package/src/time-field/TimeField.tsx +221 -0
  38. package/src/use-date-time/useDateTime.spec.ts +45 -0
  39. package/src/use-date-time/useDateTime.ts +31 -0
  40. package/src/use-date-time-range/useDateTimeRange.spec.ts +53 -0
  41. package/src/use-date-time-range/useDateTimeRange.ts +24 -0
  42. package/tsconfig.json +19 -0
  43. package/LICENSE +0 -21
  44. /package/{dist-node → pkg/dist-node}/index.js +0 -0
  45. /package/{dist-node → pkg/dist-node}/index.js.map +0 -0
  46. /package/{dist-src → pkg/dist-src}/base-date-picker/BaseDatePicker.js +0 -0
  47. /package/{dist-src → pkg/dist-src}/calendar/Calendar.js +0 -0
  48. /package/{dist-src → pkg/dist-src}/calendar/CalendarQuickSelection.js +0 -0
  49. /package/{dist-src → pkg/dist-src}/calendar/InternalCalendarComponents.js +0 -0
  50. /package/{dist-src → pkg/dist-src}/date-config/DateConfig.js +0 -0
  51. /package/{dist-src → pkg/dist-src}/date-field/DateField.js +0 -0
  52. /package/{dist-src → pkg/dist-src}/date-range-field/DateRangeField.js +0 -0
  53. /package/{dist-src → pkg/dist-src}/date-time-utils/DateTimeUtils.js +0 -0
  54. /package/{dist-src → pkg/dist-src}/date-utils/DateUtils.js +0 -0
  55. /package/{dist-src → pkg/dist-src}/formatted-date/FormattedDate.js +0 -0
  56. /package/{dist-src → pkg/dist-src}/formatted-relative-time/FormattedRelativeTime.js +0 -0
  57. /package/{dist-src → pkg/dist-src}/index.js +0 -0
  58. /package/{dist-src → pkg/dist-src}/time-field/TimeField.js +0 -0
  59. /package/{dist-src → pkg/dist-src}/use-date-time/useDateTime.js +0 -0
  60. /package/{dist-src → pkg/dist-src}/use-date-time-range/useDateTimeRange.js +0 -0
  61. /package/{dist-web → pkg/dist-web}/index.js +0 -0
  62. /package/{dist-web → pkg/dist-web}/index.js.map +0 -0
@@ -0,0 +1,534 @@
1
+ import { Divider, Grid, GridDirection, Hidden, Theme } from '@material-ui/core';
2
+ import { ClassNameMap, makeStyles } from '@material-ui/styles';
3
+ import { Color, ColorVariant } from '@superdispatch/ui';
4
+ import { DateTime } from 'luxon';
5
+ import { forwardRef, ReactNode, useMemo } from 'react';
6
+ import DayPicker, {
7
+ DayModifiers,
8
+ DayPickerProps,
9
+ FunctionModifier,
10
+ Modifiers,
11
+ } from 'react-day-picker';
12
+ import {
13
+ DateConfig,
14
+ DateFormat,
15
+ useDateConfig,
16
+ } from '../date-config/DateConfig';
17
+ import {
18
+ DatePayload,
19
+ NullableDateInput,
20
+ stringifyDate,
21
+ } from '../date-time-utils/DateTimeUtils';
22
+ import { useDateTime } from '../use-date-time/useDateTime';
23
+ import {
24
+ CalendarCaption,
25
+ CalendarNavbar,
26
+ CalendarWeekDay,
27
+ } from './InternalCalendarComponents';
28
+
29
+ //
30
+ // Styles
31
+ //
32
+
33
+ export type CalendarDayHighlightColor = Exclude<
34
+ ColorVariant,
35
+ 'grey' | 'silver'
36
+ >;
37
+
38
+ export type CalendarClassNames =
39
+ | keyof NonNullable<DayPickerProps['classNames']>
40
+ | CalendarDayHighlightColor
41
+ | 'firstDayOfMonth'
42
+ | 'lastDayOfMonth';
43
+
44
+ export type CalendarClassNameMap = ClassNameMap<CalendarClassNames>;
45
+
46
+ const useStyles = makeStyles<
47
+ Theme,
48
+ { classes?: Partial<CalendarClassNameMap> },
49
+ CalendarClassNames
50
+ >(
51
+ (theme) => ({
52
+ container: {
53
+ display: 'inline-block',
54
+ },
55
+
56
+ wrapper: {
57
+ userSelect: 'none',
58
+ position: 'relative',
59
+ flexDirection: 'row',
60
+ paddingBottom: theme.spacing(2),
61
+ '&:focus': {
62
+ outline: 'none',
63
+ },
64
+ },
65
+
66
+ interactionDisabled: {},
67
+
68
+ navBar: {},
69
+ navButtonPrev: {
70
+ position: 'absolute',
71
+ top: theme.spacing(1.5),
72
+ left: theme.spacing(1.5),
73
+ },
74
+ navButtonNext: {
75
+ position: 'absolute',
76
+ top: theme.spacing(1.5),
77
+ right: theme.spacing(1.5),
78
+ },
79
+ navButtonInteractionDisabled: {},
80
+
81
+ months: {
82
+ display: 'flex',
83
+ flexWrap: 'wrap',
84
+ justifyContent: 'center',
85
+ },
86
+
87
+ month: {
88
+ userSelect: 'none',
89
+ margin: theme.spacing(2, 2, 0, 2),
90
+ },
91
+
92
+ caption: {
93
+ textAlign: 'center',
94
+ display: 'table-caption',
95
+ marginBottom: theme.spacing(1),
96
+ padding: theme.spacing(0, 1),
97
+ },
98
+
99
+ weekdays: {
100
+ display: 'table-header-group',
101
+ },
102
+ weekdaysRow: {
103
+ display: 'flex',
104
+ margin: theme.spacing(1, 0),
105
+ },
106
+ weekday: {
107
+ margin: '1px',
108
+ display: 'flex',
109
+ alignItems: 'center',
110
+ justifyContent: 'center',
111
+ textDecoration: 'none',
112
+
113
+ color: Color.Dark300,
114
+ width: theme.spacing(5),
115
+ height: theme.spacing(5),
116
+ },
117
+
118
+ weekNumber: {},
119
+
120
+ body: {
121
+ display: 'flex',
122
+ flexDirection: 'column',
123
+ },
124
+
125
+ week: {
126
+ display: 'flex',
127
+ },
128
+
129
+ // Day modifiers.
130
+ today: {},
131
+ outside: {},
132
+ selected: {},
133
+ disabled: {},
134
+ firstDayOfMonth: {},
135
+ lastDayOfMonth: {},
136
+
137
+ blue: {},
138
+ green: {},
139
+ purple: {},
140
+ red: {},
141
+ teal: {},
142
+ yellow: {},
143
+
144
+ day: {
145
+ zIndex: 1,
146
+ margin: '1px',
147
+ width: theme.spacing(5),
148
+ height: theme.spacing(5),
149
+ borderRadius: theme.spacing(0.5),
150
+
151
+ position: 'relative',
152
+
153
+ display: 'flex',
154
+ alignItems: 'center',
155
+ justifyContent: 'center',
156
+
157
+ transition: theme.transitions.create(['color', 'background-color']),
158
+
159
+ '&:before': {
160
+ content: '""',
161
+ top: 0,
162
+ left: -1,
163
+ right: -1,
164
+ bottom: 0,
165
+ zIndex: -1,
166
+ position: 'absolute',
167
+ backgroundColor: Color.Transparent,
168
+ transition: theme.transitions.create('background-color'),
169
+ },
170
+
171
+ '&:first-child, &$firstDayOfMonth': {
172
+ '&:before': {
173
+ borderRadius: theme.spacing(0.5, 0, 0, 0.5),
174
+ },
175
+ },
176
+
177
+ '&:last-child, &$lastDayOfMonth': {
178
+ '&:before': {
179
+ borderRadius: theme.spacing(0, 0.5, 0.5, 0),
180
+ },
181
+ },
182
+
183
+ '&:after': {
184
+ content: '""',
185
+ borderRadius: theme.spacing(0.5),
186
+
187
+ top: 0,
188
+ left: 0,
189
+ right: 0,
190
+ bottom: 0,
191
+ zIndex: -1,
192
+ position: 'absolute',
193
+ backgroundColor: Color.Transparent,
194
+ transition: theme.transitions.create('background-color'),
195
+ },
196
+
197
+ '&:hover, &:focus': {
198
+ outline: 'none',
199
+ },
200
+
201
+ '&$disabled': {
202
+ color: Color.Dark100,
203
+ '&$selected:not($outside):after': {
204
+ backgroundColor: Color.Silver300,
205
+ },
206
+ },
207
+
208
+ '&:not($outside):not($disabled)': {
209
+ cursor: 'pointer',
210
+ color: Color.Dark500,
211
+
212
+ '&:not($selected):not(:active)': {
213
+ '&$today': {
214
+ color: Color.Blue300,
215
+ },
216
+
217
+ '&:hover, &:focus': {
218
+ backgroundColor: Color.Silver100,
219
+ },
220
+
221
+ '&$blue': {
222
+ color: Color.Blue500,
223
+ '&': {
224
+ backgroundColor: Color.Blue50,
225
+ },
226
+ },
227
+ '&$green': {
228
+ color: Color.Green500,
229
+ '&': {
230
+ backgroundColor: Color.Green50,
231
+ },
232
+ },
233
+ '&$purple': {
234
+ color: Color.Purple500,
235
+ '&': {
236
+ backgroundColor: Color.Purple50,
237
+ },
238
+ },
239
+ '&$red': {
240
+ color: Color.Red500,
241
+ '&': {
242
+ backgroundColor: Color.Red50,
243
+ },
244
+ },
245
+ '&$teal': {
246
+ color: Color.Teal500,
247
+ '&': {
248
+ backgroundColor: Color.Teal50,
249
+ },
250
+ },
251
+ '&$yellow': {
252
+ color: Color.Yellow500,
253
+ '&': {
254
+ backgroundColor: Color.Yellow50,
255
+ },
256
+ },
257
+ },
258
+
259
+ '&:active, &$selected': {
260
+ color: Color.White,
261
+ '&:after': {
262
+ backgroundColor: Color.Blue300,
263
+ },
264
+ },
265
+ },
266
+ },
267
+
268
+ footer: {
269
+ padding: theme.spacing(2),
270
+ },
271
+
272
+ todayButton: {},
273
+ }),
274
+ { name: 'SD-Calendar' },
275
+ );
276
+
277
+ //
278
+ // Utility Types
279
+ //
280
+
281
+ export type CalendarModifier = (info: DatePayload) => boolean;
282
+
283
+ export interface CalendarDateEvent extends DatePayload {
284
+ disabled: boolean;
285
+ selected: boolean;
286
+ }
287
+
288
+ export type CalendarDayEventHandler = (event: CalendarDateEvent) => void;
289
+
290
+ export interface CalendarModifiers {
291
+ today?: CalendarModifier;
292
+ outside?: CalendarModifier;
293
+ [other: string]: undefined | CalendarModifier;
294
+ }
295
+
296
+ export type CalendarHighlightedDays = Partial<
297
+ Record<CalendarDayHighlightColor, CalendarModifier>
298
+ >;
299
+
300
+ //
301
+ // Internal Utils
302
+ //
303
+
304
+ function toDayPickerModifier(
305
+ config: DateConfig,
306
+ modifier: undefined | CalendarModifier,
307
+ ): undefined | FunctionModifier {
308
+ if (!modifier) {
309
+ return undefined;
310
+ }
311
+
312
+ return (localDate) => {
313
+ const dateValue = DateTime.fromObject({
314
+ year: localDate.getFullYear(),
315
+ month: localDate.getMonth() + 1,
316
+ day: localDate.getDate(),
317
+ hour: localDate.getHours(),
318
+ minute: localDate.getMinutes(),
319
+ second: localDate.getSeconds(),
320
+ millisecond: localDate.getMilliseconds(),
321
+ });
322
+
323
+ return modifier({
324
+ config,
325
+ dateValue,
326
+ stringValue: stringifyDate(dateValue, config),
327
+ });
328
+ };
329
+ }
330
+
331
+ function toDayPickerHandler(
332
+ config: DateConfig,
333
+ classes: CalendarClassNameMap,
334
+ initialTime: DateTime,
335
+ handler: undefined | CalendarDayEventHandler,
336
+ ): undefined | ((localDate: Date, modifiers: DayModifiers) => void) {
337
+ if (!handler) {
338
+ return undefined;
339
+ }
340
+
341
+ return (localDate: Date, modifiers: DayModifiers) => {
342
+ const dateValue = DateTime.fromObject({
343
+ year: localDate.getFullYear(),
344
+ month: localDate.getMonth() + 1,
345
+ day: localDate.getDate(),
346
+ hour: initialTime.hour,
347
+ minute: initialTime.minute,
348
+ second: initialTime.second,
349
+ millisecond: initialTime.millisecond,
350
+ });
351
+
352
+ handler({
353
+ disabled: !!modifiers[classes.disabled],
354
+ selected: !!modifiers[classes.selected],
355
+
356
+ config,
357
+ dateValue,
358
+ stringValue: stringifyDate(dateValue, config),
359
+ });
360
+ };
361
+ }
362
+
363
+ //
364
+ // Calendar
365
+ //
366
+
367
+ export interface CalendarProps extends Pick<DayPickerProps, 'numberOfMonths'> {
368
+ direction?: GridDirection;
369
+ classes?: Partial<CalendarClassNameMap>;
370
+
371
+ footer?: ReactNode;
372
+ quickSelection?: ReactNode;
373
+
374
+ format?: DateFormat;
375
+ initialTime?: NullableDateInput;
376
+ initialMonth?: NullableDateInput;
377
+
378
+ modifiers?: CalendarModifiers;
379
+ selectedDays?: CalendarModifier;
380
+ disabledDays?: CalendarModifier;
381
+ highlightedDays?: CalendarHighlightedDays;
382
+
383
+ onDayClick?: CalendarDayEventHandler;
384
+ onDayKeyDown?: CalendarDayEventHandler;
385
+ onDayMouseEnter?: CalendarDayEventHandler;
386
+ onDayMouseLeave?: CalendarDayEventHandler;
387
+ onDayMouseDown?: CalendarDayEventHandler;
388
+ onDayMouseUp?: CalendarDayEventHandler;
389
+ onDayTouchEnd?: CalendarDayEventHandler;
390
+ onDayTouchStart?: CalendarDayEventHandler;
391
+ }
392
+
393
+ export const Calendar = forwardRef<HTMLDivElement, CalendarProps>(
394
+ (
395
+ {
396
+ footer,
397
+ classes,
398
+ direction,
399
+ quickSelection,
400
+ selectedDays,
401
+ disabledDays,
402
+
403
+ onDayClick,
404
+ onDayKeyDown,
405
+ onDayMouseEnter,
406
+ onDayMouseLeave,
407
+ onDayMouseDown,
408
+ onDayMouseUp,
409
+ onDayTouchEnd,
410
+ onDayTouchStart,
411
+
412
+ modifiers,
413
+ highlightedDays,
414
+
415
+ format: formatProp,
416
+ initialTime: initialTimeInputProp,
417
+ initialMonth: initialMonthInputProp,
418
+
419
+ ...dayPickerProps
420
+ },
421
+ ref,
422
+ ) => {
423
+ const styles = useStyles({ classes });
424
+ const config = useDateConfig({ format: formatProp });
425
+
426
+ const initialTimeInput = useDateTime(initialTimeInputProp, config);
427
+ const initialMonthInput = useDateTime(initialMonthInputProp, config);
428
+
429
+ const [initialTime, initialMonth] = useMemo(() => {
430
+ let time = initialTimeInput;
431
+ let month = initialMonthInput;
432
+
433
+ if (!month.isValid) {
434
+ month = DateTime.local().startOf('month');
435
+ }
436
+
437
+ if (!time.isValid) {
438
+ time = month;
439
+ }
440
+
441
+ return [
442
+ time,
443
+ new Date(
444
+ month.year,
445
+ month.month - 1,
446
+ month.day,
447
+ month.hour,
448
+ month.minute,
449
+ month.second,
450
+ month.millisecond,
451
+ ),
452
+ ];
453
+ }, [initialTimeInput, initialMonthInput]);
454
+
455
+ const wrapModifier = toDayPickerModifier.bind(null, config);
456
+ const wrapHandler = toDayPickerHandler.bind(
457
+ null,
458
+ config,
459
+ styles,
460
+ initialTime,
461
+ );
462
+
463
+ const dayPickerModifiers: Partial<Modifiers> = {
464
+ [styles.firstDayOfMonth]: wrapModifier(
465
+ ({ dateValue }) => dateValue.day === 1,
466
+ ),
467
+ [styles.lastDayOfMonth]: wrapModifier(
468
+ ({ dateValue }) => dateValue.day === dateValue.daysInMonth,
469
+ ),
470
+ };
471
+
472
+ if (modifiers) {
473
+ for (const [key, modifier] of Object.entries(modifiers)) {
474
+ dayPickerModifiers[key] = wrapModifier(modifier);
475
+ }
476
+ }
477
+
478
+ if (highlightedDays) {
479
+ for (const [key, modifier] of Object.entries(highlightedDays) as Array<
480
+ [CalendarDayHighlightColor, CalendarModifier]
481
+ >) {
482
+ dayPickerModifiers[styles[key]] = wrapModifier(modifier);
483
+ }
484
+ }
485
+
486
+ return (
487
+ <Grid ref={ref} container={true} direction={direction}>
488
+ {!!quickSelection && (
489
+ <>
490
+ <Grid item={true} xs={12} sm="auto">
491
+ {quickSelection}
492
+ </Grid>
493
+
494
+ <Hidden xsDown={true}>
495
+ <Grid item={true} sm="auto">
496
+ <Divider orientation="vertical" />
497
+ </Grid>
498
+ </Hidden>
499
+
500
+ <Hidden smUp={true}>
501
+ <Grid item={true} xs={12}>
502
+ <Divider orientation="horizontal" />
503
+ </Grid>
504
+ </Hidden>
505
+ </>
506
+ )}
507
+
508
+ <Grid item={true} xs={12} sm="auto">
509
+ <DayPicker
510
+ {...dayPickerProps}
511
+ classNames={styles}
512
+ navbarElement={CalendarNavbar}
513
+ captionElement={CalendarCaption}
514
+ weekdayElement={CalendarWeekDay}
515
+ initialMonth={initialMonth}
516
+ modifiers={dayPickerModifiers}
517
+ selectedDays={wrapModifier(selectedDays)}
518
+ disabledDays={wrapModifier(disabledDays)}
519
+ onDayClick={wrapHandler(onDayClick)}
520
+ onDayKeyDown={wrapHandler(onDayKeyDown)}
521
+ onDayMouseEnter={wrapHandler(onDayMouseEnter)}
522
+ onDayMouseLeave={wrapHandler(onDayMouseLeave)}
523
+ onDayMouseDown={wrapHandler(onDayMouseDown)}
524
+ onDayMouseUp={wrapHandler(onDayMouseUp)}
525
+ onDayTouchEnd={wrapHandler(onDayTouchEnd)}
526
+ onDayTouchStart={wrapHandler(onDayTouchStart)}
527
+ />
528
+
529
+ {!!footer && <div className={styles.footer}>{footer}</div>}
530
+ </Grid>
531
+ </Grid>
532
+ );
533
+ },
534
+ );
@@ -0,0 +1,34 @@
1
+ import { List, ListItem, Typography } from '@material-ui/core';
2
+ import { forwardRef, ReactNode } from 'react';
3
+
4
+ export interface CalendarQuickSelectionItemProps {
5
+ children?: ReactNode;
6
+ selected?: boolean;
7
+ onClick?: () => void;
8
+ }
9
+
10
+ export const CalendarQuickSelectionItem = forwardRef<
11
+ HTMLDivElement,
12
+ CalendarQuickSelectionItemProps
13
+ >(({ onClick, selected, children }, ref) => (
14
+ <ListItem ref={ref} button={true} selected={selected} onClick={onClick}>
15
+ {children}
16
+ </ListItem>
17
+ ));
18
+
19
+ export interface CalendarQuickSelectionProps {
20
+ children?: ReactNode;
21
+ }
22
+
23
+ export const CalendarQuickSelection = forwardRef<
24
+ HTMLUListElement,
25
+ CalendarQuickSelectionProps
26
+ >(({ children }, ref) => (
27
+ <List ref={ref}>
28
+ <ListItem>
29
+ <Typography variant="h4">Quick Selection</Typography>
30
+ </ListItem>
31
+
32
+ {children}
33
+ </List>
34
+ ));
@@ -0,0 +1,79 @@
1
+ import { IconButton, Typography } from '@material-ui/core';
2
+ import { ChevronLeft, ChevronRight } from '@material-ui/icons';
3
+ import { ReactElement } from 'react';
4
+ import {
5
+ CaptionElementProps,
6
+ NavbarElementProps,
7
+ WeekdayElementProps,
8
+ } from 'react-day-picker';
9
+
10
+ export function CalendarCaption({
11
+ date,
12
+ localeUtils,
13
+ classNames,
14
+ onClick,
15
+ }: CaptionElementProps): ReactElement {
16
+ return (
17
+ <Typography variant="h4" onClick={onClick} className={classNames.caption}>
18
+ {localeUtils.formatMonthTitle(date)}
19
+ </Typography>
20
+ );
21
+ }
22
+
23
+ export function CalendarNavbar({
24
+ labels,
25
+ classNames,
26
+ onNextClick,
27
+ onPreviousClick,
28
+ showNextButton,
29
+ showPreviousButton,
30
+ }: NavbarElementProps): ReactElement {
31
+ return (
32
+ <>
33
+ <IconButton
34
+ size="small"
35
+ color="primary"
36
+ disabled={!showPreviousButton}
37
+ onClick={() => {
38
+ onPreviousClick();
39
+ }}
40
+ aria-label={labels.previousMonth}
41
+ className={classNames.navButtonPrev}
42
+ >
43
+ <ChevronLeft color="action" />
44
+ </IconButton>
45
+
46
+ <IconButton
47
+ size="small"
48
+ color="primary"
49
+ disabled={!showNextButton}
50
+ onClick={() => {
51
+ onNextClick();
52
+ }}
53
+ aria-label={labels.nextMonth}
54
+ className={classNames.navButtonNext}
55
+ >
56
+ <ChevronRight color="action" />
57
+ </IconButton>
58
+ </>
59
+ );
60
+ }
61
+
62
+ const SHORT_WEEKDAYS = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
63
+
64
+ export function CalendarWeekDay({
65
+ weekday,
66
+ className,
67
+ localeUtils,
68
+ }: WeekdayElementProps): ReactElement {
69
+ return (
70
+ <Typography
71
+ variant="h5"
72
+ component="abbr"
73
+ className={className}
74
+ title={localeUtils.formatWeekdayLong(weekday)}
75
+ >
76
+ {SHORT_WEEKDAYS[weekday]}
77
+ </Typography>
78
+ );
79
+ }
@@ -0,0 +1,23 @@
1
+ import { renderHook } from '@testing-library/react-hooks';
2
+ import { ReactElement } from 'react';
3
+ import {
4
+ DateConfigProvider,
5
+ DateConfigProviderProps,
6
+ useDateConfig,
7
+ } from './DateConfig';
8
+
9
+ test('basic', () => {
10
+ const { result } = renderHook(useDateConfig);
11
+
12
+ expect(result.current.format).toBe('DateTimeISO');
13
+ });
14
+
15
+ test('format overrides', () => {
16
+ function Wrapper(props: DateConfigProviderProps): ReactElement {
17
+ return <DateConfigProvider {...props} format="JodaISO" />;
18
+ }
19
+
20
+ const { result } = renderHook(useDateConfig, { wrapper: Wrapper });
21
+
22
+ expect(result.current.format).toBe('JodaISO');
23
+ });