Skip to content

Commit

Permalink
feat(Resize): completed resize module
Browse files Browse the repository at this point in the history
  • Loading branch information
alisahinozcelik committed Sep 2, 2020
1 parent 1fad30a commit 968c1a0
Show file tree
Hide file tree
Showing 18 changed files with 333 additions and 12 deletions.
86 changes: 86 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ Trigger openning selection by another element

Create your own custom modals, dialogs etc.

_Dependencies:_
* @angular/cdk

### OverlayComponent

`tha-overlay` component comes with no styling except cdk prebuilt styles. It contains only the open/close functionality based on `CdkOverlay` so feel free to use it with your other `CdkOverlay` based components.
Expand Down Expand Up @@ -144,6 +147,89 @@ export class FooModule { }
</tha-overlay>
```

## Resize

Observe element's size changes, animate their size, etc..

_Dependencies:_
* @angular/animations
* @angular/platform-browser
* @thalesrc/resize-manager

### ResizeService

Observe an element's size changes, listen window.resize

Usage:
```typescript
@Component({
selector: 'app-foo',
templateUrl: './foo.component.html',
styleUrls: ['./foo.component.scss']
})
export class FooComponent implements OnInit {
constructor(
private resizeService: ResizeService,
private el: ElementRef
) {}

ngOnInit() {
this.resizeService.windowResize$.subscribe(({width, height}) => {
console.log(width, height);
});

this.resizeService.observe(this.el.nativeElement).subscribe(({width, height}) => {
console.log(width, height);
});

this.resizeService.observe(document.querySelector('bar')).subscribe(({width, height}) => {
console.log(width, height);
});
}
}

```

### ResizeDirective

Emits size change events of an element

Usage:

```html
<!-- Listen both width and height change ($event: {width: number, height: number}) -->
<img [src]="src$ | async" thaResize (onResize)="postSizeChange($event)">

<!-- Listen only width change ($event: number) -->
<img [src]="src$ | async" thaResize="width" (onResize)="postWidthChange($event)">

<!-- Listen only height change ($event: number) -->
<img [src]="src$ | async" thaResize="height" (onResize)="postHeightChange($event)">
```

### AnimateResizeDirective

Animate resizing of an element

Usage:

```html
<!-- Animate both width and height change -->
<img [src]="src$ | async" thaAnimateResize>

<!-- Animate only width change -->
<img [src]="src$ | async" thaAnimateResize="width">

<!-- Animate only height change -->
<img [src]="src$ | async" thaAnimateResize="height">

<!-- Set animation duration -->
<img [src]="src$ | async" thaAnimateResize duration="1000">

<!-- Do smth when animation completed -->
<img [src]="src$ | async" thaAnimateResize (animationComplete)="doSomething()">
```

## Substitute

Create portals in components and manage it from outside
Expand Down
20 changes: 18 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,23 @@
"util",
"utils",
"library",
"image-input",
"advanced-route"
"image",
"input",
"route",
"router",
"data",
"portal",
"substitute",
"overlay",
"modal",
"dialog",
"stream",
"host",
"listener",
"size",
"resize",
"change",
"animate"
],
"author": {
"name": "Ali Şahin Özçelik",
Expand Down Expand Up @@ -38,6 +53,7 @@
"@angular/platform-browser-dynamic": "~8.0.3",
"@angular/router": "~8.0.3",
"@thalesrc/js-utils": "^2.2.0",
"@thalesrc/resize-manager": "^0.3.3",
"rxjs": "~6.4.0",
"tslib": "^1.9.0",
"zone.js": "~0.9.1"
Expand Down
3 changes: 3 additions & 0 deletions projects/ng-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@
"version-update": "npm version $PACKAGE_VERSION --no-git-tag-version"
},
"peerDependencies": {
"@angular/animations": "~8.0.3",
"@angular/common": "^8.0.3",
"@angular/core": "^8.0.3",
"@angular/forms": "^8.0.3",
"@angular/cdk": "^8.2.3",
"@angular/platform-browser": "~8.0.3",
"@thalesrc/resize-manager": "^0.3.2",
"rxjs": "^6.4.0"
},
"dependencies": {
Expand Down
1 change: 1 addition & 0 deletions projects/ng-utils/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

export * from './advanced-route/index';
export * from './form/image-input/index';
export * from './resize/index';
export * from './substitute/index';
export * from './overlay/index';

Expand Down
8 changes: 8 additions & 0 deletions projects/ng-utils/src/resize/animate-resize.directive.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { AnimateResizeDirective } from './animate-resize.directive';

describe('AnimateResizeDirective', () => {
it('should create an instance', () => {
const directive = new AnimateResizeDirective(null, null, null);
expect(directive).toBeTruthy();
});
});
81 changes: 81 additions & 0 deletions projects/ng-utils/src/resize/animate-resize.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Directive, ElementRef, Input, Output, EventEmitter } from '@angular/core';
import { AnimationBuilder, AnimationFactory, style, animate } from '@angular/animations';
import { Unsubscriber } from '../utils/unsubscriber';
import { ResizeService } from './resize.service';
import { of, merge, interval } from 'rxjs';
import { distinctUntilChanged, takeUntil, mapTo, exhaustMap, take, filter, pairwise } from 'rxjs/operators';
import { ResizeEvent } from '@thalesrc/resize-manager';
import { ResizeMode } from './resize-mode';
import { isTruthy } from '@thalesrc/js-utils/legacy';

@Directive({
selector: '[thaAnimateResize]',
exportAs: 'thaAnimateResize'
})
export class AnimateResizeDirective extends Unsubscriber {
@Input('thaAnimateResize')
// tslint:disable-next-line:variable-name
public mode: ResizeMode;

@Input('duration')
// tslint:disable-next-line:variable-name
public _duration: number;

@Output()
public animationComplete = new EventEmitter<void>();

private get duration(): number {
return Number.isNaN(+this._duration) ? 180 : +this._duration;
}

constructor(
service: ResizeService,
{nativeElement}: ElementRef,
builder: AnimationBuilder
) {
super();

service.observe(nativeElement, 0).pipe(
distinctUntilChanged(({width, height}, next) => {
switch (this.mode) {
case 'width':
return width === next.width;
case 'height':
return height === next.height;
default:
return width === next.width && height === next.height;
}
}),
pairwise(),
exhaustMap(event =>
merge(
of(null).pipe(mapTo(event)),
interval(this.duration + 100).pipe(mapTo(null))
).pipe(take(2))),
filter<[ResizeEvent, ResizeEvent]>(isTruthy),
takeUntil(this.onDestroy$)
).subscribe(([prev, {width, height}]) => {
let factory: AnimationFactory;

switch (this.mode) {
case 'width':
factory = builder.build([style({width: prev.width}), animate(this.duration, style({width}))]);
break;
case 'height':
factory = builder.build([style({height: prev.height}), animate(this.duration, style({height}))]);
break;
default:
factory = builder.build([style({width: prev.width, height: prev.height}), animate(this.duration, style({width, height}))]);
}

const player = factory.create(nativeElement);

player.play();

player.onDone(() => {
player.destroy();
this.animationComplete.emit();
});
});
}
}
4 changes: 4 additions & 0 deletions projects/ng-utils/src/resize/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './animate-resize.directive';
export * from './resize.directive';
export * from './resize.module';
export * from './resize.service';
1 change: 1 addition & 0 deletions projects/ng-utils/src/resize/resize-mode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type ResizeMode = 'both' | 'width' | 'height';
8 changes: 8 additions & 0 deletions projects/ng-utils/src/resize/resize.directive.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ResizeDirective } from './resize.directive';

describe('ResizeDirective', () => {
it('should create an instance', () => {
const directive = new ResizeDirective(null, null);
expect(directive).toBeTruthy();
});
});
39 changes: 39 additions & 0 deletions projects/ng-utils/src/resize/resize.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Directive, ElementRef, Input, Output, EventEmitter } from '@angular/core';
import { Unsubscriber } from '../utils/unsubscriber';
import { ResizeService } from './resize.service';
import { InputStream } from '../utils/input-stream';
import { Observable } from 'rxjs';
import { combineLatest, map, distinctUntilChanged, takeUntil } from 'rxjs/operators';
import { ResizeEvent } from '@thalesrc/resize-manager';
import { ResizeMode } from './resize-mode';

@Directive({
selector: '[thaResize]',
exportAs: 'thaResize'
})
export class ResizeDirective extends Unsubscriber {
@Input('thaResize')
@InputStream('both')
public mode: Observable<ResizeMode>;

// tslint:disable-next-line:no-output-on-prefix
@Output()
public onResize = new EventEmitter<ResizeEvent | number>();

constructor(
service: ResizeService,
{nativeElement}: ElementRef
) {
super();

service.observe(nativeElement, 0).pipe(
combineLatest(this.mode.pipe(
map(mode => mode || 'both'),
distinctUntilChanged()
)),
takeUntil(this.onDestroy$)
).subscribe(([{width, height}, mode]) => {
this.onResize.emit(mode === 'both' ? {width, height} : mode === 'width' ? width : height);
});
}
}
19 changes: 19 additions & 0 deletions projects/ng-utils/src/resize/resize.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ResizeDirective } from './resize.directive';
import { AnimateResizeDirective } from './animate-resize.directive';

@NgModule({
imports: [
BrowserAnimationsModule,
],
declarations: [
ResizeDirective,
AnimateResizeDirective
],
exports: [
ResizeDirective,
AnimateResizeDirective
]
})
export class ResizeModule { }
12 changes: 12 additions & 0 deletions projects/ng-utils/src/resize/resize.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';

import { ResizeService } from './resize.service';

describe('ResizeService', () => {
beforeEach(() => TestBed.configureTestingModule({}));

it('should be created', () => {
const service: ResizeService = TestBed.get(ResizeService);
expect(service).toBeTruthy();
});
});
16 changes: 16 additions & 0 deletions projects/ng-utils/src/resize/resize.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Injectable } from '@angular/core';
import { ResizeManager, ResizeEvent } from '@thalesrc/resize-manager';
import { Observable } from 'rxjs';

@Injectable({
providedIn: 'root'
})
export class ResizeService {
private static manager = new ResizeManager(0);

public windowResize$: Observable<ResizeEvent> = ResizeService.manager.root.resize;

public observe(target: HTMLElement, throttleBy = 90): Observable<ResizeEvent> {
return ResizeService.manager.observe(target).throttleBy(throttleBy);
}
}
4 changes: 2 additions & 2 deletions projects/ng-utils/tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
"directive-selector": [
true,
"attribute",
"lib",
"tha",
"camelCase"
],
"component-selector": [
true,
"element",
"lib",
"tha",
"kebab-case"
]
}
Expand Down
15 changes: 14 additions & 1 deletion projects/playground/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
<form #form="ngForm">
<img [src]="image | async" [thaImageInput]="{button: imgBtn}" [disabled]="false" ngModel name="image" (ngModelChange)="modelChange($event)">
<img
[src]="image | async"
thaImageInput
[changeButton]="imgBtn"
[disabled]="false"
ngModel
name="image"
(ngModelChange)="modelChange($event)"
thaAnimateResize
duration="300">
</form>
<button #imgBtn>Change Image</button>
<button (click)="changeImage()">reset image</button>
Expand All @@ -16,3 +25,7 @@
<tha-overlay #overlay>
<button (click)="overlay.close({yepp: true})">Submit</button>
</tha-overlay>

<textarea resize="both" >
dsadsa
</textarea>
4 changes: 2 additions & 2 deletions projects/playground/src/app/app.component.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
img {
width: 300px;
height: auto;
// width: 300px;
// height: auto;
}
Loading

0 comments on commit 968c1a0

Please sign in to comment.