@instructure/ui-menu 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.
Files changed (180) hide show
  1. package/CHANGELOG.md +41 -297
  2. package/es/Menu/{MenuItem → v1/MenuItem}/index.js +2 -2
  3. package/es/Menu/{MenuItemGroup → v1/MenuItemGroup}/index.js +1 -1
  4. package/es/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/index.js +1 -1
  5. package/es/Menu/{index.js → v1/index.js} +3 -3
  6. package/es/Menu/v2/MenuItem/index.js +262 -0
  7. package/es/Menu/v2/MenuItem/props.js +26 -0
  8. package/es/Menu/v2/MenuItem/styles.js +146 -0
  9. package/es/Menu/v2/MenuItemGroup/index.js +175 -0
  10. package/es/Menu/v2/MenuItemGroup/props.js +26 -0
  11. package/es/Menu/v2/MenuItemGroup/styles.js +60 -0
  12. package/es/Menu/v2/MenuItemSeparator/index.js +70 -0
  13. package/es/Menu/v2/MenuItemSeparator/props.js +29 -0
  14. package/es/Menu/v2/MenuItemSeparator/styles.js +46 -0
  15. package/es/Menu/v2/index.js +405 -0
  16. package/es/Menu/v2/props.js +26 -0
  17. package/es/Menu/v2/styles.js +61 -0
  18. package/es/{index.js → exports/a.js} +1 -1
  19. package/es/exports/b.js +24 -0
  20. package/es/{MenuContext.js → utils/v1/MenuContext.js} +2 -0
  21. package/lib/Menu/{MenuItem → v1/MenuItem}/index.js +4 -4
  22. package/lib/Menu/{MenuItemGroup → v1/MenuItemGroup}/index.js +1 -1
  23. package/lib/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/index.js +1 -1
  24. package/lib/Menu/v1/index.js +432 -0
  25. package/lib/Menu/v2/MenuItem/index.js +271 -0
  26. package/lib/Menu/v2/MenuItem/props.js +31 -0
  27. package/lib/Menu/v2/MenuItem/styles.js +152 -0
  28. package/lib/Menu/v2/MenuItemGroup/index.js +183 -0
  29. package/lib/Menu/v2/MenuItemGroup/props.js +31 -0
  30. package/lib/Menu/v2/MenuItemGroup/styles.js +66 -0
  31. package/lib/Menu/v2/MenuItemSeparator/index.js +75 -0
  32. package/lib/Menu/v2/MenuItemSeparator/props.js +34 -0
  33. package/lib/Menu/v2/MenuItemSeparator/styles.js +52 -0
  34. package/lib/Menu/{index.js → v2/index.js} +4 -5
  35. package/lib/Menu/v2/props.js +31 -0
  36. package/lib/Menu/v2/styles.js +66 -0
  37. package/lib/{index.js → exports/a.js} +5 -5
  38. package/lib/exports/b.js +30 -0
  39. package/lib/{MenuContext.js → utils/v1/MenuContext.js} +1 -0
  40. package/package.json +45 -23
  41. package/src/Menu/{MenuItem → v1/MenuItem}/index.tsx +2 -2
  42. package/src/Menu/{MenuItemGroup → v1/MenuItemGroup}/index.tsx +1 -1
  43. package/src/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/index.tsx +1 -1
  44. package/src/Menu/{index.tsx → v1/index.tsx} +3 -3
  45. package/src/Menu/{props.ts → v1/props.ts} +1 -1
  46. package/src/Menu/v2/MenuItem/index.tsx +318 -0
  47. package/src/Menu/v2/MenuItem/props.ts +132 -0
  48. package/src/Menu/v2/MenuItem/styles.ts +172 -0
  49. package/src/Menu/v2/MenuItemGroup/index.tsx +245 -0
  50. package/src/Menu/v2/MenuItemGroup/props.ts +105 -0
  51. package/src/Menu/v2/MenuItemGroup/styles.ts +66 -0
  52. package/src/Menu/v2/MenuItemSeparator/index.tsx +79 -0
  53. package/src/Menu/v2/MenuItemSeparator/props.ts +48 -0
  54. package/src/Menu/v2/MenuItemSeparator/styles.ts +52 -0
  55. package/src/Menu/v2/README.md +104 -0
  56. package/src/Menu/v2/index.tsx +514 -0
  57. package/src/Menu/v2/props.ts +213 -0
  58. package/src/Menu/v2/styles.ts +68 -0
  59. package/src/{index.ts → exports/a.ts} +5 -5
  60. package/src/exports/b.ts +29 -0
  61. package/src/{MenuContext.ts → utils/v1/MenuContext.ts} +3 -3
  62. package/tsconfig.build.tsbuildinfo +1 -1
  63. package/types/Menu/{MenuItem → v1/MenuItem}/index.d.ts +3 -3
  64. package/types/Menu/v1/MenuItem/index.d.ts.map +1 -0
  65. package/types/Menu/v1/MenuItem/props.d.ts.map +1 -0
  66. package/types/Menu/v1/MenuItem/styles.d.ts.map +1 -0
  67. package/types/Menu/v1/MenuItem/theme.d.ts.map +1 -0
  68. package/types/Menu/v1/MenuItemGroup/index.d.ts.map +1 -0
  69. package/types/Menu/v1/MenuItemGroup/props.d.ts.map +1 -0
  70. package/types/Menu/v1/MenuItemGroup/styles.d.ts.map +1 -0
  71. package/types/Menu/v1/MenuItemGroup/theme.d.ts.map +1 -0
  72. package/types/Menu/v1/MenuItemSeparator/index.d.ts.map +1 -0
  73. package/types/Menu/v1/MenuItemSeparator/props.d.ts.map +1 -0
  74. package/types/Menu/v1/MenuItemSeparator/styles.d.ts.map +1 -0
  75. package/types/Menu/v1/MenuItemSeparator/theme.d.ts.map +1 -0
  76. package/types/Menu/{index.d.ts → v1/index.d.ts} +3 -3
  77. package/types/Menu/v1/index.d.ts.map +1 -0
  78. package/types/Menu/{props.d.ts → v1/props.d.ts} +1 -1
  79. package/types/Menu/v1/props.d.ts.map +1 -0
  80. package/types/Menu/v1/styles.d.ts.map +1 -0
  81. package/types/Menu/v1/theme.d.ts.map +1 -0
  82. package/types/Menu/v2/MenuItem/index.d.ts +66 -0
  83. package/types/Menu/v2/MenuItem/index.d.ts.map +1 -0
  84. package/types/Menu/v2/MenuItem/props.d.ts +73 -0
  85. package/types/Menu/v2/MenuItem/props.d.ts.map +1 -0
  86. package/types/Menu/v2/MenuItem/styles.d.ts +15 -0
  87. package/types/Menu/v2/MenuItem/styles.d.ts.map +1 -0
  88. package/types/Menu/v2/MenuItemGroup/index.d.ts +52 -0
  89. package/types/Menu/v2/MenuItemGroup/index.d.ts.map +1 -0
  90. package/types/Menu/v2/MenuItemGroup/props.d.ts +51 -0
  91. package/types/Menu/v2/MenuItemGroup/props.d.ts.map +1 -0
  92. package/types/Menu/v2/MenuItemGroup/styles.d.ts +15 -0
  93. package/types/Menu/v2/MenuItemGroup/styles.d.ts.map +1 -0
  94. package/types/Menu/v2/MenuItemSeparator/index.d.ts +21 -0
  95. package/types/Menu/v2/MenuItemSeparator/index.d.ts.map +1 -0
  96. package/types/Menu/v2/MenuItemSeparator/props.d.ts +11 -0
  97. package/types/Menu/v2/MenuItemSeparator/props.d.ts.map +1 -0
  98. package/types/Menu/v2/MenuItemSeparator/styles.d.ts +15 -0
  99. package/types/Menu/v2/MenuItemSeparator/styles.d.ts.map +1 -0
  100. package/types/Menu/v2/index.d.ts +118 -0
  101. package/types/Menu/v2/index.d.ts.map +1 -0
  102. package/types/Menu/v2/props.d.ts +138 -0
  103. package/types/Menu/v2/props.d.ts.map +1 -0
  104. package/types/Menu/v2/styles.d.ts +15 -0
  105. package/types/Menu/v2/styles.d.ts.map +1 -0
  106. package/types/exports/a.d.ts +6 -0
  107. package/types/exports/a.d.ts.map +1 -0
  108. package/types/exports/b.d.ts +6 -0
  109. package/types/exports/b.d.ts.map +1 -0
  110. package/types/utils/v1/MenuContext.d.ts +13 -0
  111. package/types/utils/v1/MenuContext.d.ts.map +1 -0
  112. package/types/Menu/MenuItem/index.d.ts.map +0 -1
  113. package/types/Menu/MenuItem/props.d.ts.map +0 -1
  114. package/types/Menu/MenuItem/styles.d.ts.map +0 -1
  115. package/types/Menu/MenuItem/theme.d.ts.map +0 -1
  116. package/types/Menu/MenuItemGroup/index.d.ts.map +0 -1
  117. package/types/Menu/MenuItemGroup/props.d.ts.map +0 -1
  118. package/types/Menu/MenuItemGroup/styles.d.ts.map +0 -1
  119. package/types/Menu/MenuItemGroup/theme.d.ts.map +0 -1
  120. package/types/Menu/MenuItemSeparator/index.d.ts.map +0 -1
  121. package/types/Menu/MenuItemSeparator/props.d.ts.map +0 -1
  122. package/types/Menu/MenuItemSeparator/styles.d.ts.map +0 -1
  123. package/types/Menu/MenuItemSeparator/theme.d.ts.map +0 -1
  124. package/types/Menu/index.d.ts.map +0 -1
  125. package/types/Menu/props.d.ts.map +0 -1
  126. package/types/Menu/styles.d.ts.map +0 -1
  127. package/types/Menu/theme.d.ts.map +0 -1
  128. package/types/MenuContext.d.ts +0 -14
  129. package/types/MenuContext.d.ts.map +0 -1
  130. package/types/index.d.ts +0 -6
  131. package/types/index.d.ts.map +0 -1
  132. /package/es/Menu/{MenuItem → v1/MenuItem}/props.js +0 -0
  133. /package/es/Menu/{MenuItem → v1/MenuItem}/styles.js +0 -0
  134. /package/es/Menu/{MenuItem → v1/MenuItem}/theme.js +0 -0
  135. /package/es/Menu/{MenuItemGroup → v1/MenuItemGroup}/props.js +0 -0
  136. /package/es/Menu/{MenuItemGroup → v1/MenuItemGroup}/styles.js +0 -0
  137. /package/es/Menu/{MenuItemGroup → v1/MenuItemGroup}/theme.js +0 -0
  138. /package/es/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/props.js +0 -0
  139. /package/es/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/styles.js +0 -0
  140. /package/es/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/theme.js +0 -0
  141. /package/es/Menu/{props.js → v1/props.js} +0 -0
  142. /package/es/Menu/{styles.js → v1/styles.js} +0 -0
  143. /package/es/Menu/{theme.js → v1/theme.js} +0 -0
  144. /package/lib/Menu/{MenuItem → v1/MenuItem}/props.js +0 -0
  145. /package/lib/Menu/{MenuItem → v1/MenuItem}/styles.js +0 -0
  146. /package/lib/Menu/{MenuItem → v1/MenuItem}/theme.js +0 -0
  147. /package/lib/Menu/{MenuItemGroup → v1/MenuItemGroup}/props.js +0 -0
  148. /package/lib/Menu/{MenuItemGroup → v1/MenuItemGroup}/styles.js +0 -0
  149. /package/lib/Menu/{MenuItemGroup → v1/MenuItemGroup}/theme.js +0 -0
  150. /package/lib/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/props.js +0 -0
  151. /package/lib/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/styles.js +0 -0
  152. /package/lib/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/theme.js +0 -0
  153. /package/lib/Menu/{props.js → v1/props.js} +0 -0
  154. /package/lib/Menu/{styles.js → v1/styles.js} +0 -0
  155. /package/lib/Menu/{theme.js → v1/theme.js} +0 -0
  156. /package/src/Menu/{MenuItem → v1/MenuItem}/props.ts +0 -0
  157. /package/src/Menu/{MenuItem → v1/MenuItem}/styles.ts +0 -0
  158. /package/src/Menu/{MenuItem → v1/MenuItem}/theme.ts +0 -0
  159. /package/src/Menu/{MenuItemGroup → v1/MenuItemGroup}/props.ts +0 -0
  160. /package/src/Menu/{MenuItemGroup → v1/MenuItemGroup}/styles.ts +0 -0
  161. /package/src/Menu/{MenuItemGroup → v1/MenuItemGroup}/theme.ts +0 -0
  162. /package/src/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/props.ts +0 -0
  163. /package/src/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/styles.ts +0 -0
  164. /package/src/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/theme.ts +0 -0
  165. /package/src/Menu/{README.md → v1/README.md} +0 -0
  166. /package/src/Menu/{styles.ts → v1/styles.ts} +0 -0
  167. /package/src/Menu/{theme.ts → v1/theme.ts} +0 -0
  168. /package/types/Menu/{MenuItem → v1/MenuItem}/props.d.ts +0 -0
  169. /package/types/Menu/{MenuItem → v1/MenuItem}/styles.d.ts +0 -0
  170. /package/types/Menu/{MenuItem → v1/MenuItem}/theme.d.ts +0 -0
  171. /package/types/Menu/{MenuItemGroup → v1/MenuItemGroup}/index.d.ts +0 -0
  172. /package/types/Menu/{MenuItemGroup → v1/MenuItemGroup}/props.d.ts +0 -0
  173. /package/types/Menu/{MenuItemGroup → v1/MenuItemGroup}/styles.d.ts +0 -0
  174. /package/types/Menu/{MenuItemGroup → v1/MenuItemGroup}/theme.d.ts +0 -0
  175. /package/types/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/index.d.ts +0 -0
  176. /package/types/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/props.d.ts +0 -0
  177. /package/types/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/styles.d.ts +0 -0
  178. /package/types/Menu/{MenuItemSeparator → v1/MenuItemSeparator}/theme.d.ts +0 -0
  179. /package/types/Menu/{styles.d.ts → v1/styles.d.ts} +0 -0
  180. /package/types/Menu/{theme.d.ts → v1/theme.d.ts} +0 -0
@@ -0,0 +1,245 @@
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 { ComponentElement, Children, Component } from 'react'
26
+
27
+ import { withStyle } from '@instructure/emotion'
28
+ import {
29
+ omitProps,
30
+ safeCloneElement,
31
+ matchComponentTypes,
32
+ withDeterministicId
33
+ } from '@instructure/ui-react-utils'
34
+ import { hasVisibleChildren } from '@instructure/ui-a11y-utils'
35
+
36
+ import { MenuItem } from '../MenuItem'
37
+ import type { OnMenuItemSelect, MenuItemProps } from '../MenuItem/props'
38
+ import { MenuItemSeparator } from '../MenuItemSeparator'
39
+ import type { MenuSeparatorProps } from '../MenuItemSeparator/props'
40
+
41
+ import generateStyle from './styles'
42
+
43
+ import { allowedProps } from './props'
44
+ import type { MenuGroupProps, MenuGroupState } from './props'
45
+
46
+ type MenuItemChild = ComponentElement<MenuItemProps, MenuItem>
47
+ type MenuSeparatorChild = ComponentElement<
48
+ MenuSeparatorProps,
49
+ MenuItemSeparator
50
+ >
51
+
52
+ /**
53
+ ---
54
+ parent: Menu
55
+ id: Menu.Group
56
+ ---
57
+ **/
58
+ @withDeterministicId()
59
+ @withStyle(generateStyle)
60
+ class MenuItemGroup extends Component<MenuGroupProps, MenuGroupState> {
61
+ static readonly componentId = 'Menu.Group'
62
+
63
+ static allowedProps = allowedProps
64
+ static defaultProps = {
65
+ disabled: false,
66
+ children: null,
67
+ isTabbable: false,
68
+ allowMultiple: false,
69
+ defaultSelected: []
70
+ }
71
+
72
+ constructor(props: MenuGroupProps) {
73
+ super(props)
74
+
75
+ if (typeof props.selected === 'undefined') {
76
+ this.state = {
77
+ selected: this.selectedFromChildren(props) || props.defaultSelected!
78
+ }
79
+ }
80
+ }
81
+
82
+ ref: Element | null = null
83
+
84
+ handleRef = (el: Element | null) => {
85
+ this.ref = el
86
+ }
87
+
88
+ componentDidMount() {
89
+ this.props.makeStyles?.()
90
+ }
91
+
92
+ componentDidUpdate() {
93
+ this.props.makeStyles?.()
94
+ }
95
+
96
+ handleSelect: OnMenuItemSelect = (e, value, selected, item) => {
97
+ if (this.props.disabled) {
98
+ e.preventDefault()
99
+ return
100
+ }
101
+
102
+ if (this.props.selected) {
103
+ this.updateSelected(e, value, this.props.selected, selected, item)
104
+ } else {
105
+ this.setState((state) => {
106
+ return {
107
+ selected: this.updateSelected(
108
+ e,
109
+ value,
110
+ state.selected,
111
+ selected,
112
+ item
113
+ )
114
+ }
115
+ })
116
+ }
117
+ }
118
+
119
+ updateSelected = (
120
+ e: React.MouseEvent,
121
+ value: MenuItemProps['value'],
122
+ items: MenuGroupState['selected'],
123
+ selected: MenuItemProps['selected'],
124
+ item: MenuItem
125
+ ) => {
126
+ const { allowMultiple } = this.props
127
+ let updated = allowMultiple ? [...items] : []
128
+ const location = updated.indexOf(value!)
129
+
130
+ if (selected === true && location < 0) {
131
+ updated.push(value!)
132
+ } else if (selected === false && location !== -1) {
133
+ updated.splice(location, 1)
134
+ } else if (!allowMultiple && updated.length < 1) {
135
+ // don't allow nothing selected if it's not allowMultiple/checkbox
136
+ updated = [...items]
137
+ }
138
+
139
+ if (typeof this.props.onSelect === 'function') {
140
+ this.props.onSelect(e, updated, selected, item)
141
+ }
142
+
143
+ return updated
144
+ }
145
+
146
+ selectedFromChildren(props: MenuGroupProps) {
147
+ const { children, allowMultiple } = props
148
+ const selected: MenuGroupState['selected'] = []
149
+
150
+ const items = (
151
+ Children.toArray(children) as (MenuItemChild | MenuSeparatorChild)[]
152
+ ).filter((child) => {
153
+ return matchComponentTypes<MenuItemChild>(child, [MenuItem])
154
+ }) as MenuItemChild[]
155
+
156
+ items.forEach((item, index) => {
157
+ if (
158
+ (selected.length === 0 || allowMultiple) &&
159
+ (item.props.selected || item.props.defaultSelected)
160
+ ) {
161
+ selected.push(item.props.value || index)
162
+ }
163
+ })
164
+
165
+ return selected.length > 0 ? selected : null
166
+ }
167
+
168
+ get selected() {
169
+ if (
170
+ typeof this.props.selected === 'undefined' &&
171
+ typeof this.state.selected === 'undefined'
172
+ ) {
173
+ return []
174
+ } else {
175
+ return typeof this.props.selected === 'undefined'
176
+ ? [...this.state.selected]
177
+ : [...this.props.selected]
178
+ }
179
+ }
180
+
181
+ renderLabel() {
182
+ const { label } = this.props
183
+
184
+ return hasVisibleChildren(label) ? (
185
+ <span css={this.props.styles?.label}>{label}</span>
186
+ ) : (
187
+ label
188
+ )
189
+ }
190
+
191
+ renderChildren() {
192
+ const { disabled, controls, allowMultiple, isTabbable, onMouseOver } =
193
+ this.props
194
+ const children = this.props.children as (
195
+ | MenuItemChild
196
+ | MenuSeparatorChild
197
+ )[]
198
+ let index = -1
199
+
200
+ return Children.map(children, (child) => {
201
+ if (matchComponentTypes<MenuItemChild>(child, [MenuItem])) {
202
+ ++index
203
+ const value = child.props.value || index
204
+
205
+ return safeCloneElement(child, {
206
+ tabIndex: isTabbable && index === 0 ? 0 : -1,
207
+ controls,
208
+ value,
209
+ children: child.props.children,
210
+ type: allowMultiple ? 'checkbox' : 'radio',
211
+ ref: this.props.itemRef,
212
+ disabled: disabled || child.props.disabled,
213
+ selected: this.selected.indexOf(value) > -1,
214
+ onSelect: this.handleSelect,
215
+ onMouseOver
216
+ })
217
+ } else {
218
+ return child
219
+ }
220
+ })
221
+ }
222
+
223
+ render() {
224
+ const props = omitProps(this.props, MenuItemGroup.allowedProps)
225
+ return (
226
+ <span
227
+ {...props}
228
+ css={this.props.styles?.menuItemGroup}
229
+ ref={this.handleRef}
230
+ data-cid="MenuItemGroup"
231
+ >
232
+ {this.renderLabel()}
233
+ <div
234
+ css={this.props.styles?.items}
235
+ aria-disabled={this.props.disabled ? 'true' : undefined}
236
+ >
237
+ {this.renderChildren()}
238
+ </div>
239
+ </span>
240
+ )
241
+ }
242
+ }
243
+
244
+ export default MenuItemGroup
245
+ export { MenuItemGroup }
@@ -0,0 +1,105 @@
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 React from 'react'
26
+
27
+ import { MenuItem } from '../MenuItem'
28
+
29
+ import type {
30
+ MenuGroupTheme,
31
+ OtherHTMLAttributes
32
+ } from '@instructure/shared-types'
33
+ import type { WithStyleProps, ComponentStyle } from '@instructure/emotion'
34
+ import type { MenuItemProps } from '../MenuItem/props'
35
+ import type { WithDeterministicIdProps } from '@instructure/ui-react-utils'
36
+
37
+ type MenuGroupOwnProps = {
38
+ label: React.ReactNode
39
+ allowMultiple?: boolean
40
+ /**
41
+ * children of type `Menu.Item`, `Menu.Separator`
42
+ */
43
+ children?: React.ReactNode // TODO: oneOf([MenuItem, MenuItemSeparator])
44
+ /**
45
+ * an array of the values (or indices by default) for the selected items
46
+ */
47
+ selected?: (string | number)[] // TODO: controllable(PropTypes.array, 'onSelect', 'defaultSelected')
48
+ /**
49
+ * an array of the values (or indices by default) for the selected items on initial render
50
+ */
51
+ defaultSelected?: (string | number)[]
52
+ /**
53
+ * call this function when a menu item is selected
54
+ */
55
+ onSelect?: (
56
+ e: React.MouseEvent,
57
+ updated: MenuItemProps['value'][],
58
+ selected: MenuItemProps['selected'],
59
+ item: MenuItem
60
+ ) => void
61
+ onMouseOver?: (e: React.MouseEvent, args: MenuItem) => void
62
+ /**
63
+ * the id of the element that the menu items will act upon
64
+ */
65
+ controls?: string
66
+ /**
67
+ * returns a reference to the `MenuItem`
68
+ */
69
+ itemRef?: (element: MenuItem | null) => void
70
+ disabled?: boolean
71
+ /**
72
+ * should the group appear in the tab order (the first item will have a tabIndex of 0)
73
+ */
74
+ isTabbable?: boolean
75
+ }
76
+
77
+ type PropKeys = keyof MenuGroupOwnProps
78
+
79
+ type AllowedPropKeys = Readonly<Array<PropKeys>>
80
+
81
+ type MenuGroupProps = MenuGroupOwnProps &
82
+ WithStyleProps<MenuGroupTheme, MenuGroupStyle> &
83
+ OtherHTMLAttributes<MenuGroupOwnProps> &
84
+ WithDeterministicIdProps
85
+
86
+ type MenuGroupStyle = ComponentStyle<'menuItemGroup' | 'label' | 'items'>
87
+ const allowedProps: AllowedPropKeys = [
88
+ 'label',
89
+ 'allowMultiple',
90
+ 'children',
91
+ 'selected',
92
+ 'defaultSelected',
93
+ 'onSelect',
94
+ 'onMouseOver',
95
+ 'controls',
96
+ 'itemRef',
97
+ 'disabled',
98
+ 'isTabbable'
99
+ ]
100
+
101
+ type MenuGroupState = {
102
+ selected: (string | number)[]
103
+ }
104
+ export type { MenuGroupProps, MenuGroupStyle, MenuGroupState }
105
+ export { allowedProps }
@@ -0,0 +1,66 @@
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 } from '@instructure/ui-themes'
26
+ import type { MenuGroupStyle } from './props'
27
+
28
+ /**
29
+ * ---
30
+ * private: true
31
+ * ---
32
+ * Generates the style object from the theme and provided additional information
33
+ * @param {Object} componentTheme The theme variable object.
34
+ * @param {Object} props the props of the component, the style is applied to
35
+ * @param {Object} state the state of the component, the style is applied to
36
+ * @return {Object} The final style object, which will be used in the component
37
+ */
38
+ const generateStyle = (
39
+ componentTheme: NewComponentTypes['MenuGroup']
40
+ ): MenuGroupStyle => {
41
+ return {
42
+ menuItemGroup: {
43
+ label: 'menuItemGroup',
44
+ display: 'block'
45
+ },
46
+ label: {
47
+ label: 'menuItemGroup__label',
48
+ background: componentTheme.background,
49
+ padding: `${componentTheme.paddingVertical} ${componentTheme.paddingHorizontal}`,
50
+ display: 'block',
51
+ fontSize: componentTheme.fontSize,
52
+ fontFamily: componentTheme.fontFamily,
53
+ fontWeight: componentTheme.fontWeight,
54
+ color: componentTheme.color,
55
+ textAlign: 'start'
56
+ },
57
+ items: {
58
+ label: 'menuItemGroup__items',
59
+ padding: '0',
60
+ margin: '0 0 0 0',
61
+ listStyleType: 'none'
62
+ }
63
+ }
64
+ }
65
+
66
+ export default generateStyle
@@ -0,0 +1,79 @@
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 } from 'react'
26
+
27
+ import { withStyle } from '@instructure/emotion'
28
+ import { omitProps } from '@instructure/ui-react-utils'
29
+
30
+ import generateStyle from './styles'
31
+
32
+ import { allowedProps } from './props'
33
+ import type { MenuSeparatorProps } from './props'
34
+
35
+ /**
36
+ ---
37
+ parent: Menu
38
+ id: Menu.Separator
39
+ ---
40
+ @module MenuItemSeparator
41
+ **/
42
+ @withStyle(generateStyle)
43
+ class MenuItemSeparator extends Component<MenuSeparatorProps> {
44
+ static readonly componentId = 'Menu.Separator'
45
+
46
+ static allowedProps = allowedProps
47
+
48
+ ref: Element | null = null
49
+
50
+ handleRef = (el: Element | null) => {
51
+ this.ref = el
52
+ }
53
+
54
+ componentDidMount() {
55
+ this.props.makeStyles?.()
56
+ }
57
+
58
+ componentDidUpdate() {
59
+ this.props.makeStyles?.()
60
+ }
61
+
62
+ render() {
63
+ const props = omitProps(this.props, MenuItemSeparator.allowedProps)
64
+ // role="separator" would fit better here, but it causes NVDA to stop the
65
+ // MenuItem count after it
66
+ return (
67
+ <div
68
+ {...props}
69
+ role="presentation"
70
+ css={this.props.styles?.menuItemSeparator}
71
+ ref={this.handleRef}
72
+ data-cid="MenuItemSeparator"
73
+ />
74
+ )
75
+ }
76
+ }
77
+
78
+ export default MenuItemSeparator
79
+ export { MenuItemSeparator }
@@ -0,0 +1,48 @@
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 { WithStyleProps, ComponentStyle } from '@instructure/emotion'
26
+ import type {
27
+ MenuSeparatorTheme,
28
+ OtherHTMLAttributes
29
+ } from '@instructure/shared-types'
30
+
31
+ // keeping here to keep the structure of props.ts
32
+ // eslint-disable-next-line
33
+ type MenuSeparatorOwnProps = {}
34
+
35
+ type PropKeys = keyof MenuSeparatorOwnProps
36
+
37
+ type AllowedPropKeys = Readonly<Array<PropKeys>>
38
+
39
+ type MenuSeparatorProps = MenuSeparatorOwnProps &
40
+ WithStyleProps<MenuSeparatorTheme, MenuSeparatorStyle> &
41
+ OtherHTMLAttributes<MenuSeparatorOwnProps>
42
+
43
+ type MenuSeparatorStyle = ComponentStyle<'menuItemSeparator'>
44
+
45
+ const allowedProps: AllowedPropKeys = []
46
+
47
+ export type { MenuSeparatorProps, MenuSeparatorStyle }
48
+ export { allowedProps }
@@ -0,0 +1,52 @@
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 } from '@instructure/ui-themes'
26
+ import type { MenuSeparatorStyle } from './props'
27
+
28
+ /**
29
+ * ---
30
+ * private: true
31
+ * ---
32
+ * Generates the style object from the theme and provided additional information
33
+ * @param {Object} componentTheme The theme variable object.
34
+ * @param {Object} props the props of the component, the style is applied to
35
+ * @param {Object} state the state of the component, the style is applied to
36
+ * @return {Object} The final style object, which will be used in the component
37
+ */
38
+ const generateStyle = (
39
+ componentTheme: NewComponentTypes['MenuSeparator']
40
+ ): MenuSeparatorStyle => {
41
+ return {
42
+ menuItemSeparator: {
43
+ label: 'menuItemSeparator',
44
+ height: componentTheme.height,
45
+ margin: `${componentTheme.marginVertical} ${componentTheme.marginHorizontal}`,
46
+ overflow: 'hidden',
47
+ background: componentTheme.background
48
+ }
49
+ }
50
+ }
51
+
52
+ export default generateStyle
@@ -0,0 +1,104 @@
1
+ ---
2
+ describes: Menu
3
+ ---
4
+
5
+ The `Menu` component is a special type of Popover that is meant to be used as a list of actions or functions (`<Menu.Items/>` that are keyboard accessible) that the user may want to invoke often related to or controlling some other content on the page.
6
+
7
+ - Menu should not be used for navigation.
8
+ - Menu should not be used as a form input.
9
+ - Menu is usually triggered on click of a trigger element (often a ‘...’ or cog icon button).
10
+ - The Menu provides custom focus management, trapping focus within the ContextView, allowing navigation between Menu.Items via arrow keys.
11
+ - Menu uses Popover internally and provides additional semantic markup and focus behavior.
12
+
13
+ Passing a node to the `trigger` prop will render a toggle button which, when clicked, shows or hides
14
+ the [Menu](Menu) in a [Popover](Popover).
15
+
16
+ Note: `<Menu/>` cannot contain content that is not a `<Menu.Item/>` (links or buttons). If
17
+ you need to include more complex content, take a look at [Popover](Popover).
18
+
19
+ ```js
20
+ ---
21
+ type: example
22
+ ---
23
+ const Example = () => {
24
+ const [singleSelection, setSingleSelection] = useState(['itemOne'])
25
+ const [multipleSelection, setMultipleSelection] = useState([
26
+ 'optionOne',
27
+ 'optionThree'
28
+ ])
29
+
30
+ const handleSingleSelect = (e, newSelected) => {
31
+ setSingleSelection(newSelected)
32
+ }
33
+
34
+ const handleMultipleSelect = (e, newSelected) => {
35
+ setMultipleSelection(newSelected)
36
+ }
37
+
38
+ return (
39
+ <View padding="medium" textAlign="center">
40
+ <Menu
41
+ placement="bottom"
42
+ trigger={<Button>Menu</Button>}
43
+ mountNode={() => document.getElementById('main')}
44
+ >
45
+ <Menu.Item value="mastery">Learning Mastery</Menu.Item>
46
+ <Menu.Item
47
+ href="https://instructure.github.io/instructure-ui/"
48
+ target="_blank"
49
+ >
50
+ Default (Grid view)
51
+ </Menu.Item>
52
+ <Menu.Item disabled>Individual (List view)</Menu.Item>
53
+ <Menu label="More Options">
54
+ <Menu.Group
55
+ allowMultiple
56
+ label="Select Many"
57
+ selected={multipleSelection}
58
+ onSelect={handleMultipleSelect}
59
+ >
60
+ <Menu.Item value="optionOne">Option 1</Menu.Item>
61
+ <Menu.Item value="optionTwo">Option 2</Menu.Item>
62
+ <Menu.Item value="optionThree">Option 3</Menu.Item>
63
+ </Menu.Group>
64
+ <Menu.Separator />
65
+ <Menu.Item value="navigation">Navigation</Menu.Item>
66
+ <Menu.Item value="set">Set as default</Menu.Item>
67
+ </Menu>
68
+ <Menu.Separator />
69
+ <Menu.Group
70
+ label="Select One"
71
+ selected={singleSelection}
72
+ onSelect={handleSingleSelect}
73
+ >
74
+ <Menu.Item value="itemOne">Item 1</Menu.Item>
75
+ <Menu.Item value="itemTwo">Item 2</Menu.Item>
76
+ </Menu.Group>
77
+ <Menu.Separator />
78
+ <Menu.Item value="baz">Open grading history...</Menu.Item>
79
+ </Menu>
80
+ </View>
81
+ )
82
+ }
83
+
84
+ render(<Example />)
85
+ ```
86
+
87
+ ### Guidelines
88
+
89
+ ```js
90
+ ---
91
+ type: embed
92
+ ---
93
+ <Guidelines>
94
+ <Figure recommendation="yes" title="Do">
95
+ <Figure.Item>Make the text within Menu direct so users can quickly decide on an action</Figure.Item>
96
+ <Figure.Item>Use for radio or checkbox type interactions</Figure.Item>
97
+ </Figure>
98
+ <Figure recommendation="no" title="Don't">
99
+ <Figure.Item>Nest Menu.Items more than two levels deep</Figure.Item>
100
+ <Figure.Item>Use content that is not a Menu.Item (links or buttons)</Figure.Item>
101
+ <Figure.Item>Include complex content</Figure.Item>
102
+ </Figure>
103
+ </Guidelines>
104
+ ```