|
1 | 1 | import {Component, Input, Output, EventEmitter} from '@angular/core'; |
2 | 2 | import {SuiAccordionService} from "./accordion.service"; |
| 3 | +import {TransitionController} from '../transition/transition-controller'; |
| 4 | +import {Transition, TransitionDirection} from '../transition/transition'; |
3 | 5 |
|
4 | 6 | @Component({ |
5 | 7 | selector: 'sui-accordion-panel', |
6 | 8 | exportAs: 'suiAccordionPanel', |
7 | 9 | template: ` |
8 | | -<div class="title" [class.active]="isOpen" (click)="toggleOpen($event)"> |
| 10 | +<!-- Title --> |
| 11 | +<div class="title" [class.active]="isOpen" (click)="toggleOpen($event)" > |
9 | 12 | <ng-content select="[title]"></ng-content> |
10 | 13 | </div> |
11 | | -<div [suiCollapse]="!isOpen"> |
12 | | - <div class="content" [class.active]="isOpen"> |
| 14 | +<!-- Content --> |
| 15 | +<div [suiCollapse]="!isOpen" [collapseDuration]="transitionDuration"> |
| 16 | + <div class="content" [class.active]="isOpen" [suiTransition]="transitionController"> |
13 | 17 | <ng-content select="[content]"></ng-content> |
14 | 18 | </div> |
15 | 19 | </div> |
16 | 20 | `, |
17 | 21 | styles: [` |
| 22 | +/* Manual style as Semantic UI relies on > selector */ |
18 | 23 | .content { |
19 | | - padding: .5em 0 1em |
| 24 | + padding: .5em 0 1em; |
20 | 25 | } |
21 | 26 |
|
22 | | -:host:last-child .content { |
23 | | - padding-bottom: 0 |
| 27 | +/* Another > selector fix */ |
| 28 | +:host:first-child .title { |
| 29 | + border-top: none; |
24 | 30 | } |
25 | 31 | `] |
26 | 32 | }) |
27 | 33 | export class SuiAccordionPanel { |
28 | 34 | private _service:SuiAccordionService; |
| 35 | + |
| 36 | + public transitionController:TransitionController; |
| 37 | + |
29 | 38 | public set service(service:SuiAccordionService) { |
30 | 39 | this._service = service; |
31 | 40 | } |
32 | 41 |
|
33 | | - @Input() public isDisabled:boolean; |
| 42 | + @Input() |
| 43 | + public isDisabled:boolean; |
| 44 | + |
| 45 | + private _isOpen:boolean; |
34 | 46 |
|
35 | 47 | @Input() |
36 | | - public get isOpen():boolean { |
| 48 | + public get isOpen() { |
37 | 49 | return this._isOpen; |
38 | 50 | } |
39 | | - @Output() public isOpenChange:EventEmitter<boolean> = new EventEmitter<boolean>(false); |
40 | 51 |
|
41 | 52 | public set isOpen(value:boolean) { |
42 | | - this._isOpen = value; |
43 | | - if (value && this._service) { |
44 | | - this._service.closeOtherPanels(this); |
| 53 | + if (value != this.isOpen) { |
| 54 | + // Only update if the value has changed. |
| 55 | + this._isOpen = value; |
| 56 | + |
| 57 | + if (value && this._service) { |
| 58 | + // If we are opening this panel, we must close the other ones. |
| 59 | + this._service.closeOtherPanels(this); |
| 60 | + } |
| 61 | + this.isOpenChange.emit(this.isOpen); |
| 62 | + |
| 63 | + // Cancel all current animations, and fade the contents. The direction is automatic. |
| 64 | + this.transitionController.stopAll(); |
| 65 | + this.transitionController.animate(new Transition("fade", this.transitionDuration)); |
| 66 | + } |
| 67 | + } |
| 68 | + |
| 69 | + public get transitionDuration() { |
| 70 | + if (this._service) { |
| 71 | + // Return the service defined transition duration. |
| 72 | + return this._service.transitionDuration; |
45 | 73 | } |
46 | | - this.isOpenChange.emit(this._isOpen); |
| 74 | + // Revert to instantaneous if the service is not yet loaded. |
| 75 | + return 0; |
47 | 76 | } |
48 | 77 |
|
49 | | - private _isOpen:boolean = false; |
| 78 | + @Output() |
| 79 | + public isOpenChange:EventEmitter<boolean>; |
| 80 | + |
| 81 | + constructor() { |
| 82 | + this.transitionController = new TransitionController(false); |
50 | 83 |
|
51 | | - public toggleOpen(event:MouseEvent):any { |
| 84 | + this._isOpen = false; |
| 85 | + this.isOpenChange = new EventEmitter<boolean>(false); |
| 86 | + } |
| 87 | + |
| 88 | + public toggleOpen(event:MouseEvent) { |
52 | 89 | event.preventDefault(); |
| 90 | + |
53 | 91 | if (!this.isDisabled) { |
54 | 92 | this.isOpen = !this.isOpen; |
55 | 93 | } |
|
0 commit comments