This commit is contained in:
Ben Grynhaus 2018-06-28 19:36:31 +03:00
Родитель a92a90dc3c
Коммит 8967593512
21 изменённых файлов: 354 добавлений и 85 удалений

2
.vscode/settings.json поставляемый
Просмотреть файл

@ -1,8 +1,10 @@
{ {
"cSpell.words": [ "cSpell.words": [
"Focusable",
"Injectable", "Injectable",
"Packagr", "Packagr",
"Renderable", "Renderable",
"nrwl",
"unmount", "unmount",
"whitelisted" "whitelisted"
] ]

Просмотреть файл

@ -3,21 +3,40 @@
<h2>Getting up and running...</h2> <h2>Getting up and running...</h2>
<ol> <ol>
<li>Add <i>AngularReactBrowserModule</i>> to <i>app.module.ts</i> in place of the default <i>BrowserModule</i>.</li> <li>Add
<li>Add <i>Fab[component]Module</i> or <i>Mat[component]Module</i> to <i>app.module.ts</i> imports.</li> <i>AngularReactBrowserModule</i>> to
<i>app.module.ts</i> in place of the default
<i>BrowserModule</i>.</li>
<li>Add
<i>Fab[component]Module</i> or
<i>Mat[component]Module</i> to
<i>app.module.ts</i> imports.</li>
<li>Add Fabric or Material components to your views.</li> <li>Add Fabric or Material components to your views.</li>
</ol> </ol>
</div> </div>
<div> <div>
<fab-button label="Test Dialog" (onClick)="toggleDialog()"></fab-button> <fab-button text="Test Dialog" (onClick)="toggleDialog()"></fab-button>
<fab-dialog [hidden]="dialogHidden" (onDismiss)="toggleDialog()" key="d2" title="Fabric [React] Dialog" subText="Use Fabric React components inside your Angular app!" [type]="DialogType.largeHeader"> <fab-dialog [hidden]="dialogHidden" (onDismiss)="toggleDialog()" key="d2" title="Fabric [React] Dialog" subText="Use Fabric React components inside your Angular app!"
[type]="DialogType.largeHeader">
Hello world! {{ counter }} Hello world! {{ counter }}
<fab-dialog-footer> <fab-dialog-footer>
<fab-button (onClick)="incrementCounter()" label='Save' style="margin-right:10px;"></fab-button> <fab-button (onClick)="incrementCounter()" text='Save' style="margin-right:10px;"></fab-button>
<fab-button (onClick)="toggleDialog()" label='Cancel'></fab-button> <fab-button (onClick)="toggleDialog()" text='Cancel'></fab-button>
</fab-dialog-footer> </fab-dialog-footer>
</fab-dialog> </fab-dialog>
</div>
<img src="assets/app-module-dif.png"> <!-- <fab-button [primary]="true" [split]="true" [menuProps]="menuProps" [iconProps]="iconProps" [text]="'Test Dialog'" (onClick)="onClick($event)"></fab-button>
<fab-icon [iconName]="'Add'"></fab-icon> -->
<!-- <fab-image src="http://placehold.it/350x150" alt="Example implementation with no image fit property and no height or width is specified."></fab-image> -->
<fab-button (onClick)="isPanelOpen = !isPanelOpen" text="Open panel"></fab-button>
<fab-panel [isOpen]="isPanelOpen">
<fab-panel-header>
<div>Hello header!</div>
</fab-panel-header>
</fab-panel>
</div>

Просмотреть файл

@ -1,5 +1,6 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { DialogType } from 'office-ui-fabric-react/lib/Dialog'; import { DialogType } from 'office-ui-fabric-react/lib/Dialog';
import { IButtonProps } from '../../../../node_modules/office-ui-fabric-react/lib/Button';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@ -12,10 +13,47 @@ export class AppComponent {
dialogHidden = true; dialogHidden = true;
counter = 0; counter = 0;
isPanelOpen = false;
menuProps: IButtonProps['menuProps'] = {
items: [
{
key: 'emailMessage',
text: 'Email message',
onClick: () => alert('email clicked!'),
iconProps: {
iconName: 'Mail',
style: {
color: 'red',
},
}
},
{
key: 'calendarEvent',
text: 'Calendar event',
iconProps: {
iconName: 'Calendar'
}
}
]
}
iconProps = {
iconName: 'Add',
styles: {
root: { fontSize: 'x-large' }
}
};
toggleDialog() { toggleDialog() {
this.dialogHidden = !this.dialogHidden; this.dialogHidden = !this.dialogHidden;
} }
onClick() {
alert('clicked!');
}
incrementCounter() { incrementCounter() {
this.counter += 1; this.counter += 1;
} }

Просмотреть файл

@ -1,14 +1,25 @@
import { AngularReactBrowserModule } from '@angular-react/core';
import { FabButtonModule, FabDialogModule, FabIconModule, FabImageModule, FabPanelModule } from '@angular-react/fabric';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { NxModule } from '@nrwl/nx'; import { NxModule } from '@nrwl/nx';
import { initializeIcons } from 'office-ui-fabric-react/lib/Icons';
import { AngularReactBrowserModule } from '@angular-react/core';
import { FabDialogModule, FabButtonModule } from '@angular-react/fabric';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { WrapperComponent } from './wrapper.component';
@NgModule({ @NgModule({
imports: [AngularReactBrowserModule, NxModule.forRoot(), FabButtonModule, FabDialogModule], imports: [AngularReactBrowserModule,
declarations: [AppComponent], NxModule.forRoot(),
bootstrap: [AppComponent] FabIconModule,
FabButtonModule,
FabDialogModule,
FabImageModule,
FabPanelModule,
],
declarations: [AppComponent, WrapperComponent],
bootstrap: [AppComponent],
}) })
export class AppModule {} export class AppModule {
constructor() {
initializeIcons();
}
}

Просмотреть файл

@ -0,0 +1,8 @@
import { Component } from '@angular/core';
@Component({
selector: 'wrapper',
template: `<ng-content></ng-content>`,
styles: ['react-renderer'],
})
export class WrapperComponent { }

Просмотреть файл

@ -4,6 +4,10 @@
"version": "0.1.12", "version": "0.1.12",
"ngPackage": { "ngPackage": {
"lib": { "lib": {
"languageLevel": [
"dom",
"es2017"
],
"entryFile": "public-api.ts", "entryFile": "public-api.ts",
"umdModuleIds": { "umdModuleIds": {
"react": "React", "react": "React",

Просмотреть файл

@ -1,2 +1,3 @@
export { registerElement } from './src/renderer/registry';
export { AngularReactBrowserModule } from './src/angular-react-browser.module'; export { AngularReactBrowserModule } from './src/angular-react-browser.module';
export { ReactWrapperComponent } from './src/components/wrapper-component';
export { registerElement } from './src/renderer/registry';

Просмотреть файл

@ -1,5 +1,5 @@
import { isReactNode } from "@angular-react/core/src/renderer/react-node";
import { AfterViewInit, ElementRef } from "@angular/core"; import { AfterViewInit, ElementRef } from "@angular/core";
import { isReactNode } from "../renderer/react-node";
const blacklistedAttributesAsProps = [ const blacklistedAttributesAsProps = [
'class', 'class',
@ -7,7 +7,7 @@ const blacklistedAttributesAsProps = [
]; ];
const blacklistedAttributeMatchers = [ const blacklistedAttributeMatchers = [
/^_ng.*/ /^_?ng-?.*/
] ]

Просмотреть файл

@ -2,7 +2,7 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom'; import * as ReactDOM from 'react-dom';
const DEBUG = false; const DEBUG = true;
export const CHILDREN_TO_APPEND_PROP = 'children-to-append'; export const CHILDREN_TO_APPEND_PROP = 'children-to-append';
export class ReactContent extends React.Component { export class ReactContent extends React.Component {

Просмотреть файл

@ -1,10 +1,12 @@
/// <reference path="../types/StringMap.d.ts" />
import * as React from 'react'; import * as React from 'react';
import * as ReactDOM from 'react-dom'; import * as ReactDOM from 'react-dom';
import removeUndefinedProperties from '../utils/object/remove-undefined-properties'; import removeUndefinedProperties from '../utils/object/remove-undefined-properties';
import { CHILDREN_TO_APPEND_PROP } from './react-content'; import { CHILDREN_TO_APPEND_PROP } from './react-content';
import { getComponentClass, ReactComponentClass } from "./registry"; import { getComponentClass, ReactComponentClass } from "./registry";
const DEBUG = false; const DEBUG = true;
export function isReactNode(node: any): node is ReactNode { export function isReactNode(node: any): node is ReactNode {
return (<ReactNode>node).setRenderPendingCallback !== undefined; return (<ReactNode>node).setRenderPendingCallback !== undefined;
@ -182,12 +184,37 @@ export class ReactNode {
this.props[CHILDREN_TO_APPEND_PROP] = this.childrenToAppend; this.props[CHILDREN_TO_APPEND_PROP] = this.childrenToAppend;
const clearedProps = removeUndefinedProperties(this.props); const clearedProps = this.transformProps(
removeUndefinedProperties(this.props)
);
if (DEBUG) { console.warn('ReactNode > renderRecursive > type:', this.toString(), 'props:', this.props, 'children:', children); } if (DEBUG) { console.warn('ReactNode > renderRecursive > type:', this.toString(), 'props:', this.props, 'children:', children); }
return React.createElement(this.type, clearedProps, children.length > 0 ? children : undefined); return React.createElement(this.type, clearedProps, children.length > 0 ? children : undefined);
} }
private transformProps(props: object) {
return Object.entries(props).reduce((acc, [key, value]) => {
const [transformKey, transformValue] = this.transformProp(key, value);
return {
...acc,
[transformKey]: transformValue,
};
}, {});
}
private transformProp<TValue = any>(name: string, value: TValue): [string, TValue] {
// prop name is camelCased already
const firstLetter = name[0];
if (firstLetter === firstLetter.toLowerCase()) {
return [name, value];
}
// prop name is PascalCased & is a function - assuming render prop
if (typeof value === 'function') {
return [`on${name}`, value];
}
}
// This is called by Angular core when projected content is being added. // This is called by Angular core when projected content is being added.
appendChild(projectedContent: HTMLElement) { appendChild(projectedContent: HTMLElement) {
if (DEBUG) { console.error('ReactNode > appendChild > node:', this.toString(), 'projectedContent:', projectedContent.toString().trim()); } if (DEBUG) { console.error('ReactNode > appendChild > node:', this.toString(), 'projectedContent:', projectedContent.toString().trim()); }

Просмотреть файл

@ -1,25 +1,10 @@
// tslint:disable:no-bitwise // tslint:disable:no-bitwise
import { import { Injectable, Renderer2, RendererStyleFlags2, RendererType2 } from '@angular/core';
Injectable, import { EventManager, ɵDomRendererFactory2, ɵDomSharedStylesHost } from '@angular/platform-browser';
RendererType2, import { isReactNode, ReactNode } from './react-node';
Renderer2,
RendererStyleFlags2
} from '@angular/core';
import { BrowserModule, EventManager } from '@angular/platform-browser';
import {
ɵDomRendererFactory2,
ɵDomSharedStylesHost,
ɵNAMESPACE_URIS
} from '@angular/platform-browser';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { ReactComponentClass, getComponentClass } from './registry'; const DEBUG = true;
import { ReactNode, isReactNode } from './react-node';
const DEBUG = false;
@Injectable() @Injectable()
export class AngularReactRendererFactory extends ɵDomRendererFactory2 { export class AngularReactRendererFactory extends ɵDomRendererFactory2 {
@ -52,7 +37,7 @@ export class AngularReactRendererFactory extends ɵDomRendererFactory2 {
return this.defaultReactRenderer; return this.defaultReactRenderer;
} }
return super.createRenderer(element, type); return super.createRenderer(element, type);
} }
begin() { } begin() { }
@ -73,9 +58,9 @@ export class AngularReactRendererFactory extends ɵDomRendererFactory2 {
class ReactRenderer implements Renderer2 { class ReactRenderer implements Renderer2 {
data: { [key: string]: any } = Object.create(null); data: { [key: string]: any } = Object.create(null);
constructor(private rootRenderer: AngularReactRendererFactory) {} constructor(private rootRenderer: AngularReactRendererFactory) { }
destroy(): void {} destroy(): void { }
destroyNode(node: ReactNode): void { destroyNode(node: ReactNode): void {
if (DEBUG) { console.error('Renderer > destroyNode > node:', node.toString()); } if (DEBUG) { console.error('Renderer > destroyNode > node:', node.toString()); }
@ -171,7 +156,7 @@ class ReactRenderer implements Renderer2 {
if (DEBUG) { console.log('NOT IMPLEMENTED - Renderer > nextSibling > node:', node.toString()); } if (DEBUG) { console.log('NOT IMPLEMENTED - Renderer > nextSibling > node:', node.toString()); }
} }
setAttribute(node: ReactNode, name: string, value: string, namespace?: string ): void { setAttribute(node: ReactNode, name: string, value: string, namespace?: string): void {
if (DEBUG) { console.log('Renderer > setAttribute > node:', node.toString(), 'name:', name, 'value:', value, namespace ? 'namespace:' : '', namespace); } if (DEBUG) { console.log('Renderer > setAttribute > node:', node.toString(), 'name:', name, 'value:', value, namespace ? 'namespace:' : '', namespace); }
node.setProperty(name, value); node.setProperty(name, value);
} }
@ -208,7 +193,7 @@ class ReactRenderer implements Renderer2 {
} }
removeStyle(node: ReactNode, style: string, flags: RendererStyleFlags2): void { removeStyle(node: ReactNode, style: string, flags: RendererStyleFlags2): void {
if (DEBUG) { console.log( 'Renderer > removeStyle > node:', node.toString(), 'style:', style, 'flags:', flags); } if (DEBUG) { console.log('Renderer > removeStyle > node:', node.toString(), 'style:', style, 'flags:', flags); }
node.removeProperty('style', style); node.removeProperty('style', style);
} }

Просмотреть файл

Просмотреть файл

@ -1,8 +1,10 @@
export * from './src/button/button.module';
export * from './src/button/button.component'; export * from './src/button/button.component';
export * from './src/dialog/dialog.module' export * from './src/button/button.module';
export * from './src/dialog/dialog.component'; export * from './src/dialog/dialog.component';
export * from './src/dialog/dialog.module';
export * from './src/icon/icon.component'; export * from './src/icon/icon.component';
export * from './src/icon/icon.module'; export * from './src/icon/icon.module';
export * from './src/image/image.component'; export * from './src/image/image.component';
export * from './src/image/image.module'; export * from './src/image/image.module';
export * from './src/panel/panel.component';
export * from './src/panel/panel.module';

Просмотреть файл

@ -4,35 +4,41 @@
// tslint:disable:use-host-property-decorator // tslint:disable:use-host-property-decorator
// tslint:disable:no-output-on-prefix // tslint:disable:no-output-on-prefix
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output } from '@angular/core'; import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { IButtonProps } from 'office-ui-fabric-react/lib/Button';
import { IButtonProps, DefaultButton } from 'office-ui-fabric-react/lib/Button';
@Component({ @Component({
selector: 'fab-button', selector: 'fab-button',
exportAs: 'fabButton', exportAs: 'fabButton',
template: ` template: `
<DefaultButton <DefaultButton
key="c1"
data-automation-id='test_automation_id'
[primary]="primary" [primary]="primary"
[disabled]="disabled" [disabled]="disabled"
[text]="text" [text]="text"
(onClick)="onClick.emit($event)"></DefaultButton> [split]="split"
[href]="href"
[menuProps]="menuProps"
[iconProps]="iconProps"
(onClick)="onClick.emit($event)">
</DefaultButton>
`, `,
styles: [ styles: [
'react-renderer', 'react-renderer',
':host { display: inline-block; background: red; }' // TODO: this isn't working. Problem with react-renderer.
], ],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { 'class': 'fab-button' } host: { 'class': 'fab-button' }
}) })
export class FabButtonComponent { export class FabButtonComponent {
@Input() disabled = false; @Input() disabled?: IButtonProps['disabled'];
@Input() primary = true; @Input() primary?: IButtonProps['primary'];
@Input('label') text = ''; @Input() checked?: IButtonProps['checked'];
@Input() href?: IButtonProps['href'];
@Input() text?: IButtonProps['text'];
@Input() split?: IButtonProps['split'];
@Input() menuProps?: IButtonProps['menuProps'];
@Input() iconProps?: IButtonProps['iconProps'];
@Input() primaryDisabled?: IButtonProps['primaryDisabled'];
@Output() onClick: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>(); @Output() onClick: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();

Просмотреть файл

@ -3,23 +3,16 @@
// tslint:disable:no-output-rename // tslint:disable:no-output-rename
// tslint:disable:use-host-property-decorator // tslint:disable:use-host-property-decorator
import { import { ReactWrapperComponent } from '@angular-react/core';
ChangeDetectionStrategy, import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
Component, import { DialogType, IDialogProps } from 'office-ui-fabric-react/lib/components/Dialog';
EventEmitter,
Input,
OnChanges,
Output,
} from '@angular/core';
import { IDialogProps, Dialog, DialogType, DialogFooter } from 'office-ui-fabric-react/lib/components/Dialog';
@Component({ @Component({
selector: 'fab-dialog', selector: 'fab-dialog',
exportAs: 'fabDialog', exportAs: 'fabDialog',
template: ` template: `
<Dialog <Dialog
#reactNode
[hidden]="hidden" [hidden]="hidden"
(onDismiss)="onDismiss($event)" (onDismiss)="onDismiss($event)"
[dialogContentProps]="{ [dialogContentProps]="{
@ -39,7 +32,8 @@ import { IDialogProps, Dialog, DialogType, DialogFooter } from 'office-ui-fabric
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { 'class': 'fab-dialog' } host: { 'class': 'fab-dialog' }
}) })
export class FabDialogComponent { export class FabDialogComponent extends ReactWrapperComponent<IDialogProps> {
@ViewChild('reactNode') protected reactNodeRef: ElementRef;
@Input() hidden = false; @Input() hidden = false;
@Input() type = DialogType.normal; @Input() type = DialogType.normal;
@ -49,16 +43,22 @@ export class FabDialogComponent {
@Input() isBlocking = false; @Input() isBlocking = false;
@Input() containerClassName = 'ms-dialogMainOverride'; @Input() containerClassName = 'ms-dialogMainOverride';
@Output('onDismiss') dismiss: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>(); @Output('onDismiss') dismiss = new EventEmitter<MouseEvent>();
onDismiss = ev => this.dismiss.emit(ev as any);
}
constructor(elementRef: ElementRef) {
super(elementRef);
}
onDismiss(reactEvent: React.MouseEvent<HTMLButtonElement>) {
this.dismiss.emit(reactEvent.nativeEvent);
}
}
@Component({ @Component({
selector: 'fab-dialog-footer', selector: 'fab-dialog-footer',
exportAs: 'fabDialogFooter', exportAs: 'fabDialogFooter',
template: ` template: `
<DialogFooter key="4"> <DialogFooter>
<ReactContent><ng-content></ng-content></ReactContent> <ReactContent><ng-content></ng-content></ReactContent>
</DialogFooter> </DialogFooter>
`, `,

Просмотреть файл

@ -1,4 +1,4 @@
import { ReactWrapperComponent } from '@angular-react/core/src/components/wrapper-component'; import { ReactWrapperComponent } from '@angular-react/core';
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core'; import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { IImageProps, ImageLoadState } from 'office-ui-fabric-react/lib/Image'; import { IImageProps, ImageLoadState } from 'office-ui-fabric-react/lib/Image';

Просмотреть файл

@ -0,0 +1 @@
export * from './public-api';

Просмотреть файл

@ -0,0 +1,145 @@
// tslint:disable:component-selector
// tslint:disable:no-input-rename
// tslint:disable:no-output-rename
// tslint:disable:use-host-property-decorator
// tslint:disable:no-output-on-prefix
import { ReactWrapperComponent } from '@angular-react/core';
import { ChangeDetectionStrategy, Component, ContentChild, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { IPanelHeaderRenderer, IPanelProps } from 'office-ui-fabric-react/lib/Panel';
@Component({
selector: 'fab-panel',
exportAs: 'fabPanel',
template: `
<Panel
#reactNode
[componentRef]="componentRef"
[isOpen]="isOpen"
[hasCloseButton]="hasCloseButton"
[isLightDismiss]="isLightDismiss"
[isHiddenOnDismiss]="isHiddenOnDismiss"
[isBlocking]="isBlocking"
[isFooterAtBottom]="isFooterAtBottom"
[headerText]="headerText"
[className]="className"
[type]="type"
[customWidth]="customWidth"
[closeButtonAriaLabel]="closeButtonAriaLabel"
[headerClassName]="headerClassName"
[elementToFocusOnDismiss]="elementToFocusOnDismiss"
[ignoreExternalFocusing]="ignoreExternalFocusing"
[forceFocusInsideTrap]="forceFocusInsideTrap"
[firstFocusableSelector]="firstFocusableSelector"
[focusTrapZoneProps]="focusTrapZoneProps"
[layerProps]="layerProps"
[componentId]="componentId"
(onDismiss)="onDismiss.emit($event)"
(onDismissed)="onDismissed.emit($event)"
(onLightDismissClick)="onLightDismissClick.emit($event)">
<!--
[RenderHeader]="onRenderHeader"
(onRenderBody)="onRenderBody.emit($event)"
(onRenderFooter)="onRenderFooter.emit($event)"
(onRenderFooterContent)="onRenderFooterContent.emit($event)"
(onRenderNavigation)="onRenderNavigation.emit($event)"
-->
</Panel>
<ng-content select="[fab-panel-header]"></ng-content>
<ng-template>
</ng-template>
`,
styles: [
'react-renderer',
],
changeDetection: ChangeDetectionStrategy.OnPush,
host: { 'class': 'fab-panel' }
})
export class FabPanelComponent extends ReactWrapperComponent<IPanelProps> {
@ViewChild('reactNode') protected reactNodeRef: ElementRef;
@Input() componentRef?: IPanelProps['componentRef'];
@Input() isOpen?: IPanelProps['isOpen'];
@Input() hasCloseButton?: IPanelProps['hasCloseButton'];
@Input() isLightDismiss?: IPanelProps['isLightDismiss'];
@Input() isHiddenOnDismiss?: IPanelProps['isHiddenOnDismiss'];
@Input() isBlocking?: IPanelProps['isBlocking'];
@Input() isFooterAtBottom?: IPanelProps['isFooterAtBottom'];
@Input() headerText?: IPanelProps['headerText'];
@Input() className?: IPanelProps['className'];
@Input() type?: IPanelProps['type'];
@Input() customWidth?: IPanelProps['customWidth'];
@Input() closeButtonAriaLabel?: IPanelProps['closeButtonAriaLabel'];
@Input() headerClassName?: IPanelProps['headerClassName'];
@Input() elementToFocusOnDismiss?: IPanelProps['elementToFocusOnDismiss'];
@Input() ignoreExternalFocusing?: IPanelProps['ignoreExternalFocusing'];
@Input() forceFocusInsideTrap?: IPanelProps['forceFocusInsideTrap'];
@Input() firstFocusableSelector?: IPanelProps['firstFocusableSelector'];
@Input() focusTrapZoneProps?: IPanelProps['focusTrapZoneProps'];
@Input() layerProps?: IPanelProps['layerProps'];
@Input() componentId?: IPanelProps['componentId'];
// @Input() headerTemplate?: TemplateRef<IPanelHeaderTemplateContext>
@Output() onLightDismissClick = new EventEmitter<void>();
@Output() onDismiss = new EventEmitter<void>();
@Output() onDismissed = new EventEmitter<void>();
@Output() onRenderNavigation = new EventEmitter<IPanelProps>();
// @Output() onRenderHeader = new EventEmitter<IPanelProps['onRenderHeader']>();
// @Output() onRenderBody = new EventEmitter<IPanelProps['onRenderBody']>();
// @Output() onRenderFooter = new EventEmitter<IPanelProps['onRenderFooter']>();
// @Output() onRenderFooterContent = new EventEmitter<IPanelProps['onRenderFooterContent']>();
@ContentChild('[fab-panel-header]') headerTemplate?: ElementRef;
constructor(elementRef: ElementRef) {
super(elementRef);
// coming from React context - we need to bind to this so we can access the Angular Component properties
this.onRenderHeader = this.onRenderHeader.bind(this);
}
onRenderHeader(props?: IPanelProps, defaultRender?: IPanelHeaderRenderer, headerTextId?: string | undefined) {
if (!this.headerTemplate) {
return null;
}
// FIXME: temp
return null;
/*
const tagName = (this.headerTemplate.nativeElement as HTMLElement).tagName;
return React.createElement(
tagName,
{},
undefined
); */
/* this.headerTemplate.createEmbeddedView({
props: ren
}) */
}
}
/**
* Counterpart of `IPanelHeaderRenderer`.
*/
export interface IPanelHeaderTemplateContext {
props?: IPanelProps
headerTextId?: string | undefined
}
@Component({
selector: 'fab-panel-header',
exportAs: 'fabPanelHeader',
template: `
<PanelHeader>
<ReactContent><ng-content></ng-content></ReactContent>
</PanelHeader>
`,
styles: ['react-renderer'],
changeDetection: ChangeDetectionStrategy.OnPush,
host: { 'class': 'fab-panel-header' }
})
export class FabPanelHeaderComponent { }

Просмотреть файл

@ -0,0 +1,25 @@
import { registerElement } from '@angular-react/core';
import { CommonModule } from '@angular/common';
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
import { Panel } from 'office-ui-fabric-react/lib/Panel';
import { FabPanelComponent, FabPanelHeaderComponent } from './panel.component';
const components = [
FabPanelComponent,
FabPanelHeaderComponent,
];
@NgModule({
imports: [CommonModule],
declarations: components,
exports: components,
schemas: [NO_ERRORS_SCHEMA]
})
export class FabPanelModule {
constructor() {
// Add any React elements to the registry (used by the renderer).
registerElement('Panel', () => Panel);
}
}

Просмотреть файл

@ -0,0 +1,2 @@
export * from './panel.component';
export * from './panel.module';

Просмотреть файл

@ -5,15 +5,8 @@
"module": "es2015", "module": "es2015",
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@angular-react/*": [ "@angular-react/*": ["@angular-react/*"]
"@angular-react/*"
]
} }
}, },
"exclude": [ "exclude": ["**/*.spec.ts", "**/*.e2e-spec.ts", "node_modules", "tmp"]
"**/*.spec.ts",
"**/*.e2e-spec.ts",
"node_modules",
"tmp"
]
} }