Skip to content

Commit

Permalink
feat(ddesign): change daffSizeMixin to a directive
Browse files Browse the repository at this point in the history
  • Loading branch information
xelaint committed Jul 19, 2024
1 parent c58c263 commit ceb32bf
Show file tree
Hide file tree
Showing 12 changed files with 191 additions and 216 deletions.
20 changes: 20 additions & 0 deletions libs/design/button/src/button/button-sizable.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Directive } from '@angular/core';

import {
DaffSizableDirective,
DaffSizeLargeType,
DaffSizeMediumType,
DaffSizeSmallType,
} from '@daffodil/design';

/**
* The DaffSizable {@link DaffSizable } types that the DaffButtonComponent can implement.
*/
export type DaffButtonSize = DaffSizeSmallType | DaffSizeMediumType | DaffSizeLargeType;

@Directive({
standalone: true,
})

export class DaffButtonSizableDirective extends DaffSizableDirective<DaffButtonSize> {}

8 changes: 3 additions & 5 deletions libs/design/button/src/button/button.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ import {
DaffLoadingIconComponent,
} from '@daffodil/design/loading-icon';

import {
DaffButtonComponent,
DaffButtonSize,
} from './button.component';
import { DaffButtonSize } from './button-sizable.directive';
import { DaffButtonComponent } from './button.component';

@Component({
template: `
Expand Down Expand Up @@ -197,7 +195,7 @@ describe('@daffodil/design/button | DaffButtonComponent', () => {
});

describe('using the size property of a button', () => {
it('should add the class of the defined size to the host element', () => {
it('should take size as an input', () => {
wrapper.size = 'md';
fixture.detectChanges();

Expand Down
39 changes: 22 additions & 17 deletions libs/design/button/src/button/button.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,13 @@ import {
DaffSuffixable,
daffPrefixableMixin,
daffSuffixableMixin,
DaffSizable,
DaffSizeSmallType,
DaffSizeMediumType,
DaffSizeLargeType,
daffSizeMixin,
DaffStatusable,
daffStatusMixin,
DaffArticleEncapsulatedDirective,
} from '@daffodil/design';

import { DaffButtonSizableDirective } from './button-sizable.directive';

/**
* List of classes to add to DaffButtonComponent instances based on host attributes to style as different variants.
*/
Expand All @@ -46,15 +43,10 @@ class DaffButtonBase{
constructor(public _elementRef: ElementRef, public _renderer: Renderer2) {}
}

const _daffButtonBase = daffPrefixableMixin(daffSuffixableMixin(daffColorMixin(daffStatusMixin(daffSizeMixin<DaffButtonSize>(DaffButtonBase, 'md')))));
const _daffButtonBase = daffPrefixableMixin(daffSuffixableMixin(daffColorMixin(daffStatusMixin((DaffButtonBase)))));

export type DaffButtonType = 'daff-button' | 'daff-stroked-button' | 'daff-raised-button' | 'daff-flat-button' | 'daff-icon-button' | 'daff-underline-button' | undefined;

/**
* The DaffSizable types that the DaffButtonComponent can implement
*/
export type DaffButtonSize = DaffSizeSmallType | DaffSizeMediumType | DaffSizeLargeType;

enum DaffButtonTypeEnum {
Default = 'daff-button',
Stroked = 'daff-stroked-button',
Expand Down Expand Up @@ -86,27 +78,40 @@ enum DaffButtonTypeEnum {
styleUrls: ['./button.component.scss'],
//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', 'size', 'status'],
hostDirectives: [{
directive: DaffArticleEncapsulatedDirective,
}],
inputs: ['color', 'status'],
hostDirectives: [
{ directive: DaffArticleEncapsulatedDirective },
{
directive: DaffButtonSizableDirective,
inputs: ['size'],
},
],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DaffButtonComponent
extends _daffButtonBase
implements OnInit, DaffPrefixable, DaffSuffixable, DaffColorable, DaffSizable<DaffButtonSize>, DaffStatusable {
implements OnInit, DaffPrefixable, DaffSuffixable, DaffColorable, DaffStatusable {

private buttonType: DaffButtonType;

constructor(private elementRef: ElementRef, private renderer: Renderer2) {
constructor(
private elementRef: ElementRef,
private renderer: Renderer2,
private size: DaffButtonSizableDirective,
) {
super(elementRef, renderer);

for (const attr of BUTTON_HOST_ATTRIBUTES) {
if (this._hasHostAttributes(attr)) {
(<HTMLElement>elementRef.nativeElement).classList.add(attr);
}
}

/**
* Sets the default size of a button to medium.
*/
this.size.defaultSize = 'md';
}

/**
Expand Down
1 change: 1 addition & 0 deletions libs/design/button/src/public_api.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { DaffButtonComponent } from './button/button.component';
export { DaffButtonModule } from './button.module';
export { DaffButtonSizableDirective } from './button/button-sizable.directive';
14 changes: 7 additions & 7 deletions libs/design/container/src/container/container.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,16 @@ describe('@daffodil/design/container | DaffContainerComponent', () => {
});

describe('setting the size', () => {
it('should take size as an input', () => {
wrapper.size = 'md';
fixture.detectChanges();

expect(de.nativeElement.classList.contains('daff-md')).toEqual(true);
});

it('should not set a default size', () => {
de = fixture.debugElement.query(By.css('daff-container'));
expect(de.nativeElement.classList.toString()).toEqual('daff-container');
});

it('should add the size class on the host element for the defined size', () => {
wrapper.size = 'xs';
fixture.detectChanges();

expect(de.nativeElement.classList.contains('daff-xs')).toEqual(true);
});
});
});
34 changes: 8 additions & 26 deletions libs/design/container/src/container/container.component.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
import {
Component,
Input,
ChangeDetectionStrategy,
HostBinding,
ElementRef,
Renderer2,
} from '@angular/core';

import {
DaffSizable,
DaffSizeAllType,
daffSizeMixin,
} from '@daffodil/design';

/**
* An _elementRef and an instance of renderer2 are needed for the Sizeable mixin
*/
class DaffContainerBase{
constructor(public _elementRef: ElementRef, public _renderer: Renderer2) {}
}

const _daffContainerBase = daffSizeMixin(DaffContainerBase);
import { DaffSizableDirective } from '@daffodil/design';

/**
* @inheritdoc
Expand All @@ -29,19 +13,17 @@ const _daffContainerBase = daffSizeMixin(DaffContainerBase);
selector: 'daff-container',
styleUrls: ['./container.component.scss'],
template: '<ng-content></ng-content>',
//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: ['size'],
hostDirectives: [
{
directive: DaffSizableDirective,
inputs: ['size'],
},
],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DaffContainerComponent extends _daffContainerBase implements DaffSizable<DaffSizeAllType> {

export class DaffContainerComponent {
/**
* @docs-private
*/
@HostBinding('class.daff-container') class = true;

constructor(private elementRef: ElementRef, private renderer: Renderer2) {
super(elementRef, renderer);
}
}
2 changes: 1 addition & 1 deletion libs/design/src/core/sizable/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ export {
DaffSizeLargeType,
DaffSizeXLargeType,
} from './sizable';
export { daffSizeMixin } from './sizable-mixin';
export { DaffSizableDirective } from './sizable.directive';
52 changes: 0 additions & 52 deletions libs/design/src/core/sizable/sizable-mixin.ts

This file was deleted.

68 changes: 68 additions & 0 deletions libs/design/src/core/sizable/sizable.directive.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import {
Component,
DebugElement,
} from '@angular/core';
import {
waitForAsync,
ComponentFixture,
TestBed,
} from '@angular/core/testing';
import { By } from '@angular/platform-browser';

import { DaffSizeAllType } from './sizable';
import { DaffSizableDirective } from './sizable.directive';

@Component({
template: `
<div daffSizable [size]="size"></div>`,
})

class WrapperComponent {
size: string;
}

describe('@daffodil/design | DaffSizableDirective', () => {
let wrapper: WrapperComponent;
let de: DebugElement;
let fixture: ComponentFixture<WrapperComponent>;
let directive: DaffSizableDirective<DaffSizeAllType>;

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [
WrapperComponent,
],
imports: [
DaffSizableDirective,
],
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(WrapperComponent);
wrapper = fixture.componentInstance;
de = fixture.debugElement.query(By.css('[daffSizable]'));

directive = de.injector.get(DaffSizableDirective);
fixture.detectChanges();
});

it('should create', () => {
expect(wrapper).toBeTruthy();
expect(directive).toBeTruthy();
});

it('should take size as an input', () => {
expect(directive.size).toEqual(wrapper.size);
});

it('should add a class of .daff-md to the host element if size is set to md', () => {
wrapper.size = 'md';
fixture.detectChanges();

expect(directive.class).toEqual(jasmine.objectContaining({
'daff-md': true,
}));
});
});
57 changes: 57 additions & 0 deletions libs/design/src/core/sizable/sizable.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {
Directive,
HostBinding,
Input,
OnChanges,
OnInit,
SimpleChanges,
} from '@angular/core';

import {
DaffSizable,
DaffSizableEnum,
DaffSizeAllType,
} from './sizable';

@Directive({
selector: '[daffSizable]',
standalone: true,
})

export class DaffSizableDirective<T extends DaffSizeAllType> implements DaffSizable<T>, OnChanges, OnInit {
/**
* @docs-private
*/
@HostBinding('class') get class() {
return {
'daff-xs': this.size === DaffSizableEnum.XSmall,
'daff-sm': this.size === DaffSizableEnum.Small,
'daff-md': this.size === DaffSizableEnum.Medium,
'daff-lg': this.size === DaffSizableEnum.Large,
'daff-xl': this.size === DaffSizableEnum.XLarge,
};
}

/**
* Sets the size on a component.
*/
@Input() size: T;

/**
* Sets a default size.
*/
defaultSize: T;

ngOnChanges(changes: SimpleChanges) {
if(!changes.size.currentValue) {
this.size = this.defaultSize;
}
}

ngOnInit() {
if(!this.size) {
this.size = this.defaultSize;
}
}
}

Loading

0 comments on commit ceb32bf

Please sign in to comment.