Skip to content

Commit

Permalink
feat(fract): AlwatrObserveDirective
Browse files Browse the repository at this point in the history
  • Loading branch information
alimd committed Jun 26, 2023
1 parent 40544a7 commit 82b5a15
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 3 deletions.
1 change: 1 addition & 0 deletions core/fract/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
},
"dependencies": {
"@alwatr/logger": "^1.0.0",
"@alwatr/signal2": "^1.0.0",
"lit-html": "^2.7.4",
"tslib": "^2.5.3"
}
Expand Down
2 changes: 1 addition & 1 deletion core/fract/src/map.ts → core/fract/src/directives/map.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {nothing} from './lit-html.js';
import {nothing} from '../lit-html.js';

/**
* Returns an iterable containing the result of calling `f(value)` on each value in `items`.
Expand Down
55 changes: 55 additions & 0 deletions core/fract/src/directives/observe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

import {AlwatrDynamicDirective} from '../dynamic-directive.js';
import {directive, noChange, type PartInfo} from '../lit-html.js';

import type {AlwatrObservableInterface} from '@alwatr/signal2';

class AlwatrObserveDirective<T extends AlwatrObservableInterface<unknown>> extends AlwatrDynamicDirective {
protected _$observable?: T;
protected _$render?: (data: unknown) => unknown;
unsubscribe?: () => void;

constructor(partInfo: PartInfo) {
super(partInfo, '<alwatr-observe>');
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
render(observable: T, render: (data: any) => unknown): unknown {
this._logger.logMethodArgs?.('render', {observable, render});

this._$render = render;
if (this._$observable !== observable) {
// When the observable changes, unsubscribe to the old one and subscribe to the new one
this.unsubscribe?.();
this._$observable = observable;
if (this.isConnected) {
this.subscribe(observable);
}
}

return noChange;
}

/**
* Subscribes to the observable, calling the directive's asynchronous and setValue each time the value changes.
*/
subscribe(observable: T): void {
this._logger.logMethod?.('subscribe');
this.unsubscribe = observable.subscribe((v) => {
this.setValue(this._$render!(v));
}, {receivePrevious: true}).unsubscribe;
}

// When the directive is disconnected from the DOM, unsubscribe to ensure
// the directive instance can be garbage collected
override disconnected(): void {
this.unsubscribe!();
}
// If the subtree the directive is in was disconnected and subsequently
// re-connected, re-subscribe to make the directive operable again
override reconnected(): void {
this.subscribe(this._$observable!);
}
}

export const alwatrObserve = directive(AlwatrObserveDirective);
3 changes: 2 additions & 1 deletion core/fract/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './directive.js';
export * from './dynamic-directive.js';
export * from './map.js';
export * from './directives/map.js';
export * from './directives/observe.js';
export * from './lit-html.js';
1 change: 1 addition & 0 deletions core/fract/src/lit-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export {html, render, noChange, nothing} from 'lit-html';
export {Directive, PartType, directive} from 'lit-html/directive.js';
export {AsyncDirective} from 'lit-html/async-directive.js';
export {unsafeSVG} from 'lit-html/directives/unsafe-svg.js';
export {ifDefined} from 'lit-html/directives/if-defined.js';

export type {Part, PartInfo} from 'lit-html/directive.js';
3 changes: 2 additions & 1 deletion core/fract/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"include": ["src/**/*.ts"],
"exclude": [],
"references": [
{"path": "../logger"}
{"path": "../logger"},
{"path": "../signal2"}
]
}

0 comments on commit 82b5a15

Please sign in to comment.