1 | import { EventEmitter, Component, ChangeDetectionStrategy, ViewEncapsulation, Inject, forwardRef, ChangeDetectorRef, Input, Output, ContentChildren, ElementRef, NgModule } from '@angular/core';
|
2 | import { trigger, state, style, transition, animate } from '@angular/animations';
|
3 | import { CommonModule } from '@angular/common';
|
4 | import { Header, PrimeTemplate, SharedModule } from 'primeng/api';
|
5 |
|
6 | let idx = 0;
|
7 | class AccordionTab {
|
8 | constructor(accordion, changeDetector) {
|
9 | this.changeDetector = changeDetector;
|
10 | this.cache = true;
|
11 | this.selectedChange = new EventEmitter();
|
12 | this.transitionOptions = '400ms cubic-bezier(0.86, 0, 0.07, 1)';
|
13 | this.id = `p-accordiontab-${idx++}`;
|
14 | this.accordion = accordion;
|
15 | }
|
16 | get selected() {
|
17 | return this._selected;
|
18 | }
|
19 | set selected(val) {
|
20 | this._selected = val;
|
21 | if (!this.loaded) {
|
22 | this.changeDetector.detectChanges();
|
23 | }
|
24 | }
|
25 | ngAfterContentInit() {
|
26 | this.templates.forEach((item) => {
|
27 | switch (item.getType()) {
|
28 | case 'content':
|
29 | this.contentTemplate = item.template;
|
30 | break;
|
31 | case 'header':
|
32 | this.headerTemplate = item.template;
|
33 | break;
|
34 | default:
|
35 | this.contentTemplate = item.template;
|
36 | break;
|
37 | }
|
38 | });
|
39 | }
|
40 | toggle(event) {
|
41 | if (this.disabled) {
|
42 | return false;
|
43 | }
|
44 | let index = this.findTabIndex();
|
45 | if (this.selected) {
|
46 | this.selected = false;
|
47 | this.accordion.onClose.emit({ originalEvent: event, index: index });
|
48 | }
|
49 | else {
|
50 | if (!this.accordion.multiple) {
|
51 | for (var i = 0; i < this.accordion.tabs.length; i++) {
|
52 | this.accordion.tabs[i].selected = false;
|
53 | this.accordion.tabs[i].selectedChange.emit(false);
|
54 | this.accordion.tabs[i].changeDetector.markForCheck();
|
55 | }
|
56 | }
|
57 | this.selected = true;
|
58 | this.loaded = true;
|
59 | this.accordion.onOpen.emit({ originalEvent: event, index: index });
|
60 | }
|
61 | this.selectedChange.emit(this.selected);
|
62 | this.accordion.updateActiveIndex();
|
63 | this.changeDetector.markForCheck();
|
64 | event.preventDefault();
|
65 | }
|
66 | findTabIndex() {
|
67 | let index = -1;
|
68 | for (var i = 0; i < this.accordion.tabs.length; i++) {
|
69 | if (this.accordion.tabs[i] == this) {
|
70 | index = i;
|
71 | break;
|
72 | }
|
73 | }
|
74 | return index;
|
75 | }
|
76 | get hasHeaderFacet() {
|
77 | return this.headerFacet && this.headerFacet.length > 0;
|
78 | }
|
79 | onKeydown(event) {
|
80 | if (event.which === 32 || event.which === 13) {
|
81 | this.toggle(event);
|
82 | event.preventDefault();
|
83 | }
|
84 | }
|
85 | ngOnDestroy() {
|
86 | this.accordion.tabs.splice(this.findTabIndex(), 1);
|
87 | }
|
88 | }
|
89 | AccordionTab.decorators = [
|
90 | { type: Component, args: [{
|
91 | selector: 'p-accordionTab',
|
92 | template: `
|
93 | <div class="p-accordion-tab" [ngClass]="{'p-accordion-tab-active': selected}">
|
94 | <div class="p-accordion-header" [ngClass]="{'p-highlight': selected, 'p-disabled': disabled}">
|
95 | <a role="tab" class="p-accordion-header-link" (click)="toggle($event)" (keydown)="onKeydown($event)" [attr.tabindex]="disabled ? null : 0"
|
96 | [attr.id]="id" [attr.aria-controls]="id + '-content'" [attr.aria-expanded]="selected">
|
97 | <span class="p-accordion-toggle-icon" [ngClass]="selected ? accordion.collapseIcon : accordion.expandIcon"></span>
|
98 | <span class="p-accordion-header-text" *ngIf="!hasHeaderFacet">
|
99 | {{header}}
|
100 | </span>
|
101 | <ng-container *ngTemplateOutlet="headerTemplate"></ng-container>
|
102 | <ng-content select="p-header" *ngIf="hasHeaderFacet"></ng-content>
|
103 | </a>
|
104 | </div>
|
105 | <div [attr.id]="id + '-content'" class="p-toggleable-content" [@tabContent]="selected ? {value: 'visible', params: {transitionParams: transitionOptions}} : {value: 'hidden', params: {transitionParams: transitionOptions}}"
|
106 | role="region" [attr.aria-hidden]="!selected" [attr.aria-labelledby]="id">
|
107 | <div class="p-accordion-content">
|
108 | <ng-content></ng-content>
|
109 | <ng-container *ngIf="contentTemplate && (cache ? loaded : selected)">
|
110 | <ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
|
111 | </ng-container>
|
112 | </div>
|
113 | </div>
|
114 | </div>
|
115 | `,
|
116 | animations: [
|
117 | trigger('tabContent', [
|
118 | state('hidden', style({
|
119 | height: '0',
|
120 | overflow: 'hidden'
|
121 | })),
|
122 | state('visible', style({
|
123 | height: '*'
|
124 | })),
|
125 | transition('visible <=> hidden', [style({ overflow: 'hidden' }), animate('{{transitionParams}}')]),
|
126 | transition('void => *', animate(0))
|
127 | ])
|
128 | ],
|
129 | changeDetection: ChangeDetectionStrategy.OnPush,
|
130 | encapsulation: ViewEncapsulation.None,
|
131 | styles: [".p-accordion-header-link{-moz-user-select:none;-ms-flex-align:center;-ms-user-select:none;-webkit-user-select:none;align-items:center;cursor:pointer;display:-ms-flexbox;display:flex;position:relative;text-decoration:none;user-select:none}.p-accordion-header-link:focus{z-index:1}.p-accordion-header-text{line-height:1}"]
|
132 | },] }
|
133 | ];
|
134 | AccordionTab.ctorParameters = () => [
|
135 | { type: undefined, decorators: [{ type: Inject, args: [forwardRef(() => Accordion),] }] },
|
136 | { type: ChangeDetectorRef }
|
137 | ];
|
138 | AccordionTab.propDecorators = {
|
139 | header: [{ type: Input }],
|
140 | disabled: [{ type: Input }],
|
141 | cache: [{ type: Input }],
|
142 | selectedChange: [{ type: Output }],
|
143 | transitionOptions: [{ type: Input }],
|
144 | headerFacet: [{ type: ContentChildren, args: [Header,] }],
|
145 | templates: [{ type: ContentChildren, args: [PrimeTemplate,] }],
|
146 | selected: [{ type: Input }]
|
147 | };
|
148 | class Accordion {
|
149 | constructor(el, changeDetector) {
|
150 | this.el = el;
|
151 | this.changeDetector = changeDetector;
|
152 | this.onClose = new EventEmitter();
|
153 | this.onOpen = new EventEmitter();
|
154 | this.expandIcon = 'pi pi-fw pi-chevron-right';
|
155 | this.collapseIcon = 'pi pi-fw pi-chevron-down';
|
156 | this.activeIndexChange = new EventEmitter();
|
157 | this.tabs = [];
|
158 | }
|
159 | ngAfterContentInit() {
|
160 | this.initTabs();
|
161 | this.tabListSubscription = this.tabList.changes.subscribe(_ => {
|
162 | this.initTabs();
|
163 | });
|
164 | }
|
165 | initTabs() {
|
166 | this.tabs = this.tabList.toArray();
|
167 | this.updateSelectionState();
|
168 | this.changeDetector.markForCheck();
|
169 | }
|
170 | getBlockableElement() {
|
171 | return this.el.nativeElement.children[0];
|
172 | }
|
173 | get activeIndex() {
|
174 | return this._activeIndex;
|
175 | }
|
176 | set activeIndex(val) {
|
177 | this._activeIndex = val;
|
178 | if (this.preventActiveIndexPropagation) {
|
179 | this.preventActiveIndexPropagation = false;
|
180 | return;
|
181 | }
|
182 | this.updateSelectionState();
|
183 | }
|
184 | updateSelectionState() {
|
185 | if (this.tabs && this.tabs.length && this._activeIndex != null) {
|
186 | for (let i = 0; i < this.tabs.length; i++) {
|
187 | let selected = this.multiple ? this._activeIndex.includes(i) : (i === this._activeIndex);
|
188 | let changed = selected !== this.tabs[i].selected;
|
189 | if (changed) {
|
190 | this.tabs[i].selected = selected;
|
191 | this.tabs[i].selectedChange.emit(selected);
|
192 | }
|
193 | }
|
194 | }
|
195 | }
|
196 | updateActiveIndex() {
|
197 | let index = this.multiple ? [] : null;
|
198 | this.tabs.forEach((tab, i) => {
|
199 | if (tab.selected) {
|
200 | if (this.multiple) {
|
201 | index.push(i);
|
202 | }
|
203 | else {
|
204 | index = i;
|
205 | return;
|
206 | }
|
207 | }
|
208 | });
|
209 | this.preventActiveIndexPropagation = true;
|
210 | this.activeIndexChange.emit(index);
|
211 | }
|
212 | ngOnDestroy() {
|
213 | if (this.tabListSubscription) {
|
214 | this.tabListSubscription.unsubscribe();
|
215 | }
|
216 | }
|
217 | }
|
218 | Accordion.decorators = [
|
219 | { type: Component, args: [{
|
220 | selector: 'p-accordion',
|
221 | template: `
|
222 | <div [ngClass]="'p-accordion p-component'" [ngStyle]="style" [class]="styleClass" role="tablist">
|
223 | <ng-content></ng-content>
|
224 | </div>
|
225 | `,
|
226 | changeDetection: ChangeDetectionStrategy.OnPush
|
227 | },] }
|
228 | ];
|
229 | Accordion.ctorParameters = () => [
|
230 | { type: ElementRef },
|
231 | { type: ChangeDetectorRef }
|
232 | ];
|
233 | Accordion.propDecorators = {
|
234 | multiple: [{ type: Input }],
|
235 | onClose: [{ type: Output }],
|
236 | onOpen: [{ type: Output }],
|
237 | style: [{ type: Input }],
|
238 | styleClass: [{ type: Input }],
|
239 | expandIcon: [{ type: Input }],
|
240 | collapseIcon: [{ type: Input }],
|
241 | activeIndexChange: [{ type: Output }],
|
242 | tabList: [{ type: ContentChildren, args: [AccordionTab,] }],
|
243 | activeIndex: [{ type: Input }]
|
244 | };
|
245 | class AccordionModule {
|
246 | }
|
247 | AccordionModule.decorators = [
|
248 | { type: NgModule, args: [{
|
249 | imports: [CommonModule],
|
250 | exports: [Accordion, AccordionTab, SharedModule],
|
251 | declarations: [Accordion, AccordionTab]
|
252 | },] }
|
253 | ];
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 | export { Accordion, AccordionModule, AccordionTab };
|
260 |
|