@instructure/ui-tree-browser 10.3.0 → 10.3.1-snapshot-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.
- package/CHANGELOG.md +8 -0
- package/package.json +14 -14
- package/src/TreeBrowser/README.md +886 -288
|
@@ -7,60 +7,163 @@ to receive a normalized data structure, examples can be seen at https://github.c
|
|
|
7
7
|
|
|
8
8
|
### Size
|
|
9
9
|
|
|
10
|
-
```js
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
- ```js
|
|
11
|
+
class Example extends React.Component {
|
|
12
|
+
constructor(props) {
|
|
13
|
+
super(props)
|
|
14
|
+
this.state = {
|
|
15
|
+
size: 'medium'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
this.sizes = ['small', 'medium', 'large']
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
handleSizeSelect = (e, size) => {
|
|
22
|
+
this.setState({ size })
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
render() {
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
<View display="block" margin="none none medium">
|
|
29
|
+
<RadioInputGroup
|
|
30
|
+
name="treeBrowserSize"
|
|
31
|
+
defaultValue="medium"
|
|
32
|
+
description={
|
|
33
|
+
<ScreenReaderContent>
|
|
34
|
+
TreeBrowser size selector
|
|
35
|
+
</ScreenReaderContent>
|
|
36
|
+
}
|
|
37
|
+
variant="toggle"
|
|
38
|
+
onChange={this.handleSizeSelect}
|
|
39
|
+
>
|
|
40
|
+
{this.sizes.map((size) => (
|
|
41
|
+
<RadioInput key={size} label={size} value={size} />
|
|
42
|
+
))}
|
|
43
|
+
</RadioInputGroup>
|
|
44
|
+
</View>
|
|
45
|
+
|
|
46
|
+
<TreeBrowser
|
|
47
|
+
size={this.state.size}
|
|
48
|
+
collections={{
|
|
49
|
+
1: {
|
|
50
|
+
id: 1,
|
|
51
|
+
name: 'Assignments',
|
|
52
|
+
collections: [2, 3],
|
|
53
|
+
items: [3],
|
|
54
|
+
descriptor: 'Class Assignments'
|
|
55
|
+
},
|
|
56
|
+
2: {
|
|
57
|
+
id: 2,
|
|
58
|
+
name: 'English Assignments',
|
|
59
|
+
collections: [4],
|
|
60
|
+
items: []
|
|
61
|
+
},
|
|
62
|
+
3: {
|
|
63
|
+
id: 3,
|
|
64
|
+
name: 'Math Assignments',
|
|
65
|
+
collections: [5],
|
|
66
|
+
items: [1, 2]
|
|
67
|
+
},
|
|
68
|
+
4: {
|
|
69
|
+
id: 4,
|
|
70
|
+
name: 'Reading Assignments',
|
|
71
|
+
collections: [],
|
|
72
|
+
items: [4]
|
|
73
|
+
},
|
|
74
|
+
5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
|
|
75
|
+
}}
|
|
76
|
+
items={{
|
|
77
|
+
1: { id: 1, name: 'Addition Worksheet' },
|
|
78
|
+
2: { id: 2, name: 'Subtraction Worksheet' },
|
|
79
|
+
3: { id: 3, name: 'General Questions' },
|
|
80
|
+
4: { id: 4, name: 'Vogon Poetry' },
|
|
81
|
+
5: {
|
|
82
|
+
id: 5,
|
|
83
|
+
name: 'Bistromath',
|
|
84
|
+
descriptor: 'Explain the Bistromathic Drive'
|
|
85
|
+
}
|
|
86
|
+
}}
|
|
87
|
+
defaultExpanded={[1, 3]}
|
|
88
|
+
rootId={1}
|
|
89
|
+
/>
|
|
90
|
+
</>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
22
93
|
}
|
|
23
94
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
95
|
+
render(<Example />)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- ```js
|
|
99
|
+
const Example = () => {
|
|
100
|
+
const [size, setSize] = useState('medium')
|
|
101
|
+
const sizes = ['small', 'medium', 'large']
|
|
102
|
+
|
|
103
|
+
const handleSizeSelect = (e, size) => {
|
|
104
|
+
setSize(size)
|
|
105
|
+
}
|
|
27
106
|
|
|
28
|
-
render () {
|
|
29
107
|
return (
|
|
30
108
|
<>
|
|
31
109
|
<View display="block" margin="none none medium">
|
|
32
110
|
<RadioInputGroup
|
|
33
111
|
name="treeBrowserSize"
|
|
34
112
|
defaultValue="medium"
|
|
35
|
-
description={
|
|
113
|
+
description={
|
|
114
|
+
<ScreenReaderContent>
|
|
115
|
+
TreeBrowser size selector
|
|
116
|
+
</ScreenReaderContent>
|
|
117
|
+
}
|
|
36
118
|
variant="toggle"
|
|
37
|
-
onChange={
|
|
119
|
+
onChange={handleSizeSelect}
|
|
38
120
|
>
|
|
39
|
-
{
|
|
121
|
+
{sizes.map((size) => (
|
|
122
|
+
<RadioInput key={size} label={size} value={size} />
|
|
123
|
+
))}
|
|
40
124
|
</RadioInputGroup>
|
|
41
125
|
</View>
|
|
42
126
|
|
|
43
127
|
<TreeBrowser
|
|
44
|
-
size={
|
|
128
|
+
size={size}
|
|
45
129
|
collections={{
|
|
46
130
|
1: {
|
|
47
131
|
id: 1,
|
|
48
|
-
name:
|
|
49
|
-
collections: [2,3],
|
|
132
|
+
name: 'Assignments',
|
|
133
|
+
collections: [2, 3],
|
|
50
134
|
items: [3],
|
|
51
|
-
descriptor:
|
|
135
|
+
descriptor: 'Class Assignments'
|
|
136
|
+
},
|
|
137
|
+
2: {
|
|
138
|
+
id: 2,
|
|
139
|
+
name: 'English Assignments',
|
|
140
|
+
collections: [4],
|
|
141
|
+
items: []
|
|
142
|
+
},
|
|
143
|
+
3: {
|
|
144
|
+
id: 3,
|
|
145
|
+
name: 'Math Assignments',
|
|
146
|
+
collections: [5],
|
|
147
|
+
items: [1, 2]
|
|
148
|
+
},
|
|
149
|
+
4: {
|
|
150
|
+
id: 4,
|
|
151
|
+
name: 'Reading Assignments',
|
|
152
|
+
collections: [],
|
|
153
|
+
items: [4]
|
|
52
154
|
},
|
|
53
|
-
|
|
54
|
-
3: { id: 3, name: "Math Assignments", collections: [5], items: [1,2] },
|
|
55
|
-
4: { id: 4, name: "Reading Assignments", collections: [], items: [4] },
|
|
56
|
-
5: { id: 5, name: "Advanced Math Assignments", items: [5]}
|
|
155
|
+
5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
|
|
57
156
|
}}
|
|
58
157
|
items={{
|
|
59
|
-
1: { id: 1, name:
|
|
60
|
-
2: { id: 2, name:
|
|
61
|
-
3: { id: 3, name:
|
|
62
|
-
4: { id: 4, name:
|
|
63
|
-
5: {
|
|
158
|
+
1: { id: 1, name: 'Addition Worksheet' },
|
|
159
|
+
2: { id: 2, name: 'Subtraction Worksheet' },
|
|
160
|
+
3: { id: 3, name: 'General Questions' },
|
|
161
|
+
4: { id: 4, name: 'Vogon Poetry' },
|
|
162
|
+
5: {
|
|
163
|
+
id: 5,
|
|
164
|
+
name: 'Bistromath',
|
|
165
|
+
descriptor: 'Explain the Bistromathic Drive'
|
|
166
|
+
}
|
|
64
167
|
}}
|
|
65
168
|
defaultExpanded={[1, 3]}
|
|
66
169
|
rootId={1}
|
|
@@ -68,80 +171,184 @@ class Example extends React.Component {
|
|
|
68
171
|
</>
|
|
69
172
|
)
|
|
70
173
|
}
|
|
71
|
-
}
|
|
72
174
|
|
|
73
|
-
render(<Example/>)
|
|
74
|
-
|
|
75
|
-
```
|
|
175
|
+
render(<Example />)
|
|
176
|
+
```
|
|
76
177
|
|
|
77
178
|
### Managing State
|
|
78
179
|
|
|
79
180
|
`<TreeBrowser />` can be fully controlled. The following example uses the `onCollectionToggle` callback function to set the state. It then uses the `expanded` prop to configure which collections are open or closed.
|
|
80
181
|
|
|
81
|
-
```js
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
182
|
+
- ```js
|
|
183
|
+
class Example extends React.Component {
|
|
184
|
+
constructor(props) {
|
|
185
|
+
super(props)
|
|
186
|
+
this.state = {
|
|
187
|
+
expanded: [2]
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
handleCollectionClick = (id, collection) => {
|
|
192
|
+
console.log(collection.id)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
handleCollectionToggle = (collection) => {
|
|
196
|
+
this.setState((state) => {
|
|
197
|
+
const expanded = [...state.expanded]
|
|
198
|
+
const index = expanded.indexOf(collection.id)
|
|
199
|
+
|
|
200
|
+
if (!collection.expanded) {
|
|
201
|
+
expanded.splice(index, 1)
|
|
202
|
+
} else if (index < 0) {
|
|
203
|
+
expanded.push(collection.id)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return { expanded }
|
|
207
|
+
})
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
render() {
|
|
211
|
+
return (
|
|
212
|
+
<TreeBrowser
|
|
213
|
+
variant="indent"
|
|
214
|
+
selectionType="single"
|
|
215
|
+
collections={{
|
|
216
|
+
1: { id: 1, name: 'Grade 1', collections: [2, 3, 6] },
|
|
217
|
+
2: {
|
|
218
|
+
id: 2,
|
|
219
|
+
name: 'Math Outcomes',
|
|
220
|
+
collections: [4],
|
|
221
|
+
items: [3, 4],
|
|
222
|
+
descriptor: '1 Group | 2 Outcomes'
|
|
223
|
+
},
|
|
224
|
+
3: {
|
|
225
|
+
id: 3,
|
|
226
|
+
name: 'Reading Outcome',
|
|
227
|
+
collections: [5],
|
|
228
|
+
items: [1, 2],
|
|
229
|
+
descriptor: '1 Group | 2 Outcomes'
|
|
230
|
+
},
|
|
231
|
+
4: {
|
|
232
|
+
id: 4,
|
|
233
|
+
name: 'Advanced Math',
|
|
234
|
+
items: [6],
|
|
235
|
+
descriptor: '1 Outcome'
|
|
236
|
+
},
|
|
237
|
+
5: {
|
|
238
|
+
id: 5,
|
|
239
|
+
name: 'Advanced Reading',
|
|
240
|
+
items: [5],
|
|
241
|
+
descriptor: '1 Group | 2 Outcomes'
|
|
242
|
+
},
|
|
243
|
+
6: {
|
|
244
|
+
id: 6,
|
|
245
|
+
name: 'Advanced Outcomes',
|
|
246
|
+
items: [5, 6],
|
|
247
|
+
descriptor: '2 Outcomes'
|
|
248
|
+
}
|
|
249
|
+
}}
|
|
250
|
+
items={{
|
|
251
|
+
1: { id: 1, name: 'Can read' },
|
|
252
|
+
2: { id: 2, name: 'Can write' },
|
|
253
|
+
3: { id: 3, name: 'Can add' },
|
|
254
|
+
4: { id: 4, name: 'Can subtract' },
|
|
255
|
+
5: { id: 5, name: 'Can read Shakespeare' },
|
|
256
|
+
6: { id: 6, name: 'Can do quantum physics' }
|
|
257
|
+
}}
|
|
258
|
+
showRootCollection={false}
|
|
259
|
+
rootId={1}
|
|
260
|
+
expanded={this.state.expanded}
|
|
261
|
+
onCollectionToggle={this.handleCollectionToggle}
|
|
262
|
+
onCollectionClick={this.handleCollectionClick}
|
|
263
|
+
/>
|
|
264
|
+
)
|
|
90
265
|
}
|
|
91
266
|
}
|
|
92
267
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
};
|
|
268
|
+
render(<Example />)
|
|
269
|
+
```
|
|
96
270
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const index = expanded.indexOf(collection.id)
|
|
271
|
+
- ```js
|
|
272
|
+
const Example = () => {
|
|
273
|
+
const [expanded, setExpanded] = useState([2])
|
|
101
274
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
275
|
+
const handleCollectionClick = (id, collection) => {
|
|
276
|
+
console.log(collection.id)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const handleCollectionToggle = (collection) => {
|
|
280
|
+
setExpanded((prevExpanded) => {
|
|
281
|
+
const newExpanded = [...prevExpanded]
|
|
282
|
+
const index = newExpanded.indexOf(collection.id)
|
|
107
283
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
284
|
+
if (!collection.expanded) {
|
|
285
|
+
newExpanded.splice(index, 1)
|
|
286
|
+
} else if (index < 0) {
|
|
287
|
+
newExpanded.push(collection.id)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return newExpanded
|
|
291
|
+
})
|
|
292
|
+
}
|
|
111
293
|
|
|
112
|
-
render () {
|
|
113
294
|
return (
|
|
114
295
|
<TreeBrowser
|
|
115
296
|
variant="indent"
|
|
116
297
|
selectionType="single"
|
|
117
298
|
collections={{
|
|
118
|
-
1: { id: 1, name:
|
|
119
|
-
2: {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
299
|
+
1: { id: 1, name: 'Grade 1', collections: [2, 3, 6] },
|
|
300
|
+
2: {
|
|
301
|
+
id: 2,
|
|
302
|
+
name: 'Math Outcomes',
|
|
303
|
+
collections: [4],
|
|
304
|
+
items: [3, 4],
|
|
305
|
+
descriptor: '1 Group | 2 Outcomes'
|
|
306
|
+
},
|
|
307
|
+
3: {
|
|
308
|
+
id: 3,
|
|
309
|
+
name: 'Reading Outcome',
|
|
310
|
+
collections: [5],
|
|
311
|
+
items: [1, 2],
|
|
312
|
+
descriptor: '1 Group | 2 Outcomes'
|
|
313
|
+
},
|
|
314
|
+
4: {
|
|
315
|
+
id: 4,
|
|
316
|
+
name: 'Advanced Math',
|
|
317
|
+
items: [6],
|
|
318
|
+
descriptor: '1 Outcome'
|
|
319
|
+
},
|
|
320
|
+
5: {
|
|
321
|
+
id: 5,
|
|
322
|
+
name: 'Advanced Reading',
|
|
323
|
+
items: [5],
|
|
324
|
+
descriptor: '1 Group | 2 Outcomes'
|
|
325
|
+
},
|
|
326
|
+
6: {
|
|
327
|
+
id: 6,
|
|
328
|
+
name: 'Advanced Outcomes',
|
|
329
|
+
items: [5, 6],
|
|
330
|
+
descriptor: '2 Outcomes'
|
|
331
|
+
}
|
|
124
332
|
}}
|
|
125
333
|
items={{
|
|
126
|
-
1: { id: 1, name:
|
|
127
|
-
2: { id: 2, name:
|
|
128
|
-
3: { id: 3, name:
|
|
129
|
-
4: { id: 4, name:
|
|
130
|
-
5: { id: 5, name:
|
|
131
|
-
6: { id: 6, name:
|
|
334
|
+
1: { id: 1, name: 'Can read' },
|
|
335
|
+
2: { id: 2, name: 'Can write' },
|
|
336
|
+
3: { id: 3, name: 'Can add' },
|
|
337
|
+
4: { id: 4, name: 'Can subtract' },
|
|
338
|
+
5: { id: 5, name: 'Can read Shakespeare' },
|
|
339
|
+
6: { id: 6, name: 'Can do quantum physics' }
|
|
132
340
|
}}
|
|
133
341
|
showRootCollection={false}
|
|
134
342
|
rootId={1}
|
|
135
|
-
expanded={
|
|
136
|
-
onCollectionToggle={
|
|
137
|
-
onCollectionClick={
|
|
343
|
+
expanded={expanded}
|
|
344
|
+
onCollectionToggle={handleCollectionToggle}
|
|
345
|
+
onCollectionClick={handleCollectionClick}
|
|
138
346
|
/>
|
|
139
347
|
)
|
|
140
348
|
}
|
|
141
|
-
}
|
|
142
349
|
|
|
143
|
-
render(<Example/>)
|
|
144
|
-
```
|
|
350
|
+
render(<Example />)
|
|
351
|
+
```
|
|
145
352
|
|
|
146
353
|
### Customizing Icons
|
|
147
354
|
|
|
@@ -292,117 +499,240 @@ type: example
|
|
|
292
499
|
|
|
293
500
|
An example of a `<TreeBrowser />` with a custom item after each collection.
|
|
294
501
|
|
|
295
|
-
```js
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
expanded: true,
|
|
304
|
-
hoveredLine: null
|
|
502
|
+
- ```js
|
|
503
|
+
class Example extends React.Component {
|
|
504
|
+
constructor(props) {
|
|
505
|
+
super(props)
|
|
506
|
+
this.state = {
|
|
507
|
+
expanded: true,
|
|
508
|
+
hoveredLine: null
|
|
509
|
+
}
|
|
305
510
|
}
|
|
306
|
-
}
|
|
307
511
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
512
|
+
renderInput = () => {
|
|
513
|
+
const { expanded } = this.state
|
|
514
|
+
if (expanded) {
|
|
515
|
+
return (
|
|
516
|
+
<InstUISettingsProvider
|
|
517
|
+
theme={
|
|
518
|
+
this.state.hoveredLine === 'renderAfter'
|
|
519
|
+
? {
|
|
520
|
+
componentOverrides: {
|
|
521
|
+
View: {
|
|
522
|
+
focusColorInfo: 'white'
|
|
523
|
+
},
|
|
524
|
+
TextInput: {
|
|
525
|
+
focusOutlineColor: 'white'
|
|
526
|
+
}
|
|
322
527
|
}
|
|
323
528
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
>
|
|
328
|
-
<View
|
|
329
|
-
as="div"
|
|
330
|
-
padding="xx-small"
|
|
331
|
-
onFocus={(e) => e.stopPropagation()}
|
|
332
|
-
onClick={(e) => e.stopPropagation()}
|
|
333
|
-
onMouseEnter={() => this.setState({ hoveredLine: 'renderAfter' })}
|
|
334
|
-
onMouseLeave={() => this.setState({ hoveredLine: 'null' })}
|
|
529
|
+
: undefined
|
|
530
|
+
}
|
|
335
531
|
>
|
|
336
|
-
<
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
}}
|
|
344
|
-
/>
|
|
345
|
-
<IconButton
|
|
346
|
-
screenReaderLabel="Cancel"
|
|
347
|
-
onClick={(e) => this.setExpand(e, !expanded)}
|
|
348
|
-
onKeyDown={(e) => {
|
|
349
|
-
if (e.code === 'Space' || e.code === 'Enter') {
|
|
350
|
-
e.preventDefault()
|
|
351
|
-
this.setExpand(e, !expanded)
|
|
352
|
-
}
|
|
353
|
-
}}
|
|
354
|
-
margin="0 0 0 small"
|
|
355
|
-
>
|
|
356
|
-
<IconXSolid />
|
|
357
|
-
</IconButton>
|
|
358
|
-
<IconButton
|
|
359
|
-
screenReaderLabel="Add new group"
|
|
360
|
-
onClick={(e) => this.setExpand(e, !expanded)}
|
|
361
|
-
onKeyDown={(e) => {
|
|
362
|
-
if (e.code === 'Space' || e.code === 'Enter') {
|
|
363
|
-
e.preventDefault()
|
|
364
|
-
this.setExpand(e, !expanded)
|
|
365
|
-
}
|
|
366
|
-
}}
|
|
367
|
-
margin="0 0 0 small"
|
|
532
|
+
<View
|
|
533
|
+
as="div"
|
|
534
|
+
padding="xx-small"
|
|
535
|
+
onFocus={(e) => e.stopPropagation()}
|
|
536
|
+
onClick={(e) => e.stopPropagation()}
|
|
537
|
+
onMouseEnter={() => this.setState({ hoveredLine: 'renderAfter' })}
|
|
538
|
+
onMouseLeave={() => this.setState({ hoveredLine: 'null' })}
|
|
368
539
|
>
|
|
369
|
-
<
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
540
|
+
<TextInput
|
|
541
|
+
placeholder="Enter new group name"
|
|
542
|
+
display="inline-block"
|
|
543
|
+
width="12rem"
|
|
544
|
+
renderLabel=""
|
|
545
|
+
onKeyDown={(e) => {
|
|
546
|
+
e.stopPropagation()
|
|
547
|
+
}}
|
|
548
|
+
/>
|
|
549
|
+
<IconButton
|
|
550
|
+
screenReaderLabel="Cancel"
|
|
551
|
+
onClick={(e) => this.setExpand(e, !expanded)}
|
|
552
|
+
onKeyDown={(e) => {
|
|
553
|
+
if (e.code === 'Space' || e.code === 'Enter') {
|
|
554
|
+
e.preventDefault()
|
|
555
|
+
this.setExpand(e, !expanded)
|
|
556
|
+
}
|
|
557
|
+
}}
|
|
558
|
+
margin="0 0 0 small"
|
|
559
|
+
>
|
|
560
|
+
<IconXSolid />
|
|
561
|
+
</IconButton>
|
|
562
|
+
<IconButton
|
|
563
|
+
screenReaderLabel="Add new group"
|
|
564
|
+
onClick={(e) => this.setExpand(e, !expanded)}
|
|
565
|
+
onKeyDown={(e) => {
|
|
566
|
+
if (e.code === 'Space' || e.code === 'Enter') {
|
|
567
|
+
e.preventDefault()
|
|
568
|
+
this.setExpand(e, !expanded)
|
|
569
|
+
}
|
|
570
|
+
}}
|
|
571
|
+
margin="0 0 0 small"
|
|
572
|
+
>
|
|
573
|
+
<IconCheckSolid />
|
|
574
|
+
</IconButton>
|
|
575
|
+
</View>
|
|
576
|
+
</InstUISettingsProvider>
|
|
577
|
+
)
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return <View as="div">Create New Group</View>
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
setExpand = (e, expanded) => {
|
|
584
|
+
e.stopPropagation()
|
|
585
|
+
this.setState({ expanded })
|
|
586
|
+
this._node.focus()
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
renderNode = () => {
|
|
590
|
+
const { expanded } = this.state
|
|
591
|
+
return (
|
|
592
|
+
<TreeBrowser.Node
|
|
593
|
+
containerRef={(el) => (this._node = el)}
|
|
594
|
+
onClick={(e) => this.setExpand(e, !expanded)}
|
|
595
|
+
onKeyDown={(e) => {
|
|
596
|
+
if (e.code === 'Space' || e.code === 'Enter') {
|
|
597
|
+
e.preventDefault()
|
|
598
|
+
this.setExpand(e, !expanded)
|
|
599
|
+
}
|
|
600
|
+
}}
|
|
601
|
+
itemIcon={this.state.expanded ? '' : <IconPlusLine />}
|
|
602
|
+
size="large"
|
|
603
|
+
>
|
|
604
|
+
{this.renderInput()}
|
|
605
|
+
</TreeBrowser.Node>
|
|
373
606
|
)
|
|
374
607
|
}
|
|
375
608
|
|
|
376
|
-
|
|
609
|
+
render() {
|
|
610
|
+
return (
|
|
611
|
+
<TreeBrowser
|
|
612
|
+
selectionType="single"
|
|
613
|
+
size="large"
|
|
614
|
+
defaultExpanded={[1, 2]}
|
|
615
|
+
collections={{
|
|
616
|
+
1: {
|
|
617
|
+
id: 1,
|
|
618
|
+
name: 'Grade 1',
|
|
619
|
+
collections: [2]
|
|
620
|
+
},
|
|
621
|
+
2: {
|
|
622
|
+
id: 2,
|
|
623
|
+
name: 'Math Outcomes',
|
|
624
|
+
collections: [],
|
|
625
|
+
items: [1, 2],
|
|
626
|
+
descriptor: '1 Group | 2 Outcomes',
|
|
627
|
+
renderAfterItems: this.renderNode()
|
|
628
|
+
}
|
|
629
|
+
}}
|
|
630
|
+
items={{
|
|
631
|
+
1: { id: 1, name: 'Can add' },
|
|
632
|
+
2: { id: 2, name: 'Can subtract' }
|
|
633
|
+
}}
|
|
634
|
+
showRootCollection={true}
|
|
635
|
+
rootId={1}
|
|
636
|
+
/>
|
|
637
|
+
)
|
|
638
|
+
}
|
|
377
639
|
}
|
|
378
640
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
641
|
+
render(<Example />)
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
- ```js
|
|
645
|
+
const Example = () => {
|
|
646
|
+
const [expanded, setExpanded] = useState(true)
|
|
647
|
+
const [hoveredLine, setHoveredLine] = useState(null)
|
|
648
|
+
const nodeRef = useRef(null)
|
|
649
|
+
|
|
650
|
+
const handleExpandToggle = useCallback((e, newExpandedState) => {
|
|
651
|
+
e.stopPropagation()
|
|
652
|
+
setExpanded(newExpandedState)
|
|
653
|
+
nodeRef.current?.focus()
|
|
654
|
+
}, [])
|
|
655
|
+
|
|
656
|
+
const handleKeyPress = useCallback(
|
|
657
|
+
(e, newExpandedState) => {
|
|
658
|
+
if (e.code === 'Space' || e.code === 'Enter') {
|
|
659
|
+
e.preventDefault()
|
|
660
|
+
handleExpandToggle(e, newExpandedState)
|
|
661
|
+
}
|
|
662
|
+
},
|
|
663
|
+
[handleExpandToggle]
|
|
664
|
+
)
|
|
384
665
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
666
|
+
const renderInput = () => {
|
|
667
|
+
if (expanded) {
|
|
668
|
+
return (
|
|
669
|
+
<InstUISettingsProvider
|
|
670
|
+
theme={
|
|
671
|
+
hoveredLine === 'renderAfter'
|
|
672
|
+
? {
|
|
673
|
+
componentOverrides: {
|
|
674
|
+
View: {
|
|
675
|
+
focusColorInfo: 'white'
|
|
676
|
+
},
|
|
677
|
+
TextInput: {
|
|
678
|
+
focusOutlineColor: 'white'
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
: undefined
|
|
683
|
+
}
|
|
684
|
+
>
|
|
685
|
+
<View
|
|
686
|
+
as="div"
|
|
687
|
+
padding="xx-small"
|
|
688
|
+
onFocus={(e) => e.stopPropagation()}
|
|
689
|
+
onClick={(e) => e.stopPropagation()}
|
|
690
|
+
onMouseEnter={() => setHoveredLine('renderAfter')}
|
|
691
|
+
onMouseLeave={() => setHoveredLine(null)}
|
|
692
|
+
>
|
|
693
|
+
<TextInput
|
|
694
|
+
placeholder="Enter new group name"
|
|
695
|
+
display="inline-block"
|
|
696
|
+
width="12rem"
|
|
697
|
+
renderLabel=""
|
|
698
|
+
onKeyDown={(e) => e.stopPropagation()}
|
|
699
|
+
/>
|
|
700
|
+
<IconButton
|
|
701
|
+
screenReaderLabel="Cancel"
|
|
702
|
+
onClick={(e) => handleExpandToggle(e, false)}
|
|
703
|
+
onKeyDown={(e) => handleKeyPress(e, false)}
|
|
704
|
+
margin="0 0 0 small"
|
|
705
|
+
>
|
|
706
|
+
<IconXSolid />
|
|
707
|
+
</IconButton>
|
|
708
|
+
<IconButton
|
|
709
|
+
screenReaderLabel="Add new group"
|
|
710
|
+
onClick={(e) => handleExpandToggle(e, false)}
|
|
711
|
+
onKeyDown={(e) => handleKeyPress(e, false)}
|
|
712
|
+
margin="0 0 0 small"
|
|
713
|
+
>
|
|
714
|
+
<IconCheckSolid />
|
|
715
|
+
</IconButton>
|
|
716
|
+
</View>
|
|
717
|
+
</InstUISettingsProvider>
|
|
718
|
+
)
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
return <View as="div">Create New Group</View>
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
const renderNode = () => (
|
|
388
725
|
<TreeBrowser.Node
|
|
389
|
-
containerRef={(el) => (
|
|
390
|
-
onClick={(e) =>
|
|
391
|
-
onKeyDown={(e) =>
|
|
392
|
-
|
|
393
|
-
e.preventDefault()
|
|
394
|
-
this.setExpand(e, !expanded)
|
|
395
|
-
}
|
|
396
|
-
}}
|
|
397
|
-
itemIcon={this.state.expanded ? '' : <IconPlusLine />}
|
|
726
|
+
containerRef={(el) => (nodeRef.current = el)}
|
|
727
|
+
onClick={(e) => handleExpandToggle(e, !expanded)}
|
|
728
|
+
onKeyDown={(e) => handleKeyPress(e, !expanded)}
|
|
729
|
+
itemIcon={expanded ? '' : <IconPlusLine />}
|
|
398
730
|
size="large"
|
|
399
731
|
>
|
|
400
|
-
{
|
|
732
|
+
{renderInput()}
|
|
401
733
|
</TreeBrowser.Node>
|
|
402
734
|
)
|
|
403
|
-
}
|
|
404
735
|
|
|
405
|
-
render() {
|
|
406
736
|
return (
|
|
407
737
|
<TreeBrowser
|
|
408
738
|
selectionType="single"
|
|
@@ -420,7 +750,7 @@ class Example extends React.Component {
|
|
|
420
750
|
collections: [],
|
|
421
751
|
items: [1, 2],
|
|
422
752
|
descriptor: '1 Group | 2 Outcomes',
|
|
423
|
-
renderAfterItems:
|
|
753
|
+
renderAfterItems: renderNode()
|
|
424
754
|
}
|
|
425
755
|
}}
|
|
426
756
|
items={{
|
|
@@ -432,10 +762,9 @@ class Example extends React.Component {
|
|
|
432
762
|
/>
|
|
433
763
|
)
|
|
434
764
|
}
|
|
435
|
-
}
|
|
436
765
|
|
|
437
|
-
render(<Example/>)
|
|
438
|
-
```
|
|
766
|
+
render(<Example />)
|
|
767
|
+
```
|
|
439
768
|
|
|
440
769
|
### Change the order of appearance of items and collections
|
|
441
770
|
|
|
@@ -449,156 +778,408 @@ This works with all collections and items of the TreeBrowser.
|
|
|
449
778
|
|
|
450
779
|
---
|
|
451
780
|
|
|
452
|
-
```js
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
size: 'medium',
|
|
461
|
-
sorted: false
|
|
781
|
+
- ```js
|
|
782
|
+
class Example extends React.Component {
|
|
783
|
+
constructor(props) {
|
|
784
|
+
super(props)
|
|
785
|
+
this.state = {
|
|
786
|
+
size: 'medium',
|
|
787
|
+
sorted: false
|
|
788
|
+
}
|
|
462
789
|
}
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
790
|
+
toggleSort = (event) => {
|
|
791
|
+
this.setState({ sorted: !this.state.sorted })
|
|
792
|
+
}
|
|
793
|
+
render() {
|
|
794
|
+
return (
|
|
795
|
+
<>
|
|
796
|
+
<View display="block" margin="none none medium">
|
|
797
|
+
<FormFieldGroup description="Turn on/off sorting">
|
|
470
798
|
<Checkbox
|
|
471
799
|
checked={this.state.sorted}
|
|
472
800
|
label="Sort"
|
|
473
801
|
onChange={this.toggleSort}
|
|
474
802
|
/>
|
|
475
|
-
|
|
803
|
+
</FormFieldGroup>
|
|
804
|
+
</View>
|
|
805
|
+
|
|
806
|
+
<TreeBrowser
|
|
807
|
+
size={this.state.size}
|
|
808
|
+
collections={{
|
|
809
|
+
1: {
|
|
810
|
+
id: 1,
|
|
811
|
+
name: 'Assignments',
|
|
812
|
+
collections: [3, 2],
|
|
813
|
+
items: [3],
|
|
814
|
+
descriptor: 'Class Assignments'
|
|
815
|
+
},
|
|
816
|
+
2: {
|
|
817
|
+
id: 2,
|
|
818
|
+
name: 'English Assignments',
|
|
819
|
+
collections: [4],
|
|
820
|
+
items: []
|
|
821
|
+
},
|
|
822
|
+
3: {
|
|
823
|
+
id: 3,
|
|
824
|
+
name: 'Math Assignments',
|
|
825
|
+
collections: [5],
|
|
826
|
+
items: [2, 1]
|
|
827
|
+
},
|
|
828
|
+
4: {
|
|
829
|
+
id: 4,
|
|
830
|
+
name: 'Reading Assignments',
|
|
831
|
+
collections: [],
|
|
832
|
+
items: [4]
|
|
833
|
+
},
|
|
834
|
+
5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
|
|
835
|
+
}}
|
|
836
|
+
items={{
|
|
837
|
+
1: { id: 1, name: 'Addition Worksheet' },
|
|
838
|
+
2: { id: 2, name: 'Subtraction Worksheet' },
|
|
839
|
+
3: { id: 3, name: 'General Questions' },
|
|
840
|
+
4: { id: 4, name: 'Vogon Poetry' },
|
|
841
|
+
5: {
|
|
842
|
+
id: 5,
|
|
843
|
+
name: 'Bistromath',
|
|
844
|
+
descriptor: 'Explain the Bistromathic Drive'
|
|
845
|
+
}
|
|
846
|
+
}}
|
|
847
|
+
defaultExpanded={[1, 3]}
|
|
848
|
+
rootId={1}
|
|
849
|
+
sortOrder={
|
|
850
|
+
this.state.sorted
|
|
851
|
+
? (a, b) => {
|
|
852
|
+
return a.name.localeCompare(b.name)
|
|
853
|
+
}
|
|
854
|
+
: (a, b) => {
|
|
855
|
+
return 0
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
/>
|
|
859
|
+
</>
|
|
860
|
+
)
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
render(<Example />)
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
- ```js
|
|
868
|
+
const Example = () => {
|
|
869
|
+
const [size, setSize] = useState('medium')
|
|
870
|
+
const [sorted, setSorted] = useState(false)
|
|
871
|
+
|
|
872
|
+
const toggleSort = () => {
|
|
873
|
+
setSorted(!sorted)
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
return (
|
|
877
|
+
<>
|
|
878
|
+
<View display="block" margin="none none medium">
|
|
879
|
+
<FormFieldGroup description="Turn on/off sorting">
|
|
880
|
+
<Checkbox checked={sorted} label="Sort" onChange={toggleSort} />
|
|
881
|
+
</FormFieldGroup>
|
|
476
882
|
</View>
|
|
477
883
|
|
|
478
884
|
<TreeBrowser
|
|
479
|
-
size={
|
|
885
|
+
size={size}
|
|
480
886
|
collections={{
|
|
481
887
|
1: {
|
|
482
888
|
id: 1,
|
|
483
|
-
name:
|
|
484
|
-
collections: [3,2],
|
|
889
|
+
name: 'Assignments',
|
|
890
|
+
collections: [3, 2],
|
|
485
891
|
items: [3],
|
|
486
|
-
descriptor:
|
|
892
|
+
descriptor: 'Class Assignments'
|
|
893
|
+
},
|
|
894
|
+
2: {
|
|
895
|
+
id: 2,
|
|
896
|
+
name: 'English Assignments',
|
|
897
|
+
collections: [4],
|
|
898
|
+
items: []
|
|
487
899
|
},
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
900
|
+
3: {
|
|
901
|
+
id: 3,
|
|
902
|
+
name: 'Math Assignments',
|
|
903
|
+
collections: [5],
|
|
904
|
+
items: [2, 1]
|
|
905
|
+
},
|
|
906
|
+
4: {
|
|
907
|
+
id: 4,
|
|
908
|
+
name: 'Reading Assignments',
|
|
909
|
+
collections: [],
|
|
910
|
+
items: [4]
|
|
911
|
+
},
|
|
912
|
+
5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
|
|
492
913
|
}}
|
|
493
914
|
items={{
|
|
494
|
-
1: { id: 1, name:
|
|
495
|
-
2: { id: 2, name:
|
|
496
|
-
3: { id: 3, name:
|
|
497
|
-
4: { id: 4, name:
|
|
498
|
-
5: {
|
|
915
|
+
1: { id: 1, name: 'Addition Worksheet' },
|
|
916
|
+
2: { id: 2, name: 'Subtraction Worksheet' },
|
|
917
|
+
3: { id: 3, name: 'General Questions' },
|
|
918
|
+
4: { id: 4, name: 'Vogon Poetry' },
|
|
919
|
+
5: {
|
|
920
|
+
id: 5,
|
|
921
|
+
name: 'Bistromath',
|
|
922
|
+
descriptor: 'Explain the Bistromathic Drive'
|
|
923
|
+
}
|
|
499
924
|
}}
|
|
500
925
|
defaultExpanded={[1, 3]}
|
|
501
926
|
rootId={1}
|
|
502
|
-
|
|
927
|
+
sortOrder={sorted ? (a, b) => a.name.localeCompare(b.name) : () => 0}
|
|
503
928
|
/>
|
|
504
929
|
</>
|
|
505
930
|
)
|
|
506
931
|
}
|
|
507
|
-
}
|
|
508
932
|
|
|
509
|
-
render(<Example/>)
|
|
510
|
-
|
|
511
|
-
```
|
|
933
|
+
render(<Example />)
|
|
934
|
+
```
|
|
512
935
|
|
|
513
936
|
There is another way to sort the children of one collection. By adding the `compareFunc` as the comparison function to the collection's properties. This will be effective only within the collection's scope. For more convenience, we support a prop called `type` to specify whether the collection's children is either an item or a subcollection (this is only make sense in `compareFunc`)
|
|
514
937
|
|
|
515
|
-
```js
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
this.state = {
|
|
523
|
-
size: 'medium'
|
|
938
|
+
- ```js
|
|
939
|
+
class Example extends React.Component {
|
|
940
|
+
constructor(props) {
|
|
941
|
+
super(props)
|
|
942
|
+
this.state = {
|
|
943
|
+
size: 'medium'
|
|
944
|
+
}
|
|
524
945
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
return (
|
|
946
|
+
render() {
|
|
947
|
+
return (
|
|
528
948
|
<TreeBrowser
|
|
529
949
|
size={this.state.size}
|
|
530
950
|
collections={{
|
|
531
951
|
1: {
|
|
532
952
|
id: 1,
|
|
533
|
-
name:
|
|
534
|
-
collections: [3,2],
|
|
953
|
+
name: 'Assignments',
|
|
954
|
+
collections: [3, 2],
|
|
535
955
|
items: [3],
|
|
536
|
-
descriptor:
|
|
956
|
+
descriptor: 'Class Assignments',
|
|
537
957
|
// Sort the direct children of "Assignment" by their name in alphabetical order
|
|
538
|
-
compareFunc: (a,b)=>{
|
|
539
|
-
|
|
540
|
-
2: { id: 2, name: "English Assignments", collections: [4], items: [] },
|
|
541
|
-
3: { id: 3, name: "Math Assignments", collections: [5], items: [2,1],
|
|
542
|
-
// The items appear before subcollections
|
|
543
|
-
compareFunc: (a,b)=>{
|
|
544
|
-
if(a.type === "item" && b.type === "collection"){
|
|
545
|
-
return -1
|
|
958
|
+
compareFunc: (a, b) => {
|
|
959
|
+
return a.name.localeCompare(b.name)
|
|
546
960
|
}
|
|
547
|
-
|
|
548
|
-
|
|
961
|
+
},
|
|
962
|
+
2: {
|
|
963
|
+
id: 2,
|
|
964
|
+
name: 'English Assignments',
|
|
965
|
+
collections: [4],
|
|
966
|
+
items: []
|
|
967
|
+
},
|
|
968
|
+
3: {
|
|
969
|
+
id: 3,
|
|
970
|
+
name: 'Math Assignments',
|
|
971
|
+
collections: [5],
|
|
972
|
+
items: [2, 1],
|
|
973
|
+
// The items appear before subcollections
|
|
974
|
+
compareFunc: (a, b) => {
|
|
975
|
+
if (a.type === 'item' && b.type === 'collection') {
|
|
976
|
+
return -1
|
|
977
|
+
}
|
|
978
|
+
if (a.type === 'collection' && b.type === 'item') {
|
|
979
|
+
return 1
|
|
980
|
+
}
|
|
981
|
+
return 0
|
|
549
982
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
983
|
+
},
|
|
984
|
+
4: {
|
|
985
|
+
id: 4,
|
|
986
|
+
name: 'Reading Assignments',
|
|
987
|
+
collections: [],
|
|
988
|
+
items: [4]
|
|
989
|
+
},
|
|
990
|
+
5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
|
|
554
991
|
}}
|
|
555
992
|
items={{
|
|
556
|
-
1: { id: 1, name:
|
|
557
|
-
2: { id: 2, name:
|
|
558
|
-
3: { id: 3, name:
|
|
559
|
-
4: { id: 4, name:
|
|
560
|
-
5: {
|
|
993
|
+
1: { id: 1, name: 'Addition Worksheet' },
|
|
994
|
+
2: { id: 2, name: 'Subtraction Worksheet' },
|
|
995
|
+
3: { id: 3, name: 'General Questions' },
|
|
996
|
+
4: { id: 4, name: 'Vogon Poetry' },
|
|
997
|
+
5: {
|
|
998
|
+
id: 5,
|
|
999
|
+
name: 'Bistromath',
|
|
1000
|
+
descriptor: 'Explain the Bistromathic Drive'
|
|
1001
|
+
}
|
|
561
1002
|
}}
|
|
562
1003
|
defaultExpanded={[1, 3]}
|
|
563
1004
|
rootId={1}
|
|
564
1005
|
/>
|
|
565
|
-
|
|
1006
|
+
)
|
|
1007
|
+
}
|
|
566
1008
|
}
|
|
567
|
-
}
|
|
568
1009
|
|
|
569
|
-
render(<Example/>)
|
|
1010
|
+
render(<Example />)
|
|
1011
|
+
```
|
|
570
1012
|
|
|
571
|
-
```
|
|
1013
|
+
- ```js
|
|
1014
|
+
const Example = () => {
|
|
1015
|
+
const [size, setSize] = useState('medium')
|
|
1016
|
+
|
|
1017
|
+
return (
|
|
1018
|
+
<TreeBrowser
|
|
1019
|
+
size={size}
|
|
1020
|
+
collections={{
|
|
1021
|
+
1: {
|
|
1022
|
+
id: 1,
|
|
1023
|
+
name: 'Assignments',
|
|
1024
|
+
collections: [3, 2],
|
|
1025
|
+
items: [3],
|
|
1026
|
+
descriptor: 'Class Assignments',
|
|
1027
|
+
// Sort the direct children of "Assignment" by their name in alphabetical order
|
|
1028
|
+
compareFunc: (a, b) => a.name.localeCompare(b.name)
|
|
1029
|
+
},
|
|
1030
|
+
2: {
|
|
1031
|
+
id: 2,
|
|
1032
|
+
name: 'English Assignments',
|
|
1033
|
+
collections: [4],
|
|
1034
|
+
items: []
|
|
1035
|
+
},
|
|
1036
|
+
3: {
|
|
1037
|
+
id: 3,
|
|
1038
|
+
name: 'Math Assignments',
|
|
1039
|
+
collections: [5],
|
|
1040
|
+
items: [2, 1],
|
|
1041
|
+
// The items appear before subcollections
|
|
1042
|
+
compareFunc: (a, b) => {
|
|
1043
|
+
if (a.type === 'item' && b.type === 'collection') {
|
|
1044
|
+
return -1
|
|
1045
|
+
}
|
|
1046
|
+
if (a.type === 'collection' && b.type === 'item') {
|
|
1047
|
+
return 1
|
|
1048
|
+
}
|
|
1049
|
+
return 0
|
|
1050
|
+
}
|
|
1051
|
+
},
|
|
1052
|
+
4: {
|
|
1053
|
+
id: 4,
|
|
1054
|
+
name: 'Reading Assignments',
|
|
1055
|
+
collections: [],
|
|
1056
|
+
items: [4]
|
|
1057
|
+
},
|
|
1058
|
+
5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
|
|
1059
|
+
}}
|
|
1060
|
+
items={{
|
|
1061
|
+
1: { id: 1, name: 'Addition Worksheet' },
|
|
1062
|
+
2: { id: 2, name: 'Subtraction Worksheet' },
|
|
1063
|
+
3: { id: 3, name: 'General Questions' },
|
|
1064
|
+
4: { id: 4, name: 'Vogon Poetry' },
|
|
1065
|
+
5: {
|
|
1066
|
+
id: 5,
|
|
1067
|
+
name: 'Bistromath',
|
|
1068
|
+
descriptor: 'Explain the Bistromathic Drive'
|
|
1069
|
+
}
|
|
1070
|
+
}}
|
|
1071
|
+
defaultExpanded={[1, 3]}
|
|
1072
|
+
rootId={1}
|
|
1073
|
+
/>
|
|
1074
|
+
)
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
render(<Example />)
|
|
1078
|
+
```
|
|
572
1079
|
|
|
573
1080
|
### showRootCollection
|
|
574
1081
|
|
|
575
1082
|
The `showRootCollection` prop sets whether the root collection (specified in `rootId` prop) is displayed or to begin with its immediate sub-collections and items instead. It defaults to `true`.
|
|
576
1083
|
|
|
577
|
-
```js
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
this.state = {
|
|
585
|
-
showRootCollection: true
|
|
1084
|
+
- ```js
|
|
1085
|
+
class Example extends React.Component {
|
|
1086
|
+
constructor(props) {
|
|
1087
|
+
super(props)
|
|
1088
|
+
this.state = {
|
|
1089
|
+
showRootCollection: true
|
|
1090
|
+
}
|
|
586
1091
|
}
|
|
587
|
-
}
|
|
588
1092
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
1093
|
+
handleSwitch = () => {
|
|
1094
|
+
this.setState({ showRootCollection: !this.state.showRootCollection })
|
|
1095
|
+
}
|
|
592
1096
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
1097
|
+
renderNode = () => {
|
|
1098
|
+
return (
|
|
1099
|
+
<TreeBrowser.Node itemIcon={<IconPlusLine />}>More</TreeBrowser.Node>
|
|
1100
|
+
)
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
render() {
|
|
1104
|
+
return (
|
|
1105
|
+
<>
|
|
1106
|
+
<View display="block" margin="none none medium">
|
|
1107
|
+
<Checkbox
|
|
1108
|
+
label="showRootCollection"
|
|
1109
|
+
variant="toggle"
|
|
1110
|
+
size="medium"
|
|
1111
|
+
checked={this.state.showRootCollection}
|
|
1112
|
+
onChange={this.handleSwitch}
|
|
1113
|
+
/>
|
|
1114
|
+
</View>
|
|
1115
|
+
|
|
1116
|
+
<TreeBrowser
|
|
1117
|
+
collections={{
|
|
1118
|
+
1: {
|
|
1119
|
+
id: 1,
|
|
1120
|
+
name: 'Assignments',
|
|
1121
|
+
collections: [2, 3],
|
|
1122
|
+
items: [3, 5],
|
|
1123
|
+
descriptor: 'Class Assignments',
|
|
1124
|
+
renderAfterItems: this.renderNode()
|
|
1125
|
+
},
|
|
1126
|
+
2: {
|
|
1127
|
+
id: 2,
|
|
1128
|
+
name: 'English Assignments',
|
|
1129
|
+
collections: [4],
|
|
1130
|
+
items: []
|
|
1131
|
+
},
|
|
1132
|
+
3: {
|
|
1133
|
+
id: 3,
|
|
1134
|
+
name: 'Math Assignments',
|
|
1135
|
+
collections: [5],
|
|
1136
|
+
items: [1, 2]
|
|
1137
|
+
},
|
|
1138
|
+
4: {
|
|
1139
|
+
id: 4,
|
|
1140
|
+
name: 'Reading Assignments',
|
|
1141
|
+
collections: [],
|
|
1142
|
+
items: [4]
|
|
1143
|
+
},
|
|
1144
|
+
5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
|
|
1145
|
+
}}
|
|
1146
|
+
items={{
|
|
1147
|
+
1: { id: 1, name: 'Addition Worksheet' },
|
|
1148
|
+
2: { id: 2, name: 'Subtraction Worksheet' },
|
|
1149
|
+
3: { id: 3, name: 'General Questions' },
|
|
1150
|
+
4: { id: 4, name: 'Vogon Poetry' },
|
|
1151
|
+
5: {
|
|
1152
|
+
id: 5,
|
|
1153
|
+
name: 'Bistromath',
|
|
1154
|
+
descriptor: 'Explain the Bistromathic Drive'
|
|
1155
|
+
}
|
|
1156
|
+
}}
|
|
1157
|
+
defaultExpanded={[1, 3]}
|
|
1158
|
+
rootId={1}
|
|
1159
|
+
showRootCollection={this.state.showRootCollection}
|
|
1160
|
+
/>
|
|
1161
|
+
</>
|
|
1162
|
+
)
|
|
1163
|
+
}
|
|
599
1164
|
}
|
|
600
1165
|
|
|
601
|
-
render
|
|
1166
|
+
render(<Example />)
|
|
1167
|
+
```
|
|
1168
|
+
|
|
1169
|
+
- ```js
|
|
1170
|
+
const Example = () => {
|
|
1171
|
+
const [showRootCollection, setShowRootCollection] = useState(true)
|
|
1172
|
+
|
|
1173
|
+
const handleSwitch = () => {
|
|
1174
|
+
setShowRootCollection(!showRootCollection)
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
const renderNode = () => {
|
|
1178
|
+
return (
|
|
1179
|
+
<TreeBrowser.Node itemIcon={<IconPlusLine />}>More</TreeBrowser.Node>
|
|
1180
|
+
)
|
|
1181
|
+
}
|
|
1182
|
+
|
|
602
1183
|
return (
|
|
603
1184
|
<>
|
|
604
1185
|
<View display="block" margin="none none medium">
|
|
@@ -606,8 +1187,8 @@ class Example extends React.Component {
|
|
|
606
1187
|
label="showRootCollection"
|
|
607
1188
|
variant="toggle"
|
|
608
1189
|
size="medium"
|
|
609
|
-
checked={
|
|
610
|
-
onChange={
|
|
1190
|
+
checked={showRootCollection}
|
|
1191
|
+
onChange={handleSwitch}
|
|
611
1192
|
/>
|
|
612
1193
|
</View>
|
|
613
1194
|
|
|
@@ -615,36 +1196,53 @@ class Example extends React.Component {
|
|
|
615
1196
|
collections={{
|
|
616
1197
|
1: {
|
|
617
1198
|
id: 1,
|
|
618
|
-
name:
|
|
619
|
-
collections: [2,3],
|
|
1199
|
+
name: 'Assignments',
|
|
1200
|
+
collections: [2, 3],
|
|
620
1201
|
items: [3, 5],
|
|
621
|
-
descriptor:
|
|
622
|
-
renderAfterItems:
|
|
1202
|
+
descriptor: 'Class Assignments',
|
|
1203
|
+
renderAfterItems: renderNode()
|
|
1204
|
+
},
|
|
1205
|
+
2: {
|
|
1206
|
+
id: 2,
|
|
1207
|
+
name: 'English Assignments',
|
|
1208
|
+
collections: [4],
|
|
1209
|
+
items: []
|
|
1210
|
+
},
|
|
1211
|
+
3: {
|
|
1212
|
+
id: 3,
|
|
1213
|
+
name: 'Math Assignments',
|
|
1214
|
+
collections: [5],
|
|
1215
|
+
items: [1, 2]
|
|
623
1216
|
},
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
1217
|
+
4: {
|
|
1218
|
+
id: 4,
|
|
1219
|
+
name: 'Reading Assignments',
|
|
1220
|
+
collections: [],
|
|
1221
|
+
items: [4]
|
|
1222
|
+
},
|
|
1223
|
+
5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
|
|
628
1224
|
}}
|
|
629
1225
|
items={{
|
|
630
|
-
1: { id: 1, name:
|
|
631
|
-
2: { id: 2, name:
|
|
632
|
-
3: { id: 3, name:
|
|
633
|
-
4: { id: 4, name:
|
|
634
|
-
5: {
|
|
1226
|
+
1: { id: 1, name: 'Addition Worksheet' },
|
|
1227
|
+
2: { id: 2, name: 'Subtraction Worksheet' },
|
|
1228
|
+
3: { id: 3, name: 'General Questions' },
|
|
1229
|
+
4: { id: 4, name: 'Vogon Poetry' },
|
|
1230
|
+
5: {
|
|
1231
|
+
id: 5,
|
|
1232
|
+
name: 'Bistromath',
|
|
1233
|
+
descriptor: 'Explain the Bistromathic Drive'
|
|
1234
|
+
}
|
|
635
1235
|
}}
|
|
636
1236
|
defaultExpanded={[1, 3]}
|
|
637
1237
|
rootId={1}
|
|
638
|
-
showRootCollection={
|
|
1238
|
+
showRootCollection={showRootCollection}
|
|
639
1239
|
/>
|
|
640
1240
|
</>
|
|
641
1241
|
)
|
|
642
1242
|
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
render(<Example/>)
|
|
646
1243
|
|
|
647
|
-
|
|
1244
|
+
render(<Example />)
|
|
1245
|
+
```
|
|
648
1246
|
|
|
649
1247
|
### Guidelines
|
|
650
1248
|
|