From 8da0adfaee44ad8fcf055b80984af29138b3890f Mon Sep 17 00:00:00 2001 From: xelaint Date: Thu, 18 Jul 2024 09:14:16 -0600 Subject: [PATCH] feat(design)!: change daffManageContainerLayoutMixin to a directive BREAKING CHANGE: daffManageContainerLayoutMixin has been removed in favor of DaffManageContainerLayoutDirective. Update usage by using the hostDirective feature. --- .../callout/src/callout/callout.component.ts | 11 ++-- libs/design/hero/src/hero/hero.component.ts | 11 ++-- .../navbar/src/navbar/navbar.component.ts | 7 ++- .../manage-container-layout-mixin.ts | 26 --------- .../manage-container-layout.directive.spec.ts | 57 +++++++++++++++++++ .../manage-container-layout.directive.ts | 35 ++++++++++++ .../manage-container-layout.spec.ts | 35 ------------ .../manage-container-layout/public_api.ts | 2 +- 8 files changed, 110 insertions(+), 74 deletions(-) delete mode 100644 libs/design/src/core/manage-container-layout/manage-container-layout-mixin.ts create mode 100644 libs/design/src/core/manage-container-layout/manage-container-layout.directive.spec.ts create mode 100644 libs/design/src/core/manage-container-layout/manage-container-layout.directive.ts delete mode 100644 libs/design/src/core/manage-container-layout/manage-container-layout.spec.ts diff --git a/libs/design/callout/src/callout/callout.component.ts b/libs/design/callout/src/callout/callout.component.ts index ad584860de..fd2fee8ce4 100644 --- a/libs/design/callout/src/callout/callout.component.ts +++ b/libs/design/callout/src/callout/callout.component.ts @@ -13,7 +13,7 @@ import { daffColorMixin, DaffCompactable, daffCompactableMixin, - daffManageContainerLayoutMixin, + DaffManageContainerLayoutDirective, DaffTextAlignable, daffTextAlignmentMixin, } from '@daffodil/design'; @@ -25,7 +25,7 @@ class DaffCalloutBase { constructor(public _elementRef: ElementRef, public _renderer: Renderer2) {} } -const _daffCalloutBase = daffManageContainerLayoutMixin(daffColorMixin(daffCompactableMixin(daffTextAlignmentMixin(DaffCalloutBase, 'left')))); +const _daffCalloutBase = daffColorMixin(daffCompactableMixin(daffTextAlignmentMixin(DaffCalloutBase, 'left'))); /** * @inheritdoc @@ -38,9 +38,10 @@ const _daffCalloutBase = daffManageContainerLayoutMixin(daffColorMixin(daffCompa //todo(damienwebdev): remove once decorators hit stage 3 - https://github.com/microsoft/TypeScript/issues/7342 // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: ['color', 'compact', 'textAlignment'], - hostDirectives: [{ - directive: DaffArticleEncapsulatedDirective, - }], + hostDirectives: [ + { directive: DaffArticleEncapsulatedDirective }, + { directive: DaffManageContainerLayoutDirective }, + ], changeDetection: ChangeDetectionStrategy.OnPush, }) export class DaffCalloutComponent extends _daffCalloutBase implements DaffColorable, DaffTextAlignable, DaffCompactable { diff --git a/libs/design/hero/src/hero/hero.component.ts b/libs/design/hero/src/hero/hero.component.ts index 1ea3decd7c..f1bed4b1cf 100644 --- a/libs/design/hero/src/hero/hero.component.ts +++ b/libs/design/hero/src/hero/hero.component.ts @@ -13,7 +13,7 @@ import { daffColorMixin, DaffCompactable, daffCompactableMixin, - daffManageContainerLayoutMixin, + DaffManageContainerLayoutDirective, DaffTextAlignable, daffTextAlignmentMixin, } from '@daffodil/design'; @@ -25,7 +25,7 @@ class DaffHeroBase { constructor(public _elementRef: ElementRef, public _renderer: Renderer2) {} } -const _daffHeroBase = daffManageContainerLayoutMixin(daffColorMixin(daffCompactableMixin(daffTextAlignmentMixin(DaffHeroBase, 'left')))); +const _daffHeroBase = daffColorMixin(daffCompactableMixin(daffTextAlignmentMixin(DaffHeroBase, 'left'))); /** * @inheritdoc @@ -38,9 +38,10 @@ const _daffHeroBase = daffManageContainerLayoutMixin(daffColorMixin(daffCompacta //todo(damienwebdev): remove once decorators hit stage 3 - https://github.com/microsoft/TypeScript/issues/7342 // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: ['color', 'compact', 'textAlignment'], - hostDirectives: [{ - directive: DaffArticleEncapsulatedDirective, - }], + hostDirectives: [ + { directive: DaffArticleEncapsulatedDirective }, + { directive: DaffManageContainerLayoutDirective }, + ], changeDetection: ChangeDetectionStrategy.OnPush, }) export class DaffHeroComponent extends _daffHeroBase implements DaffColorable, DaffTextAlignable, DaffCompactable { diff --git a/libs/design/navbar/src/navbar/navbar.component.ts b/libs/design/navbar/src/navbar/navbar.component.ts index 7aaddd1a33..1a1a6b164b 100644 --- a/libs/design/navbar/src/navbar/navbar.component.ts +++ b/libs/design/navbar/src/navbar/navbar.component.ts @@ -9,8 +9,8 @@ import { import { DaffColorable, + DaffManageContainerLayoutDirective, daffColorMixin, - daffManageContainerLayoutMixin, } from '@daffodil/design'; /** @@ -20,7 +20,7 @@ class DaffNavbarBase { constructor(public _elementRef: ElementRef, public _renderer: Renderer2) {} } -const _daffNavbarBase = daffManageContainerLayoutMixin(daffColorMixin(DaffNavbarBase)); +const _daffNavbarBase = daffColorMixin(DaffNavbarBase); /** * @inheritdoc @@ -33,6 +33,9 @@ const _daffNavbarBase = daffManageContainerLayoutMixin(daffColorMixin(DaffNavbar //todo(damienwebdev): remove once decorators hit stage 3 - https://github.com/microsoft/TypeScript/issues/7342 // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property inputs: ['color'], + hostDirectives: [{ + directive: DaffManageContainerLayoutDirective, + }], changeDetection: ChangeDetectionStrategy.OnPush, }) export class DaffNavbarComponent extends _daffNavbarBase implements DaffColorable { diff --git a/libs/design/src/core/manage-container-layout/manage-container-layout-mixin.ts b/libs/design/src/core/manage-container-layout/manage-container-layout-mixin.ts deleted file mode 100644 index 208fcfb63e..0000000000 --- a/libs/design/src/core/manage-container-layout/manage-container-layout-mixin.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { - ElementRef, - Renderer2, -} from '@angular/core'; - -import { Constructor } from '../constructor/constructor'; - -export interface HasElementRef { - _elementRef: ElementRef; - _renderer: Renderer2; -} - -/** - * A mixin for giving a component the ability to manage a DaffContainerComponent's layout. - * It passes predetermined layout styles down to the container. In order for a component to - * do this, it must implement this mixin. - */ -export function -daffManageContainerLayoutMixin>(Base: T) { - return class extends Base { - constructor(...args: any[]) { - super(...args); - this._renderer.addClass(this._elementRef.nativeElement, `daff-manage-container-layout`); - } - }; -} diff --git a/libs/design/src/core/manage-container-layout/manage-container-layout.directive.spec.ts b/libs/design/src/core/manage-container-layout/manage-container-layout.directive.spec.ts new file mode 100644 index 0000000000..bac90888c7 --- /dev/null +++ b/libs/design/src/core/manage-container-layout/manage-container-layout.directive.spec.ts @@ -0,0 +1,57 @@ +import { + Component, + DebugElement, +} from '@angular/core'; +import { + waitForAsync, + ComponentFixture, + TestBed, +} from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; + +import { DaffManageContainerLayoutDirective } from './manage-container-layout.directive'; + +@Component({ + template: ` +
`, +}) + +class WrapperComponent {} + +describe('@daffodil/design | DaffManageContainerLayoutDirective', () => { + let wrapper: WrapperComponent; + let de: DebugElement; + let fixture: ComponentFixture; + let directive: DaffManageContainerLayoutDirective; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [ + WrapperComponent, + ], + imports: [ + DaffManageContainerLayoutDirective, + ], + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(WrapperComponent); + wrapper = fixture.componentInstance; + de = fixture.debugElement.query(By.css('[daffManageContainerLayout]')); + directive = de.injector.get(DaffManageContainerLayoutDirective); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(wrapper).toBeTruthy(); + expect(directive).toBeTruthy(); + }); + + it('should add a class of "daff-manage-container-layout" to the host element', () => { + expect(de.classes).toEqual(jasmine.objectContaining({ + 'daff-manage-container-layout': true, + })); + }); +}); diff --git a/libs/design/src/core/manage-container-layout/manage-container-layout.directive.ts b/libs/design/src/core/manage-container-layout/manage-container-layout.directive.ts new file mode 100644 index 0000000000..6c4c3d0583 --- /dev/null +++ b/libs/design/src/core/manage-container-layout/manage-container-layout.directive.ts @@ -0,0 +1,35 @@ +import { + Directive, + HostBinding, +} from '@angular/core'; + +/** + * A directive that gives a component the ability to manage a DaffContainerComponent's layout. + * By including this directive, predetermined layout styles are passed down to the container. + * + * To understand the motivation for this directive, consider: + * + * ```html + * + * + * + * ``` + * vs. + * + * ```html + * + * + * + * ``` + * + * The former may inappropriately constrain the width of its child elements, + * while the latter (without `DaffManageContainerLayoutDirective`) may unexpectedly + * interfere in the layout features of its parent element (i.e. display: grid, display: flex). + */ +@Directive({ + selector: '[daffManageContainerLayout]', + standalone: true, +}) +export class DaffManageContainerLayoutDirective { + @HostBinding('class.daff-manage-container-layout') class = true; +} diff --git a/libs/design/src/core/manage-container-layout/manage-container-layout.spec.ts b/libs/design/src/core/manage-container-layout/manage-container-layout.spec.ts deleted file mode 100644 index 2ef3910f95..0000000000 --- a/libs/design/src/core/manage-container-layout/manage-container-layout.spec.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ElementRef } from '@angular/core'; - -import { - daffManageContainerLayoutMixin, - HasElementRef, -} from './manage-container-layout-mixin'; - -class TestingClass implements HasElementRef { - element: HTMLElement = document.createElement('div'); - - _elementRef = new ElementRef(this.element); - _renderer: any = { - addClass: (el: HTMLElement, className: string) => { - el.classList.add(className); - }, - removeClass: (el: HTMLElement, className: string) => { - el.classList.remove(className); - }, - }; -} - -describe('@daffodil/design | daffManageContainerLayoutMixin', () => { - let instance; - let manageContainerLayoutClass; - - beforeEach(() => { - manageContainerLayoutClass = daffManageContainerLayoutMixin(TestingClass); - instance = new manageContainerLayoutClass(); - }); - - - it('should set a namespaced manage container layout class', () => { - expect(instance.element.classList).toContain('daff-manage-container-layout'); - }); -}); diff --git a/libs/design/src/core/manage-container-layout/public_api.ts b/libs/design/src/core/manage-container-layout/public_api.ts index a6857f4d99..40201f7ddb 100644 --- a/libs/design/src/core/manage-container-layout/public_api.ts +++ b/libs/design/src/core/manage-container-layout/public_api.ts @@ -1 +1 @@ -export { daffManageContainerLayoutMixin } from './manage-container-layout-mixin'; +export { DaffManageContainerLayoutDirective } from './manage-container-layout.directive';