@instructure/ui-menu 8.13.1-snapshot.9 → 8.14.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/es/Menu/MenuItem/index.js +28 -21
  3. package/es/Menu/MenuItem/props.js +0 -23
  4. package/es/Menu/MenuItemGroup/index.js +17 -13
  5. package/es/Menu/MenuItemGroup/props.js +1 -30
  6. package/es/Menu/MenuItemSeparator/index.js +6 -2
  7. package/es/Menu/index.js +59 -56
  8. package/es/Menu/props.js +1 -113
  9. package/es/MenuContext.js +3 -3
  10. package/lib/Menu/MenuItem/index.js +28 -21
  11. package/lib/Menu/MenuItem/props.js +0 -23
  12. package/lib/Menu/MenuItemGroup/index.js +17 -13
  13. package/lib/Menu/MenuItemGroup/props.js +1 -30
  14. package/lib/Menu/MenuItemSeparator/index.js +6 -2
  15. package/lib/Menu/index.js +61 -56
  16. package/lib/Menu/props.js +1 -113
  17. package/lib/MenuContext.js +2 -2
  18. package/package.json +21 -22
  19. package/src/Menu/MenuItem/index.tsx +24 -34
  20. package/src/Menu/MenuItem/props.ts +36 -27
  21. package/src/Menu/MenuItemGroup/index.tsx +28 -48
  22. package/src/Menu/MenuItemGroup/props.ts +37 -30
  23. package/src/Menu/MenuItemSeparator/index.tsx +2 -4
  24. package/src/Menu/index.tsx +81 -135
  25. package/src/Menu/props.ts +79 -84
  26. package/src/MenuContext.ts +3 -2
  27. package/tsconfig.build.json +25 -2
  28. package/tsconfig.build.tsbuildinfo +1 -0
  29. package/types/Menu/MenuItem/MenuItemLocator.d.ts +52 -52
  30. package/types/Menu/MenuItem/index.d.ts +24 -23
  31. package/types/Menu/MenuItem/index.d.ts.map +1 -1
  32. package/types/Menu/MenuItem/props.d.ts +30 -7
  33. package/types/Menu/MenuItem/props.d.ts.map +1 -1
  34. package/types/Menu/MenuItemGroup/MenuItemGroupLocator.d.ts +182 -182
  35. package/types/Menu/MenuItemGroup/index.d.ts +22 -22
  36. package/types/Menu/MenuItemGroup/index.d.ts.map +1 -1
  37. package/types/Menu/MenuItemGroup/props.d.ts +33 -8
  38. package/types/Menu/MenuItemGroup/props.d.ts.map +1 -1
  39. package/types/Menu/MenuItemSeparator/index.d.ts.map +1 -1
  40. package/types/Menu/MenuLocator.d.ts +576 -576
  41. package/types/Menu/index.d.ts +58 -68
  42. package/types/Menu/index.d.ts.map +1 -1
  43. package/types/Menu/props.d.ts +94 -16
  44. package/types/Menu/props.d.ts.map +1 -1
  45. package/types/MenuContext.d.ts +3 -2
  46. package/types/MenuContext.d.ts.map +1 -1
  47. package/LICENSE.md +0 -27
@@ -24,7 +24,7 @@
24
24
 
25
25
  import React from 'react'
26
26
  import PropTypes from 'prop-types'
27
-
27
+ import MenuItem from '../MenuItem'
28
28
  import { controllable } from '@instructure/ui-prop-types'
29
29
 
30
30
  import type {
@@ -35,17 +35,42 @@ import type {
35
35
  } from '@instructure/shared-types'
36
36
  import type { WithStyleProps, ComponentStyle } from '@instructure/emotion'
37
37
 
38
+ type OnMenuItemSelect = (
39
+ e: React.MouseEvent,
40
+ value: MenuItemOwnProps['value'],
41
+ selected: MenuItemOwnProps['selected'],
42
+ args: MenuItem
43
+ ) => void
44
+
38
45
  type MenuItemOwnProps = {
46
+ /**
47
+ * the menu item label
48
+ */
39
49
  children: React.ReactNode
50
+ /**
51
+ * whether to set the menu item state to selected or not on initial render
52
+ */
40
53
  defaultSelected?: boolean
41
- selected?: any // TODO: controllable(PropTypes.bool, 'onSelect', 'defaultSelected')
42
- onSelect?: (...args: any[]) => any
43
- onClick?: (...args: any[]) => any
44
- onKeyDown?: (...args: any[]) => any
45
- onKeyUp?: (...args: any[]) => any
46
- onMouseOver?: (...args: any[]) => any
54
+ /**
55
+ * whether the menu item is selected or not (must be accompanied by an `onSelect` prop)
56
+ */
57
+ selected?: boolean // TODO: controllable(PropTypes.bool, 'onSelect', 'defaultSelected')
58
+ /**
59
+ * when used with the `selected` prop, the component will not control its own state
60
+ */
61
+ onSelect?: OnMenuItemSelect
62
+ onClick?: (e: React.MouseEvent) => void
63
+ onKeyDown?: (e: React.KeyboardEvent) => void
64
+ onKeyUp?: (e: React.KeyboardEvent) => void
65
+ onMouseOver?: (e: React.MouseEvent, args: MenuItem) => void
66
+ /**
67
+ * the id of the element that the menu item will act upon
68
+ */
47
69
  controls?: string
48
70
  disabled?: boolean
71
+ /**
72
+ * the element type to render as (will default to `<a>` if href is provided)
73
+ */
49
74
  as?: AsElementType
50
75
  type?: 'button' | 'checkbox' | 'radio' | 'flyout'
51
76
  value?: string | number
@@ -63,34 +88,16 @@ type MenuItemProps = MenuItemOwnProps &
63
88
  type MenuItemStyle = ComponentStyle<'menuItem' | 'icon' | 'label'>
64
89
 
65
90
  const propTypes: PropValidators<PropKeys> = {
66
- /**
67
- * the menu item label
68
- */
69
91
  children: PropTypes.node.isRequired,
70
- /**
71
- * whether to set the menu item state to selected or not on initial render
72
- */
73
92
  defaultSelected: PropTypes.bool,
74
- /**
75
- * whether the menu item is selected or not (must be accompanied by an `onSelect` prop)
76
- */
77
93
  selected: controllable(PropTypes.bool, 'onSelect', 'defaultSelected'),
78
- /**
79
- * when used with the `selected` prop, the component will not control its own state
80
- */
81
94
  onSelect: PropTypes.func,
82
95
  onClick: PropTypes.func,
83
96
  onKeyDown: PropTypes.func,
84
97
  onKeyUp: PropTypes.func,
85
98
  onMouseOver: PropTypes.func,
86
- /**
87
- * the id of the element that the menu item will act upon
88
- */
89
99
  controls: PropTypes.string,
90
100
  disabled: PropTypes.bool,
91
- /**
92
- * the element type to render as (will default to `<a>` if href is provided)
93
- */
94
101
  as: PropTypes.elementType, // eslint-disable-line react/require-default-props
95
102
  type: PropTypes.oneOf(['button', 'checkbox', 'radio', 'flyout']),
96
103
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
@@ -113,6 +120,8 @@ const allowedProps: AllowedPropKeys = [
113
120
  'value',
114
121
  'href'
115
122
  ]
116
-
117
- export type { MenuItemProps, MenuItemStyle }
123
+ type MenuItemState = {
124
+ selected: boolean
125
+ }
126
+ export type { MenuItemProps, MenuItemStyle, MenuItemState, OnMenuItemSelect }
118
127
  export { propTypes, allowedProps }
@@ -41,17 +41,19 @@ import generateStyle from './styles'
41
41
  import generateComponentTheme from './theme'
42
42
 
43
43
  import { propTypes, allowedProps } from './props'
44
- import type { MenuGroupProps } from './props'
44
+ import type { MenuGroupProps, MenuGroupState } from './props'
45
+ import type { OnMenuItemSelect, MenuItemProps } from '../MenuItem/props'
45
46
 
46
47
  /**
47
48
  ---
48
49
  parent: Menu
49
50
  id: Menu.Group
50
51
  ---
52
+ @tsProps
51
53
  **/
52
54
  @withStyle(generateStyle, generateComponentTheme)
53
55
  @testable()
54
- class MenuItemGroup extends Component<MenuGroupProps> {
56
+ class MenuItemGroup extends Component<MenuGroupProps, MenuGroupState> {
55
57
  static readonly componentId = 'Menu.Group'
56
58
 
57
59
  static propTypes = propTypes
@@ -61,28 +63,22 @@ class MenuItemGroup extends Component<MenuGroupProps> {
61
63
  children: null,
62
64
  isTabbable: false,
63
65
  allowMultiple: false,
64
- defaultSelected: [],
65
- // @ts-expect-error ts-migrate(6133) FIXME: 'item' is declared but its value is never read.
66
- itemRef: function (item) {},
67
- // @ts-expect-error ts-migrate(6133) FIXME: 'e' is declared but its value is never read.
68
- onSelect: function (e, value, selected, item) {}
66
+ defaultSelected: []
69
67
  }
70
68
 
71
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'props' implicitly has an 'any' type.
72
- constructor(props) {
73
- // @ts-expect-error ts-migrate(2554) FIXME: Expected 1-2 arguments, but got 0.
74
- super()
69
+ constructor(props: MenuGroupProps) {
70
+ super(props)
75
71
 
76
72
  if (typeof props.selected === 'undefined') {
77
73
  this.state = {
78
- selected: this.selectedFromChildren(props) || props.defaultSelected
74
+ selected: this.selectedFromChildren(props) || props.defaultSelected!
79
75
  }
80
76
  }
81
77
 
82
- // @ts-expect-error ts-migrate(2339) FIXME: Property '_labelId' does not exist on type 'MenuIt... Remove this comment to see the full error message
83
78
  this._labelId = uid('MenuItemGroup')
84
79
  }
85
80
 
81
+ private _labelId: string
86
82
  ref: Element | null = null
87
83
 
88
84
  handleRef = (el: Element | null) => {
@@ -90,17 +86,14 @@ class MenuItemGroup extends Component<MenuGroupProps> {
90
86
  }
91
87
 
92
88
  componentDidMount() {
93
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
94
- this.props.makeStyles()
89
+ this.props.makeStyles?.()
95
90
  }
96
91
 
97
92
  componentDidUpdate() {
98
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
99
- this.props.makeStyles()
93
+ this.props.makeStyles?.()
100
94
  }
101
95
 
102
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'e' implicitly has an 'any' type.
103
- handleSelect = (e, value, selected, item) => {
96
+ handleSelect: OnMenuItemSelect = (e, value, selected, item) => {
104
97
  if (this.props.disabled) {
105
98
  e.preventDefault()
106
99
  return
@@ -114,7 +107,6 @@ class MenuItemGroup extends Component<MenuGroupProps> {
114
107
  selected: this.updateSelected(
115
108
  e,
116
109
  value,
117
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'selected' does not exist on type 'Readon... Remove this comment to see the full error message
118
110
  state.selected,
119
111
  selected,
120
112
  item
@@ -124,14 +116,19 @@ class MenuItemGroup extends Component<MenuGroupProps> {
124
116
  }
125
117
  }
126
118
 
127
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'e' implicitly has an 'any' type.
128
- updateSelected = (e, value, items, selected, item) => {
119
+ updateSelected = (
120
+ e: React.MouseEvent,
121
+ value: MenuItemProps['value'],
122
+ items: MenuGroupState['selected'],
123
+ selected: MenuItemProps['selected'],
124
+ item: MenuItem
125
+ ) => {
129
126
  const { allowMultiple } = this.props
130
127
  let updated = allowMultiple ? [...items] : []
131
- const location = updated.indexOf(value)
128
+ const location = updated.indexOf(value!)
132
129
 
133
130
  if (selected === true && location < 0) {
134
- updated.push(value)
131
+ updated.push(value!)
135
132
  } else if (selected === false && location !== -1) {
136
133
  updated.splice(location, 1)
137
134
  } else if (!allowMultiple && updated.length < 1) {
@@ -146,42 +143,35 @@ class MenuItemGroup extends Component<MenuGroupProps> {
146
143
  return updated
147
144
  }
148
145
 
149
- // @ts-expect-error ts-migrate(7006) FIXME: Parameter 'props' implicitly has an 'any' type.
150
- selectedFromChildren(props) {
146
+ selectedFromChildren(props: MenuGroupProps) {
151
147
  const { children, allowMultiple } = props
152
- // @ts-expect-error ts-migrate(7034) FIXME: Variable 'selected' implicitly has type 'any[]' in... Remove this comment to see the full error message
153
- const selected = []
148
+ const selected: MenuGroupState['selected'] = []
154
149
 
155
150
  const items = Children.toArray(children).filter((child) => {
156
151
  return matchComponentTypes(child as MenuItem, [MenuItem])
157
- })
152
+ }) as MenuItem[]
158
153
 
159
154
  items.forEach((item, index) => {
160
155
  if (
161
156
  (selected.length === 0 || allowMultiple) &&
162
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
163
157
  (item.props.selected || item.props.defaultSelected)
164
158
  ) {
165
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'props' does not exist on type 'string | ... Remove this comment to see the full error message
166
159
  selected.push(item.props.value || index)
167
160
  }
168
161
  })
169
162
 
170
- // @ts-expect-error ts-migrate(7005) FIXME: Variable 'selected' implicitly has an 'any[]' type... Remove this comment to see the full error message
171
163
  return selected.length > 0 ? selected : null
172
164
  }
173
165
 
174
166
  get selected() {
175
167
  if (
176
168
  typeof this.props.selected === 'undefined' &&
177
- // @ts-expect-error ts-migrate(2339) FIXME: Property 'selected' does not exist on type 'Readon... Remove this comment to see the full error message
178
169
  typeof this.state.selected === 'undefined'
179
170
  ) {
180
171
  return []
181
172
  } else {
182
173
  return typeof this.props.selected === 'undefined'
183
- ? // @ts-expect-error ts-migrate(2339) FIXME: Property 'selected' does not exist on type 'Readon... Remove this comment to see the full error message
184
- [...this.state.selected]
174
+ ? [...this.state.selected]
185
175
  : [...this.props.selected]
186
176
  }
187
177
  }
@@ -197,21 +187,14 @@ class MenuItemGroup extends Component<MenuGroupProps> {
197
187
  }
198
188
 
199
189
  renderChildren() {
200
- const {
201
- children,
202
- disabled,
203
- controls,
204
- allowMultiple,
205
- isTabbable,
206
- onMouseOver
207
- } = this.props
208
-
190
+ const { disabled, controls, allowMultiple, isTabbable, onMouseOver } =
191
+ this.props
192
+ const children = this.props.children as ReactElement[]
209
193
  let index = -1
210
194
 
211
195
  return Children.map(children, (child) => {
212
196
  if (matchComponentTypes(child, [MenuItem])) {
213
197
  ++index
214
- // @ts-expect-error ts-migrate(2533) FIXME: Object is possibly 'null' or 'undefined'.
215
198
  const value = child.props.value || index
216
199
 
217
200
  return (
@@ -223,7 +206,6 @@ class MenuItemGroup extends Component<MenuGroupProps> {
223
206
  value,
224
207
  type: allowMultiple ? 'checkbox' : 'radio',
225
208
  ref: this.props.itemRef,
226
- // @ts-expect-error ts-migrate(2533) FIXME: Object is possibly 'null' or 'undefined'.
227
209
  disabled: disabled || child.props.disabled,
228
210
  selected: this.selected.indexOf(value) > -1,
229
211
  onSelect: this.handleSelect,
@@ -246,13 +228,11 @@ class MenuItemGroup extends Component<MenuGroupProps> {
246
228
  role="presentation"
247
229
  ref={this.handleRef}
248
230
  >
249
- {/* @ts-expect-error ts-migrate(2339) FIXME: Property '_labelId' does not exist on type 'MenuIt... Remove this comment to see the full error message */}
250
231
  <span id={this._labelId}>{this.renderLabel()}</span>
251
232
  <ul
252
233
  role="menu"
253
234
  css={this.props.styles?.items}
254
235
  aria-disabled={this.props.disabled ? 'true' : undefined}
255
- // @ts-expect-error ts-migrate(2339) FIXME: Property '_labelId' does not exist on type 'MenuIt... Remove this comment to see the full error message
256
236
  aria-labelledby={this._labelId}
257
237
  >
258
238
  {this.renderChildren()}
@@ -38,19 +38,46 @@ import type {
38
38
  OtherHTMLAttributes
39
39
  } from '@instructure/shared-types'
40
40
  import type { WithStyleProps, ComponentStyle } from '@instructure/emotion'
41
+ import type { MenuItemProps } from '../MenuItem/props'
42
+ import React from 'react'
41
43
 
42
44
  type MenuGroupOwnProps = {
43
45
  label: React.ReactNode
44
46
  allowMultiple?: boolean
47
+ /**
48
+ * children of type `Menu.Item`, `Menu.Separator`
49
+ */
45
50
  children?: React.ReactNode // TODO: oneOf([MenuItem, MenuItemSeparator])
46
- selected?: any // TODO: controllable(PropTypes.array, 'onSelect', 'defaultSelected')
47
- defaultSelected?: any[]
48
- onSelect?: (...args: any[]) => any
49
- onMouseOver?: (...args: any[]) => any
50
- onKeyDown?: (...args: any[]) => any
51
+ /**
52
+ * an array of the values (or indices by default) for the selected items
53
+ */
54
+ selected?: (string | number)[] // TODO: controllable(PropTypes.array, 'onSelect', 'defaultSelected')
55
+ /**
56
+ * an array of the values (or indices by default) for the selected items on initial render
57
+ */
58
+ defaultSelected?: (string | number)[]
59
+ /**
60
+ * call this function when a menu item is selected
61
+ */
62
+ onSelect?: (
63
+ e: React.MouseEvent,
64
+ updated: MenuItemProps['value'][],
65
+ selected: MenuItemProps['selected'],
66
+ item: MenuItem
67
+ ) => void
68
+ onMouseOver?: (e: React.MouseEvent, args: MenuItem) => void
69
+ /**
70
+ * the id of the element that the menu items will act upon
71
+ */
51
72
  controls?: string
52
- itemRef?: (...args: any[]) => any
73
+ /**
74
+ * returns a reference to the `MenuItem`
75
+ */
76
+ itemRef?: (element: Element | null) => void
53
77
  disabled?: boolean
78
+ /**
79
+ * should the group appear in the tab order (the first item will have a tabIndex of 0)
80
+ */
54
81
  isTabbable?: boolean
55
82
  }
56
83
 
@@ -67,36 +94,14 @@ type MenuGroupStyle = ComponentStyle<'menuItemGroup' | 'label' | 'items'>
67
94
  const propTypes: PropValidators<PropKeys> = {
68
95
  label: PropTypes.node.isRequired,
69
96
  allowMultiple: PropTypes.bool,
70
- /**
71
- * children of type `Menu.Item`, `Menu.Separator`
72
- */
73
97
  children: ChildrenPropTypes.oneOf([MenuItem, MenuItemSeparator]),
74
- /**
75
- * an array of the values (or indices by default) for the selected items
76
- */
77
98
  selected: controllable(PropTypes.array, 'onSelect', 'defaultSelected'),
78
- /**
79
- * an array of the values (or indices by default) for the selected items on initial render
80
- */
81
99
  defaultSelected: PropTypes.array,
82
- /**
83
- * call this function when a menu item is selected
84
- */
85
100
  onSelect: PropTypes.func,
86
101
  onMouseOver: PropTypes.func,
87
- onKeyDown: PropTypes.func,
88
- /**
89
- * the id of the element that the menu items will act upon
90
- */
91
102
  controls: PropTypes.string,
92
- /**
93
- * returns a reference to the `MenuItem`
94
- */
95
103
  itemRef: PropTypes.func,
96
104
  disabled: PropTypes.bool,
97
- /**
98
- * should the group appear in the tab order (the first item will have a tabIndex of 0)
99
- */
100
105
  isTabbable: PropTypes.bool
101
106
  }
102
107
 
@@ -108,12 +113,14 @@ const allowedProps: AllowedPropKeys = [
108
113
  'defaultSelected',
109
114
  'onSelect',
110
115
  'onMouseOver',
111
- 'onKeyDown',
112
116
  'controls',
113
117
  'itemRef',
114
118
  'disabled',
115
119
  'isTabbable'
116
120
  ]
117
121
 
118
- export type { MenuGroupProps, MenuGroupStyle }
122
+ type MenuGroupState = {
123
+ selected: (string | number)[]
124
+ }
125
+ export type { MenuGroupProps, MenuGroupStyle, MenuGroupState }
119
126
  export { propTypes, allowedProps }
@@ -57,13 +57,11 @@ class MenuItemSeparator extends Component<MenuSeparatorProps> {
57
57
  }
58
58
 
59
59
  componentDidMount() {
60
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
61
- this.props.makeStyles()
60
+ this.props.makeStyles?.()
62
61
  }
63
62
 
64
63
  componentDidUpdate() {
65
- // @ts-expect-error ts-migrate(2722) FIXME: Cannot invoke an object which is possibly 'undefin... Remove this comment to see the full error message
66
- this.props.makeStyles()
64
+ this.props.makeStyles?.()
67
65
  }
68
66
 
69
67
  render() {