[Panel] WIP
This commit is contained in:
Родитель
a92a90dc3c
Коммит
8967593512
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"cSpell.words": [
|
||||
"Focusable",
|
||||
"Injectable",
|
||||
"Packagr",
|
||||
"Renderable",
|
||||
"nrwl",
|
||||
"unmount",
|
||||
"whitelisted"
|
||||
]
|
||||
|
|
|
@ -3,21 +3,40 @@
|
|||
<h2>Getting up and running...</h2>
|
||||
|
||||
<ol>
|
||||
<li>Add <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
|
||||
<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>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<fab-button label="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-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">
|
||||
Hello world! {{ counter }}
|
||||
<fab-dialog-footer>
|
||||
<fab-button (onClick)="incrementCounter()" label='Save' style="margin-right:10px;"></fab-button>
|
||||
<fab-button (onClick)="toggleDialog()" label='Cancel'></fab-button>
|
||||
<fab-button (onClick)="incrementCounter()" text='Save' style="margin-right:10px;"></fab-button>
|
||||
<fab-button (onClick)="toggleDialog()" text='Cancel'></fab-button>
|
||||
</fab-dialog-footer>
|
||||
</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 { DialogType } from 'office-ui-fabric-react/lib/Dialog';
|
||||
import { IButtonProps } from '../../../../node_modules/office-ui-fabric-react/lib/Button';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
|
@ -12,10 +13,47 @@ export class AppComponent {
|
|||
dialogHidden = true;
|
||||
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() {
|
||||
this.dialogHidden = !this.dialogHidden;
|
||||
}
|
||||
|
||||
onClick() {
|
||||
alert('clicked!');
|
||||
}
|
||||
|
||||
incrementCounter() {
|
||||
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 { NxModule } from '@nrwl/nx';
|
||||
|
||||
import { AngularReactBrowserModule } from '@angular-react/core';
|
||||
import { FabDialogModule, FabButtonModule } from '@angular-react/fabric';
|
||||
import { initializeIcons } from 'office-ui-fabric-react/lib/Icons';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
import { WrapperComponent } from './wrapper.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [AngularReactBrowserModule, NxModule.forRoot(), FabButtonModule, FabDialogModule],
|
||||
declarations: [AppComponent],
|
||||
bootstrap: [AppComponent]
|
||||
imports: [AngularReactBrowserModule,
|
||||
NxModule.forRoot(),
|
||||
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",
|
||||
"ngPackage": {
|
||||
"lib": {
|
||||
"languageLevel": [
|
||||
"dom",
|
||||
"es2017"
|
||||
],
|
||||
"entryFile": "public-api.ts",
|
||||
"umdModuleIds": {
|
||||
"react": "React",
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
export { registerElement } from './src/renderer/registry';
|
||||
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 { isReactNode } from "../renderer/react-node";
|
||||
|
||||
const blacklistedAttributesAsProps = [
|
||||
'class',
|
||||
|
@ -7,7 +7,7 @@ const blacklistedAttributesAsProps = [
|
|||
];
|
||||
|
||||
const blacklistedAttributeMatchers = [
|
||||
/^_ng.*/
|
||||
/^_?ng-?.*/
|
||||
]
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as React from 'react';
|
|||
import * as ReactDOM from 'react-dom';
|
||||
|
||||
|
||||
const DEBUG = false;
|
||||
const DEBUG = true;
|
||||
export const CHILDREN_TO_APPEND_PROP = 'children-to-append';
|
||||
|
||||
export class ReactContent extends React.Component {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
/// <reference path="../types/StringMap.d.ts" />
|
||||
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import removeUndefinedProperties from '../utils/object/remove-undefined-properties';
|
||||
import { CHILDREN_TO_APPEND_PROP } from './react-content';
|
||||
import { getComponentClass, ReactComponentClass } from "./registry";
|
||||
|
||||
const DEBUG = false;
|
||||
const DEBUG = true;
|
||||
|
||||
export function isReactNode(node: any): node is ReactNode {
|
||||
return (<ReactNode>node).setRenderPendingCallback !== undefined;
|
||||
|
@ -182,12 +184,37 @@ export class ReactNode {
|
|||
|
||||
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); }
|
||||
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.
|
||||
appendChild(projectedContent: HTMLElement) {
|
||||
if (DEBUG) { console.error('ReactNode > appendChild > node:', this.toString(), 'projectedContent:', projectedContent.toString().trim()); }
|
||||
|
|
|
@ -1,25 +1,10 @@
|
|||
// tslint:disable:no-bitwise
|
||||
|
||||
import {
|
||||
Injectable,
|
||||
RendererType2,
|
||||
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 { Injectable, Renderer2, RendererStyleFlags2, RendererType2 } from '@angular/core';
|
||||
import { EventManager, ɵDomRendererFactory2, ɵDomSharedStylesHost } from '@angular/platform-browser';
|
||||
import { isReactNode, ReactNode } from './react-node';
|
||||
|
||||
import { ReactComponentClass, getComponentClass } from './registry';
|
||||
import { ReactNode, isReactNode } from './react-node';
|
||||
|
||||
|
||||
const DEBUG = false;
|
||||
const DEBUG = true;
|
||||
|
||||
@Injectable()
|
||||
export class AngularReactRendererFactory extends ɵDomRendererFactory2 {
|
||||
|
@ -52,7 +37,7 @@ export class AngularReactRendererFactory extends ɵDomRendererFactory2 {
|
|||
return this.defaultReactRenderer;
|
||||
}
|
||||
|
||||
return super.createRenderer(element, type);
|
||||
return super.createRenderer(element, type);
|
||||
}
|
||||
|
||||
begin() { }
|
||||
|
@ -73,9 +58,9 @@ export class AngularReactRendererFactory extends ɵDomRendererFactory2 {
|
|||
class ReactRenderer implements Renderer2 {
|
||||
data: { [key: string]: any } = Object.create(null);
|
||||
|
||||
constructor(private rootRenderer: AngularReactRendererFactory) {}
|
||||
constructor(private rootRenderer: AngularReactRendererFactory) { }
|
||||
|
||||
destroy(): void {}
|
||||
destroy(): void { }
|
||||
|
||||
destroyNode(node: ReactNode): void {
|
||||
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()); }
|
||||
}
|
||||
|
||||
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); }
|
||||
node.setProperty(name, value);
|
||||
}
|
||||
|
@ -208,7 +193,7 @@ class ReactRenderer implements Renderer2 {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
export * from './src/button/button.module';
|
||||
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.module';
|
||||
export * from './src/icon/icon.component';
|
||||
export * from './src/icon/icon.module';
|
||||
export * from './src/image/image.component';
|
||||
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:no-output-on-prefix
|
||||
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output } from '@angular/core';
|
||||
|
||||
import { IButtonProps, DefaultButton } from 'office-ui-fabric-react/lib/Button';
|
||||
|
||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { IButtonProps } from 'office-ui-fabric-react/lib/Button';
|
||||
|
||||
@Component({
|
||||
selector: 'fab-button',
|
||||
exportAs: 'fabButton',
|
||||
template: `
|
||||
<DefaultButton
|
||||
key="c1"
|
||||
data-automation-id='test_automation_id'
|
||||
[primary]="primary"
|
||||
[disabled]="disabled"
|
||||
[text]="text"
|
||||
(onClick)="onClick.emit($event)"></DefaultButton>
|
||||
[split]="split"
|
||||
[href]="href"
|
||||
[menuProps]="menuProps"
|
||||
[iconProps]="iconProps"
|
||||
(onClick)="onClick.emit($event)">
|
||||
</DefaultButton>
|
||||
`,
|
||||
styles: [
|
||||
'react-renderer',
|
||||
':host { display: inline-block; background: red; }' // TODO: this isn't working. Problem with react-renderer.
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { 'class': 'fab-button' }
|
||||
})
|
||||
export class FabButtonComponent {
|
||||
|
||||
@Input() disabled = false;
|
||||
@Input() primary = true;
|
||||
@Input('label') text = '';
|
||||
@Input() disabled?: IButtonProps['disabled'];
|
||||
@Input() primary?: IButtonProps['primary'];
|
||||
@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>();
|
||||
|
||||
|
|
|
@ -3,23 +3,16 @@
|
|||
// tslint:disable:no-output-rename
|
||||
// tslint:disable:use-host-property-decorator
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
OnChanges,
|
||||
Output,
|
||||
} from '@angular/core';
|
||||
|
||||
import { IDialogProps, Dialog, DialogType, DialogFooter } from 'office-ui-fabric-react/lib/components/Dialog';
|
||||
|
||||
import { ReactWrapperComponent } from '@angular-react/core';
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
||||
import { DialogType, IDialogProps } from 'office-ui-fabric-react/lib/components/Dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'fab-dialog',
|
||||
exportAs: 'fabDialog',
|
||||
template: `
|
||||
<Dialog
|
||||
#reactNode
|
||||
[hidden]="hidden"
|
||||
(onDismiss)="onDismiss($event)"
|
||||
[dialogContentProps]="{
|
||||
|
@ -39,7 +32,8 @@ import { IDialogProps, Dialog, DialogType, DialogFooter } from 'office-ui-fabric
|
|||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: { 'class': 'fab-dialog' }
|
||||
})
|
||||
export class FabDialogComponent {
|
||||
export class FabDialogComponent extends ReactWrapperComponent<IDialogProps> {
|
||||
@ViewChild('reactNode') protected reactNodeRef: ElementRef;
|
||||
|
||||
@Input() hidden = false;
|
||||
@Input() type = DialogType.normal;
|
||||
|
@ -49,16 +43,22 @@ export class FabDialogComponent {
|
|||
@Input() isBlocking = false;
|
||||
@Input() containerClassName = 'ms-dialogMainOverride';
|
||||
|
||||
@Output('onDismiss') dismiss: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
|
||||
onDismiss = ev => this.dismiss.emit(ev as any);
|
||||
}
|
||||
@Output('onDismiss') dismiss = new EventEmitter<MouseEvent>();
|
||||
|
||||
constructor(elementRef: ElementRef) {
|
||||
super(elementRef);
|
||||
}
|
||||
|
||||
onDismiss(reactEvent: React.MouseEvent<HTMLButtonElement>) {
|
||||
this.dismiss.emit(reactEvent.nativeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'fab-dialog-footer',
|
||||
exportAs: 'fabDialogFooter',
|
||||
template: `
|
||||
<DialogFooter key="4">
|
||||
<DialogFooter>
|
||||
<ReactContent><ng-content></ng-content></ReactContent>
|
||||
</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 { 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",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@angular-react/*": [
|
||||
"@angular-react/*"
|
||||
]
|
||||
"@angular-react/*": ["@angular-react/*"]
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.e2e-spec.ts",
|
||||
"node_modules",
|
||||
"tmp"
|
||||
]
|
||||
"exclude": ["**/*.spec.ts", "**/*.e2e-spec.ts", "node_modules", "tmp"]
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче