Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion projects/angular-components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@frankframework/angular-components",
"version": "1.3.0",
"version": "1.3.1",
"description": "A collection of reusable components designed for use in Frank!Framework projects",
"main": "",
"author": "Vivy Booman",
Expand Down
33 changes: 33 additions & 0 deletions projects/angular-components/src/lib/collapse.directive.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { CollapseDirective } from './collapse.directive';
import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';

@Component({
template: ``,
imports: [
/*CollapseDirective*/
],
})
class TestComponent {}

describe('CollapseDirective', () => {
let fixture: ComponentFixture<TestComponent>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let des: DebugElement[];
let component: TestComponent;

beforeEach(() => {
fixture = TestBed.configureTestingModule({
imports: [CollapseDirective, TestComponent],
}).createComponent(TestComponent);
fixture.detectChanges(); // initial binding
// all elements with an attached HighlightDirective
des = fixture.debugElement.queryAll(By.directive(CollapseDirective));
component = fixture.componentInstance;
});

it('should create an instance', () => {
expect(component).toBeTruthy();
});
});
88 changes: 88 additions & 0 deletions projects/angular-components/src/lib/collapse.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {
Directive,
HostListener,
Input,
booleanAttribute,
Output,
EventEmitter,
AfterViewInit,
inject,
Renderer2,
} from '@angular/core';

@Directive({
selector: '[collapse]',
standalone: true,
})
export class CollapseDirective implements AfterViewInit {
@Input({ required: true }) collapse!: HTMLElement;
@Input({ transform: booleanAttribute }) collapsed = false;
@Input() animationSpeed = 300;
@Output() collapsedChange = new EventEmitter<boolean>();

private collapseAnimation: Animation | null = null;
private clientHeight = 0;
private readonly renderer: Renderer2 = inject(Renderer2);

ngAfterViewInit(): void {
this.setInitialState();
}

@HostListener('click')
onClick(): void {
this.collapsed = !this.collapsed;
this.collapsedChange.emit(this.collapsed);
this.updateState();
}

updateState(): void {
if (this.collapseAnimation) {
this.collapseAnimation.cancel();
return;
}

if (this.collapsed) {
this.clientHeight = this.collapse.clientHeight;
this.collapseElement();
} else {
this.expandElement();
}
}

private setInitialState(): void {
if (this.collapsed) {
this.clientHeight = this.collapse.clientHeight;
this.renderer.addClass(this.collapse, 'collapsed')
}
}

private collapseElement(): void {
this.collapse.classList.add('transforming');
this.collapseAnimation = this.collapse.animate(
{ height: [`${this.clientHeight}px`, '0px'] },
{ duration: this.animationSpeed, easing: 'ease-in-out' },
);
this.collapseAnimation.finished
.then(() => {
this.renderer.addClass(this.collapse, 'collapsed')
})
.finally(() => {
this.renderer.removeClass(this.collapse, 'transforming');
this.collapseAnimation = null;
});
}

private expandElement(): void {
this.collapseAnimation = this.collapse.animate(
{ height: ['0px', `${this.clientHeight}px`] },
{ duration: this.animationSpeed, easing: 'ease-in-out' },
);
this.collapseAnimation.finished
.then(() => {
this.renderer.removeClass(this.collapse, 'collapsed');
})
.finally(() => {
this.collapseAnimation = null;
});
}
}
2 changes: 2 additions & 0 deletions projects/angular-components/src/lib/library.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { DatatableComponent } from './datatable/datatable.component';
import { CheckboxComponent } from './checkbox/checkbox.component';
import { DtContentDirective } from './datatable/dt-content.directive';
import { ThSortableDirective } from './th-sortable.directive';
import { CollapseDirective } from './collapse.directive';

const components = [
ButtonComponent,
Expand All @@ -16,6 +17,7 @@ const components = [
DatatableComponent,
CheckboxComponent,
DtContentDirective,
CollapseDirective,
ThSortableDirective,
];

Expand Down
1 change: 1 addition & 0 deletions projects/angular-components/src/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from './lib/chip/chip.component';
export * from './lib/datatable/datatable.component';
export * from './lib/checkbox/checkbox.component';

export * from './lib/collapse.directive';
export * from './lib/th-sortable.directive';
export * from './lib/datatable/dt-content.directive';

Expand Down
5 changes: 5 additions & 0 deletions projects/angular-components/src/styles/_light_theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,8 @@ th[sortable] {
right: 0;
}
}

.collapsed {
height: 0;
overflow: hidden;
}
20 changes: 10 additions & 10 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<h1>FF Components</h1>
<ul class="components-list">
<li>
<h2>Button</h2>
<div class="components">
<h2 [collapse]="buttons">Button</h2>
<div #buttons class="components">
<ff-button>Click me!</ff-button>
<ff-button><app-svg-add-icon colour="#fff" [width]="16" [height]="16" /> Click me!</ff-button>
<ff-button active="true">Active</ff-button>
Expand All @@ -11,8 +11,8 @@ <h2>Button</h2>
</div>
</li>
<li>
<h2>Checkbox</h2>
<div class="components">
<h2 [collapse]="checkboxes">Checkbox</h2>
<div #checkboxes class="components">
<ff-checkbox [(ngModel)]="checked" />
<ff-checkbox [(ngModel)]="checked2" />
<ff-checkbox checked />
Expand All @@ -22,8 +22,8 @@ <h2>Checkbox</h2>
<p>Checkbox 1: {{ checked }}, checkbox 2: {{ checked2 }}</p>
</li>
<li>
<h2>Search</h2>
<div class="components">
<h2 [collapse]="search">Search</h2>
<div #search class="components">
<ff-search style="width: 100%" forceFocus autofocus [(ngModel)]="searchText" />
<div class="separator">
<ff-search placeholder="Test the focus key" focusKey="=" style="width: 100%" />
Expand All @@ -35,8 +35,8 @@ <h2>Search</h2>
<ff-button (click)="changeSearchQuery()">Update search query</ff-button>
</li>
<li>
<h2>Alert</h2>
<div class="components">
<h2 [collapse]="alerts">Alert</h2>
<div #alerts class="components">
<ff-alert type="info">Info</ff-alert>
<ff-alert type="success">Success</ff-alert>
<ff-alert type="warning">Warning</ff-alert>
Expand Down Expand Up @@ -64,8 +64,8 @@ <h2>Alert</h2>
</div>
</li>
<li>
<h2>Chip</h2>
<div class="components">
<h2 [collapse]="chips">Chip</h2>
<div #chips class="components">
<ff-chip rounded>L</ff-chip>
<ff-chip>Label</ff-chip>
<ff-chip colour="#345678" rounded>Colour!</ff-chip>
Expand Down