@instructure/ui-tree-browser 8.14.1-snapshot.7 → 8.15.1-snapshot.2
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 +4 -0
- package/es/TreeBrowser/TreeBrowserLocator.js +2 -1
- package/es/TreeBrowser/TreeButton/index.js +14 -15
- package/es/TreeBrowser/TreeCollection/index.js +18 -31
- package/es/TreeBrowser/TreeCollection/props.js +1 -9
- package/es/TreeBrowser/TreeNode/index.js +10 -13
- package/es/TreeBrowser/TreeNode/props.js +0 -8
- package/es/TreeBrowser/index.js +36 -32
- package/es/TreeBrowser/props.js +0 -55
- package/lib/TreeBrowser/TreeBrowserLocator.js +2 -1
- package/lib/TreeBrowser/TreeButton/index.js +14 -14
- package/lib/TreeBrowser/TreeCollection/index.js +17 -30
- package/lib/TreeBrowser/TreeCollection/props.js +1 -9
- package/lib/TreeBrowser/TreeNode/index.js +10 -12
- package/lib/TreeBrowser/TreeNode/props.js +0 -8
- package/lib/TreeBrowser/index.js +37 -33
- package/lib/TreeBrowser/props.js +0 -55
- package/package.json +15 -15
- package/src/TreeBrowser/TreeButton/index.tsx +21 -36
- package/src/TreeBrowser/TreeButton/props.ts +11 -10
- package/src/TreeBrowser/TreeCollection/index.tsx +57 -108
- package/src/TreeBrowser/TreeCollection/props.ts +17 -32
- package/src/TreeBrowser/TreeNode/index.tsx +10 -21
- package/src/TreeBrowser/TreeNode/props.ts +5 -7
- package/src/TreeBrowser/index.tsx +81 -108
- package/src/TreeBrowser/props.ts +133 -59
- package/tsconfig.build.tsbuildinfo +1 -1
- package/types/TreeBrowser/TreeBrowserLocator.d.ts +14 -14
- package/types/TreeBrowser/TreeButton/index.d.ts +5 -51
- package/types/TreeBrowser/TreeButton/index.d.ts.map +1 -1
- package/types/TreeBrowser/TreeButton/props.d.ts +11 -10
- package/types/TreeBrowser/TreeButton/props.d.ts.map +1 -1
- package/types/TreeBrowser/TreeCollection/index.d.ts +33 -85
- package/types/TreeBrowser/TreeCollection/index.d.ts.map +1 -1
- package/types/TreeBrowser/TreeCollection/props.d.ts +11 -25
- package/types/TreeBrowser/TreeCollection/props.d.ts.map +1 -1
- package/types/TreeBrowser/TreeNode/index.d.ts +4 -12
- package/types/TreeBrowser/TreeNode/index.d.ts.map +1 -1
- package/types/TreeBrowser/TreeNode/props.d.ts +5 -1
- package/types/TreeBrowser/TreeNode/props.d.ts.map +1 -1
- package/types/TreeBrowser/index.d.ts +35 -73
- package/types/TreeBrowser/index.d.ts.map +1 -1
- package/types/TreeBrowser/props.d.ts +113 -16
- package/types/TreeBrowser/props.d.ts.map +1 -1
|
@@ -30,26 +30,27 @@ import type {
|
|
|
30
30
|
PropValidators,
|
|
31
31
|
TreeBrowserButtonTheme
|
|
32
32
|
} from '@instructure/shared-types'
|
|
33
|
+
import type { TreeBrowserCommonProps } from '../props'
|
|
33
34
|
|
|
34
35
|
type TreeBrowserButtonOwnProps = {
|
|
35
36
|
id?: string | number
|
|
36
37
|
name?: string
|
|
37
38
|
descriptor?: string
|
|
38
|
-
type?: string
|
|
39
|
-
size?: 'small' | 'medium' | 'large'
|
|
40
|
-
variant?: 'folderTree' | 'indent'
|
|
41
|
-
collectionIcon?: React.ReactNode | ((...args: any[]) => any)
|
|
42
|
-
collectionIconExpanded?: React.ReactNode | ((...args: any[]) => any)
|
|
43
|
-
itemIcon?: React.ReactNode | ((...args: any[]) => any)
|
|
39
|
+
type?: 'collection' | 'item' | string // | string is for custom type
|
|
44
40
|
thumbnail?: string
|
|
45
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Called when this button is clicked
|
|
43
|
+
*/
|
|
44
|
+
onClick?: (e: React.MouseEvent) => void
|
|
46
45
|
expanded?: boolean
|
|
47
46
|
selected?: boolean
|
|
48
47
|
focused?: boolean
|
|
49
48
|
level?: number
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
/**
|
|
50
|
+
* A function that returns a reference to the parent li element
|
|
51
|
+
*/
|
|
52
|
+
containerRef?: (el: HTMLElement | null) => void
|
|
53
|
+
} & TreeBrowserCommonProps
|
|
53
54
|
|
|
54
55
|
type PropKeys = keyof TreeBrowserButtonOwnProps
|
|
55
56
|
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
/** @jsx jsx */
|
|
26
26
|
/** @jsxFrag React.Fragment */
|
|
27
27
|
// eslint-disable-next-line no-unused-vars
|
|
28
|
-
import React, { Component } from 'react'
|
|
28
|
+
import React, { Component, ReactElement, SyntheticEvent } from 'react'
|
|
29
29
|
|
|
30
30
|
import { testable } from '@instructure/ui-testable'
|
|
31
31
|
import { withStyle, jsx } from '@instructure/emotion'
|
|
@@ -35,19 +35,25 @@ import { TreeButton } from '../TreeButton'
|
|
|
35
35
|
|
|
36
36
|
import generateStyles from './styles'
|
|
37
37
|
import generateComponentTheme from './theme'
|
|
38
|
-
import type { TreeBrowserCollectionProps } from './props'
|
|
38
|
+
import type { TreeBrowserCollectionProps, TreeCollectionState } from './props'
|
|
39
39
|
import { allowedProps, propTypes } from './props'
|
|
40
|
+
import { CollectionItem, CollectionProps, CollectionData } from '../props'
|
|
41
|
+
|
|
42
|
+
type AriaSelectedType = { 'aria-selected'?: boolean }
|
|
40
43
|
|
|
41
44
|
/**
|
|
42
45
|
---
|
|
43
46
|
parent: TreeBrowser
|
|
44
47
|
id: TreeBrowser.Collection
|
|
45
48
|
---
|
|
49
|
+
@tsProps
|
|
46
50
|
**/
|
|
47
|
-
|
|
48
51
|
@withStyle(generateStyles, generateComponentTheme)
|
|
49
52
|
@testable()
|
|
50
|
-
class TreeCollection extends Component<
|
|
53
|
+
class TreeCollection extends Component<
|
|
54
|
+
TreeBrowserCollectionProps,
|
|
55
|
+
TreeCollectionState
|
|
56
|
+
> {
|
|
51
57
|
static readonly componentId = 'TreeBrowser.Collection'
|
|
52
58
|
|
|
53
59
|
static allowedProps = allowedProps
|
|
@@ -60,34 +66,15 @@ class TreeCollection extends Component<TreeBrowserCollectionProps> {
|
|
|
60
66
|
selection: '',
|
|
61
67
|
size: 'medium',
|
|
62
68
|
variant: 'folderTree',
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
id: undefined,
|
|
67
|
-
name: undefined,
|
|
68
|
-
descriptor: undefined,
|
|
69
|
-
collectionIconExpanded: undefined,
|
|
70
|
-
collectionIcon: undefined,
|
|
71
|
-
itemIcon: undefined,
|
|
72
|
-
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'props' implicitly has an 'any' type.
|
|
73
|
-
getItemProps: (props) => props,
|
|
74
|
-
// @ts-expect-error ts-migrate(7006) FIXME: Parameter 'props' implicitly has an 'any' type.
|
|
75
|
-
getCollectionProps: (props) => props,
|
|
76
|
-
numChildren: undefined,
|
|
77
|
-
level: undefined,
|
|
78
|
-
position: undefined,
|
|
79
|
-
renderBeforeItems: null,
|
|
80
|
-
renderAfterItems: null,
|
|
81
|
-
containerRef: function () {},
|
|
82
|
-
isCollectionFlattened: false,
|
|
83
|
-
renderContent: undefined
|
|
69
|
+
getItemProps: (props: unknown) => props,
|
|
70
|
+
getCollectionProps: (props: unknown) => props,
|
|
71
|
+
isCollectionFlattened: false
|
|
84
72
|
}
|
|
73
|
+
|
|
85
74
|
ref: Element | null = null
|
|
86
75
|
|
|
87
|
-
|
|
88
|
-
constructor(props) {
|
|
76
|
+
constructor(props: TreeBrowserCollectionProps) {
|
|
89
77
|
super(props)
|
|
90
|
-
|
|
91
78
|
this.state = { focused: '' }
|
|
92
79
|
}
|
|
93
80
|
|
|
@@ -100,45 +87,38 @@ class TreeCollection extends Component<TreeBrowserCollectionProps> {
|
|
|
100
87
|
|
|
101
88
|
get itemsLevel() {
|
|
102
89
|
const { level, isCollectionFlattened } = this.props
|
|
103
|
-
// @ts-expect-error ts-migrate(2532) FIXME: Object is possibly 'undefined'.
|
|
104
90
|
return isCollectionFlattened ? level : level + 1
|
|
105
91
|
}
|
|
106
92
|
|
|
107
|
-
|
|
108
|
-
handleFocus = (e, item) => {
|
|
93
|
+
handleFocus = (e: SyntheticEvent, item: CollectionData) => {
|
|
109
94
|
e.stopPropagation()
|
|
110
95
|
this.setState({ focused: `${item.type}_${item.id}` })
|
|
111
96
|
}
|
|
112
97
|
|
|
113
|
-
|
|
114
|
-
handleBlur = (e, item) => {
|
|
98
|
+
handleBlur = (e: SyntheticEvent, _item: CollectionData) => {
|
|
115
99
|
e.stopPropagation()
|
|
116
100
|
this.setState({ focused: '' })
|
|
117
101
|
}
|
|
118
102
|
|
|
119
|
-
|
|
120
|
-
handleCollectionClick = (e) => {
|
|
103
|
+
handleCollectionClick = (e: React.MouseEvent) => {
|
|
121
104
|
const { id, onCollectionClick, expanded } = this.props
|
|
122
105
|
const collection = {
|
|
123
106
|
id,
|
|
124
107
|
expanded: !expanded,
|
|
125
|
-
type: 'collection'
|
|
108
|
+
type: 'collection' as const
|
|
126
109
|
}
|
|
127
|
-
|
|
128
110
|
if (onCollectionClick && typeof onCollectionClick === 'function') {
|
|
129
111
|
onCollectionClick(e, collection)
|
|
130
112
|
}
|
|
131
113
|
}
|
|
132
114
|
|
|
133
|
-
|
|
134
|
-
handleCollectionKeyDown = (e) => {
|
|
115
|
+
handleCollectionKeyDown = (e: React.KeyboardEvent) => {
|
|
135
116
|
const { id, onKeyDown, expanded } = this.props
|
|
136
117
|
const collection = {
|
|
137
118
|
id,
|
|
138
119
|
expanded: !expanded,
|
|
139
|
-
type: 'collection'
|
|
120
|
+
type: 'collection' as const
|
|
140
121
|
}
|
|
141
|
-
|
|
142
122
|
if (onKeyDown && typeof onKeyDown === 'function') {
|
|
143
123
|
onKeyDown(e, collection)
|
|
144
124
|
}
|
|
@@ -164,13 +144,8 @@ class TreeCollection extends Component<TreeBrowserCollectionProps> {
|
|
|
164
144
|
}
|
|
165
145
|
|
|
166
146
|
renderChildren() {
|
|
167
|
-
const {
|
|
168
|
-
|
|
169
|
-
items,
|
|
170
|
-
id,
|
|
171
|
-
renderBeforeItems,
|
|
172
|
-
renderAfterItems
|
|
173
|
-
} = this.props
|
|
147
|
+
const { collections, items, id, renderBeforeItems, renderAfterItems } =
|
|
148
|
+
this.props
|
|
174
149
|
|
|
175
150
|
let position = 1
|
|
176
151
|
return (
|
|
@@ -182,12 +157,10 @@ class TreeCollection extends Component<TreeBrowserCollectionProps> {
|
|
|
182
157
|
position++,
|
|
183
158
|
'before'
|
|
184
159
|
)}
|
|
185
|
-
{
|
|
186
|
-
{collections.map((collection) => {
|
|
160
|
+
{collections!.map((collection) => {
|
|
187
161
|
return this.renderCollectionNode(collection, position++)
|
|
188
162
|
})}
|
|
189
|
-
{
|
|
190
|
-
{items.map((item) => {
|
|
163
|
+
{items!.map((item) => {
|
|
191
164
|
return this.renderItemNode(item, position++)
|
|
192
165
|
})}
|
|
193
166
|
{renderAfterItems &&
|
|
@@ -201,23 +174,24 @@ class TreeCollection extends Component<TreeBrowserCollectionProps> {
|
|
|
201
174
|
)
|
|
202
175
|
}
|
|
203
176
|
|
|
204
|
-
|
|
205
|
-
|
|
177
|
+
renderCollectionChildren(
|
|
178
|
+
collectionId: string | number | undefined,
|
|
179
|
+
child: ReactElement,
|
|
180
|
+
position: number,
|
|
181
|
+
keyword: 'before' | 'after'
|
|
182
|
+
) {
|
|
206
183
|
const { selection, onKeyDown, getItemProps, styles } = this.props
|
|
207
184
|
const key = `${collectionId}_${keyword}`
|
|
208
|
-
const ariaSelected = {}
|
|
185
|
+
const ariaSelected: AriaSelectedType = {}
|
|
209
186
|
if (selection) {
|
|
210
|
-
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
|
211
187
|
ariaSelected['aria-selected'] = selection === `child_${key}`
|
|
212
188
|
}
|
|
213
189
|
|
|
214
|
-
const itemHash = { id: key, type: 'child' }
|
|
190
|
+
const itemHash: CollectionData = { id: key, type: 'child' }
|
|
215
191
|
|
|
216
|
-
|
|
217
|
-
const itemProps = getItemProps({
|
|
192
|
+
const itemProps = getItemProps!({
|
|
218
193
|
key: key,
|
|
219
194
|
selected: selection === `child_${key}`,
|
|
220
|
-
// @ts-expect-error ts-migrate(2339) FIXME: Property 'focused' does not exist on type 'Readonl... Remove this comment to see the full error message
|
|
221
195
|
focused: this.state.focused === `child_${key}`,
|
|
222
196
|
level: this.itemsLevel
|
|
223
197
|
})
|
|
@@ -227,8 +201,7 @@ class TreeCollection extends Component<TreeBrowserCollectionProps> {
|
|
|
227
201
|
id={key}
|
|
228
202
|
role="treeitem"
|
|
229
203
|
css={styles?.item}
|
|
230
|
-
|
|
231
|
-
tabIndex="-1"
|
|
204
|
+
tabIndex={-1}
|
|
232
205
|
key={key}
|
|
233
206
|
aria-posinset={position}
|
|
234
207
|
aria-setsize={this.childCount}
|
|
@@ -242,27 +215,23 @@ class TreeCollection extends Component<TreeBrowserCollectionProps> {
|
|
|
242
215
|
e.stopPropagation()
|
|
243
216
|
}
|
|
244
217
|
}}
|
|
245
|
-
|
|
246
|
-
onFocus={(e, n) => this.handleFocus(e, itemHash)}
|
|
218
|
+
onFocus={(e) => this.handleFocus(e, itemHash)}
|
|
247
219
|
// @ts-expect-error ts-migrate(2322) FIXME: Type '(e: any, n: any) => void' is not assignable ... Remove this comment to see the full error message
|
|
248
220
|
onKeyDown={(e, n) => {
|
|
249
221
|
if (typeof child.props.onKeyDown === 'function') {
|
|
250
222
|
child.props.onKeyDown(e, n)
|
|
251
223
|
} else {
|
|
252
|
-
|
|
253
|
-
onKeyDown(e, itemHash)
|
|
224
|
+
onKeyDown?.(e, itemHash)
|
|
254
225
|
}
|
|
255
226
|
}}
|
|
256
|
-
|
|
257
|
-
onBlur={(e, n) => this.handleBlur(e, itemHash)}
|
|
227
|
+
onBlur={(e) => this.handleBlur(e, itemHash)}
|
|
258
228
|
>
|
|
259
229
|
{safeCloneElement(child, itemProps)}
|
|
260
230
|
</li>
|
|
261
231
|
)
|
|
262
232
|
}
|
|
263
233
|
|
|
264
|
-
|
|
265
|
-
renderCollectionNode(collection, position) {
|
|
234
|
+
renderCollectionNode(collection: CollectionProps, position: number) {
|
|
266
235
|
return (
|
|
267
236
|
<TreeCollection
|
|
268
237
|
{...this.props}
|
|
@@ -284,57 +253,43 @@ class TreeCollection extends Component<TreeBrowserCollectionProps> {
|
|
|
284
253
|
)
|
|
285
254
|
}
|
|
286
255
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
selection,
|
|
291
|
-
onItemClick,
|
|
292
|
-
onKeyDown,
|
|
293
|
-
getItemProps,
|
|
294
|
-
styles
|
|
295
|
-
} = this.props
|
|
256
|
+
renderItemNode(item: CollectionItem, position: number) {
|
|
257
|
+
const { selection, onItemClick, onKeyDown, getItemProps, styles } =
|
|
258
|
+
this.props
|
|
296
259
|
|
|
297
|
-
const ariaSelected = {}
|
|
260
|
+
const ariaSelected: AriaSelectedType = {}
|
|
298
261
|
|
|
299
262
|
if (selection) {
|
|
300
|
-
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
|
301
263
|
ariaSelected['aria-selected'] = selection === `item_${item.id}`
|
|
302
264
|
}
|
|
303
265
|
|
|
304
|
-
const itemHash = { id: item.id, type: 'item' }
|
|
266
|
+
const itemHash: CollectionData = { id: item.id, type: 'item' }
|
|
305
267
|
|
|
306
|
-
|
|
307
|
-
const itemProps = getItemProps({
|
|
268
|
+
const itemProps = getItemProps!({
|
|
308
269
|
...this.getCommonButtonProps(),
|
|
309
270
|
id: item.id,
|
|
310
271
|
name: item.name,
|
|
311
272
|
descriptor: item.descriptor,
|
|
312
273
|
thumbnail: item.thumbnail,
|
|
313
274
|
selected: selection === `item_${item.id}`,
|
|
314
|
-
// @ts-expect-error ts-migrate(2339) FIXME: Property 'focused' does not exist on type 'Readonl... Remove this comment to see the full error message
|
|
315
275
|
focused: this.state.focused === `item_${item.id}`,
|
|
316
|
-
type: 'item'
|
|
276
|
+
type: 'item' as const
|
|
317
277
|
})
|
|
318
278
|
|
|
319
279
|
return (
|
|
320
280
|
<li
|
|
321
281
|
key={`i${position}`}
|
|
322
|
-
|
|
323
|
-
tabIndex="-1"
|
|
282
|
+
tabIndex={-1}
|
|
324
283
|
role="treeitem"
|
|
325
284
|
aria-label={item.name}
|
|
326
285
|
css={styles?.item}
|
|
327
286
|
aria-level={this.itemsLevel}
|
|
328
287
|
aria-posinset={position}
|
|
329
288
|
aria-setsize={this.childCount}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
// @ts-expect-error ts-migrate(2322) FIXME: Type '(e: any, n: any) => void' is not assignable ... Remove this comment to see the full error message
|
|
335
|
-
onFocus={(e, n) => this.handleFocus(e, itemHash)}
|
|
336
|
-
// @ts-expect-error ts-migrate(2322) FIXME: Type '(e: any, n: any) => void' is not assignable ... Remove this comment to see the full error message
|
|
337
|
-
onBlur={(e, n) => this.handleBlur(e, itemHash)}
|
|
289
|
+
onClick={(e) => onItemClick?.(e, itemHash)}
|
|
290
|
+
onKeyDown={(e) => onKeyDown?.(e, itemHash)}
|
|
291
|
+
onFocus={(e) => this.handleFocus(e, itemHash)}
|
|
292
|
+
onBlur={(e) => this.handleBlur(e, itemHash)}
|
|
338
293
|
{...ariaSelected}
|
|
339
294
|
>
|
|
340
295
|
<TreeButton {...itemProps} />
|
|
@@ -369,23 +324,20 @@ class TreeCollection extends Component<TreeBrowserCollectionProps> {
|
|
|
369
324
|
styles
|
|
370
325
|
} = this.props
|
|
371
326
|
|
|
372
|
-
|
|
373
|
-
const collectionProps = getCollectionProps({
|
|
327
|
+
const collectionProps = getCollectionProps!({
|
|
374
328
|
...this.getCommonButtonProps(),
|
|
375
329
|
expanded: expanded,
|
|
376
330
|
collectionIcon: collectionIcon,
|
|
377
331
|
collectionIconExpanded: collectionIconExpanded,
|
|
378
|
-
type: 'collection',
|
|
332
|
+
type: 'collection' as const,
|
|
379
333
|
containerRef: this.props.containerRef,
|
|
380
334
|
selected: this.props.selection === `collection_${id}`,
|
|
381
|
-
// @ts-expect-error ts-migrate(2339) FIXME: Property 'focused' does not exist on type 'Readonl... Remove this comment to see the full error message
|
|
382
335
|
focused: this.state.focused === `collection_${id}`,
|
|
383
336
|
level
|
|
384
337
|
})
|
|
385
338
|
|
|
386
|
-
const ariaSelected = {}
|
|
339
|
+
const ariaSelected: AriaSelectedType = {}
|
|
387
340
|
if (this.props.selection)
|
|
388
|
-
// @ts-expect-error ts-migrate(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
|
|
389
341
|
ariaSelected['aria-selected'] =
|
|
390
342
|
this.props.selection === `collection_${id}`
|
|
391
343
|
|
|
@@ -397,8 +349,7 @@ class TreeCollection extends Component<TreeBrowserCollectionProps> {
|
|
|
397
349
|
this.ref = el
|
|
398
350
|
}}
|
|
399
351
|
css={styles?.treeCollection}
|
|
400
|
-
|
|
401
|
-
tabIndex="-1"
|
|
352
|
+
tabIndex={-1}
|
|
402
353
|
role="treeitem"
|
|
403
354
|
aria-label={this.props.name}
|
|
404
355
|
aria-level={level}
|
|
@@ -407,10 +358,8 @@ class TreeCollection extends Component<TreeBrowserCollectionProps> {
|
|
|
407
358
|
aria-expanded={expanded}
|
|
408
359
|
onClick={this.handleCollectionClick}
|
|
409
360
|
onKeyDown={this.handleCollectionKeyDown}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
// @ts-expect-error ts-migrate(2322) FIXME: Type '(e: any, n: any) => void' is not assignable ... Remove this comment to see the full error message
|
|
413
|
-
onBlur={(e, n) => this.handleBlur(e, { id: id, type: 'collection' })}
|
|
361
|
+
onFocus={(e) => this.handleFocus(e, { id: id, type: 'collection' })}
|
|
362
|
+
onBlur={(e) => this.handleBlur(e, { id: id, type: 'collection' })}
|
|
414
363
|
{...ariaSelected}
|
|
415
364
|
>
|
|
416
365
|
<TreeButton {...collectionProps} />
|
|
@@ -28,40 +28,25 @@ import PropTypes from 'prop-types'
|
|
|
28
28
|
import { Children } from '@instructure/ui-prop-types'
|
|
29
29
|
|
|
30
30
|
import { TreeNode } from '../TreeNode'
|
|
31
|
+
import type { CollectionData } from '../props'
|
|
31
32
|
|
|
32
33
|
import type {
|
|
33
34
|
PropValidators,
|
|
34
35
|
TreeBrowserCollectionTheme
|
|
35
36
|
} from '@instructure/shared-types'
|
|
36
37
|
import type { WithStyleProps, ComponentStyle } from '@instructure/emotion'
|
|
38
|
+
import { CollectionProps, TreeBrowserBaseProps } from '../props'
|
|
37
39
|
|
|
38
40
|
type TreeBrowserCollectionOwnProps = {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
collections?: any[]
|
|
44
|
-
expanded?: boolean
|
|
45
|
-
selection?: string
|
|
46
|
-
size?: 'small' | 'medium' | 'large'
|
|
47
|
-
variant?: 'folderTree' | 'indent'
|
|
48
|
-
collectionIcon?: React.ReactNode | ((...args: any[]) => any)
|
|
49
|
-
collectionIconExpanded?: React.ReactNode | ((...args: any[]) => any)
|
|
50
|
-
itemIcon?: React.ReactNode | ((...args: any[]) => any)
|
|
51
|
-
getItemProps?: (...args: any[]) => any
|
|
52
|
-
getCollectionProps?: (...args: any[]) => any
|
|
53
|
-
onItemClick?: (...args: any[]) => any
|
|
54
|
-
onCollectionClick?: (...args: any[]) => any
|
|
55
|
-
onKeyDown?: (...args: any[]) => any
|
|
41
|
+
level: number
|
|
42
|
+
onKeyDown?: (e: React.KeyboardEvent, data: CollectionData) => void
|
|
43
|
+
// TODO it would be nice to use the same handler as in TreeBrowser
|
|
44
|
+
onItemClick?: (e: React.MouseEvent, data: CollectionData) => void
|
|
56
45
|
numChildren?: number
|
|
57
|
-
level?: number
|
|
58
46
|
position?: number
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
isCollectionFlattened?: boolean
|
|
63
|
-
renderContent?: (...args: any[]) => any
|
|
64
|
-
}
|
|
47
|
+
selection?: string
|
|
48
|
+
} & CollectionProps &
|
|
49
|
+
TreeBrowserBaseProps
|
|
65
50
|
|
|
66
51
|
type PropKeys = keyof TreeBrowserCollectionOwnProps
|
|
67
52
|
|
|
@@ -93,15 +78,9 @@ const propTypes: PropValidators<PropKeys> = {
|
|
|
93
78
|
onCollectionClick: PropTypes.func,
|
|
94
79
|
onKeyDown: PropTypes.func,
|
|
95
80
|
numChildren: PropTypes.number,
|
|
96
|
-
level: PropTypes.number,
|
|
81
|
+
level: PropTypes.number.isRequired,
|
|
97
82
|
position: PropTypes.number,
|
|
98
|
-
/**
|
|
99
|
-
* children of type TreeNode
|
|
100
|
-
*/
|
|
101
83
|
renderBeforeItems: Children.oneOf([TreeNode]),
|
|
102
|
-
/**
|
|
103
|
-
* children of type TreeNode
|
|
104
|
-
*/
|
|
105
84
|
renderAfterItems: Children.oneOf([TreeNode]),
|
|
106
85
|
containerRef: PropTypes.func,
|
|
107
86
|
isCollectionFlattened: PropTypes.bool,
|
|
@@ -136,5 +115,11 @@ const allowedProps: AllowedPropKeys = [
|
|
|
136
115
|
'renderContent'
|
|
137
116
|
]
|
|
138
117
|
|
|
139
|
-
|
|
118
|
+
type TreeCollectionState = { focused: string }
|
|
119
|
+
|
|
120
|
+
export type {
|
|
121
|
+
TreeBrowserCollectionProps,
|
|
122
|
+
TreeBrowserCollectionStyle,
|
|
123
|
+
TreeCollectionState
|
|
124
|
+
}
|
|
140
125
|
export { propTypes, allowedProps }
|
|
@@ -36,17 +36,17 @@ import generateComponentTheme from '../TreeButton/theme'
|
|
|
36
36
|
import type { TreeBrowserNodeProps } from './props'
|
|
37
37
|
import { allowedProps, propTypes } from './props'
|
|
38
38
|
|
|
39
|
+
// Todo: merge TreeButton and TreeNode: TreeButton should be a special type of TreeNode
|
|
40
|
+
|
|
39
41
|
/**
|
|
40
42
|
---
|
|
41
43
|
parent: TreeBrowser
|
|
42
44
|
id: TreeBrowser.Node
|
|
43
45
|
---
|
|
46
|
+
@tsProps
|
|
44
47
|
A helper class used to render the :renderBeforeItems and :renderAfterItems
|
|
45
48
|
in the TreeBrowser.
|
|
46
49
|
**/
|
|
47
|
-
|
|
48
|
-
// Todo: merge TreeButton and TreeNode: TreeButton should be a special type of TreeNode
|
|
49
|
-
|
|
50
50
|
@withStyle(generateStyles, generateComponentTheme)
|
|
51
51
|
@testable()
|
|
52
52
|
class TreeNode extends Component<TreeBrowserNodeProps> {
|
|
@@ -56,19 +56,10 @@ class TreeNode extends Component<TreeBrowserNodeProps> {
|
|
|
56
56
|
static propTypes = propTypes
|
|
57
57
|
|
|
58
58
|
static defaultProps = {
|
|
59
|
-
id: undefined,
|
|
60
59
|
size: 'medium',
|
|
61
60
|
variant: 'folderTree',
|
|
62
61
|
selected: false,
|
|
63
|
-
focused: false
|
|
64
|
-
children: undefined,
|
|
65
|
-
itemIcon: undefined,
|
|
66
|
-
thumbnail: undefined,
|
|
67
|
-
level: undefined,
|
|
68
|
-
containerRef: function () {},
|
|
69
|
-
parentRef: undefined,
|
|
70
|
-
onKeyDown: undefined,
|
|
71
|
-
onClick: undefined
|
|
62
|
+
focused: false
|
|
72
63
|
}
|
|
73
64
|
|
|
74
65
|
ref: Element | null = null
|
|
@@ -76,21 +67,20 @@ class TreeNode extends Component<TreeBrowserNodeProps> {
|
|
|
76
67
|
componentDidMount() {
|
|
77
68
|
this.props.makeStyles?.()
|
|
78
69
|
}
|
|
70
|
+
|
|
79
71
|
componentDidUpdate() {
|
|
80
72
|
this.props.makeStyles?.()
|
|
81
73
|
}
|
|
82
74
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
75
|
+
handleRef = (el: HTMLDivElement) => {
|
|
76
|
+
if (el && typeof this.props.containerRef === 'function') {
|
|
77
|
+
this.props.containerRef(el.parentElement)
|
|
78
|
+
}
|
|
87
79
|
this.ref = el
|
|
88
80
|
}
|
|
89
81
|
|
|
90
|
-
// @ts-expect-error ts-migrate(7030) FIXME: Not all code paths return a value.
|
|
91
82
|
renderItemImage() {
|
|
92
83
|
const { thumbnail, itemIcon, styles } = this.props
|
|
93
|
-
|
|
94
84
|
if (thumbnail) {
|
|
95
85
|
return (
|
|
96
86
|
<div css={styles?.thumbnail}>
|
|
@@ -98,15 +88,14 @@ class TreeNode extends Component<TreeBrowserNodeProps> {
|
|
|
98
88
|
</div>
|
|
99
89
|
)
|
|
100
90
|
}
|
|
101
|
-
|
|
102
91
|
if (itemIcon) {
|
|
103
92
|
return <div css={styles?.icon}>{callRenderProp(itemIcon)}</div>
|
|
104
93
|
}
|
|
94
|
+
return undefined
|
|
105
95
|
}
|
|
106
96
|
|
|
107
97
|
render() {
|
|
108
98
|
const { children, styles } = this.props
|
|
109
|
-
|
|
110
99
|
return (
|
|
111
100
|
<div ref={this.handleRef} tabIndex={-1} css={styles?.treeButton}>
|
|
112
101
|
<span css={styles?.layout}>
|
|
@@ -35,6 +35,7 @@ import type {
|
|
|
35
35
|
TreeBrowserButtonProps,
|
|
36
36
|
TreeBrowserButtonStyle
|
|
37
37
|
} from '../TreeButton/props'
|
|
38
|
+
import { CollectionData } from '../props'
|
|
38
39
|
|
|
39
40
|
type TreeBrowserNodeOwnProps = Pick<
|
|
40
41
|
TreeBrowserButtonProps,
|
|
@@ -49,7 +50,10 @@ type TreeBrowserNodeOwnProps = Pick<
|
|
|
49
50
|
| 'containerRef'
|
|
50
51
|
| 'onClick'
|
|
51
52
|
> & {
|
|
52
|
-
onKeyDown?: (
|
|
53
|
+
onKeyDown?: (e: React.KeyboardEvent, data: CollectionData) => void
|
|
54
|
+
/**
|
|
55
|
+
* The children to be rendered within the `<TreeNode />`
|
|
56
|
+
*/
|
|
53
57
|
children?: React.ReactNode
|
|
54
58
|
}
|
|
55
59
|
|
|
@@ -69,13 +73,7 @@ const propTypes: PropValidators<PropKeys> = {
|
|
|
69
73
|
itemIcon: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
|
70
74
|
thumbnail: PropTypes.string,
|
|
71
75
|
level: PropTypes.number,
|
|
72
|
-
/**
|
|
73
|
-
* The children to be rendered within the `<TreeNode />`
|
|
74
|
-
*/
|
|
75
76
|
children: PropTypes.node,
|
|
76
|
-
/**
|
|
77
|
-
* A function that returns a reference to the parent li element
|
|
78
|
-
*/
|
|
79
77
|
containerRef: PropTypes.func,
|
|
80
78
|
onKeyDown: PropTypes.func,
|
|
81
79
|
onClick: PropTypes.func
|