@wolsok/thanos 18.4.5 → 18.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -173,7 +173,8 @@ directly in html via template ref:
173
173
  <button (click)="thanos.vaporize(true)">Vaporize</button>
174
174
  ```
175
175
 
176
- - `vaporize(removeElem = true)` starts the effect and returns an observable that emits once it is complete.
176
+ - `vaporize(removeElem = true)` starts the effect and returns an observable that emits once and completes when the effect is over,
177
+ also when the effect failed (the error is logged) or the directive was destroyed meanwhile, so a caller waiting on it never hangs.
177
178
  With `removeElem = false` the element fades back in afterwards instead of being removed.
178
179
  - `vaporize$(removeElem = true)` returns an observable of the `AnimationState` of every frame. Subscribe to start the effect.
179
180
 
@@ -1,6 +1,6 @@
1
1
  import { Directive, ElementRef, Output, afterNextRender, inject, input, } from '@angular/core';
2
2
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
- import { finalize, Subject, take, tap } from 'rxjs';
3
+ import { finalize, ReplaySubject, Subject, tap } from 'rxjs';
4
4
  import { WS_THANOS_OPTIONS_TOKEN } from './ws-thanos-options.token';
5
5
  import { WsThanosService } from './ws-thanos.service';
6
6
  import * as i0 from "@angular/core";
@@ -55,11 +55,24 @@ export class WsThanosDirective {
55
55
  /**
56
56
  * Vaporize the dom element of this directive
57
57
  * @param removeElem remove the vaporized dom element or blend back in after a while
58
- *
58
+ * @returns an observable that emits once and completes when the effect is
59
+ * over: after it finished, after it failed and when the directive was
60
+ * destroyed meanwhile. It replays, so a caller that subscribes after a
61
+ * synchronous failure still gets the completion. A failure is logged
62
+ * (`console.error`) and not thrown further: a caller that wants the error
63
+ * itself subscribes to `vaporize$` instead.
59
64
  */
60
65
  vaporize(removeElem = true) {
61
- this.vaporize$(removeElem).pipe(this.untilDestroyed).subscribe();
62
- return this.wsThanosComplete.pipe(take(1));
66
+ const done = new ReplaySubject(1);
67
+ this.vaporize$(removeElem)
68
+ .pipe(finalize(() => {
69
+ done.next();
70
+ done.complete();
71
+ }), this.untilDestroyed)
72
+ // Logged by vaporize$ already; left unhandled, RxJS would report it a
73
+ // second time as an error on the window, without its context.
74
+ .subscribe({ error: () => undefined });
75
+ return done.asObservable();
63
76
  }
64
77
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.2.3", ngImport: i0, type: WsThanosDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
65
78
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.2.3", type: WsThanosDirective, isStandalone: true, selector: "[wsThanos], ws-thanos", inputs: { wsThanosOptions: { classPropertyName: "wsThanosOptions", publicName: "wsThanosOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { wsThanosComplete: "wsThanosComplete" }, exportAs: ["thanos"], ngImport: i0 }); }
@@ -1 +1 @@
1
- {"version":3,"file":"ws-thanos.directive.js","sourceRoot":"","sources":["../../../../../../libs/public/ws-thanos/src/lib/ws-thanos.directive.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,UAAU,EACV,MAAM,EACN,eAAe,EACf,MAAM,EACN,KAAK,GACN,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAc,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;AAEhE,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;;AAQtD,MAAM,OAAO,iBAAiB;IAkB5B;QAjBQ,4BAAuB,GAAG,IAAI,OAAO,EAAQ,CAAC;QAC9C,mBAAc,GAAG,kBAAkB,EAAE,CAAC;QAE9C,qDAAqD;QACrC,oBAAe,GAAG,KAAK;uGAA4B,CAAC;QAG7D,qBAAgB,GACrB,IAAI,CAAC,uBAAuB,CAAC,YAAY,EAAE,CAAC;QAE7B,oBAAe,GAC9B,MAAM,CAAC,UAAU,CAAC,CAAC;QACJ,kBAAa,GAAoB,MAAM,CAAC,eAAe,CAAC,CAAC;QACzD,kBAAa,GAAoB,MAAM,CACtD,uBAAuB,CACxB,CAAC;QAGA,iEAAiE;QACjE,eAAe,CAAC,GAAG,EAAE;YACnB,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YACzE,IAAI,OAAO,EAAE,CAAC;gBACZ,KAAK,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;YACpC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACI,SAAS,CAAC,UAAU,GAAG,IAAI;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC;QAChD,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC,IAAI,CACnE,GAAG,CAAC;YACF,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;gBACf,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,EAAE;oBACvC,cAAc,EAAE,IAAI;oBACpB,UAAU;iBACX,CAAC,CAAC;YACL,CAAC;SACF,CAAC,EACF,QAAQ,CAAC,GAAG,EAAE;YACZ,IAAI,UAAU,EAAE,CAAC;gBACf,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACN,qBAAqB;gBACrB,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,eAAe,CAAC;gBACxC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;YAC3B,CAAC;YACD,IAAI,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC;QACtC,CAAC,CAAC,CACH,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACI,QAAQ,CAAC,UAAU,GAAG,IAAI;QAC/B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,SAAS,EAAE,CAAC;QACjE,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;8GApEU,iBAAiB;kGAAjB,iBAAiB;;2FAAjB,iBAAiB;kBAN7B,SAAS;mBAAC;oBACT,4FAA4F;oBAC5F,8DAA8D;oBAC9D,QAAQ,EAAE,uBAAuB;oBACjC,QAAQ,EAAE,QAAQ;iBACnB;;sBAQE,MAAM","sourcesContent":["import {\n Directive,\n ElementRef,\n Output,\n afterNextRender,\n inject,\n input,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { finalize, Observable, Subject, take, tap } from 'rxjs';\nimport { AnimationState } from './animation.state';\nimport { WS_THANOS_OPTIONS_TOKEN } from './ws-thanos-options.token';\nimport type { WsThanosOptions } from './ws-thanos.options';\nimport { WsThanosService } from './ws-thanos.service';\n\n@Directive({\n // Bare prefix is the published public API of @wolsok/thanos; renaming it would be breaking.\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: '[wsThanos], ws-thanos',\n exportAs: 'thanos',\n})\nexport class WsThanosDirective {\n private wsThanosCompleteSubject = new Subject<void>();\n private untilDestroyed = takeUntilDestroyed();\n\n /** override the provided options for this element */\n public readonly wsThanosOptions = input<Partial<WsThanosOptions>>();\n\n @Output()\n public wsThanosComplete: Observable<void> =\n this.wsThanosCompleteSubject.asObservable();\n\n private readonly vaporizeDomElem: ElementRef<HTMLElement> =\n inject(ElementRef);\n private readonly thanosService: WsThanosService = inject(WsThanosService);\n private readonly thanosOptions: WsThanosOptions = inject(\n WS_THANOS_OPTIONS_TOKEN\n );\n\n public constructor() {\n // only in the browser, the service runs it once for all elements\n afterNextRender(() => {\n const { preload } = { ...this.thanosOptions, ...this.wsThanosOptions() };\n if (preload) {\n void this.thanosService.preload();\n }\n });\n }\n\n /**\n *\n * Vaporize the dom element of this directive\n * @param removeElem remove the vaporized dom element or blend back in after a while\n *\n * Subscribe to the returned observable to start vaporization\n *\n */\n public vaporize$(removeElem = true): Observable<AnimationState> {\n const elem = this.vaporizeDomElem.nativeElement;\n return this.thanosService.vaporize(elem, this.wsThanosOptions()).pipe(\n tap({\n error: (error) => {\n console.error('Error vaporizing', error, {\n elemTovaporize: elem,\n removeElem,\n });\n },\n }),\n finalize(() => {\n if (removeElem) {\n elem.remove();\n } else {\n // make visible again\n elem.style.transition = 'opacity 700ms';\n elem.style.opacity = '1';\n }\n this.wsThanosCompleteSubject.next();\n })\n );\n }\n\n /**\n * Vaporize the dom element of this directive\n * @param removeElem remove the vaporized dom element or blend back in after a while\n *\n */\n public vaporize(removeElem = true): Observable<void> {\n this.vaporize$(removeElem).pipe(this.untilDestroyed).subscribe();\n return this.wsThanosComplete.pipe(take(1));\n }\n}\n"]}
1
+ {"version":3,"file":"ws-thanos.directive.js","sourceRoot":"","sources":["../../../../../../libs/public/ws-thanos/src/lib/ws-thanos.directive.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Directive,\n ElementRef,\n Output,\n afterNextRender,\n inject,\n input,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { finalize, Observable, ReplaySubject, Subject, tap } from 'rxjs';\nimport { AnimationState } from './animation.state';\nimport { WS_THANOS_OPTIONS_TOKEN } from './ws-thanos-options.token';\nimport type { WsThanosOptions } from './ws-thanos.options';\nimport { WsThanosService } from './ws-thanos.service';\n\n@Directive({\n // Bare prefix is the published public API of @wolsok/thanos; renaming it would be breaking.\n // eslint-disable-next-line @angular-eslint/directive-selector\n selector: '[wsThanos], ws-thanos',\n exportAs: 'thanos',\n})\nexport class WsThanosDirective {\n private wsThanosCompleteSubject = new Subject<void>();\n private untilDestroyed = takeUntilDestroyed();\n\n /** override the provided options for this element */\n public readonly wsThanosOptions = input<Partial<WsThanosOptions>>();\n\n @Output()\n public wsThanosComplete: Observable<void> =\n this.wsThanosCompleteSubject.asObservable();\n\n private readonly vaporizeDomElem: ElementRef<HTMLElement> =\n inject(ElementRef);\n private readonly thanosService: WsThanosService = inject(WsThanosService);\n private readonly thanosOptions: WsThanosOptions = inject(\n WS_THANOS_OPTIONS_TOKEN\n );\n\n public constructor() {\n // only in the browser, the service runs it once for all elements\n afterNextRender(() => {\n const { preload } = { ...this.thanosOptions, ...this.wsThanosOptions() };\n if (preload) {\n void this.thanosService.preload();\n }\n });\n }\n\n /**\n *\n * Vaporize the dom element of this directive\n * @param removeElem remove the vaporized dom element or blend back in after a while\n *\n * Subscribe to the returned observable to start vaporization\n *\n */\n public vaporize$(removeElem = true): Observable<AnimationState> {\n const elem = this.vaporizeDomElem.nativeElement;\n return this.thanosService.vaporize(elem, this.wsThanosOptions()).pipe(\n tap({\n error: (error) => {\n console.error('Error vaporizing', error, {\n elemTovaporize: elem,\n removeElem,\n });\n },\n }),\n finalize(() => {\n if (removeElem) {\n elem.remove();\n } else {\n // make visible again\n elem.style.transition = 'opacity 700ms';\n elem.style.opacity = '1';\n }\n this.wsThanosCompleteSubject.next();\n })\n );\n }\n\n /**\n * Vaporize the dom element of this directive\n * @param removeElem remove the vaporized dom element or blend back in after a while\n * @returns an observable that emits once and completes when the effect is\n * over: after it finished, after it failed and when the directive was\n * destroyed meanwhile. It replays, so a caller that subscribes after a\n * synchronous failure still gets the completion. A failure is logged\n * (`console.error`) and not thrown further: a caller that wants the error\n * itself subscribes to `vaporize$` instead.\n */\n public vaporize(removeElem = true): Observable<void> {\n const done = new ReplaySubject<void>(1);\n this.vaporize$(removeElem)\n .pipe(\n finalize(() => {\n done.next();\n done.complete();\n }),\n this.untilDestroyed\n )\n // Logged by vaporize$ already; left unhandled, RxJS would report it a\n // second time as an error on the window, without its context.\n .subscribe({ error: () => undefined });\n return done.asObservable();\n }\n}\n"]}
@@ -24,7 +24,12 @@ export declare class WsThanosDirective {
24
24
  /**
25
25
  * Vaporize the dom element of this directive
26
26
  * @param removeElem remove the vaporized dom element or blend back in after a while
27
- *
27
+ * @returns an observable that emits once and completes when the effect is
28
+ * over: after it finished, after it failed and when the directive was
29
+ * destroyed meanwhile. It replays, so a caller that subscribes after a
30
+ * synchronous failure still gets the completion. A failure is logged
31
+ * (`console.error`) and not thrown further: a caller that wants the error
32
+ * itself subscribes to `vaporize$` instead.
28
33
  */
29
34
  vaporize(removeElem?: boolean): Observable<void>;
30
35
  static ɵfac: i0.ɵɵFactoryDeclaration<WsThanosDirective, never>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wolsok/thanos",
3
- "version": "18.4.5",
3
+ "version": "18.4.7",
4
4
  "description": "Wolf Soko's implementation of a cool Thanos snapping vaporizing effect for destroying dom elements",
5
5
  "bugs": {
6
6
  "url": "https://github.com/WolfSoko/wol-sok-mono/issues"