@instructure/ui-tree-browser 11.0.1-snapshot-0 → 11.0.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.
@@ -7,348 +7,177 @@ to receive a normalized data structure, examples can be seen at https://github.c
7
7
 
8
8
  ### Size
9
9
 
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 })
23
- }
24
-
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
- }
93
- }
94
-
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
- }
106
-
107
- return (
108
- <>
109
- <View display="block" margin="none none medium">
110
- <RadioInputGroup
111
- name="treeBrowserSize"
112
- defaultValue="medium"
113
- description={
114
- <ScreenReaderContent>
115
- TreeBrowser size selector
116
- </ScreenReaderContent>
117
- }
118
- variant="toggle"
119
- onChange={handleSizeSelect}
120
- >
121
- {sizes.map((size) => (
122
- <RadioInput key={size} label={size} value={size} />
123
- ))}
124
- </RadioInputGroup>
125
- </View>
126
-
127
- <TreeBrowser
128
- size={size}
129
- collections={{
130
- 1: {
131
- id: 1,
132
- name: 'Assignments',
133
- collections: [2, 3],
134
- items: [3],
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]
154
- },
155
- 5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
156
- }}
157
- items={{
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
- }
167
- }}
168
- defaultExpanded={[1, 3]}
169
- rootId={1}
170
- />
171
- </>
172
- )
173
- }
174
-
175
- render(<Example />)
176
- ```
177
-
178
- ### Managing State
179
-
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.
181
-
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
- }
10
+ ```js
11
+ ---
12
+ type: example
13
+ ---
14
+ const Example = () => {
15
+ const [size, setSize] = useState('medium')
16
+ const sizes = ['small', 'medium', 'large']
209
17
 
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
- )
265
- }
18
+ const handleSizeSelect = (e, size) => {
19
+ setSize(size)
266
20
  }
267
21
 
268
- render(<Example />)
269
- ```
270
-
271
- - ```js
272
- const Example = () => {
273
- const [expanded, setExpanded] = useState([2])
274
-
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)
283
-
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
- }
22
+ return (
23
+ <>
24
+ <View display="block" margin="none none medium">
25
+ <RadioInputGroup
26
+ name="treeBrowserSize"
27
+ defaultValue="medium"
28
+ description={
29
+ <ScreenReaderContent>
30
+ TreeBrowser size selector
31
+ </ScreenReaderContent>
32
+ }
33
+ variant="toggle"
34
+ onChange={handleSizeSelect}
35
+ >
36
+ {sizes.map((size) => (
37
+ <RadioInput key={size} label={size} value={size} />
38
+ ))}
39
+ </RadioInputGroup>
40
+ </View>
293
41
 
294
- return (
295
42
  <TreeBrowser
296
- variant="indent"
297
- selectionType="single"
43
+ size={size}
298
44
  collections={{
299
- 1: { id: 1, name: 'Grade 1', collections: [2, 3, 6] },
45
+ 1: {
46
+ id: 1,
47
+ name: 'Assignments',
48
+ collections: [2, 3],
49
+ items: [3],
50
+ descriptor: 'Class Assignments'
51
+ },
300
52
  2: {
301
53
  id: 2,
302
- name: 'Math Outcomes',
54
+ name: 'English Assignments',
303
55
  collections: [4],
304
- items: [3, 4],
305
- descriptor: '1 Group | 2 Outcomes'
56
+ items: []
306
57
  },
307
58
  3: {
308
59
  id: 3,
309
- name: 'Reading Outcome',
60
+ name: 'Math Assignments',
310
61
  collections: [5],
311
- items: [1, 2],
312
- descriptor: '1 Group | 2 Outcomes'
62
+ items: [1, 2]
313
63
  },
314
64
  4: {
315
65
  id: 4,
316
- name: 'Advanced Math',
317
- items: [6],
318
- descriptor: '1 Outcome'
66
+ name: 'Reading Assignments',
67
+ collections: [],
68
+ items: [4]
319
69
  },
70
+ 5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
71
+ }}
72
+ items={{
73
+ 1: { id: 1, name: 'Addition Worksheet' },
74
+ 2: { id: 2, name: 'Subtraction Worksheet' },
75
+ 3: { id: 3, name: 'General Questions' },
76
+ 4: { id: 4, name: 'Vogon Poetry' },
320
77
  5: {
321
78
  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'
79
+ name: 'Bistromath',
80
+ descriptor: 'Explain the Bistromathic Drive'
331
81
  }
332
82
  }}
333
- items={{
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' }
340
- }}
341
- showRootCollection={false}
83
+ defaultExpanded={[1, 3]}
342
84
  rootId={1}
343
- expanded={expanded}
344
- onCollectionToggle={handleCollectionToggle}
345
- onCollectionClick={handleCollectionClick}
346
85
  />
347
- )
86
+ </>
87
+ )
88
+ }
89
+
90
+ render(<Example />)
91
+ ```
92
+
93
+ ### Managing State
94
+
95
+ `<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.
96
+
97
+ ```js
98
+ ---
99
+ type: example
100
+ ---
101
+ const Example = () => {
102
+ const [expanded, setExpanded] = useState([2])
103
+
104
+ const handleCollectionClick = (id, collection) => {
105
+ console.log(collection.id)
106
+ }
107
+
108
+ const handleCollectionToggle = (collection) => {
109
+ setExpanded((prevExpanded) => {
110
+ const newExpanded = [...prevExpanded]
111
+ const index = newExpanded.indexOf(collection.id)
112
+
113
+ if (!collection.expanded) {
114
+ newExpanded.splice(index, 1)
115
+ } else if (index < 0) {
116
+ newExpanded.push(collection.id)
117
+ }
118
+
119
+ return newExpanded
120
+ })
348
121
  }
349
122
 
350
- render(<Example />)
351
- ```
123
+ return (
124
+ <TreeBrowser
125
+ variant="indent"
126
+ selectionType="single"
127
+ collections={{
128
+ 1: { id: 1, name: 'Grade 1', collections: [2, 3, 6] },
129
+ 2: {
130
+ id: 2,
131
+ name: 'Math Outcomes',
132
+ collections: [4],
133
+ items: [3, 4],
134
+ descriptor: '1 Group | 2 Outcomes'
135
+ },
136
+ 3: {
137
+ id: 3,
138
+ name: 'Reading Outcome',
139
+ collections: [5],
140
+ items: [1, 2],
141
+ descriptor: '1 Group | 2 Outcomes'
142
+ },
143
+ 4: {
144
+ id: 4,
145
+ name: 'Advanced Math',
146
+ items: [6],
147
+ descriptor: '1 Outcome'
148
+ },
149
+ 5: {
150
+ id: 5,
151
+ name: 'Advanced Reading',
152
+ items: [5],
153
+ descriptor: '1 Group | 2 Outcomes'
154
+ },
155
+ 6: {
156
+ id: 6,
157
+ name: 'Advanced Outcomes',
158
+ items: [5, 6],
159
+ descriptor: '2 Outcomes'
160
+ }
161
+ }}
162
+ items={{
163
+ 1: { id: 1, name: 'Can read' },
164
+ 2: { id: 2, name: 'Can write' },
165
+ 3: { id: 3, name: 'Can add' },
166
+ 4: { id: 4, name: 'Can subtract' },
167
+ 5: { id: 5, name: 'Can read Shakespeare' },
168
+ 6: { id: 6, name: 'Can do quantum physics' }
169
+ }}
170
+ showRootCollection={false}
171
+ rootId={1}
172
+ expanded={expanded}
173
+ onCollectionToggle={handleCollectionToggle}
174
+ onCollectionClick={handleCollectionClick}
175
+ />
176
+ )
177
+ }
178
+
179
+ render(<Example />)
180
+ ```
352
181
 
353
182
  ### Customizing Icons
354
183
 
@@ -499,533 +328,332 @@ type: example
499
328
 
500
329
  An example of a `<TreeBrowser />` with a custom item after each collection.
501
330
 
502
- - ```js
503
- class Example extends React.Component {
504
- constructor(props) {
505
- super(props)
506
- this.state = {
507
- expanded: true,
508
- hoveredLine: null
331
+ ```js
332
+ ---
333
+ type: example
334
+ ---
335
+ const Example = () => {
336
+ const [expanded, setExpanded] = useState(true)
337
+ const [hoveredLine, setHoveredLine] = useState(null)
338
+ const nodeRef = useRef(null)
339
+
340
+ const handleExpandToggle = useCallback((e, newExpandedState) => {
341
+ e.stopPropagation()
342
+ setExpanded(newExpandedState)
343
+ nodeRef.current?.focus()
344
+ }, [])
345
+
346
+ const handleKeyPress = useCallback(
347
+ (e, newExpandedState) => {
348
+ if (e.code === 'Space' || e.code === 'Enter') {
349
+ e.preventDefault()
350
+ handleExpandToggle(e, newExpandedState)
509
351
  }
510
- }
352
+ },
353
+ [handleExpandToggle]
354
+ )
511
355
 
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
- }
356
+ const renderInput = () => {
357
+ if (expanded) {
358
+ return (
359
+ <InstUISettingsProvider
360
+ theme={
361
+ hoveredLine === 'renderAfter'
362
+ ? {
363
+ componentOverrides: {
364
+ View: {
365
+ focusColorInfo: 'white'
366
+ },
367
+ TextInput: {
368
+ focusOutlineColor: 'white'
527
369
  }
528
370
  }
529
- : undefined
530
- }
371
+ }
372
+ : undefined
373
+ }
374
+ >
375
+ <View
376
+ as="div"
377
+ padding="xx-small"
378
+ onFocus={(e) => e.stopPropagation()}
379
+ onClick={(e) => e.stopPropagation()}
380
+ onMouseEnter={() => setHoveredLine('renderAfter')}
381
+ onMouseLeave={() => setHoveredLine(null)}
531
382
  >
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' })}
383
+ <TextInput
384
+ placeholder="Enter new group name"
385
+ display="inline-block"
386
+ width="12rem"
387
+ renderLabel=""
388
+ onKeyDown={(e) => e.stopPropagation()}
389
+ />
390
+ <IconButton
391
+ screenReaderLabel="Cancel"
392
+ onClick={(e) => handleExpandToggle(e, false)}
393
+ onKeyDown={(e) => handleKeyPress(e, false)}
394
+ margin="0 0 0 small"
539
395
  >
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>
396
+ <IconXSolid />
397
+ </IconButton>
398
+ <IconButton
399
+ screenReaderLabel="Add new group"
400
+ onClick={(e) => handleExpandToggle(e, false)}
401
+ onKeyDown={(e) => handleKeyPress(e, false)}
402
+ margin="0 0 0 small"
403
+ >
404
+ <IconCheckSolid />
405
+ </IconButton>
406
+ </View>
407
+ </InstUISettingsProvider>
606
408
  )
607
409
  }
608
410
 
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
- }
411
+ return <View as="div">Create New Group</View>
639
412
  }
640
413
 
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)
414
+ const renderNode = () => (
415
+ <TreeBrowser.Node
416
+ containerRef={(el) => (nodeRef.current = el)}
417
+ onClick={(e) => handleExpandToggle(e, !expanded)}
418
+ onKeyDown={(e) => handleKeyPress(e, !expanded)}
419
+ itemIcon={expanded ? '' : <IconPlusLine />}
420
+ size="large"
421
+ >
422
+ {renderInput()}
423
+ </TreeBrowser.Node>
424
+ )
425
+
426
+ return (
427
+ <TreeBrowser
428
+ selectionType="single"
429
+ size="large"
430
+ defaultExpanded={[1, 2]}
431
+ collections={{
432
+ 1: {
433
+ id: 1,
434
+ name: 'Grade 1',
435
+ collections: [2]
436
+ },
437
+ 2: {
438
+ id: 2,
439
+ name: 'Math Outcomes',
440
+ collections: [],
441
+ items: [1, 2],
442
+ descriptor: '1 Group | 2 Outcomes',
443
+ renderAfterItems: renderNode()
661
444
  }
662
- },
663
- [handleExpandToggle]
664
- )
445
+ }}
446
+ items={{
447
+ 1: { id: 1, name: 'Can add' },
448
+ 2: { id: 2, name: 'Can subtract' }
449
+ }}
450
+ showRootCollection={true}
451
+ rootId={1}
452
+ />
453
+ )
454
+ }
455
+
456
+ render(<Example />)
457
+ ```
665
458
 
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
- }
459
+ ### Change the order of appearance of items and collections
720
460
 
721
- return <View as="div">Create New Group</View>
722
- }
461
+ By default, the order of collections and items depend on the order of `collections` and `items` array. We can override it by providing a `sortOrder` comparison function.
723
462
 
724
- const renderNode = () => (
725
- <TreeBrowser.Node
726
- containerRef={(el) => (nodeRef.current = el)}
727
- onClick={(e) => handleExpandToggle(e, !expanded)}
728
- onKeyDown={(e) => handleKeyPress(e, !expanded)}
729
- itemIcon={expanded ? '' : <IconPlusLine />}
730
- size="large"
731
- >
732
- {renderInput()}
733
- </TreeBrowser.Node>
734
- )
463
+ ---
464
+
465
+ **NOTE**
466
+
467
+ This works with all collections and items of the TreeBrowser.
468
+
469
+ ---
470
+
471
+ ```js
472
+ ---
473
+ type: example
474
+ ---
475
+ const Example = () => {
476
+ const [size, setSize] = useState('medium')
477
+ const [sorted, setSorted] = useState(false)
478
+
479
+ const toggleSort = () => {
480
+ setSorted(!sorted)
481
+ }
482
+
483
+ return (
484
+ <>
485
+ <View display="block" margin="none none medium">
486
+ <FormFieldGroup description="Turn on/off sorting">
487
+ <Checkbox checked={sorted} label="Sort" onChange={toggleSort} />
488
+ </FormFieldGroup>
489
+ </View>
735
490
 
736
- return (
737
491
  <TreeBrowser
738
- selectionType="single"
739
- size="large"
740
- defaultExpanded={[1, 2]}
492
+ size={size}
741
493
  collections={{
742
494
  1: {
743
495
  id: 1,
744
- name: 'Grade 1',
745
- collections: [2]
496
+ name: 'Assignments',
497
+ collections: [3, 2],
498
+ items: [3],
499
+ descriptor: 'Class Assignments'
746
500
  },
747
501
  2: {
748
502
  id: 2,
749
- name: 'Math Outcomes',
503
+ name: 'English Assignments',
504
+ collections: [4],
505
+ items: []
506
+ },
507
+ 3: {
508
+ id: 3,
509
+ name: 'Math Assignments',
510
+ collections: [5],
511
+ items: [2, 1]
512
+ },
513
+ 4: {
514
+ id: 4,
515
+ name: 'Reading Assignments',
750
516
  collections: [],
751
- items: [1, 2],
752
- descriptor: '1 Group | 2 Outcomes',
753
- renderAfterItems: renderNode()
754
- }
517
+ items: [4]
518
+ },
519
+ 5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
755
520
  }}
756
521
  items={{
757
- 1: { id: 1, name: 'Can add' },
758
- 2: { id: 2, name: 'Can subtract' }
522
+ 1: { id: 1, name: 'Addition Worksheet' },
523
+ 2: { id: 2, name: 'Subtraction Worksheet' },
524
+ 3: { id: 3, name: 'General Questions' },
525
+ 4: { id: 4, name: 'Vogon Poetry' },
526
+ 5: {
527
+ id: 5,
528
+ name: 'Bistromath',
529
+ descriptor: 'Explain the Bistromathic Drive'
530
+ }
759
531
  }}
760
- showRootCollection={true}
532
+ defaultExpanded={[1, 3]}
761
533
  rootId={1}
534
+ sortOrder={sorted ? (a, b) => a.name.localeCompare(b.name) : () => 0}
762
535
  />
763
- )
764
- }
765
-
766
- render(<Example />)
767
- ```
536
+ </>
537
+ )
538
+ }
768
539
 
769
- ### Change the order of appearance of items and collections
540
+ render(<Example />)
541
+ ```
770
542
 
771
- By default, the order of collections and items depend on the order of `collections` and `items` array. We can override it by providing a `sortOrder` comparison function.
543
+ 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`)
772
544
 
545
+ ```js
546
+ ---
547
+ type: example
773
548
  ---
549
+ const Example = () => {
550
+ const [size, setSize] = useState('medium')
551
+
552
+ return (
553
+ <TreeBrowser
554
+ size={size}
555
+ collections={{
556
+ 1: {
557
+ id: 1,
558
+ name: 'Assignments',
559
+ collections: [3, 2],
560
+ items: [3],
561
+ descriptor: 'Class Assignments',
562
+ // Sort the direct children of "Assignment" by their name in alphabetical order
563
+ compareFunc: (a, b) => a.name.localeCompare(b.name)
564
+ },
565
+ 2: {
566
+ id: 2,
567
+ name: 'English Assignments',
568
+ collections: [4],
569
+ items: []
570
+ },
571
+ 3: {
572
+ id: 3,
573
+ name: 'Math Assignments',
574
+ collections: [5],
575
+ items: [2, 1],
576
+ // The items appear before subcollections
577
+ compareFunc: (a, b) => {
578
+ if (a.type === 'item' && b.type === 'collection') {
579
+ return -1
580
+ }
581
+ if (a.type === 'collection' && b.type === 'item') {
582
+ return 1
583
+ }
584
+ return 0
585
+ }
586
+ },
587
+ 4: {
588
+ id: 4,
589
+ name: 'Reading Assignments',
590
+ collections: [],
591
+ items: [4]
592
+ },
593
+ 5: { id: 5, name: 'Advanced Math Assignments', items: [5] }
594
+ }}
595
+ items={{
596
+ 1: { id: 1, name: 'Addition Worksheet' },
597
+ 2: { id: 2, name: 'Subtraction Worksheet' },
598
+ 3: { id: 3, name: 'General Questions' },
599
+ 4: { id: 4, name: 'Vogon Poetry' },
600
+ 5: {
601
+ id: 5,
602
+ name: 'Bistromath',
603
+ descriptor: 'Explain the Bistromathic Drive'
604
+ }
605
+ }}
606
+ defaultExpanded={[1, 3]}
607
+ rootId={1}
608
+ />
609
+ )
610
+ }
611
+
612
+ render(<Example />)
613
+ ```
774
614
 
775
- **NOTE**
615
+ ### showRootCollection
776
616
 
777
- This works with all collections and items of the TreeBrowser.
617
+ 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`.
778
618
 
619
+ ```js
779
620
  ---
621
+ type: example
622
+ ---
623
+ const Example = () => {
624
+ const [showRootCollection, setShowRootCollection] = useState(true)
780
625
 
781
- - ```js
782
- class Example extends React.Component {
783
- constructor(props) {
784
- super(props)
785
- this.state = {
786
- size: 'medium',
787
- sorted: false
788
- }
789
- }
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">
798
- <Checkbox
799
- checked={this.state.sorted}
800
- label="Sort"
801
- onChange={this.toggleSort}
802
- />
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
- }
626
+ const handleSwitch = () => {
627
+ setShowRootCollection(!showRootCollection)
862
628
  }
863
629
 
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
-
630
+ const renderNode = () => {
876
631
  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>
882
- </View>
883
-
884
- <TreeBrowser
885
- size={size}
886
- collections={{
887
- 1: {
888
- id: 1,
889
- name: 'Assignments',
890
- collections: [3, 2],
891
- items: [3],
892
- descriptor: 'Class Assignments'
893
- },
894
- 2: {
895
- id: 2,
896
- name: 'English Assignments',
897
- collections: [4],
898
- items: []
899
- },
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] }
913
- }}
914
- items={{
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
- }
924
- }}
925
- defaultExpanded={[1, 3]}
926
- rootId={1}
927
- sortOrder={sorted ? (a, b) => a.name.localeCompare(b.name) : () => 0}
928
- />
929
- </>
632
+ <TreeBrowser.Node itemIcon={<IconPlusLine />}>More</TreeBrowser.Node>
930
633
  )
931
634
  }
932
635
 
933
- render(<Example />)
934
- ```
935
-
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`)
937
-
938
- - ```js
939
- class Example extends React.Component {
940
- constructor(props) {
941
- super(props)
942
- this.state = {
943
- size: 'medium'
944
- }
945
- }
946
- render() {
947
- return (
948
- <TreeBrowser
949
- size={this.state.size}
950
- collections={{
951
- 1: {
952
- id: 1,
953
- name: 'Assignments',
954
- collections: [3, 2],
955
- items: [3],
956
- descriptor: 'Class Assignments',
957
- // Sort the direct children of "Assignment" by their name in alphabetical order
958
- compareFunc: (a, b) => {
959
- return a.name.localeCompare(b.name)
960
- }
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
982
- }
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] }
991
- }}
992
- items={{
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
- }
1002
- }}
1003
- defaultExpanded={[1, 3]}
1004
- rootId={1}
636
+ return (
637
+ <>
638
+ <View display="block" margin="none none medium">
639
+ <Checkbox
640
+ label="showRootCollection"
641
+ variant="toggle"
642
+ size="medium"
643
+ checked={showRootCollection}
644
+ onChange={handleSwitch}
1005
645
  />
1006
- )
1007
- }
1008
- }
1009
-
1010
- render(<Example />)
1011
- ```
1012
-
1013
- - ```js
1014
- const Example = () => {
1015
- const [size, setSize] = useState('medium')
646
+ </View>
1016
647
 
1017
- return (
1018
648
  <TreeBrowser
1019
- size={size}
1020
649
  collections={{
1021
650
  1: {
1022
651
  id: 1,
1023
652
  name: 'Assignments',
1024
- collections: [3, 2],
1025
- items: [3],
653
+ collections: [2, 3],
654
+ items: [3, 5],
1026
655
  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)
656
+ renderAfterItems: renderNode()
1029
657
  },
1030
658
  2: {
1031
659
  id: 2,
@@ -1037,17 +665,7 @@ There is another way to sort the children of one collection. By adding the `comp
1037
665
  id: 3,
1038
666
  name: 'Math Assignments',
1039
667
  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
- }
668
+ items: [1, 2]
1051
669
  },
1052
670
  4: {
1053
671
  id: 4,
@@ -1070,179 +688,14 @@ There is another way to sort the children of one collection. By adding the `comp
1070
688
  }}
1071
689
  defaultExpanded={[1, 3]}
1072
690
  rootId={1}
691
+ showRootCollection={showRootCollection}
1073
692
  />
1074
- )
1075
- }
1076
-
1077
- render(<Example />)
1078
- ```
693
+ </>
694
+ )
695
+ }
1079
696
 
1080
- ### showRootCollection
1081
-
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`.
1083
-
1084
- - ```js
1085
- class Example extends React.Component {
1086
- constructor(props) {
1087
- super(props)
1088
- this.state = {
1089
- showRootCollection: true
1090
- }
1091
- }
1092
-
1093
- handleSwitch = () => {
1094
- this.setState({ showRootCollection: !this.state.showRootCollection })
1095
- }
1096
-
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
- }
1164
- }
1165
-
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
-
1183
- return (
1184
- <>
1185
- <View display="block" margin="none none medium">
1186
- <Checkbox
1187
- label="showRootCollection"
1188
- variant="toggle"
1189
- size="medium"
1190
- checked={showRootCollection}
1191
- onChange={handleSwitch}
1192
- />
1193
- </View>
1194
-
1195
- <TreeBrowser
1196
- collections={{
1197
- 1: {
1198
- id: 1,
1199
- name: 'Assignments',
1200
- collections: [2, 3],
1201
- items: [3, 5],
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]
1216
- },
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] }
1224
- }}
1225
- items={{
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
- }
1235
- }}
1236
- defaultExpanded={[1, 3]}
1237
- rootId={1}
1238
- showRootCollection={showRootCollection}
1239
- />
1240
- </>
1241
- )
1242
- }
1243
-
1244
- render(<Example />)
1245
- ```
697
+ render(<Example />)
698
+ ```
1246
699
 
1247
700
  ### Guidelines
1248
701