@@ -10,6 +10,7 @@ import { tracked } from '@glimmer/tracking';
10
10
import type { ComponentLike } from '@glint/template' ;
11
11
import { guidFor } from '@ember/object/internals' ;
12
12
import { modifier } from 'ember-modifier' ;
13
+ import { next } from '@ember/runloop' ;
13
14
14
15
import {
15
16
HdsAdvancedTableDensityValues ,
@@ -26,11 +27,13 @@ import type {
26
27
HdsAdvancedTableThSortOrder ,
27
28
HdsAdvancedTableVerticalAlignment ,
28
29
HdsAdvancedTableModel ,
30
+ HdsAdvancedTableExpandState ,
29
31
} from './types.ts' ;
30
32
import type { HdsFormCheckboxBaseSignature } from '../form/checkbox/base.ts' ;
31
33
import type { HdsAdvancedTableTdSignature } from './td.ts' ;
32
34
import type { HdsAdvancedTableThSignature } from './th.ts' ;
33
35
import type { HdsAdvancedTableTrSignature } from './tr.ts' ;
36
+ import { updateLastRowClass } from '../../../modifiers/hds-advanced-table-cell/dom-management.ts' ;
34
37
35
38
export const DENSITIES : HdsAdvancedTableDensities [ ] = Object . values (
36
39
HdsAdvancedTableDensityValues
@@ -73,7 +76,7 @@ export interface HdsAdvancedTableSignature {
73
76
Th ?: ComponentLike < HdsAdvancedTableThSignature > ;
74
77
data ?: Record < string , unknown > ;
75
78
rowIndex ?: number | string ;
76
- isOpen ?: boolean ;
79
+ isOpen ?: HdsAdvancedTableExpandState ;
77
80
} ,
78
81
] ;
79
82
} ;
@@ -88,10 +91,14 @@ export default class HdsAdvancedTable extends Component<HdsAdvancedTableSignatur
88
91
private _selectAllCheckbox ?: HdsFormCheckboxBaseSignature [ 'Element' ] =
89
92
undefined ;
90
93
@tracked private _isSelectAllCheckboxSelected ?: boolean = undefined ;
94
+ @tracked _expandAllButton ?: HTMLButtonElement = undefined ;
95
+ @tracked private _expandAllButtonState ?: boolean | 'mixed' = undefined ;
91
96
92
97
private _selectableRows : HdsAdvancedTableSelectableRow [ ] = [ ] ;
98
+ private _expandableRows : HTMLButtonElement [ ] = [ ] ;
93
99
private _captionId = 'caption-' + guidFor ( this ) ;
94
- private _observer : IntersectionObserver | undefined = undefined ;
100
+ private _intersectionObserver : IntersectionObserver | undefined = undefined ;
101
+ private _element ! : HTMLDivElement ;
95
102
96
103
get getSortCriteria ( ) : string | HdsAdvancedTableSortingFunction < unknown > {
97
104
// get the current column
@@ -282,13 +289,16 @@ export default class HdsAdvancedTable extends Component<HdsAdvancedTableSignatur
282
289
return classes . join ( ' ' ) ;
283
290
}
284
291
285
- private _setUpObserver = modifier ( ( element : HTMLElement ) => {
292
+ private _setUpObservers = modifier ( ( element : HTMLDivElement ) => {
286
293
const stickyGridHeader = element . querySelector (
287
294
'.hds-advanced-table__thead.hds-advanced-table__thead--sticky'
288
295
) ;
289
296
297
+ this . _element = element ;
298
+ this . setExpandAllState ( ) ;
299
+
290
300
if ( stickyGridHeader !== null ) {
291
- this . _observer = new IntersectionObserver (
301
+ this . _intersectionObserver = new IntersectionObserver (
292
302
( [ element ] ) =>
293
303
element ?. target . classList . toggle (
294
304
'hds-advanced-table__thead--is-pinned' ,
@@ -297,12 +307,14 @@ export default class HdsAdvancedTable extends Component<HdsAdvancedTableSignatur
297
307
{ threshold : [ 1 ] }
298
308
) ;
299
309
300
- this . _observer . observe ( stickyGridHeader ) ;
310
+ this . _intersectionObserver . observe ( stickyGridHeader ) ;
301
311
}
302
312
313
+ updateLastRowClass ( element ) ;
314
+
303
315
return ( ) => {
304
- if ( this . _observer ) {
305
- this . _observer . disconnect ( ) ;
316
+ if ( this . _intersectionObserver ) {
317
+ this . _intersectionObserver . disconnect ( ) ;
306
318
}
307
319
} ;
308
320
} ) ;
@@ -365,7 +377,6 @@ export default class HdsAdvancedTable extends Component<HdsAdvancedTableSignatur
365
377
onSelectionAllChange ( ) : void {
366
378
this . _selectableRows . forEach ( ( row ) => {
367
379
row . checkbox . checked = this . _selectAllCheckbox ?. checked ?? false ;
368
- row . checkbox . dispatchEvent ( new Event ( 'toggle' , { bubbles : false } ) ) ;
369
380
} ) ;
370
381
this . _isSelectAllCheckboxSelected =
371
382
this . _selectAllCheckbox ?. checked ?? false ;
@@ -425,9 +436,63 @@ export default class HdsAdvancedTable extends Component<HdsAdvancedTableSignatur
425
436
this . _selectAllCheckbox . indeterminate =
426
437
selectedRowsCount > 0 && selectedRowsCount < selectableRowsCount ;
427
438
this . _isSelectAllCheckboxSelected = this . _selectAllCheckbox . checked ;
428
- this . _selectAllCheckbox . dispatchEvent (
429
- new Event ( 'toggle' , { bubbles : false } )
430
- ) ;
439
+ }
440
+ }
441
+
442
+ @action didInsertExpandAllButton ( button : HTMLButtonElement ) : void {
443
+ this . _expandAllButton = button ;
444
+ }
445
+
446
+ @action willDestroyExpandAllButton ( ) : void {
447
+ this . _expandAllButton = undefined ;
448
+ }
449
+
450
+ @action
451
+ didInsertExpandButton ( button : HTMLButtonElement ) : void {
452
+ this . _expandableRows . push ( button ) ;
453
+ this . setExpandAllState ( ) ;
454
+ }
455
+
456
+ @action
457
+ willDestroyExpandButton ( button : HTMLButtonElement ) : void {
458
+ this . _expandableRows . filter ( ( btn ) => button === btn ) ;
459
+ this . setExpandAllState ( ) ;
460
+ }
461
+
462
+ @action
463
+ setExpandAllState ( ) : void {
464
+ if ( this . _expandAllButton && this . _element ) {
465
+ // eslint-disable-next-line ember/no-runloop
466
+ next ( ( ) => {
467
+ const parentRowsCount = this . _expandableRows . length ;
468
+ const expandedRowsCount = this . _expandableRows . filter (
469
+ ( button ) => button . getAttribute ( 'aria-expanded' ) === 'true'
470
+ ) . length ;
471
+
472
+ let expandAllState : HdsAdvancedTableExpandState ;
473
+
474
+ if ( parentRowsCount === expandedRowsCount ) expandAllState = true ;
475
+ else if ( expandedRowsCount === 0 ) expandAllState = false ;
476
+ else expandAllState = 'mixed' ;
477
+
478
+ this . _expandAllButtonState = expandAllState ;
479
+ updateLastRowClass ( this . _element ) ;
480
+ } ) ;
481
+ }
482
+ }
483
+
484
+ @action
485
+ onExpandAllClick ( ) : void {
486
+ if ( this . _expandAllButton && this . _element ) {
487
+ const newState = this . _expandAllButtonState === true ? false : true ;
488
+
489
+ this . _expandableRows . forEach ( ( button ) => {
490
+ button . setAttribute ( 'aria-expanded' , `${ newState } ` ) ;
491
+ button . dispatchEvent ( new Event ( 'toggle' , { bubbles : false } ) ) ;
492
+ } ) ;
493
+
494
+ this . _expandAllButtonState = newState ;
495
+ updateLastRowClass ( this . _element ) ;
431
496
}
432
497
}
433
498
}
0 commit comments