diff --git a/e2e/src/collapse/collapse.e2e-spec.ts b/e2e/src/collapse/collapse.e2e-spec.ts new file mode 100644 index 00000000..890c98a7 --- /dev/null +++ b/e2e/src/collapse/collapse.e2e-spec.ts @@ -0,0 +1,59 @@ +import { CollapsePage } from './collapse.po'; + +describe('Collapse', () => { + let page: CollapsePage; + + beforeEach(async() => { + page = new CollapsePage(); + await page.go(); + }); + + it('dovrebbe essere inizialmente non visibile nel DOM', async () => { + expect(await page.isDiv0Visible()).toBeFalsy(); + }); + + it('dovrebbe essere effettuato il toggle quando si clicca il bottone', async () => { + expect(await page.isDiv0Visible()).toBeFalsy(); + await page.clickButton(); + expect(await page.isDiv0Visible()).toBeTruthy(); + await page.clickButton(); + expect(await page.isDiv0Visible()).toBeFalsy(); + }); + + it('gli item del group dovrebbero essere inizialmente chiusi', async () => { + expect(await page.isItem0Visible()).toBeFalsy(); + expect(await page.isItem1Visible()).toBeFalsy(); + expect(await page.isItem2Visible()).toBeFalsy(); + }); + + it('gli item del group non dovrebbero essere mutuamente esclusivi', async () => { + await page.clickGroup0Button(); + expect(await page.isItem0Visible()).toBeTruthy(); + expect(await page.isItem1Visible()).toBeFalsy(); + expect(await page.isItem2Visible()).toBeFalsy(); + await page.clickGroup1Button(); + expect(await page.isItem0Visible()).toBeTruthy(); + expect(await page.isItem1Visible()).toBeTruthy(); + expect(await page.isItem2Visible()).toBeFalsy(); + await page.clickGroup2Button(); + expect(await page.isItem0Visible()).toBeTruthy(); + expect(await page.isItem1Visible()).toBeTruthy(); + expect(await page.isItem2Visible()).toBeTruthy(); + }); + + it('gli item del group dovrebbero essere mutuamente esclusivi', async () => { + await page.clickCheckbox(); + await page.clickGroup0Button(); + expect(await page.isItem0Visible()).toBeTruthy(); + expect(await page.isItem1Visible()).toBeFalsy(); + expect(await page.isItem2Visible()).toBeFalsy(); + await page.clickGroup1Button(); + expect(await page.isItem0Visible()).toBeFalsy(); + expect(await page.isItem1Visible()).toBeTruthy(); + expect(await page.isItem2Visible()).toBeFalsy(); + await page.clickGroup2Button(); + expect(await page.isItem0Visible()).toBeFalsy(); + expect(await page.isItem1Visible()).toBeFalsy(); + expect(await page.isItem2Visible()).toBeTruthy(); + }); +}); diff --git a/e2e/src/collapse/collapse.po.ts b/e2e/src/collapse/collapse.po.ts new file mode 100644 index 00000000..357b40c4 --- /dev/null +++ b/e2e/src/collapse/collapse.po.ts @@ -0,0 +1,70 @@ +import { browser, by, element } from 'protractor'; + +export class CollapsePage { + private readonly COLLAPSE_URL = '/#/componenti/collapse'; + private readonly ID_EXAMPLE_TAB = 'collapse-examples-tab'; + + private readonly ID_BUTTON = 'button-0'; + private readonly ID_DIV_0 = 'collapseExample'; + + private readonly ID_CHECKBOX_ACCORDION = this.getLabelForAttribute('checkbox-0'); + + private readonly ID_ITEM_0_HEADING = 'collapse-item-0-heading'; + private readonly ID_ITEM_0 = 'collapse-item-0'; + + private readonly ID_ITEM_1_HEADING = 'collapse-item-1-heading'; + private readonly ID_ITEM_1 = 'collapse-item-1'; + + private readonly ID_ITEM_2_HEADING = 'collapse-item-2-heading'; + private readonly ID_ITEM_2 = 'collapse-item-2'; + + async go() { + await browser.get(this.COLLAPSE_URL); + await element(by.id(this.ID_EXAMPLE_TAB)).click(); + return await browser.sleep(500); + } + + private getLabelForAttribute(attr: string) { + return `[for="${attr}"]`; + } + + async existsButton() { + return await element(by.id(this.ID_BUTTON)).isPresent(); + } + + async clickButton() { + await element(by.id(this.ID_BUTTON)).click(); + } + + async isDiv0Visible() { + return await element(by.id(this.ID_DIV_0)).isDisplayed(); + } + + async clickCheckbox() { + await element(by.css(this.ID_CHECKBOX_ACCORDION)).click(); + } + + async clickGroup0Button() { + await element(by.id(this.ID_ITEM_0_HEADING)).click(); + } + + async clickGroup1Button() { + await element(by.id(this.ID_ITEM_1_HEADING)).click(); + } + + async clickGroup2Button() { + await element(by.id(this.ID_ITEM_2_HEADING)).click(); + } + + async isItem0Visible() { + return await element(by.id(this.ID_ITEM_0)).isDisplayed(); + } + + async isItem1Visible() { + return await element(by.id(this.ID_ITEM_1)).isDisplayed(); + } + + async isItem2Visible() { + return await element(by.id(this.ID_ITEM_2)).isDisplayed(); + } +} diff --git a/projects/design-angular-kit/src/lib/collapse/collapse-group.component.css b/projects/design-angular-kit/src/lib/collapse/collapse-group.component.css new file mode 100644 index 00000000..e69de29b diff --git a/projects/design-angular-kit/src/lib/collapse/collapse-group.component.html b/projects/design-angular-kit/src/lib/collapse/collapse-group.component.html new file mode 100644 index 00000000..aee27bff --- /dev/null +++ b/projects/design-angular-kit/src/lib/collapse/collapse-group.component.html @@ -0,0 +1,3 @@ +
+ +
\ No newline at end of file diff --git a/projects/design-angular-kit/src/lib/collapse/collapse-group.component.ts b/projects/design-angular-kit/src/lib/collapse/collapse-group.component.ts new file mode 100644 index 00000000..bcdb9d13 --- /dev/null +++ b/projects/design-angular-kit/src/lib/collapse/collapse-group.component.ts @@ -0,0 +1,55 @@ +import { Component, ContentChildren, forwardRef, QueryList, + Input, HostListener, SimpleChanges, OnChanges } from '@angular/core'; +import { CollapseItemComponent } from './collapse-item.component'; +import { Util } from '../util/util'; + +let identifier = 0; + +@Component({ + selector: 'it-collapse-group', + templateUrl: './collapse-group.component.html', + styleUrls: ['./collapse-group.component.css'] +}) +export class CollapseGroupComponent implements OnChanges { + id = `collapse-group-${identifier++}`; + + /** + * Indica se gli item del gruppo sono mutuamente richiudibili (o accordion) + */ + @Input() + get accordion(): boolean { return this._accordion; } + set accordion(value: boolean) { this._accordion = Util.coerceBooleanProperty(value); } + private _accordion = false; + + @ContentChildren(forwardRef(() => CollapseItemComponent), { descendants: true }) + private _items: QueryList; // tslint:disable-line + + @HostListener('click', ['$event.target']) + onClick(target) { + if (this.accordion) { + const items = this._items.toArray(); + items.forEach(currentItem => { + const isTargetPartOfItem = (currentItem.elementRef.nativeElement as HTMLElement).contains(target); + if (!isTargetPartOfItem) { + if (currentItem.directive.isShown()) { + currentItem.directive.hide(); + } + } + }); + } + } + + ngOnChanges(simpleChanges: SimpleChanges) { + if (simpleChanges['accordion']) { + const isAccordion = simpleChanges['accordion'].currentValue; + if (isAccordion) { + const items = this._items.toArray(); + items.forEach(currentItem => { + if (currentItem.directive.isShown()) { + currentItem.directive.hide(); + } + }); + } + } + } +} diff --git a/projects/design-angular-kit/src/lib/collapse/collapse-item.component.css b/projects/design-angular-kit/src/lib/collapse/collapse-item.component.css new file mode 100644 index 00000000..e69de29b diff --git a/projects/design-angular-kit/src/lib/collapse/collapse-item.component.html b/projects/design-angular-kit/src/lib/collapse/collapse-item.component.html new file mode 100644 index 00000000..3a156061 --- /dev/null +++ b/projects/design-angular-kit/src/lib/collapse/collapse-item.component.html @@ -0,0 +1,11 @@ +
+ +
+
+
+ +
+
diff --git a/projects/design-angular-kit/src/lib/collapse/collapse-item.component.ts b/projects/design-angular-kit/src/lib/collapse/collapse-item.component.ts new file mode 100644 index 00000000..0c92663c --- /dev/null +++ b/projects/design-angular-kit/src/lib/collapse/collapse-item.component.ts @@ -0,0 +1,74 @@ +import { Component, Input, ViewChild, ElementRef, Output, EventEmitter } from '@angular/core'; +import { CollapseDirective } from './collapse.directive'; + +let identifier = 0; + +@Component({ + selector: 'it-collapse-item', + templateUrl: './collapse-item.component.html', + styleUrls: ['./collapse-item.component.css'] +}) +export class CollapseItemComponent { + @ViewChild(CollapseDirective) readonly directive: CollapseDirective; + + id = `collapse-item-${identifier++}`; + headingId = `${this.id}-heading`; + + /** + * Testo del bottone di apertura/chiusura del collapse item + */ + @Input() + get header(): string { return this._header; } + set header(value: string) { this._header = value; } + private _header; + + /** + * Evento da emettere quando il collapse sta per essere mostrato + */ + @Output('show') + get showEvent(): EventEmitter { return this._showEvent; } + set showEvent(value: EventEmitter) { this._showEvent = value; } + private _showEvent = new EventEmitter(); + + /** + * Evento da emettere quando il collapse è mostrato + */ + @Output('shown') + get shownEvent(): EventEmitter { return this._shownEvent; } + set shownEvent(value: EventEmitter) { this._shownEvent = value; } + private _shownEvent = new EventEmitter(); + + /** + * Evento da emettere quando il collapse sta per essere nascosto + */ + @Output('hide') + get hideEvent(): EventEmitter { return this._hideEvent; } + set hideEvent(value: EventEmitter) { this._hideEvent = value; } + private _hideEvent = new EventEmitter(); + + /** + * Evento da emettere quando il collapse è nascosto + */ + @Output('hidden') + get hiddenEvent(): EventEmitter { return this._hiddenEvent; } + set hiddenEvent(value: EventEmitter) { this._hiddenEvent = value; } + private _hiddenEvent = new EventEmitter(); + + show() { + this.showEvent.emit(this); + } + + hide() { + this.hideEvent.emit(this); + } + + shown() { + this.shownEvent.emit(this); + } + + hidden() { + this.hiddenEvent.emit(this); + } + + constructor(readonly elementRef: ElementRef) { } +} diff --git a/projects/design-angular-kit/src/lib/collapse/collapse.directive.spec.ts b/projects/design-angular-kit/src/lib/collapse/collapse.directive.spec.ts new file mode 100644 index 00000000..af1344a7 --- /dev/null +++ b/projects/design-angular-kit/src/lib/collapse/collapse.directive.spec.ts @@ -0,0 +1,314 @@ +import { CollapseDirective } from './collapse.directive'; +import { Component, DebugElement, Output, EventEmitter, ViewChild } from '@angular/core'; +import { TestBed, fakeAsync, async, ComponentFixture } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { CollapseItemComponent } from './collapse-item.component'; +import { CollapseGroupComponent } from './collapse-group.component'; + +/** Componente per testare una singola collapse. */ +@Component({ + template: ` +
+
` +}) +class SimpleCollapseComponent {} + +/** Componente per testare una collapse con toggle. */ +@Component({ + template: ` +
+
` +}) +class ToggleCollapseComponent { + isShown = false; +} + +/** Componente per testare l'EventEmitter. */ +@Component({ + template: ` + +
+ ` +}) +class EmitterCollapseComponent { + @ViewChild(CollapseDirective) readonly directive: CollapseDirective; + + isShown = false; +} + +/** Componente per testare il group e gli item di collapse. */ +@Component({ + template: ` + + + {{item.content}} + + + ` +}) +class GroupItemsCollapseComponent { + accordion = false; + + items = [ + { + 'header': 'item-1', + 'content': + 'Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid.\n' + + '3 wolf moon officia aute, non cupidatat skateboard dolor brunch.' + }, + { + 'header': 'item-2', + 'content': + 'Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table,\n' + + 'raw denim aesthetic synth nesciunt you probably haven\'t heard of them accusamus labore sustainable VHS.' + }, + { + 'header': 'item-3', + 'content': + 'Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor,\n' + + 'sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et.\n' + + 'Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident.' + }, + ]; +} + +describe('CollapseDirective', () => { + + beforeEach(fakeAsync(() => { + TestBed.configureTestingModule({ + declarations: [ + CollapseDirective, + SimpleCollapseComponent, + ToggleCollapseComponent, + EmitterCollapseComponent, + ] + }); + + TestBed.compileComponents(); + })); + + describe('comportamenti base', () => { + let fixture: ComponentFixture; + let debugElement: DebugElement; + let nativeElement: HTMLDivElement; + + beforeEach(async(() => { + fixture = TestBed.createComponent(SimpleCollapseComponent); + fixture.detectChanges(); + + debugElement = fixture.debugElement.query(By.directive(CollapseDirective)); + nativeElement = debugElement.nativeElement; + })); + + it(`dovrebbe essere inizialmente chiuso`, () => { + expect(nativeElement.classList).not.toContain('show'); + }); + + }); + + describe('comportamento con toggle', () => { + let fixture: ComponentFixture; + let debugElement: DebugElement; + let nativeElement: HTMLDivElement; + let testComponent: ToggleCollapseComponent; + + beforeEach(async(() => { + fixture = TestBed.createComponent(ToggleCollapseComponent); + fixture.detectChanges(); + + testComponent = fixture.debugElement.componentInstance; + + debugElement = fixture.debugElement.query(By.directive(CollapseDirective)); + nativeElement = debugElement.nativeElement; + })); + + it(`dovrebbe effettuare il toggle dell'elemento div`, () => { + testComponent.isShown = true; + fixture.detectChanges(); + expect(nativeElement.classList).toContain('show'); + testComponent.isShown = false; + fixture.detectChanges(); + expect(nativeElement.classList).not.toContain('show'); + }); + + }); + + describe('comportamento con emissione di eventi', () => { + let fixture: ComponentFixture; + let debugElement: DebugElement; + + let nativeElement: HTMLDivElement; + let btnElement: HTMLButtonElement; + + beforeEach(async(() => { + fixture = TestBed.createComponent(EmitterCollapseComponent); + fixture.detectChanges(); + + debugElement = fixture.debugElement.query(By.directive(CollapseDirective)); + nativeElement = fixture.nativeElement; + btnElement = nativeElement.querySelector('button'); + })); + + it(`dovrebbe emettere l'evento show`, () => { + const ecComponent: EmitterCollapseComponent = fixture.debugElement.componentInstance; + ecComponent.directive.showEvent.subscribe(eventHandler => { + expect(eventHandler).toEqual(ecComponent.directive); + }); + btnElement.click(); + }); + + it(`dovrebbe emettere l'evento shown`, () => { + const ecComponent: EmitterCollapseComponent = fixture.debugElement.componentInstance; + ecComponent.directive.shownEvent.subscribe(eventHandler => { + expect(eventHandler).toEqual(ecComponent.directive); + }); + btnElement.click(); + }); + + it(`dovrebbe emettere l'evento hide`, () => { + const ecComponent: EmitterCollapseComponent = fixture.debugElement.componentInstance; + ecComponent.directive.hideEvent.subscribe(eventHandler => { + expect(eventHandler).toEqual(ecComponent.directive); + }); + btnElement.click(); + }); + + it(`dovrebbe emettere l'evento hidden`, () => { + const ecComponent: EmitterCollapseComponent = fixture.debugElement.componentInstance; + ecComponent.directive.hiddenEvent.subscribe(eventHandler => { + expect(eventHandler).toEqual(ecComponent.directive); + }); + btnElement.click(); + }); + }); +}); + +describe('CollapseGroupComponent & CollapseItemComponent', () => { + + beforeEach(fakeAsync(() => { + TestBed.configureTestingModule({ + declarations: [ + CollapseDirective, + CollapseItemComponent, + CollapseGroupComponent, + GroupItemsCollapseComponent + ] + }); + + TestBed.compileComponents(); + })); + + describe('comportamenti group base', () => { + let fixture: ComponentFixture; + + let itemDebugElements: DebugElement[]; + let itemComponentInstances: CollapseItemComponent[]; + let itemNativeElements: HTMLElement[]; + let itemButtonElements: HTMLButtonElement[]; + + beforeEach(async(() => { + fixture = TestBed.createComponent(GroupItemsCollapseComponent); + fixture.detectChanges(); + + itemDebugElements = fixture.debugElement.queryAll(By.directive(CollapseItemComponent)); + itemComponentInstances = itemDebugElements.map(itemDe => itemDe.componentInstance); + itemNativeElements = itemDebugElements.map(itemDe => itemDe.nativeElement); + itemButtonElements = itemNativeElements.map(itemNe => itemNe.querySelector('button')); + })); + + it(`i suoi elementi dovrebbero essere inizialmente chiusi`, () => { + const noOfElements = itemNativeElements.length; + const noOfHiddenElements = itemComponentInstances.reduce( + (currentValue, instance) => currentValue + (!instance.directive.isShown() ? 1 : 0), 0 + ); + + expect(noOfElements).toEqual(noOfHiddenElements); + }); + + it(`comportamento con apertura di tutti i suoi elementi `, () => { + const noOfElements = itemNativeElements.length; + + itemButtonElements.forEach(button => { + button.click(); + fixture.detectChanges(); + }); + + const noOfShownElements = itemComponentInstances.reduce( + (currentValue, instance) => currentValue + (instance.directive.isShown() ? 1 : 0), 0 + ); + + expect(noOfElements).toEqual(noOfShownElements); + }); + }); + + describe('comportamenti group accordion', () => { + let fixture: ComponentFixture; + let testComponent: GroupItemsCollapseComponent; + + let itemDebugElements: DebugElement[]; + let itemComponentInstances: CollapseItemComponent[]; + let itemNativeElements: HTMLElement[]; + let itemButtonElements: HTMLButtonElement[]; + + beforeEach(async(() => { + fixture = TestBed.createComponent(GroupItemsCollapseComponent); + fixture.detectChanges(); + + testComponent = fixture.debugElement.componentInstance; + + itemDebugElements = fixture.debugElement.queryAll(By.directive(CollapseItemComponent)); + itemComponentInstances = itemDebugElements.map(itemDe => itemDe.componentInstance); + itemNativeElements = itemDebugElements.map(itemDe => itemDe.nativeElement); + itemButtonElements = itemNativeElements.map(itemNe => itemNe.querySelector('button')); + })); + + it(`passaggio da group ad accordion`, () => { + const noOfElements = itemNativeElements.length; + + itemButtonElements.forEach(button => { + button.click(); + fixture.detectChanges(); + }); + + let noOfShownElements = itemComponentInstances.reduce( + (currentValue, instance) => currentValue + (instance.directive.isShown() ? 1 : 0), 0 + ); + + expect(noOfElements).toEqual(noOfShownElements); + + testComponent.accordion = true; + fixture.detectChanges(); + + itemButtonElements.forEach(button => { + button.click(); + fixture.detectChanges(); + }); + + noOfShownElements = itemComponentInstances.reduce( + (currentValue, instance) => currentValue + (instance.directive.isShown() ? 1 : 0), 0 + ); + + expect(noOfShownElements).toEqual(1); + }); + + it(`comportamento di mutua esclusione`, () => { + testComponent.accordion = true; + fixture.detectChanges(); + + itemButtonElements.forEach(button => { + button.click(); + fixture.detectChanges(); + }); + + const noOfShownElements = itemComponentInstances.reduce( + (currentValue, instance) => currentValue + (instance.directive.isShown() ? 1 : 0), 0 + ); + + expect(noOfShownElements).toEqual(1); + }); + + }); +}); diff --git a/projects/design-angular-kit/src/lib/collapse/collapse.directive.ts b/projects/design-angular-kit/src/lib/collapse/collapse.directive.ts new file mode 100644 index 00000000..435a4b2b --- /dev/null +++ b/projects/design-angular-kit/src/lib/collapse/collapse.directive.ts @@ -0,0 +1,95 @@ +import { Directive, Output, EventEmitter, HostBinding, Input} from '@angular/core'; + +/** + * Per ottimizzare l’ingombro dei contenuti di una pagina si possono usare degli elementi richiudibili + * (in gergo definiti collassabili o collapse), che possono essere attivati indipendentemente l’uno dall’altro + */ +@Directive({ + // tslint:disable-next-line:directive-selector + selector: '[it-collapse]', + exportAs: 'it-collapse' +}) +export class CollapseDirective { + + private _isDisposed = false; + + /** + * La direttiva di collapse che opzionalmente contiene il predicato che ne stabilisce + * che sarà avvalorato a true quando il collapse è espanso, a false altrimenti + */ + @Input('it-collapse') + get itCollapse(): boolean { return this._isShown; } + set itCollapse(value: boolean) { this._isShown = value != null && `${value}` === 'true'; } + private _isShown = false; + + /** + * Evento da emettere quando il collapse sta per essere mostrato + */ + @Output('show') + get showEvent(): EventEmitter { return this._showEvent; } + set showEvent(value: EventEmitter) { this._showEvent = value; } + private _showEvent = new EventEmitter(); + + /** + * Evento da emettere quando il collapse è mostrato + */ + @Output('shown') + get shownEvent(): EventEmitter { return this._shownEvent; } + set shownEvent(value: EventEmitter) { this._shownEvent = value; } + private _shownEvent = new EventEmitter(); + + /** + * Evento da emettere quando il collapse sta per essere nascosto + */ + @Output('hide') + get hideEvent(): EventEmitter { return this._hideEvent; } + set hideEvent(value: EventEmitter) { this._hideEvent = value; } + private _hideEvent = new EventEmitter(); + + /** + * Evento da emettere quando il collapse è nascosto + */ + @Output('hidden') + get hiddenEvent(): EventEmitter { return this._hiddenEvent; } + set hiddenEvent(value: EventEmitter) { this._hiddenEvent = value; } + private _hiddenEvent = new EventEmitter(); + + @HostBinding('class') + get cssClass() { + let cssClass = 'collapse'; + if (this.isShown()) { + cssClass += ' show'; + } + return cssClass; + } + + show() { + this.showEvent.emit(this); + this._isShown = true; + this.shownEvent.emit(this); + } + + hide() { + this.hideEvent.emit(this); + if (!this._isDisposed) { + this._isShown = false; + this.hiddenEvent.emit(this); + } + } + + toggle() { + if (!this.isShown()) { + this.show(); + } else { + this.hide(); + } + } + + dispose() { + this._isDisposed = true; + } + + isShown() { + return this._isShown; + } +} diff --git a/projects/design-angular-kit/src/lib/design-angular-kit.module.ts b/projects/design-angular-kit/src/lib/design-angular-kit.module.ts index 365ed709..1d611fa1 100644 --- a/projects/design-angular-kit/src/lib/design-angular-kit.module.ts +++ b/projects/design-angular-kit/src/lib/design-angular-kit.module.ts @@ -12,6 +12,9 @@ import { TooltipDirective } from './tooltip/tooltip.directive'; import { TooltipComponent } from './tooltip/tooltip.component'; import { ButtonComponent } from './button/button.component'; import { BadgeDirective } from './badge/badge.directive'; +import { CollapseDirective } from './collapse/collapse.directive'; +import { CollapseItemComponent } from './collapse/collapse-item.component'; +import { CollapseGroupComponent } from './collapse/collapse-group.component'; import { FormInputComponent } from './form-input/form-input.component'; import { DropdownComponent } from './dropdown/dropdown.component'; import { DropdownItemComponent } from './dropdown/dropdown-item.component'; @@ -39,6 +42,9 @@ import { TabComponent } from './tabs/tab.component'; ButtonComponent, TooltipDirective, TooltipComponent, + CollapseDirective, + CollapseItemComponent, + CollapseGroupComponent, FormInputComponent, PopoverDirective, PopoverComponent, @@ -60,6 +66,9 @@ import { TabComponent } from './tabs/tab.component'; ProgressBarComponent, ButtonComponent, TooltipDirective, + CollapseDirective, + CollapseItemComponent, + CollapseGroupComponent, FormInputComponent, PopoverDirective, DropdownComponent, diff --git a/projects/design-angular-kit/src/public_api.ts b/projects/design-angular-kit/src/public_api.ts index 0dc8dc8a..aa4dc0f1 100644 --- a/projects/design-angular-kit/src/public_api.ts +++ b/projects/design-angular-kit/src/public_api.ts @@ -12,6 +12,9 @@ export * from './lib/tooltip/tooltip.directive'; export * from './lib/tooltip/tooltip.config'; export * from './lib/button/button.component'; export * from './lib/badge/badge.directive'; +export * from './lib/collapse/collapse.directive'; +export * from './lib/collapse/collapse-item.component'; +export * from './lib/collapse/collapse-group.component'; export * from './lib/form-input/form-input.component'; export * from './lib/dropdown/dropdown.component'; export * from './lib/dropdown/dropdown-item.component'; diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 719547d1..3a095de6 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -20,6 +20,7 @@ const routes: Routes = [ { path: 'tooltip', loadChildren: 'src/app/tooltip/tooltip.module#TooltipModule' }, { path: 'button', loadChildren: 'src/app/button/button.module#ButtonModule' }, { path: 'badge', loadChildren: 'src/app/badge/badge.module#BadgeModule' }, + { path: 'collapse', loadChildren: 'src/app/collapse/collapse.module#CollapseModule' }, { path: 'form-input', loadChildren: 'src/app/form-input/form-input.module#FormInputModule' }, { path: 'dropdown', loadChildren: 'src/app/dropdown/dropdown.module#DropdownModule' }, ]} diff --git a/src/app/collapse/collapse-example/collapse-example.component.html b/src/app/collapse/collapse-example/collapse-example.component.html new file mode 100644 index 00000000..e5bb3f98 --- /dev/null +++ b/src/app/collapse/collapse-example/collapse-example.component.html @@ -0,0 +1,33 @@ +
+
+

Esempio direttiva Collapse

+ +
+ + Apri/chiudi contenuto + +
+
+ Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. +
+
+
+
+ Ultima emissione dell'evento show = {{showTime}} +
+ +
+ Ultima emissione dell'evento shown = {{shownTime}} +
+ +
+ Ultima emissione dell'evento hide = {{hideTime}} +
+ +
+ Ultima emissione dell'evento hidden = {{hiddenTime}} +
+
+
\ No newline at end of file diff --git a/src/app/collapse/collapse-example/collapse-example.component.scss b/src/app/collapse/collapse-example/collapse-example.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/collapse/collapse-example/collapse-example.component.spec.ts b/src/app/collapse/collapse-example/collapse-example.component.spec.ts new file mode 100644 index 00000000..6a7ec62f --- /dev/null +++ b/src/app/collapse/collapse-example/collapse-example.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CollapseExampleComponent } from './collapse-example.component'; + +describe('CollapseExampleComponent', () => { + let component: CollapseExampleComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CollapseExampleComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CollapseExampleComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/collapse/collapse-example/collapse-example.component.ts b/src/app/collapse/collapse-example/collapse-example.component.ts new file mode 100644 index 00000000..d9188b15 --- /dev/null +++ b/src/app/collapse/collapse-example/collapse-example.component.ts @@ -0,0 +1,32 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'it-collapse-example', + templateUrl: './collapse-example.component.html', + styleUrls: ['./collapse-example.component.scss'] +}) +export class CollapseExampleComponent { + + isShown = false; + + showTime = ''; + shownTime = ''; + hideTime = ''; + hiddenTime = ''; + + logShow() { + this.showTime = new Date().toISOString(); + } + + logShown() { + this.shownTime = new Date().toISOString(); + } + + logHide() { + this.hideTime = new Date().toISOString(); + } + + logHidden() { + this.hiddenTime = new Date().toISOString(); + } +} diff --git a/src/app/collapse/collapse-examples/collapse-examples.component.scss b/src/app/collapse/collapse-examples/collapse-examples.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/collapse/collapse-examples/collapse-examples.component.spec.ts b/src/app/collapse/collapse-examples/collapse-examples.component.spec.ts new file mode 100644 index 00000000..3ba26b6c --- /dev/null +++ b/src/app/collapse/collapse-examples/collapse-examples.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CollapseExamplesComponent } from './collapse-examples.component'; + +describe('CollapseExamplesComponent', () => { + let component: CollapseExamplesComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CollapseExamplesComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CollapseExamplesComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/collapse/collapse-examples/collapse-examples.component.tpl b/src/app/collapse/collapse-examples/collapse-examples.component.tpl new file mode 100644 index 00000000..275a6f8c --- /dev/null +++ b/src/app/collapse/collapse-examples/collapse-examples.component.tpl @@ -0,0 +1,46 @@ +{% from "../../macro.template.njk" import sanitize as sanitize %} + +{% set html %} + {% include "../collapse-example/collapse-example.component.html" %} +{% endset %} + +{% set typescript %} + {% include "../collapse-example/collapse-example.component.ts" %} +{% endset %} + +{% set groupHtml %} + {% include "../collapse-group-example/collapse-group-example.component.html" %} +{% endset %} + +{% set groupTs %} + {% include "../collapse-group-example/collapse-group-example.component.ts" %} +{% endset %} + +{% set groupNestedHtml %} + {% include "../collapse-nested-example/collapse-nested-example.component.html" %} +{% endset %} + +{% set groupNestedTs %} + {% include "../collapse-nested-example/collapse-nested-example.component.ts" %} +{% endset %} + + + + + + + + + + + + + + + diff --git a/src/app/collapse/collapse-examples/collapse-examples.component.ts b/src/app/collapse/collapse-examples/collapse-examples.component.ts new file mode 100644 index 00000000..9c1e1685 --- /dev/null +++ b/src/app/collapse/collapse-examples/collapse-examples.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'it-collapse-examples', + templateUrl: './collapse-examples.component.html', + styleUrls: ['./collapse-examples.component.scss'] +}) +export class CollapseExamplesComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/collapse/collapse-group-example/collapse-group-example.component.html b/src/app/collapse/collapse-group-example/collapse-group-example.component.html new file mode 100644 index 00000000..b6b2537e --- /dev/null +++ b/src/app/collapse/collapse-group-example/collapse-group-example.component.html @@ -0,0 +1,20 @@ +
+
+

Esempio Collapse Group con Collapse Item

+ +
+ + + + Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. + + + Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. + + + Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. + + +
+
+
\ No newline at end of file diff --git a/src/app/collapse/collapse-group-example/collapse-group-example.component.scss b/src/app/collapse/collapse-group-example/collapse-group-example.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/collapse/collapse-group-example/collapse-group-example.component.spec.ts b/src/app/collapse/collapse-group-example/collapse-group-example.component.spec.ts new file mode 100644 index 00000000..64cfcfa7 --- /dev/null +++ b/src/app/collapse/collapse-group-example/collapse-group-example.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CollapseGroupExampleComponent } from './collapse-group-example.component'; + +describe('CollapseGroupExampleComponent', () => { + let component: CollapseGroupExampleComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CollapseGroupExampleComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CollapseGroupExampleComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/collapse/collapse-group-example/collapse-group-example.component.ts b/src/app/collapse/collapse-group-example/collapse-group-example.component.ts new file mode 100644 index 00000000..1d0cff7b --- /dev/null +++ b/src/app/collapse/collapse-group-example/collapse-group-example.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'it-collapse-group-example', + templateUrl: './collapse-group-example.component.html', + styleUrls: ['./collapse-group-example.component.scss'] +}) +export class CollapseGroupExampleComponent { + accordion = false; +} diff --git a/src/app/collapse/collapse-index/collapse-index.component.html b/src/app/collapse/collapse-index/collapse-index.component.html new file mode 100644 index 00000000..f4ab8121 --- /dev/null +++ b/src/app/collapse/collapse-index/collapse-index.component.html @@ -0,0 +1,30 @@ +

Collapse

+
Direttiva per l'interazione con elementi richiudibili
+ + +
+
+
+
+
+

Direttiva Collapse

+ +

Collapse Group

+ +

Collapse Item

+ +
+
+ +
+
diff --git a/src/app/collapse/collapse-index/collapse-index.component.scss b/src/app/collapse/collapse-index/collapse-index.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/collapse/collapse-index/collapse-index.component.spec.ts b/src/app/collapse/collapse-index/collapse-index.component.spec.ts new file mode 100644 index 00000000..bc442ec3 --- /dev/null +++ b/src/app/collapse/collapse-index/collapse-index.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CollapseIndexComponent } from './collapse-index.component'; + +describe('CollapseIndexComponent', () => { + let component: CollapseIndexComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CollapseIndexComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CollapseIndexComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/collapse/collapse-index/collapse-index.component.ts b/src/app/collapse/collapse-index/collapse-index.component.ts new file mode 100644 index 00000000..36c305b2 --- /dev/null +++ b/src/app/collapse/collapse-index/collapse-index.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; +import * as Documentation from '../../../assets/documentation.json'; + +@Component({ + selector: 'it-collapse-index', + templateUrl: './collapse-index.component.html', + styleUrls: ['./collapse-index.component.scss'] +}) +export class CollapseIndexComponent { + + directive: any; + groupComponent: any; + itemComponent: any; + + constructor() { + this.directive = (Documentation).directives.find(directive => directive.name === 'CollapseDirective'); + this.groupComponent = (Documentation).components.find(component => component.name === 'CollapseGroupComponent'); + this.itemComponent = (Documentation).components.find(component => component.name === 'CollapseItemComponent'); + } +} diff --git a/src/app/collapse/collapse-nested-example/collapse-nested-example.component.html b/src/app/collapse/collapse-nested-example/collapse-nested-example.component.html new file mode 100644 index 00000000..3d2033d3 --- /dev/null +++ b/src/app/collapse/collapse-nested-example/collapse-nested-example.component.html @@ -0,0 +1,93 @@ +
+
+

Esempio Collapse Group con Collapse Item Innestati

+
+ + + + + + Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf + moon officia aute, non cupidatat skateboard dolor brunch. + + + Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic + synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. + + + Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid + single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes + anderson cred nesciunt sapiente ea proident. + + + + + + + + Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf + moon officia aute, non cupidatat skateboard dolor brunch. + + + Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic + synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. + + + Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid + single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes + anderson cred nesciunt sapiente ea proident. + + + + + + + + + Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf + moon officia aute, non cupidatat skateboard dolor brunch. + + + Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic + synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS. + + + Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid + single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes + anderson cred nesciunt sapiente ea proident. + + + + + +
+ +
+ Ultimo evento show emesso da = {{showComponent}} +
+ +
+ Ultimo evento shown emesso da = {{shownComponent}} +
+ +
+ Ultimo evento hide emesso da = {{hideComponent}} +
+ +
+ Ultimo evento hidden emesso da = {{hiddenComponent}} +
+
+
diff --git a/src/app/collapse/collapse-nested-example/collapse-nested-example.component.scss b/src/app/collapse/collapse-nested-example/collapse-nested-example.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/collapse/collapse-nested-example/collapse-nested-example.component.ts b/src/app/collapse/collapse-nested-example/collapse-nested-example.component.ts new file mode 100644 index 00000000..e5129436 --- /dev/null +++ b/src/app/collapse/collapse-nested-example/collapse-nested-example.component.ts @@ -0,0 +1,30 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'it-collapse-nested-example', + templateUrl: './collapse-nested-example.component.html', + styleUrls: ['./collapse-nested-example.component.scss'] +}) +export class CollapseNestedExampleComponent { + + showComponent = ''; + shownComponent = ''; + hideComponent = ''; + hiddenComponent = ''; + + logShow($event) { + this.showComponent = $event._header; + } + + logShown($event) { + this.shownComponent = $event._header; + } + + logHide($event) { + this.hideComponent = $event._header; + } + + logHidden($event) { + this.hiddenComponent = $event._header; + } +} diff --git a/src/app/collapse/collapse-routing.module.ts b/src/app/collapse/collapse-routing.module.ts new file mode 100644 index 00000000..31cb9a1b --- /dev/null +++ b/src/app/collapse/collapse-routing.module.ts @@ -0,0 +1,13 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; +import { CollapseIndexComponent } from './collapse-index/collapse-index.component'; + +const routes: Routes = [ + { path: '', component: CollapseIndexComponent } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class CollapseRoutingModule { } diff --git a/src/app/collapse/collapse.module.ts b/src/app/collapse/collapse.module.ts new file mode 100644 index 00000000..3197fa22 --- /dev/null +++ b/src/app/collapse/collapse.module.ts @@ -0,0 +1,25 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { CollapseRoutingModule } from './collapse-routing.module'; +import { CollapseExampleComponent } from './collapse-example/collapse-example.component'; +import { CollapseExamplesComponent } from './collapse-examples/collapse-examples.component'; +import { CollapseIndexComponent } from './collapse-index/collapse-index.component'; +import { SharedModule } from '../shared/shared.module'; +import { FormsModule } from '@angular/forms'; +import { DesignAngularKitModule } from 'projects/design-angular-kit/src/public_api'; +import { CollapseGroupExampleComponent } from './collapse-group-example/collapse-group-example.component'; +import { CollapseNestedExampleComponent } from './collapse-nested-example/collapse-nested-example.component'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + DesignAngularKitModule, + SharedModule, + CollapseRoutingModule + ], + declarations: [CollapseExampleComponent, CollapseExamplesComponent, CollapseIndexComponent, + CollapseGroupExampleComponent, CollapseNestedExampleComponent] +}) +export class CollapseModule { } diff --git a/src/assets/table-of-content.json b/src/assets/table-of-content.json index 4cc29799..6539ce73 100644 --- a/src/assets/table-of-content.json +++ b/src/assets/table-of-content.json @@ -54,6 +54,10 @@ "label": "Tabs", "link": "/componenti/tabs" }, + { + "label": "Collapse", + "link": "/componenti/collapse" + }, { "label": "Form Input", "link": "/componenti/form-input"