Skip to content

Commit 082124c

Browse files
author
Ben Grynhaus
committed
Added docs to most public APIs
1 parent 56d4f03 commit 082124c

File tree

14 files changed

+104
-18
lines changed

14 files changed

+104
-18
lines changed

libs/core/src/angular-react-browser.module.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { NgModule } from '@angular/core';
22
import { BrowserModule, ɵDomRendererFactory2 } from '@angular/platform-browser';
3+
34
import { AngularReactRendererFactory } from './renderer/renderer';
45

56
@NgModule({

libs/core/src/components/wrapper-component.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ import {
1212
HostBinding,
1313
Input
1414
} from '@angular/core';
15+
import toStyle from 'css-to-style';
16+
1517
import { isReactNode } from '../renderer/react-node';
1618
import { renderComponent, renderFunc, renderTemplate } from '../renderer/renderprop-helpers';
1719
import { unreachable } from '../utils/types/unreachable';
18-
import toStyle from 'css-to-style';
19-
20-
type PropMapper = (value: any) => [string, any];
2120

2221
type AttributeNameAlternative = [string, string | undefined];
2322

@@ -51,24 +50,49 @@ export type JsxRenderFunc<TContext> = (context: TContext) => JSX.Element;
5150
*/
5251
// NOTE: TProps is not used at the moment, but a preparation for a potential future change.
5352
export abstract class ReactWrapperComponent<TProps extends {}> implements AfterViewInit, OnChanges {
53+
private _rClass: string;
54+
private _rStyle: string;
55+
5456
protected abstract reactNodeRef: ElementRef;
5557

58+
/**
59+
* Alternative to `class` using the same syntax.
60+
*
61+
* @description Since this is a wrapper component, sticking to the virtual DOM concept, this should have any styling of its own.
62+
* Any value passes to `rClass` will be passed to the root component's class.
63+
*/
5664
@Input()
5765
set rClass(value: string) {
66+
this._rClass = value;
5867
if (isReactNode(this.reactNodeRef.nativeElement)) {
5968
this.reactNodeRef.nativeElement.setProperty('className', value);
6069
this.changeDetectorRef.detectChanges();
6170
}
6271
}
6372

73+
get rClass(): string {
74+
return this._rClass;
75+
}
76+
77+
/**
78+
* Alternative to `style` using the same syntax.
79+
*
80+
* @description Since this is a wrapper component, sticking to the virtual DOM concept, this should have any styling of its own.
81+
* Any value passes to `rStyle` will be passed to the root component's style.
82+
*/
6483
@Input()
6584
set rStyle(value: string) {
85+
this._rStyle = value;
6686
if (isReactNode(this.reactNodeRef.nativeElement)) {
6787
this.reactNodeRef.nativeElement.setProperty('style', toStyle(value));
6888
this.changeDetectorRef.detectChanges();
6989
}
7090
}
7191

92+
get rStyle(): string {
93+
return this._rStyle;
94+
}
95+
7296
/**
7397
* Creates an instance of ReactWrapperComponent.
7498
* @param elementRef The host element.
@@ -94,6 +118,9 @@ export abstract class ReactWrapperComponent<TProps extends {}> implements AfterV
94118
this.detectChanges();
95119
}
96120

121+
/**
122+
* Trigger change detection on the component.
123+
*/
97124
protected detectChanges() {
98125
if (isReactNode(this.reactNodeRef.nativeElement)) {
99126
this.reactNodeRef.nativeElement.setRenderPending();

libs/core/src/renderer/components/Disguise.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
import { ReactWrapperComponent } from '../../components/wrapper-component';
2-
import { passPropsSymbol, getPassProps, PassProp } from '../../renderer/pass-prop-decorator';
31
import * as React from 'react';
42
import * as ReactDOM from 'react-dom';
3+
4+
import { ReactWrapperComponent } from '../../components/wrapper-component';
5+
import { passPropsSymbol, getPassProps, PassProp } from '../../renderer/pass-prop-decorator';
56
import { ReactContent } from '../react-content';
67
import removeUndefinedProperties from '../../utils/object/remove-undefined-properties';
78

9+
/**
10+
* Props for `Disguise` component.
11+
*/
812
export interface DisguiseProps {
913
/**
1014
* The type to render the root component as.

libs/core/src/renderer/pass-prop-decorator.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ const passPropRename: (propName: string) => PropertyDecorator =
2222
const passPropDirect: PropertyDecorator =
2323
(target, propertyKey) => passPropImpl(target, propertyKey, propertyKey);
2424

25+
/**
26+
* Decorator to specify a property that should be passed as a prop to the underlying React component implicitly.
27+
* Mainly useful for passing child components using the `Disguise` component.
28+
*/
2529
export function passProp(): PropertyDecorator;
2630
export function passProp(propName: string): PropertyDecorator;
2731
export function passProp(...args: any[]) {

libs/core/src/renderer/react-node.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import * as React from 'react';
44
import * as ReactDOM from 'react-dom';
5+
56
import removeUndefinedProperties from '../utils/object/remove-undefined-properties';
67
import { CHILDREN_TO_APPEND_PROP } from './react-content';
78
import { getComponentClass } from "./registry";

libs/core/src/renderer/registry.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as React from 'react';
2+
23
import { Disguise } from "./components/Disguise";
34
import { ReactContent } from "./react-content";
45

@@ -7,16 +8,21 @@ export type ComponentResolver = () => React.ReactType;
78
const elementMap = new Map<string, { resolver: ComponentResolver }>();
89
const camelCaseSplit = /([a-z0-9])([A-Z])/g;
910

11+
/**
12+
* Register an element to be renderer when the renderer sees the tag.
13+
* @param elementName the tag
14+
* @param resolver A resolver to the React component
15+
*/
1016
export function registerElement(
1117
elementName: string,
1218
resolver: ComponentResolver
1319
): void {
1420
if (elementMap.has(elementName)) {
15-
// Ignore multiple register attempts for the same component.
16-
// Angular doesn't allow sharing whole NgModule instances (in this case, an @NgModule for React-wrapped components) with lazy-loaded @NgModules (in the app),
17-
// To keep the API simple, allow multiple calls to `registerElement`.
18-
// Disadvantage is that you can't replace (React) component implementations at runtime. This sounds far-fetched, but solvable with a `static forRoot()` pattern for every
19-
// React-wrapper components' @NgModule, ensuring that `registerElement` is only called once.
21+
// Ignore multiple register attempts for the same component.
22+
// Angular doesn't allow sharing whole NgModule instances (in this case, an @NgModule for React-wrapped components) with lazy-loaded @NgModules (in the app),
23+
// To keep the API simple, allow multiple calls to `registerElement`.
24+
// Disadvantage is that you can't replace (React) component implementations at runtime. This sounds far-fetched, but solvable with a `static forRoot()` pattern for every
25+
// React-wrapper components' @NgModule, ensuring that `registerElement` is only called once.
2026
return;
2127
} else {
2228
const entry = { resolver: resolver };

libs/core/src/renderer/renderer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
import { Injectable, Renderer2, RendererStyleFlags2, RendererType2 } from '@angular/core';
44
import { EventManager, ɵDomRendererFactory2, ɵDomSharedStylesHost } from '@angular/platform-browser';
5+
56
import { isReactNode, ReactNode } from './react-node';
67

78
const DEBUG = false;
89

910
@Injectable()
1011
export class AngularReactRendererFactory extends ɵDomRendererFactory2 {
11-
private defaultReactRenderer: ReactRenderer;
12+
private readonly defaultReactRenderer: ReactRenderer;
1213

1314
// Collection of ReactNodes that can be evaluated and flushed at the
1415
// end of Render. This is necessary as the flow of element creation

libs/core/src/renderer/renderprop-helpers.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ComponentRef, TemplateRef } from "@angular/core";
22
import * as React from 'react';
3+
34
import { CHILDREN_TO_APPEND_PROP, ReactContent } from "../renderer/react-content";
45

56
function renderReactContent(rootNodes: HTMLElement[]): JSX.Element {
@@ -11,19 +12,37 @@ function renderReactContent(rootNodes: HTMLElement[]): JSX.Element {
1112
);
1213
}
1314

15+
/**
16+
* Wrap a `TemplateRef` with a `JSX.Element`.
17+
*
18+
* @param templateRef The template to wrap
19+
* @param context The context to pass to the template
20+
*/
1421
export function renderTemplate<TContext extends object>(templateRef: TemplateRef<TContext>, context?: TContext): JSX.Element {
1522
const viewRef = templateRef.createEmbeddedView(context);
1623
viewRef.detectChanges();
1724

1825
return renderReactContent(viewRef.rootNodes);
1926
}
2027

28+
/**
29+
* Wrap a function resolving to an `HTMLElement` with a `JSX.Element`.
30+
*
31+
* @param htmlRenderFunc The function to wrap
32+
* @param context The context to pass to the function
33+
*/
2134
export function renderFunc<TContext extends object>(htmlRenderFunc: (context: TContext) => HTMLElement, context?: TContext): JSX.Element {
2235
const rootHtmlElement = htmlRenderFunc(context);
2336

2437
return renderReactContent([rootHtmlElement]);
2538
}
2639

40+
/**
41+
* Wrap a `ComponentRef` with a `JSX.Element`.
42+
*
43+
* @param htmlRenderFunc The component reference to wrap
44+
* @param context The context to pass to the component as `@Input`
45+
*/
2746
export function renderComponent<TContext extends object>(componentRef: ComponentRef<TContext>, context?: TContext): JSX.Element {
2847
Object.assign(componentRef.instance, context);
2948
componentRef.changeDetectorRef.detectChanges();
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
1+
// NOTE: a [PR in DefinitelyTyped has been sent](https://github.com/DefinitelyTyped/DefinitelyTyped/pull/27253).
2+
// Once it gets in this type can be remove from here and required from there instead.
23
declare module 'css-to-style' {
3-
4-
function toStyle(cssText: string) : CSSStyleDeclaration;
5-
6-
export default toStyle;
4+
export default function toStyle(cssText: string): CSSStyleDeclaration;
75
}

libs/core/src/utils/object/remove-undefined-properties.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
/**
2+
* Remove all undefined properties from obj.
3+
*
4+
* Does **not** modify the original object.
5+
* @returns A clone of `obj`, with all `undefined` properties removed
6+
*/
17
const clearUndefinedProperties = <T extends object>(obj: T): Partial<T> => {
28
return Object.keys(obj).reduce((acc, key) => {
39
const _acc = acc;

0 commit comments

Comments
 (0)