[Panel] WIP
This commit is contained in:
Родитель
a92a90dc3c
Коммит
8967593512
|
@ -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"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче