|
| 1 | +import { ReactWrapperComponent, InputRendererOptions } from '@angular-react/core'; |
| 2 | +import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, ViewChild, OnInit } from '@angular/core'; |
| 3 | +import { ISearchBoxProps } from 'office-ui-fabric-react/lib/components/SearchBox'; |
| 4 | +import { IButtonProps } from 'office-ui-fabric-react/lib/components/Button'; |
| 5 | +import { IContextualMenuProps } from 'office-ui-fabric-react/lib/components/ContextualMenu'; |
| 6 | +import omit from '../../utils/omit'; |
| 7 | + |
| 8 | +@Component({ |
| 9 | + selector: 'fab-search-box', |
| 10 | + exportAs: 'fabSearchBox', |
| 11 | + template: ` |
| 12 | + <SearchBox |
| 13 | + #reactNode |
| 14 | + [componentRef]="componentRef" |
| 15 | + [placeholder]="placeholder" |
| 16 | + [labelText]="labelText" |
| 17 | + [value]="value" |
| 18 | + [defaultValue]="defaultValue" |
| 19 | + [className]="className" |
| 20 | + [ariaLabel]="ariaLabel" |
| 21 | + [clearButtonProps]="clearButtonProps" |
| 22 | + [underlined]="underlined" |
| 23 | + [theme]="theme" |
| 24 | + [styles]="styles" |
| 25 | + [disableAnimation]="disableAnimation" |
| 26 | + [Change]="onChangeHandler" |
| 27 | + [Search]="onSearchHandler" |
| 28 | + [Clear]="onClearHandler" |
| 29 | + [Escape]="onEscapeHandler" |
| 30 | + [Changed]="onChangedHandler"> |
| 31 | + </SearchBox> |
| 32 | + `, |
| 33 | + styles: ['react-renderer'], |
| 34 | + changeDetection: ChangeDetectionStrategy.OnPush, |
| 35 | + host: { 'class': 'fab-search-box' } |
| 36 | +}) |
| 37 | +export class FabSearchBoxComponent extends ReactWrapperComponent<ISearchBoxProps> { |
| 38 | + |
| 39 | + @ViewChild('reactNode') protected reactNodeRef: ElementRef; |
| 40 | + |
| 41 | + @Input() componentRef?: ISearchBoxProps['componentRef']; |
| 42 | + @Input() placeholder?: ISearchBoxProps['placeholder']; |
| 43 | + @Input() labelText?: ISearchBoxProps['labelText']; |
| 44 | + @Input() value?: ISearchBoxProps['value']; |
| 45 | + @Input() defaultValue?: ISearchBoxProps['defaultValue']; |
| 46 | + @Input() className?: ISearchBoxProps['className']; |
| 47 | + @Input() ariaLabel?: ISearchBoxProps['ariaLabel']; |
| 48 | + @Input() underlined?: ISearchBoxProps['underlined']; |
| 49 | + @Input() theme?: ISearchBoxProps['theme']; |
| 50 | + @Input() styles?: ISearchBoxProps['styles']; |
| 51 | + @Input() disableAnimation?: ISearchBoxProps['disableAnimation']; |
| 52 | + @Input() set clearButtonOptions(value: IButtonOptions) { |
| 53 | + this._clearButtonOptions = value; |
| 54 | + |
| 55 | + if (value) { |
| 56 | + this.clearButtonProps = this._transformButtonOptionsToProps(value); |
| 57 | + } |
| 58 | + } |
| 59 | + |
| 60 | + get clearButtonOptions(): IButtonOptions { |
| 61 | + return this._clearButtonOptions; |
| 62 | + } |
| 63 | + |
| 64 | + @Output() readonly onChange = new EventEmitter<{ newValue: any }>(); |
| 65 | + @Output() readonly onSearch = new EventEmitter<{ newValue: any }>(); |
| 66 | + @Output() readonly onClear = new EventEmitter<{ ev?: any }>(); |
| 67 | + @Output() readonly onEscape = new EventEmitter<{ ev?: any }>(); |
| 68 | + @Output() readonly onChanged = new EventEmitter<{ newValue: any }>(); |
| 69 | + |
| 70 | + clearButtonProps: IButtonProps; |
| 71 | + |
| 72 | + private _clearButtonOptions: IButtonOptions; |
| 73 | + |
| 74 | + constructor(elementRef: ElementRef) { |
| 75 | + super(elementRef); |
| 76 | + |
| 77 | + this.onChangeHandler = this.onChangeHandler.bind(this); |
| 78 | + this.onSearchHandler = this.onSearchHandler.bind(this); |
| 79 | + this.onClearHandler = this.onClearHandler.bind(this); |
| 80 | + this.onEscapeHandler = this.onEscapeHandler.bind(this); |
| 81 | + this.onChangedHandler = this.onChangedHandler.bind(this); |
| 82 | + } |
| 83 | + |
| 84 | + onChangeHandler(newValue: any) { |
| 85 | + this.onChange.emit({ |
| 86 | + newValue |
| 87 | + }); |
| 88 | + } |
| 89 | + onSearchHandler(newValue: any) { |
| 90 | + this.onSearch.emit({ |
| 91 | + newValue |
| 92 | + }); |
| 93 | + } |
| 94 | + onClearHandler(ev?: any) { |
| 95 | + this.onClear.emit({ |
| 96 | + ev: ev && ev.nativeElement || ev, |
| 97 | + }); |
| 98 | + } |
| 99 | + onEscapeHandler(ev?: any) { |
| 100 | + this.onEscape.emit({ |
| 101 | + ev: ev && ev.nativeElement || ev, |
| 102 | + }); |
| 103 | + } |
| 104 | + onChangedHandler(newValue: any) { |
| 105 | + this.onChange.emit({ |
| 106 | + newValue |
| 107 | + }); |
| 108 | + } |
| 109 | + |
| 110 | + private _transformButtonOptionsToProps(options: IButtonOptions): IButtonProps { |
| 111 | + const sharedProperties = omit(options, |
| 112 | + 'renderIcon', |
| 113 | + 'renderText', |
| 114 | + 'renderDescription', |
| 115 | + 'renderAriaDescription', |
| 116 | + 'renderChildren', |
| 117 | + 'renderMenuIcon', |
| 118 | + 'renderMenu' |
| 119 | + ); |
| 120 | + |
| 121 | + const iconRenderer = this.createInputJsxRenderer(options.renderIcon); |
| 122 | + const textRenderer = this.createInputJsxRenderer(options.renderText); |
| 123 | + const descriptionRenderer = this.createInputJsxRenderer(options.renderDescription); |
| 124 | + const ariaDescriptionRenderer = this.createInputJsxRenderer(options.renderAriaDescription); |
| 125 | + const childrenRenderer = this.createInputJsxRenderer(options.renderChildren); |
| 126 | + const menuIconRenderer = this.createInputJsxRenderer(options.renderMenuIcon); |
| 127 | + const menuRenderer = this.createInputJsxRenderer(options.renderMenu); |
| 128 | + |
| 129 | + return Object.assign( |
| 130 | + {}, |
| 131 | + sharedProperties, |
| 132 | + iconRenderer && { onRenderIcon: props => iconRenderer(props) } as Pick<IButtonProps, 'onRenderIcon'>, |
| 133 | + textRenderer && { onRenderText: props => textRenderer(props) } as Pick<IButtonProps, 'onRenderText'>, |
| 134 | + descriptionRenderer && { onRenderDescription: props => descriptionRenderer(props) } as Pick<IButtonProps, 'onRenderDescription'>, |
| 135 | + ariaDescriptionRenderer && { onRenderAriaDescription: props => ariaDescriptionRenderer(props) } as Pick<IButtonProps, 'onRenderAriaDescription'>, |
| 136 | + childrenRenderer && { onRenderChildren: props => childrenRenderer(props) } as Pick<IButtonProps, 'onRenderChildren'>, |
| 137 | + menuIconRenderer && { onRenderMenuIcon: props => menuIconRenderer(props) } as Pick<IButtonProps, 'onRenderMenuIcon'>, |
| 138 | + menuRenderer && { onRenderMenu: props => menuRenderer(props) } as Pick<IButtonProps, 'onRenderMenu'>, |
| 139 | + ); |
| 140 | + } |
| 141 | + |
| 142 | +} |
| 143 | + |
| 144 | +export interface IButtonOptions extends Pick<IButtonProps, 'componentRef' | 'href' | 'primary' | 'uniqueId' | 'disabled' | 'allowDisabledFocus' | 'primaryDisabled' | 'styles' | 'theme' | 'checked' | 'className' | 'ariaLabel' | 'ariaDescription' | 'ariaHidden' | 'text' | 'iconProps' | 'menuProps' | 'onAfterMenuDismiss' | 'split' | 'menuIconProps' | 'splitButtonAriaLabel' | 'onMenuClick' | 'secondaryText' | 'toggled' | 'data' | 'getClassNames' | 'getSplitButtonClassNames' | 'menuTriggerKeyCode' | 'keytipProps' | 'persistMenu'> { |
| 145 | + renderIcon: InputRendererOptions<IButtonProps>; |
| 146 | + renderText: InputRendererOptions<IButtonProps>; |
| 147 | + renderDescription: InputRendererOptions<IButtonProps>; |
| 148 | + renderAriaDescription: InputRendererOptions<IButtonProps>; |
| 149 | + renderChildren: InputRendererOptions<IButtonProps>; |
| 150 | + renderMenuIcon: InputRendererOptions<IButtonProps>; |
| 151 | + renderMenu: InputRendererOptions<IContextualMenuProps>; |
| 152 | +} |
0 commit comments