@instructure/ui-calendar 11.6.0 → 11.6.1-snapshot-129
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 +36 -286
- package/es/Calendar/{Day → v1/Day}/index.js +2 -2
- package/es/Calendar/{index.js → v1/index.js} +4 -4
- package/es/Calendar/v2/Day/index.js +148 -0
- package/{src/index.ts → es/Calendar/v2/Day/props.js} +2 -4
- package/es/Calendar/v2/Day/styles.js +78 -0
- package/es/Calendar/v2/index.js +407 -0
- package/es/Calendar/v2/props.js +26 -0
- package/es/Calendar/v2/styles.js +66 -0
- package/es/{index.js → exports/a.js} +2 -2
- package/es/exports/b.js +25 -0
- package/lib/Calendar/{Day → v1/Day}/index.js +4 -4
- package/lib/Calendar/{index.js → v1/index.js} +12 -12
- package/lib/Calendar/v2/Day/index.js +155 -0
- package/lib/Calendar/v2/Day/props.js +31 -0
- package/lib/Calendar/v2/Day/styles.js +84 -0
- package/lib/Calendar/v2/index.js +416 -0
- package/lib/Calendar/v2/props.js +31 -0
- package/lib/Calendar/v2/styles.js +72 -0
- package/lib/{index.js → exports/a.js} +3 -3
- package/lib/exports/b.js +19 -0
- package/package.json +45 -23
- package/src/Calendar/{Day → v1/Day}/index.tsx +3 -3
- package/src/Calendar/{Day → v1/Day}/props.ts +1 -1
- package/src/Calendar/{index.tsx → v1/index.tsx} +4 -4
- package/src/Calendar/v2/Day/index.tsx +176 -0
- package/src/Calendar/v2/Day/props.ts +126 -0
- package/src/Calendar/v2/Day/styles.ts +96 -0
- package/src/Calendar/v2/README.md +255 -0
- package/src/Calendar/v2/index.tsx +560 -0
- package/src/Calendar/v2/props.ts +207 -0
- package/src/Calendar/v2/styles.ts +75 -0
- package/src/exports/a.ts +28 -0
- package/src/exports/b.ts +28 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/Calendar/{Day → v1/Day}/index.d.ts +1 -1
- package/types/Calendar/v1/Day/index.d.ts.map +1 -0
- package/types/Calendar/{Day → v1/Day}/props.d.ts +1 -1
- package/types/Calendar/v1/Day/props.d.ts.map +1 -0
- package/types/Calendar/v1/Day/styles.d.ts.map +1 -0
- package/types/Calendar/v1/Day/theme.d.ts.map +1 -0
- package/types/Calendar/{index.d.ts → v1/index.d.ts} +1 -1
- package/types/Calendar/v1/index.d.ts.map +1 -0
- package/types/Calendar/v1/props.d.ts.map +1 -0
- package/types/Calendar/v1/styles.d.ts.map +1 -0
- package/types/Calendar/v1/theme.d.ts.map +1 -0
- package/types/Calendar/v2/Day/index.d.ts +49 -0
- package/types/Calendar/v2/Day/index.d.ts.map +1 -0
- package/types/Calendar/v2/Day/props.d.ts +76 -0
- package/types/Calendar/v2/Day/props.d.ts.map +1 -0
- package/types/Calendar/v2/Day/styles.d.ts +15 -0
- package/types/Calendar/v2/Day/styles.d.ts.map +1 -0
- package/types/Calendar/v2/index.d.ts +84 -0
- package/types/Calendar/v2/index.d.ts.map +1 -0
- package/types/Calendar/v2/props.d.ts +135 -0
- package/types/Calendar/v2/props.d.ts.map +1 -0
- package/types/Calendar/v2/styles.d.ts +13 -0
- package/types/Calendar/v2/styles.d.ts.map +1 -0
- package/types/exports/a.d.ts +5 -0
- package/types/exports/a.d.ts.map +1 -0
- package/types/exports/b.d.ts +5 -0
- package/types/exports/b.d.ts.map +1 -0
- package/types/Calendar/Day/index.d.ts.map +0 -1
- package/types/Calendar/Day/props.d.ts.map +0 -1
- package/types/Calendar/Day/styles.d.ts.map +0 -1
- package/types/Calendar/Day/theme.d.ts.map +0 -1
- package/types/Calendar/index.d.ts.map +0 -1
- package/types/Calendar/props.d.ts.map +0 -1
- package/types/Calendar/styles.d.ts.map +0 -1
- package/types/Calendar/theme.d.ts.map +0 -1
- package/types/index.d.ts +0 -5
- package/types/index.d.ts.map +0 -1
- /package/es/Calendar/{Day → v1/Day}/props.js +0 -0
- /package/es/Calendar/{Day → v1/Day}/styles.js +0 -0
- /package/es/Calendar/{Day → v1/Day}/theme.js +0 -0
- /package/es/Calendar/{props.js → v1/props.js} +0 -0
- /package/es/Calendar/{styles.js → v1/styles.js} +0 -0
- /package/es/Calendar/{theme.js → v1/theme.js} +0 -0
- /package/lib/Calendar/{Day → v1/Day}/props.js +0 -0
- /package/lib/Calendar/{Day → v1/Day}/styles.js +0 -0
- /package/lib/Calendar/{Day → v1/Day}/theme.js +0 -0
- /package/lib/Calendar/{props.js → v1/props.js} +0 -0
- /package/lib/Calendar/{styles.js → v1/styles.js} +0 -0
- /package/lib/Calendar/{theme.js → v1/theme.js} +0 -0
- /package/src/Calendar/{Day → v1/Day}/styles.ts +0 -0
- /package/src/Calendar/{Day → v1/Day}/theme.ts +0 -0
- /package/src/Calendar/{README.md → v1/README.md} +0 -0
- /package/src/Calendar/{props.ts → v1/props.ts} +0 -0
- /package/src/Calendar/{styles.ts → v1/styles.ts} +0 -0
- /package/src/Calendar/{theme.ts → v1/theme.ts} +0 -0
- /package/types/Calendar/{Day → v1/Day}/styles.d.ts +0 -0
- /package/types/Calendar/{Day → v1/Day}/theme.d.ts +0 -0
- /package/types/Calendar/{props.d.ts → v1/props.d.ts} +0 -0
- /package/types/Calendar/{styles.d.ts → v1/styles.d.ts} +0 -0
- /package/types/Calendar/{theme.d.ts → v1/theme.d.ts} +0 -0
|
@@ -29,7 +29,7 @@ import type {
|
|
|
29
29
|
} from '@instructure/shared-types'
|
|
30
30
|
import type { WithStyleProps, ComponentStyle } from '@instructure/emotion'
|
|
31
31
|
import { KeyboardEvent, MouseEvent } from 'react'
|
|
32
|
-
import type { ViewProps } from '@instructure/ui-view'
|
|
32
|
+
import type { ViewProps } from '@instructure/ui-view/v11_6'
|
|
33
33
|
import { Renderable } from '@instructure/shared-types'
|
|
34
34
|
|
|
35
35
|
type CalendarDayOwnProps = {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
import { Children, Component, ReactElement, MouseEvent } from 'react'
|
|
26
26
|
|
|
27
|
-
import { View } from '@instructure/ui-view'
|
|
27
|
+
import { View } from '@instructure/ui-view/v11_6'
|
|
28
28
|
import {
|
|
29
29
|
safeCloneElement,
|
|
30
30
|
callRenderProp,
|
|
@@ -35,7 +35,7 @@ import { createChainedFunction } from '@instructure/ui-utils'
|
|
|
35
35
|
import { logError as error } from '@instructure/console'
|
|
36
36
|
import { AccessibleContent } from '@instructure/ui-a11y-content'
|
|
37
37
|
|
|
38
|
-
import { withStyle } from '@instructure/emotion'
|
|
38
|
+
import { withStyleLegacy as withStyle } from '@instructure/emotion'
|
|
39
39
|
|
|
40
40
|
import { Locale, DateTime, ApplyLocaleContext } from '@instructure/ui-i18n'
|
|
41
41
|
import type { Moment } from '@instructure/ui-i18n'
|
|
@@ -49,13 +49,13 @@ import { allowedProps } from './props'
|
|
|
49
49
|
import type { CalendarProps, CalendarState } from './props'
|
|
50
50
|
import { Renderable } from '@instructure/shared-types'
|
|
51
51
|
|
|
52
|
-
import { IconButton } from '@instructure/ui-buttons'
|
|
52
|
+
import { IconButton } from '@instructure/ui-buttons/v11_6'
|
|
53
53
|
import {
|
|
54
54
|
IconArrowOpenStartSolid,
|
|
55
55
|
IconArrowOpenEndSolid
|
|
56
56
|
} from '@instructure/ui-icons'
|
|
57
57
|
|
|
58
|
-
import { SimpleSelect } from '@instructure/ui-simple-select'
|
|
58
|
+
import { SimpleSelect } from '@instructure/ui-simple-select/v11_6'
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
61
|
---
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The MIT License (MIT)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2015 - present Instructure, Inc.
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { Component, MouseEvent, KeyboardEvent } from 'react'
|
|
26
|
+
|
|
27
|
+
import { View } from '@instructure/ui-view/latest'
|
|
28
|
+
import type { ViewProps } from '@instructure/ui-view/latest'
|
|
29
|
+
import { AccessibleContent } from '@instructure/ui-a11y-content'
|
|
30
|
+
import {
|
|
31
|
+
omitProps,
|
|
32
|
+
callRenderProp,
|
|
33
|
+
getElementType
|
|
34
|
+
} from '@instructure/ui-react-utils'
|
|
35
|
+
|
|
36
|
+
import { withStyle } from '@instructure/emotion'
|
|
37
|
+
|
|
38
|
+
import generateStyle from './styles'
|
|
39
|
+
|
|
40
|
+
import { allowedProps } from './props'
|
|
41
|
+
import type { CalendarDayProps, CalendarDayStyleProps } from './props'
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
---
|
|
45
|
+
parent: Calendar
|
|
46
|
+
id: Calendar.Day
|
|
47
|
+
---
|
|
48
|
+
**/
|
|
49
|
+
@withStyle(generateStyle)
|
|
50
|
+
class Day extends Component<CalendarDayProps> {
|
|
51
|
+
static readonly componentId = 'Calendar.Day'
|
|
52
|
+
|
|
53
|
+
static allowedProps = allowedProps
|
|
54
|
+
static defaultProps = {
|
|
55
|
+
interaction: 'enabled',
|
|
56
|
+
isSelected: false,
|
|
57
|
+
isToday: false,
|
|
58
|
+
isOutsideMonth: false
|
|
59
|
+
} as const
|
|
60
|
+
|
|
61
|
+
ref: Element | null = null
|
|
62
|
+
|
|
63
|
+
componentDidMount() {
|
|
64
|
+
this.props.makeStyles?.(this.makeStylesVariables)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
componentDidUpdate() {
|
|
68
|
+
this.props.makeStyles?.(this.makeStylesVariables)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get makeStylesVariables(): CalendarDayStyleProps {
|
|
72
|
+
return { isDisabled: this.isDisabled }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get isDisabled() {
|
|
76
|
+
const { interaction } = this.props
|
|
77
|
+
return interaction === 'disabled'
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get elementType() {
|
|
81
|
+
const { as } = this.props
|
|
82
|
+
return as || getElementType(Day, this.props)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
shouldApplyAriaSelected() {
|
|
86
|
+
const { role } = this.props
|
|
87
|
+
return !!role && ['option', 'gridcell'].indexOf(role) > -1
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
handleClick = (event: MouseEvent<ViewProps & Element>) => {
|
|
91
|
+
const { onClick, date } = this.props
|
|
92
|
+
if (typeof onClick === 'function') {
|
|
93
|
+
onClick(event, { date })
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
handleKeyDown = (event: KeyboardEvent<ViewProps & Element>) => {
|
|
98
|
+
const { onKeyDown, date } = this.props
|
|
99
|
+
if (typeof onKeyDown === 'function') {
|
|
100
|
+
onKeyDown(event, { date })
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
handleElementRef = (el: Element | null) => {
|
|
105
|
+
const { elementRef } = this.props
|
|
106
|
+
this.ref = el
|
|
107
|
+
if (typeof elementRef === 'function') {
|
|
108
|
+
elementRef(el)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
render() {
|
|
113
|
+
const {
|
|
114
|
+
children,
|
|
115
|
+
label,
|
|
116
|
+
interaction,
|
|
117
|
+
isOutsideMonth,
|
|
118
|
+
isSelected,
|
|
119
|
+
isToday,
|
|
120
|
+
onClick,
|
|
121
|
+
onKeyDown,
|
|
122
|
+
as,
|
|
123
|
+
styles,
|
|
124
|
+
...props
|
|
125
|
+
} = this.props
|
|
126
|
+
|
|
127
|
+
const { elementType, isDisabled } = this
|
|
128
|
+
|
|
129
|
+
const passthroughProps = View.omitViewProps(
|
|
130
|
+
omitProps(props, Day.allowedProps),
|
|
131
|
+
Day
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<View
|
|
136
|
+
{...passthroughProps}
|
|
137
|
+
as={elementType}
|
|
138
|
+
css={styles?.calendarDay}
|
|
139
|
+
display="inline-block"
|
|
140
|
+
margin="xxx-small"
|
|
141
|
+
borderWidth="none"
|
|
142
|
+
borderColor="transparent"
|
|
143
|
+
background="transparent"
|
|
144
|
+
cursor={
|
|
145
|
+
elementType === 'button' || elementType === 'a'
|
|
146
|
+
? isDisabled
|
|
147
|
+
? 'not-allowed'
|
|
148
|
+
: 'pointer'
|
|
149
|
+
: 'auto'
|
|
150
|
+
}
|
|
151
|
+
disabled={isDisabled}
|
|
152
|
+
aria-current={isToday ? 'date' : undefined}
|
|
153
|
+
aria-selected={
|
|
154
|
+
this.shouldApplyAriaSelected()
|
|
155
|
+
? isSelected
|
|
156
|
+
? 'true'
|
|
157
|
+
: 'false'
|
|
158
|
+
: undefined
|
|
159
|
+
}
|
|
160
|
+
onClick={onClick && this.handleClick}
|
|
161
|
+
onKeyDown={onKeyDown && this.handleKeyDown}
|
|
162
|
+
elementRef={this.handleElementRef}
|
|
163
|
+
data-cid="Calendar.Day"
|
|
164
|
+
>
|
|
165
|
+
<span css={styles?.day}>
|
|
166
|
+
<AccessibleContent alt={label}>
|
|
167
|
+
{callRenderProp(children)}
|
|
168
|
+
</AccessibleContent>
|
|
169
|
+
</span>
|
|
170
|
+
</View>
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export default Day
|
|
176
|
+
export { Day }
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The MIT License (MIT)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2015 - present Instructure, Inc.
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import type {
|
|
26
|
+
AsElementType,
|
|
27
|
+
CalendarDayTheme,
|
|
28
|
+
OtherHTMLAttributes
|
|
29
|
+
} from '@instructure/shared-types'
|
|
30
|
+
import type { WithStyleProps, ComponentStyle } from '@instructure/emotion'
|
|
31
|
+
import { KeyboardEvent, MouseEvent } from 'react'
|
|
32
|
+
import type { ViewProps } from '@instructure/ui-view/latest'
|
|
33
|
+
import { Renderable } from '@instructure/shared-types'
|
|
34
|
+
|
|
35
|
+
type CalendarDayOwnProps = {
|
|
36
|
+
/**
|
|
37
|
+
* The rendered representation of the corresponding date.
|
|
38
|
+
*/
|
|
39
|
+
children?: Renderable
|
|
40
|
+
/**
|
|
41
|
+
* An ISO 8601 formatted string representing the date corresponding to
|
|
42
|
+
* this `<Calendar.Day />`
|
|
43
|
+
*/
|
|
44
|
+
date: string
|
|
45
|
+
/**
|
|
46
|
+
* Accessible label to provide more context for the date to assistive
|
|
47
|
+
* technologies. This should consist of more than just a numerical date value.
|
|
48
|
+
* It should also include the month and the year. Ex. instead of just `1`,
|
|
49
|
+
* provide `1 August 2019`.
|
|
50
|
+
*/
|
|
51
|
+
label: string
|
|
52
|
+
/**
|
|
53
|
+
* Is the `<Calendar.Day />` disabled
|
|
54
|
+
*/
|
|
55
|
+
interaction?: 'enabled' | 'disabled'
|
|
56
|
+
/**
|
|
57
|
+
* Is the `<Calendar.Day />` selected
|
|
58
|
+
*/
|
|
59
|
+
isSelected?: boolean
|
|
60
|
+
/**
|
|
61
|
+
* Is the `<Calendar.Day />` today
|
|
62
|
+
*/
|
|
63
|
+
isToday?: boolean
|
|
64
|
+
/**
|
|
65
|
+
* Is the `<Calendar.Day />` located outside the current rendered month
|
|
66
|
+
*/
|
|
67
|
+
isOutsideMonth?: boolean
|
|
68
|
+
/**
|
|
69
|
+
* Callback fired on click.
|
|
70
|
+
* @param {Object} event - the click event
|
|
71
|
+
* @param {Object} data - additional data
|
|
72
|
+
* @param data.date - the date of the corresponding `<Calendar.Day />`
|
|
73
|
+
*/
|
|
74
|
+
onClick?: (
|
|
75
|
+
event: MouseEvent<ViewProps & Element>,
|
|
76
|
+
date: { date: string }
|
|
77
|
+
) => void
|
|
78
|
+
/**
|
|
79
|
+
* Callback fired on key down.
|
|
80
|
+
* @param {Object} event - the key down event
|
|
81
|
+
* @param {Object} data - additional data
|
|
82
|
+
* @param data.date - the date of the corresponding `<Calendar.Day />`
|
|
83
|
+
*/
|
|
84
|
+
onKeyDown?: (
|
|
85
|
+
event: KeyboardEvent<ViewProps & Element>,
|
|
86
|
+
data: { date: string }
|
|
87
|
+
) => void
|
|
88
|
+
/**
|
|
89
|
+
* A ref function for the underlying DOM element.
|
|
90
|
+
*/
|
|
91
|
+
elementRef?: (element: Element | null) => void
|
|
92
|
+
/**
|
|
93
|
+
* the element type to render as
|
|
94
|
+
*/
|
|
95
|
+
as?: AsElementType
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
type CalendarDayStyleProps = {
|
|
99
|
+
isDisabled: boolean
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
type PropKeys = keyof CalendarDayOwnProps
|
|
103
|
+
|
|
104
|
+
type AllowedPropKeys = Readonly<Array<PropKeys>>
|
|
105
|
+
|
|
106
|
+
type CalendarDayProps = CalendarDayOwnProps &
|
|
107
|
+
WithStyleProps<CalendarDayTheme, CalendarDayStyle> &
|
|
108
|
+
OtherHTMLAttributes<CalendarDayOwnProps>
|
|
109
|
+
|
|
110
|
+
type CalendarDayStyle = ComponentStyle<'calendarDay' | 'day'>
|
|
111
|
+
const allowedProps: AllowedPropKeys = [
|
|
112
|
+
'children',
|
|
113
|
+
'date',
|
|
114
|
+
'label',
|
|
115
|
+
'interaction',
|
|
116
|
+
'isSelected',
|
|
117
|
+
'isToday',
|
|
118
|
+
'isOutsideMonth',
|
|
119
|
+
'onClick',
|
|
120
|
+
'onKeyDown',
|
|
121
|
+
'elementRef',
|
|
122
|
+
'as'
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
export type { CalendarDayProps, CalendarDayStyleProps, CalendarDayStyle }
|
|
126
|
+
export { allowedProps }
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The MIT License (MIT)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2015 - present Instructure, Inc.
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import type { NewComponentTypes, SharedTokens } from '@instructure/ui-themes'
|
|
26
|
+
import type {
|
|
27
|
+
CalendarDayProps,
|
|
28
|
+
CalendarDayStyleProps,
|
|
29
|
+
CalendarDayStyle
|
|
30
|
+
} from './props'
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* ---
|
|
34
|
+
* private: true
|
|
35
|
+
* ---
|
|
36
|
+
* Generates the style object from the theme and provided additional information
|
|
37
|
+
* @param {Object} componentTheme The theme variable object.
|
|
38
|
+
* @param {Object} props the props of the component, the style is applied to
|
|
39
|
+
* @param {Object} state the state of the component, the style is applied to
|
|
40
|
+
* @return {Object} The final style object, which will be used in the component
|
|
41
|
+
*/
|
|
42
|
+
const generateStyle = (
|
|
43
|
+
componentTheme: NewComponentTypes['CalendarDay'],
|
|
44
|
+
props: CalendarDayProps,
|
|
45
|
+
_sharedTokens: SharedTokens,
|
|
46
|
+
state: CalendarDayStyleProps
|
|
47
|
+
): CalendarDayStyle => {
|
|
48
|
+
const { isOutsideMonth, isSelected, isToday } = props
|
|
49
|
+
const { isDisabled } = state
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
calendarDay: {
|
|
53
|
+
label: 'calendarDay',
|
|
54
|
+
padding: 0
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
day: {
|
|
58
|
+
label: 'calendarDay__day',
|
|
59
|
+
display: 'flex',
|
|
60
|
+
alignItems: 'center',
|
|
61
|
+
justifyContent: 'center',
|
|
62
|
+
background: componentTheme.background,
|
|
63
|
+
color: componentTheme.color,
|
|
64
|
+
fontSize: componentTheme.fontSize,
|
|
65
|
+
textDecoration: 'none',
|
|
66
|
+
lineHeight: 1,
|
|
67
|
+
height: componentTheme.height,
|
|
68
|
+
minWidth: componentTheme.minWidth,
|
|
69
|
+
border: 'none',
|
|
70
|
+
margin: 0,
|
|
71
|
+
|
|
72
|
+
...(isOutsideMonth && {
|
|
73
|
+
color: componentTheme.outsideMonthColor
|
|
74
|
+
}),
|
|
75
|
+
|
|
76
|
+
...(isSelected && {
|
|
77
|
+
background: componentTheme.selectedBackground,
|
|
78
|
+
borderRadius: componentTheme.selectedBorderRadius,
|
|
79
|
+
color: componentTheme.selectedColor
|
|
80
|
+
}),
|
|
81
|
+
|
|
82
|
+
...(isToday &&
|
|
83
|
+
!isSelected && {
|
|
84
|
+
background: componentTheme.todayBackground,
|
|
85
|
+
borderRadius: componentTheme.todayBorderRadius,
|
|
86
|
+
color: componentTheme.todayColor
|
|
87
|
+
}),
|
|
88
|
+
|
|
89
|
+
...(isDisabled && {
|
|
90
|
+
opacity: 0.5
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default generateStyle
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
---
|
|
2
|
+
describes: Calendar
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
The `Calendar` component provides a visual interface for date data.
|
|
6
|
+
|
|
7
|
+
### Default config
|
|
8
|
+
|
|
9
|
+
For ease of use in most situations, the `Calendar` component provides a default
|
|
10
|
+
configuration. The default configuration can be overridden by providing props
|
|
11
|
+
to the `Calendar` component.
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
---
|
|
15
|
+
type: example
|
|
16
|
+
---
|
|
17
|
+
<Calendar/>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Default config with additional props
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
---
|
|
24
|
+
type: example
|
|
25
|
+
---
|
|
26
|
+
const Example = () => {
|
|
27
|
+
const [selectedDate, setSelectedDate] = useState('')
|
|
28
|
+
const [visibleMonth, setVisibleMonth] = useState('2025-05')
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Calendar
|
|
32
|
+
visibleMonth={visibleMonth}
|
|
33
|
+
currentDate="2023-12-15"
|
|
34
|
+
disabledDates={['2023-12-22', '2023-12-12', '2023-12-11']}
|
|
35
|
+
selectedDate={selectedDate}
|
|
36
|
+
onRequestRenderNextMonth={(_e, requestedMonth) =>
|
|
37
|
+
setVisibleMonth(requestedMonth)
|
|
38
|
+
}
|
|
39
|
+
onRequestRenderPrevMonth={(_e, requestedMonth) =>
|
|
40
|
+
setVisibleMonth(requestedMonth)
|
|
41
|
+
}
|
|
42
|
+
onDateSelected={(date) => {
|
|
43
|
+
setSelectedDate(date)
|
|
44
|
+
}}
|
|
45
|
+
/>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
render(<Example />)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### With year picker
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
---
|
|
55
|
+
type: example
|
|
56
|
+
---
|
|
57
|
+
const Example = () => {
|
|
58
|
+
const [selectedDate, setSelectedDate] = useState('')
|
|
59
|
+
const [visibleMonth, setVisibleMonth] = useState('2024-02')
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<Calendar
|
|
63
|
+
visibleMonth={visibleMonth}
|
|
64
|
+
currentDate="2024-02-29"
|
|
65
|
+
disabledDates={['2023-12-22', '2023-12-12', '2023-12-11']}
|
|
66
|
+
selectedDate={selectedDate}
|
|
67
|
+
onRequestRenderNextMonth={(_e, requestedMonth) =>
|
|
68
|
+
setVisibleMonth(requestedMonth)
|
|
69
|
+
}
|
|
70
|
+
onRequestRenderPrevMonth={(_e, requestedMonth) =>
|
|
71
|
+
setVisibleMonth(requestedMonth)
|
|
72
|
+
}
|
|
73
|
+
onDateSelected={(date) => {
|
|
74
|
+
setSelectedDate(date)
|
|
75
|
+
}}
|
|
76
|
+
withYearPicker={{
|
|
77
|
+
screenReaderLabel: 'Year picker',
|
|
78
|
+
startYear: 1999,
|
|
79
|
+
endYear: 2024,
|
|
80
|
+
maxHeight: '200px'
|
|
81
|
+
}}
|
|
82
|
+
/>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
render(<Example />)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Composing a Calendar in your Application
|
|
89
|
+
|
|
90
|
+
By design, the `Calendar` component does not dictate which date libraries or
|
|
91
|
+
formats you use in your application. The following example demonstrates how a
|
|
92
|
+
basic `Calendar` might be created using utilities from
|
|
93
|
+
[Moment.js](https://momentjs.com/docs/#/parsing/).
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
---
|
|
97
|
+
type: example
|
|
98
|
+
---
|
|
99
|
+
const Example = () => {
|
|
100
|
+
const [renderedDate, setRenderedDate] = useState(
|
|
101
|
+
parseDate('2019-08-02').toISOString()
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const todayDate = parseDate('2019-08-16').toISOString()
|
|
105
|
+
const generateMonth = () => {
|
|
106
|
+
const date = parseDate(renderedDate).startOf('month').startOf('week')
|
|
107
|
+
|
|
108
|
+
return Array.apply(null, Array(Calendar.DAY_COUNT)).map(() => {
|
|
109
|
+
const currentDate = date.clone()
|
|
110
|
+
date.add({ days: 1 })
|
|
111
|
+
|
|
112
|
+
// This workaround is needed because moment's `.add({days: 1})` function has a bug that happens when the date added lands perfectly onto the DST cutoff,
|
|
113
|
+
// in these cases adding 1 day results in 23 hours added instead,
|
|
114
|
+
// so `moment.tz('2024-09-07T00:00:00', 'America/Santiago').add({days: 1})` results
|
|
115
|
+
// in "Sat Sep 07 2024 23:00:00 GMT-0400" instead of "Sun Sep 08 2024 00:00:00 GMT-0400".
|
|
116
|
+
// which would cause duplicate dates in the calendar.
|
|
117
|
+
// More info on the bug: https://github.com/moment/moment/issues/4743
|
|
118
|
+
// Please note that this causes one hour of time difference in the affected timezones/dates and to
|
|
119
|
+
// fully solve this bug we need to change to something like luxon which handles this properly
|
|
120
|
+
if (currentDate.clone().format('HH') === '23') {
|
|
121
|
+
return currentDate.clone().add({ hours: 1 })
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return currentDate.clone()
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const renderWeekdayLabels = () => {
|
|
129
|
+
const date = parseDate(renderedDate).startOf('week')
|
|
130
|
+
|
|
131
|
+
return Array.apply(null, Array(7)).map(() => {
|
|
132
|
+
const currentDate = date.clone()
|
|
133
|
+
date.add(1, 'day')
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<AccessibleContent alt={currentDate.format('dddd')}>
|
|
137
|
+
{currentDate.format('dd')}
|
|
138
|
+
</AccessibleContent>
|
|
139
|
+
)
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const handleRenderNextMonth = (event) => {
|
|
144
|
+
modifyRenderedMonth(1)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const handleRenderPrevMonth = (event) => {
|
|
148
|
+
modifyRenderedMonth(-1)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const modifyRenderedMonth = (step) => {
|
|
152
|
+
const date = parseDate(renderedDate)
|
|
153
|
+
date.add(step, 'month')
|
|
154
|
+
setRenderedDate(date.toISOString())
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const renderDay = (date) => {
|
|
158
|
+
return (
|
|
159
|
+
<Calendar.Day
|
|
160
|
+
key={date.toISOString()}
|
|
161
|
+
date={date.toISOString()}
|
|
162
|
+
isOutsideMonth={!date.isSame(renderedDate, 'month')}
|
|
163
|
+
isToday={date.isSame(todayDate, 'day')}
|
|
164
|
+
label={`${date.format('D')} ${date.format('MMMM')} ${date.format(
|
|
165
|
+
'YYYY'
|
|
166
|
+
)}`}
|
|
167
|
+
>
|
|
168
|
+
{date.format('D')}
|
|
169
|
+
</Calendar.Day>
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const date = parseDate(renderedDate)
|
|
174
|
+
|
|
175
|
+
const buttonProps = (type = 'prev') => ({
|
|
176
|
+
size: 'small',
|
|
177
|
+
withBackground: false,
|
|
178
|
+
withBorder: false,
|
|
179
|
+
renderIcon:
|
|
180
|
+
type === 'prev' ? (
|
|
181
|
+
<ChevronLeftInstUIIcon color="baseColor" />
|
|
182
|
+
) : (
|
|
183
|
+
<ChevronRightInstUIIcon color="baseColor" />
|
|
184
|
+
),
|
|
185
|
+
screenReaderLabel: type === 'prev' ? 'Previous month' : 'Next month'
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<Calendar
|
|
190
|
+
renderPrevMonthButton={<IconButton {...buttonProps('prev')} />}
|
|
191
|
+
renderNextMonthButton={<IconButton {...buttonProps('next')} />}
|
|
192
|
+
renderNavigationLabel={
|
|
193
|
+
<span>
|
|
194
|
+
<div>{date.format('MMMM')}</div>
|
|
195
|
+
<div>{date.format('YYYY')}</div>
|
|
196
|
+
</span>
|
|
197
|
+
}
|
|
198
|
+
renderWeekdayLabels={renderWeekdayLabels()}
|
|
199
|
+
onRequestRenderNextMonth={handleRenderNextMonth}
|
|
200
|
+
onRequestRenderPrevMonth={handleRenderPrevMonth}
|
|
201
|
+
>
|
|
202
|
+
{generateMonth().map((date) => renderDay(date))}
|
|
203
|
+
</Calendar>
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const locale = 'en-us'
|
|
208
|
+
const timezone = 'America/Denver'
|
|
209
|
+
|
|
210
|
+
const parseDate = (dateStr) => {
|
|
211
|
+
return moment.tz(dateStr, [moment.ISO_8601], locale, timezone)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
render(<Example />)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### Some dates to keep track of
|
|
218
|
+
|
|
219
|
+
- `todayDate` - the date that represents today
|
|
220
|
+
- `renderedDate` - the date that the user is viewing as they navigate the `Calendar`
|
|
221
|
+
|
|
222
|
+
#### Generating a month
|
|
223
|
+
|
|
224
|
+
We generate a month based on the `renderedDate` value. The `Calendar` always
|
|
225
|
+
displays 6 weeks or 42 days (42 is defined as a constant `Calendar.DAY_COUNT`),
|
|
226
|
+
so we pad our month values with days from the previous and next month if
|
|
227
|
+
necessary. The complete implementation can be seen in the `generateMonth` function
|
|
228
|
+
in our example.
|
|
229
|
+
|
|
230
|
+
#### Rendering days
|
|
231
|
+
|
|
232
|
+
Using the month data, we can now map it to children of type `Calendar.Day`.
|
|
233
|
+
As we render each day, if it is outside the current month we can set the
|
|
234
|
+
`isOutsideMonth` prop. We can also set the `isToday` prop if it is the current
|
|
235
|
+
date. For accessibility, it is recommended that you provide more information to
|
|
236
|
+
each `Calendar.Day` using the label prop. This label will help screen readers to
|
|
237
|
+
have important context as the `Calendar` is navigated. It should include the day,
|
|
238
|
+
month, and the year (Ex. instead of `1` we would provide `1 August 2019`).
|
|
239
|
+
|
|
240
|
+
#### Rendering weekday labels
|
|
241
|
+
|
|
242
|
+
`Calendar` requires you to provide an array of 7 labels that correspond to each
|
|
243
|
+
day of the week via the `renderWeekdayLabels` prop. The visible portion of the
|
|
244
|
+
label should be abbreviated (no longer than three characters). Note that screen
|
|
245
|
+
readers will read this content preceding each date as the `Calendar` is navigated.
|
|
246
|
+
Consider using [AccessibleContent](AccessibleContent) with the `alt` prop
|
|
247
|
+
containing the full day name for assistive technologies and the children containing
|
|
248
|
+
the abbreviation. ex. `[<AccessibleContent alt="Sunday">Sun</AccessibleContent>, ...]`
|
|
249
|
+
|
|
250
|
+
#### Rendering next and previous month buttons
|
|
251
|
+
|
|
252
|
+
The `renderNextMonthButton` and `renderPrevMonthButton` can be supplied using the
|
|
253
|
+
[IconButton](IconButton) component with the `size` prop set to
|
|
254
|
+
`small`, the `withBackground` and `withBorder` props both set to `false`, and the `renderIcon` prop set to `ChevronLeftInstUIIcon` or
|
|
255
|
+
`ChevronRightInstUIIcon`.
|