diff --git a/projects/components/src/description/description.component.scss b/projects/components/src/description/description.component.scss new file mode 100644 index 000000000..2460441ea --- /dev/null +++ b/projects/components/src/description/description.component.scss @@ -0,0 +1,22 @@ +:host { + min-width: 0; +} + +.description { + display: flex; +} + +.description-button { + cursor: pointer; + text-decoration: underline; + white-space: nowrap; + &-more { + margin-left: 5px; + } +} + +.truncated-text { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/projects/components/src/description/description.component.test.ts b/projects/components/src/description/description.component.test.ts new file mode 100644 index 000000000..d86b93520 --- /dev/null +++ b/projects/components/src/description/description.component.test.ts @@ -0,0 +1,34 @@ +import { createHostFactory, Spectator } from '@ngneat/spectator/jest'; +import { DescriptionComponent } from './description.component'; + +describe('Description Component', () => { + let spectator: Spectator; + + const createHost = createHostFactory({ + component: DescriptionComponent, + shallow: true + }); + + test('should render the description', () => { + spectator = createHost(' ', { + hostProps: { + description: 'Description text' + } + }); + + expect(spectator.query('.description')).toExist(); + expect(spectator.query('.description-text')).toHaveText('Description text'); + }); + + test('should show full description text if pressed button show more', () => { + spectator = createHost(' ', { + hostProps: { + description: 'Description text' + } + }); + + expect(spectator.component.isDescriptionTextToggled).toBeFalsy(); + spectator.component.toggleDescriptionText(); + expect(spectator.component.isDescriptionTextToggled).toBeTruthy(); + }); +}); diff --git a/projects/components/src/description/description.component.ts b/projects/components/src/description/description.component.ts new file mode 100644 index 000000000..ab3d11a58 --- /dev/null +++ b/projects/components/src/description/description.component.ts @@ -0,0 +1,81 @@ +import { + AfterViewInit, + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + ElementRef, + Input, + OnChanges, + ViewChild +} from '@angular/core'; + +@Component({ + selector: 'ht-description', + styleUrls: ['./description.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` +
+
+ {{ description }} + show less +
+
+ show more +
+
+ ` +}) +export class DescriptionComponent implements OnChanges, AfterViewInit { + public isInitialized: boolean = false; + public isDescriptionTextToggled: boolean = false; + public isDescriptionTruncated!: boolean; + + @ViewChild('eventDescriptionText', { read: ElementRef }) + public readonly eventDescriptionText!: ElementRef; + + @ViewChild('eventDescriptionContainer', { read: ElementRef }) + public readonly eventDescriptionContainer!: ElementRef; + + @Input() + public description!: string; + + public constructor(private readonly cdRef: ChangeDetectorRef) {} + + public ngOnChanges(): void { + if (this.isInitialized) { + this.remeasure(); + } + } + + public ngAfterViewInit(): void { + this.isInitialized = true; + this.remeasure(); + } + + public toggleDescriptionText(): void { + this.isDescriptionTextToggled = !this.isDescriptionTextToggled; + } + + public remeasure(): void { + this.isDescriptionTextToggled = false; + this.cdRef.detectChanges(); + + this.isDescriptionTruncated = + this.eventDescriptionContainer.nativeElement.offsetWidth < this.eventDescriptionText.nativeElement.scrollWidth; + this.cdRef.detectChanges(); + } +} diff --git a/projects/components/src/description/description.module.ts b/projects/components/src/description/description.module.ts new file mode 100644 index 000000000..07ffde66d --- /dev/null +++ b/projects/components/src/description/description.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { LayoutChangeModule } from '../layout/layout-change.module'; +import { DescriptionComponent } from './description.component'; + +@NgModule({ + imports: [CommonModule, LayoutChangeModule], + declarations: [DescriptionComponent], + exports: [DescriptionComponent] +}) +export class DescriptionModule {} diff --git a/projects/components/src/public-api.ts b/projects/components/src/public-api.ts index 1d2405f99..dadcba451 100644 --- a/projects/components/src/public-api.ts +++ b/projects/components/src/public-api.ts @@ -304,3 +304,7 @@ export * from './confirmation/confirmation.service'; // Notification export * from './notification/notification.service'; export * from './notification/notification.module'; + +// Description +export * from './description/description.component'; +export * from './description/description.module';