-
Notifications
You must be signed in to change notification settings - Fork 0
/
reactular.tsx
69 lines (61 loc) · 1.83 KB
/
reactular.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import { IComponentOptions, IController, IChangesObject, auto } from 'angular';
import React from 'react';
import { createRoot, Root } from 'react-dom/client';
type OnChanges<T> = {
[K in keyof T]: IChangesObject<T[K]>;
};
export const reactular = <Props extends object>(
Component: React.ComponentType<Props>,
bindingNames: Array<keyof Props> = [],
wrapper?: string | React.FunctionComponent<React.PropsWithChildren<{}>>,
): IComponentOptions => {
const bindings: {
[prop: string]: '<';
} = {};
for (const name of bindingNames) {
bindings[name as string] = '<';
}
return {
bindings,
controller: [
'$element',
'$injector',
class implements IController {
private destroyed = false;
private props: Props = {} as Props;
private root: Root;
constructor(
private readonly $element: JQLite,
private readonly $injector: auto.IInjectorService,
) {
this.root = createRoot(this.$element[0]);
}
public $onChanges(changes: OnChanges<Props>): void {
if (this.destroyed) {
return;
}
for (const change in changes) {
if (changes.hasOwnProperty(change)) {
this.props[change] = changes[change].currentValue;
}
}
const Wrapper =
typeof wrapper === 'string'
? this.$injector.get<
React.FunctionComponent<React.PropsWithChildren<{}>>
>(wrapper)
: wrapper;
let nodes = <Component {...this.props} />;
if (Wrapper) {
nodes = <Wrapper>{nodes}</Wrapper>;
}
this.root.render(nodes);
}
public $onDestroy(): void {
this.destroyed = true;
this.root.unmount();
}
},
],
};
};