UNPKG

@tangential/input-widgets

Version:

Input Widgets with persistable, dynamic configuration.

1 lines 205 kB
{"version":3,"file":"tangential-input-widgets.mjs","sources":["../../../../projects/tangential/input-widgets/src/lib/checkbox-widget/checkbox-widget.component.ts","../../../../projects/tangential/input-widgets/src/lib/checkbox-widget/checkbox-widget-configure.component.ts","../../../../projects/tangential/input-widgets/src/lib/date-time-widget/date-time-widget.component.ts","../../../../projects/tangential/input-widgets/src/lib/date-time-widget/date-time-widget-configure.component.ts","../../../../projects/tangential/input-widgets/src/lib/number-spinner-widget/number-spinner-widget.component.ts","../../../../projects/tangential/input-widgets/src/lib/duration-picker-widget/duration-picker-dialog.ts","../../../../projects/tangential/input-widgets/src/lib/duration-picker-widget/duration-picker-dialog.html","../../../../projects/tangential/input-widgets/src/lib/duration-picker-widget/duration-picker-state.ts","../../../../projects/tangential/input-widgets/src/lib/duration-picker-widget/duration-picker-widget.component.ts","../../../../projects/tangential/input-widgets/src/lib/duration-picker-widget/duration-picker-widget-configure.component.ts","../../../../projects/tangential/input-widgets/src/lib/icon-rating-widget/icon-rating-widget.component.ts","../../../../projects/tangential/input-widgets/src/lib/icon-rating-widget/icon-rating-widget-configure.component.ts","../../../../projects/tangential/input-widgets/src/lib/number-slider-widget/number-slider-widget.component.ts","../../../../projects/tangential/input-widgets/src/lib/number-slider-widget/number-slider-widget-configure.component.ts","../../../../projects/tangential/input-widgets/src/lib/number-spinner-widget/number-spinner-widget-configure.component.ts","../../../../projects/tangential/input-widgets/src/lib/number-widget/number-widget.component.ts","../../../../projects/tangential/input-widgets/src/lib/number-widget/number-widget-configure.component.ts","../../../../projects/tangential/input-widgets/src/lib/slide-toggle-widget/slide-toggle-widget.component.ts","../../../../projects/tangential/input-widgets/src/lib/slide-toggle-widget/slide-toggle-widget-configure.component.ts","../../../../projects/tangential/input-widgets/src/lib/text-widget/text-widget.component.ts","../../../../projects/tangential/input-widgets/src/lib/text-widget/text-widget-configure.component.ts","../../../../projects/tangential/input-widgets/src/lib/input-widget.module.ts","../../../../projects/tangential/input-widgets/src/public-api.ts","../../../../projects/tangential/input-widgets/src/tangential-input-widgets.ts"],"sourcesContent":["import {\n ChangeDetectorRef,\n Component,\n EventEmitter,\n forwardRef,\n HostBinding,\n Input,\n OnInit,\n Output,\n ViewEncapsulation\n} from '@angular/core'\nimport {\n ControlValueAccessor,\n NG_VALUE_ACCESSOR\n} from '@angular/forms'\nimport {Hacks} from '@tangential/core'\n\n/**\n * Provider Expression that allows this widget to register as a ControlValueAccessor.\n * This allows it to support [(ngModel)].\n * @docs-private\n */\nexport const TANJ_CHECKBOX_WIDGET_VIEW_CONTROL_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => CheckboxWidgetComponent),\n multi: true\n};\n\nexport class CheckboxWidgetChange {\n\n constructor(public source: CheckboxWidgetComponent, public value: boolean) {\n }\n}\n\n\n@Component({\n selector: 'tanj-checkbox-widget',\n template: `<!-- -->\n <div flex class=\"tanj-input-template tanj-mode-edit\"\n [ngClass]=\"{'tanj-disabled': disabled}\"\n layout=\"row\"\n layout-align=\"center center\">\n <span *ngIf=\"!hideLabel && labelPosition == 'before'\"\n class=\"tanj-label tanj-checkbox-widget-label\">{{label}}</span>\n <div flex class=\"tanj-widget-input\" layout=\"column\" layout-align=\"start center\">\n <div *ngIf=\"!onlyLabel\"\n class=\"tanj-widget-input\"\n layout=\"column\"\n layout-align=\"start\">\n <mat-checkbox flex\n [disabled]=\"disabled\"\n [(ngModel)]=\"value\"\n (change)=\"handleValueChange(value)\">\n </mat-checkbox>\n </div>\n <div *ngIf=\"!hideLabel && labelPosition == 'below'\" class=\"tanj-label tanj-below\">{{label}}</div>\n </div>\n <span *ngIf=\"!hideLabel && labelPosition == 'after'\" class=\"tanj-label tanj-checkbox-widget-label\">{{label}}</span>\n </div>\n `,\n providers: [TANJ_CHECKBOX_WIDGET_VIEW_CONTROL_VALUE_ACCESSOR],\n encapsulation: ViewEncapsulation.None\n})\nexport class CheckboxWidgetComponent implements OnInit, ControlValueAccessor {\n\n // turn this into a class\n @HostBinding('attr.flex') flex = '';\n @HostBinding('attr.layout') flexLayout = 'column';\n @HostBinding('attr.layout-align') flexLayoutAlign = 'start';\n\n\n @Input() value: boolean = false\n @Output() valueChange: EventEmitter<boolean> = new EventEmitter(false)\n\n @Input() labelPosition: 'before' | 'after' | 'below' = 'before'\n @Input() disabled: boolean = false\n @Input() hideLabel: boolean = false\n @Input() onlyLabel: boolean = false\n\n\n /**\n * Configuration Fields\n */\n @Input() label: string = ''\n @Input() defaultValue: boolean = false\n /* end Configuration Fields */\n\n @Output() change: EventEmitter<any> = new EventEmitter(false)\n\n onTouched: () => any = () => { };\n private controlValueAccessorChangeFn: (value: any) => void = (value) => { };\n\n constructor(private changeDetectorRef: ChangeDetectorRef) {\n }\n\n ngOnInit() {\n Hacks.materialDesignPlaceholderText(this.changeDetectorRef)\n }\n\n handleValueChange(value: boolean) {\n if (!this.disabled) {\n this.value = value\n this.valueChange.emit(this.value)\n this.emitChangeEvent()\n }\n }\n\n /**\n * Boilerplate / required for Angular\n *\n */\n private emitChangeEvent() {\n this.controlValueAccessorChangeFn(this.value);\n this.change.emit(new CheckboxWidgetChange(this, this.value))\n }\n\n public writeValue(value: boolean): void {\n this.value = value\n }\n\n public registerOnChange(fn: any): void {\n this.controlValueAccessorChangeFn = fn;\n }\n\n public registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n /**\n * Sets the input's disabled state. Implemented as a part of ControlValueAccessor.\n * @param isDisabled Whether the input should be disabled.\n */\n setDisabledState(isDisabled: boolean) {\n this.disabled = isDisabled;\n }\n\n\n}\n","import {\n ChangeDetectorRef,\n Component,\n EventEmitter,\n forwardRef,\n HostBinding,\n Input,\n OnInit,\n Output,\n ViewEncapsulation\n} from '@angular/core'\nimport {\n ControlValueAccessor,\n NG_VALUE_ACCESSOR\n} from '@angular/forms'\nimport {Hacks} from '@tangential/core'\n\n\n/**\n * Provider Expression that allows this widget to register as a ControlValueAccessor.\n * This allows it to support [(ngModel)].\n * @docs-private\n */\nexport const TANJ_CHECKBOX_WIDGET_CONFIG_CONTROL_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => CheckboxWidgetConfigureComponent),\n multi: true\n};\n\nexport class CheckboxWidgetConfigureChange {\n constructor(public source: CheckboxWidgetConfigureComponent, public value: boolean) {\n }\n}\n\n\n@Component({\n selector: 'tanj-checkbox-widget-configure',\n template: `<!-- -->\n <div class=\"tanj-input-template tanj-mode-configure\" flex layout=\"column\" layout-align=\"start\">\n <mat-form-field dividerColor=\"accent\">\n <input matInput class=\"tanj-input\" type=\"text\" maxlength=\"50\" placeholder=\"Enter a label for this input\"\n (change)=\"emitChangeEvent(false, true)\"\n [(ngModel)]=\"label\"/>\n </mat-form-field>\n <ng-container *ngIf=\"label\">\n <tanj-checkbox-widget [(value)]=\"defaultValue\"\n (valueChange)=\"value = defaultValue; emitChangeEvent(true, false)\"\n [defaultValue]=\"defaultValue\"\n label=\"Default Value\"\n [labelPosition]=\"'before'\">\n\n </tanj-checkbox-widget>\n </ng-container>\n </div>\n `,\n providers: [TANJ_CHECKBOX_WIDGET_CONFIG_CONTROL_VALUE_ACCESSOR],\n encapsulation: ViewEncapsulation.None\n})\nexport class CheckboxWidgetConfigureComponent implements OnInit, ControlValueAccessor {\n\n @HostBinding('attr.flex') flex = '';\n @HostBinding('attr.layout') flexLayout = 'column';\n @HostBinding('attr.layout-align') flexLayoutAlign = 'start';\n\n @Input() value: boolean = false\n @Output() valueChange: EventEmitter<boolean> = new EventEmitter(false)\n\n @Input() labelPosition: 'before' | 'after' | 'below' = 'before'\n @Input() disabled: boolean = false\n\n /**\n * Configuration Fields\n */\n @Input() label: string = ''\n @Output() labelChange: EventEmitter<string> = new EventEmitter(false)\n\n @Input() defaultValue: boolean = false\n @Output() defaultValueChange: EventEmitter<boolean> = new EventEmitter(false)\n /* end Configuration Fields */\n\n @Output() change: EventEmitter<any> = new EventEmitter(false)\n\n /**\n * Called when the spinner is blurred. Needed to properly implement ControlValueAccessor.\n * @docs-private\n */\n onTouched: () => any = () => { };\n private controlValueAccessorChangeFn: (value: any) => void = (value) => { };\n\n constructor(private changeDetectorRef: ChangeDetectorRef) {\n }\n\n ngOnInit() {\n Hacks.materialDesignPlaceholderText(this.changeDetectorRef)\n }\n\n emitChangeEvent(value: boolean, label: boolean) {\n this.controlValueAccessorChangeFn(this.value);\n this.change.emit(new CheckboxWidgetConfigureChange(this, this.value))\n if (value) {\n this.valueChange.emit(this.value);\n this.defaultValueChange.emit(this.defaultValue)\n }\n if (label) {\n this.labelChange.emit(this.label)\n }\n }\n\n /**\n * Boilerplate / required for Angular\n *\n */\n public writeValue(value: boolean): void {\n this.value = value\n }\n\n public registerOnChange(fn: any): void {\n this.controlValueAccessorChangeFn = fn;\n }\n\n public registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n /**\n * Sets the input's disabled state. Implemented as a part of ControlValueAccessor.\n * @param isDisabled Whether the input should be disabled.\n */\n setDisabledState(isDisabled: boolean) {\n this.disabled = isDisabled;\n }\n}\n","import {\n ChangeDetectorRef, Component, EventEmitter, forwardRef, HostBinding, Input, OnChanges, OnInit, Output, SimpleChange, ViewEncapsulation\n} from '@angular/core'\nimport {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'\nimport {Hacks} from '@tangential/core'\nimport moment from 'moment'\n\n\n/**\n * Provider Expression that allows this widget to register as a ControlValueAccessor.\n * This allows it to support [(ngModel)].\n * @docs-private\n */\nexport const TANJ_DATE_TIME_WIDGET_VIEW_CONTROL_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateTimeWidgetComponent), multi: true\n};\n\nexport class DateTimeWidgetChange {\n\n constructor(public source: DateTimeWidgetComponent, public value: number) {\n }\n}\n\n\n@Component({\n selector: 'tanj-date-time-widget', template: `<!-- -->\n <div flex class=\"tanj-input-template tanj-mode-edit\"\n [ngClass]=\"{'tanj-disabled': disabled}\"\n layout=\"row\"\n layout-align=\"start center\">\n <span *ngIf=\"!hideLabel && labelPosition == 'before'\" class=\"tanj-label tanj-before\">{{label}}</span>\n <div flex class=\"tanj-widget-input\" layout=\"column\" layout-align=\"center start\">\n <div flex *ngIf=\"!onlyLabel\" class=\"tanj-widget-input\" layout=\"row\" layout-align=\"start\">\n <mat-form-field flex\n class=\"tanj-date-time-input-field tanj-widget-input\"\n dividerColor=\"accent\"\n layout=\"row\"\n layout-align=\"start\">\n <input flex\n matInput\n class=\"tanj-input\"\n type=\"datetime-local\"\n minlength=\"{{minLength}}\"\n maxlength=\"{{maxLength}}\"\n [disabled]=\"disabled\"\n (change)=\"valueChange.emit(value)\"\n [(ngModel)]=\"dateInputValue\"/>\n </mat-form-field>\n </div>\n <span *ngIf=\"!hideLabel && labelPosition == 'below'\" class=\"tanj-label tanj-below\">{{label}}</span>\n </div>\n <span *ngIf=\"!hideLabel && labelPosition == 'after'\" class=\"tanj-label tanj-after\">{{label}}</span>\n </div>\n `, providers: [TANJ_DATE_TIME_WIDGET_VIEW_CONTROL_VALUE_ACCESSOR], encapsulation: ViewEncapsulation.None\n})\nexport class DateTimeWidgetComponent implements ControlValueAccessor, OnChanges, OnInit {\n\n // turn this into a class\n @HostBinding('attr.flex') flex = '';\n @HostBinding('attr.layout') flexLayout = 'column';\n @HostBinding('attr.layout-align') flexLayoutAlign = 'start';\n\n @Input() value: number = Date.now()\n @Output() valueChange: EventEmitter<number> = new EventEmitter(false)\n\n @Input() labelPosition: 'before' | 'after' | 'below' = 'before'\n @Input() disabled: boolean = false\n @Input() hideLabel: boolean = false\n @Input() onlyLabel: boolean = false\n\n /**\n * Configuration Fields\n */\n @Input() label: string = ''\n @Input() defaultToNow: boolean = false\n @Input() defaultValue: number = 0\n @Input() maxLength: number = 100\n @Input() minLength: number = 0\n /* end Configuration Fields */\n\n @Output() change: EventEmitter<any> = new EventEmitter(false)\n onTouched: () => any = () => {\n };\n\n constructor(private changeDetectorRef: ChangeDetectorRef) {\n }\n\n private controlValueAccessorChangeFn: (value: any) => void = (value) => {\n };\n\n\n ngOnInit() {\n this.value = this.defaultToNow ? Date.now() : this.defaultValue\n Hacks.materialDesignPlaceholderText(this.changeDetectorRef)\n }\n\n get dateInputValue(): string {\n return moment(this.value).format('YYYY-MM-DDTHH:mm:ss')\n }\n\n set dateInputValue(dateString: string) {\n this.value = moment(dateString).valueOf()\n }\n\n ngOnChanges(changes: { defaultToNow: SimpleChange }) {\n if (changes.defaultToNow && !this.value) {\n this.value = this.defaultToNow ? Date.now() : this.defaultValue\n }\n }\n\n handleValueChange(value: number) {\n if (!this.disabled) {\n this.value = value\n this.valueChange.emit(this.value)\n this.emitChangeEvent()\n }\n }\n\n /**\n * Boilerplate / required for Angular\n *\n */\n private emitChangeEvent() {\n const change = new DateTimeWidgetChange(this, this.value)\n this.controlValueAccessorChangeFn(this.value);\n this.change.emit(change)\n }\n\n public writeValue(value: number): void {\n this.value = value\n }\n\n public registerOnChange(fn: any): void {\n this.controlValueAccessorChangeFn = fn;\n }\n\n public registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n /**\n * Sets the input's disabled state. Implemented as a part of ControlValueAccessor.\n * @param isDisabled Whether the input should be disabled.\n */\n setDisabledState(isDisabled: boolean) {\n this.disabled = isDisabled;\n }\n}\n","import {\n ChangeDetectorRef,\n Component,\n EventEmitter,\n forwardRef,\n HostBinding,\n Input,\n OnChanges,\n OnInit,\n Output,\n SimpleChange,\n ViewEncapsulation\n} from '@angular/core'\nimport {\n ControlValueAccessor,\n NG_VALUE_ACCESSOR\n} from '@angular/forms'\nimport {Hacks} from '@tangential/core'\n\n\n/**\n * Provider Expression that allows this widget to register as a ControlValueAccessor.\n * This allows it to support [(ngModel)].\n * @docs-private\n */\nexport const TANJ_DATE_TIME_WIDGET_CONFIG_CONTROL_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => DateTimeWidgetConfigureComponent),\n multi: true\n};\n\nexport class DateTimeWidgetConfigureChange {\n constructor(public source: DateTimeWidgetConfigureComponent, public value: number) {\n }\n}\n\n\n@Component({\n selector: 'tanj-date-time-configure',\n template: `<!-- -->\n <div class=\"tanj-input-template tanj-mode-configure\" flex layout=\"column\" layout-align=\"start\">\n <mat-form-field dividerColor=\"accent\">\n <input matInput class=\"tanj-input\" type=\"text\" maxlength=\"50\" placeholder=\"Enter a label for this input\"\n (change)=\"labelChange.emit(label)\"\n [(ngModel)]=\"label\"/>\n </mat-form-field>\n <ng-container *ngIf=\"label\">\n <mat-slide-toggle class=\"tanj-input\" [labelPosition]=\"'before'\" [(ngModel)]=\"defaultToNow\">Default to current time?\n </mat-slide-toggle>\n <tanj-date-time-widget *ngIf=\"!defaultToNow\" [(value)]=\"defaultValue\"\n (valueChange)=\"value = defaultValue; emitChangeEvent(true, false)\"\n [defaultValue]=\"defaultValue\"\n label=\"Default Value\"></tanj-date-time-widget>\n </ng-container>\n </div>\n `,\n providers: [TANJ_DATE_TIME_WIDGET_CONFIG_CONTROL_VALUE_ACCESSOR],\n encapsulation: ViewEncapsulation.None\n})\nexport class DateTimeWidgetConfigureComponent implements OnInit, OnChanges, ControlValueAccessor {\n\n\n @HostBinding('attr.flex') flex = '';\n @HostBinding('attr.layout') flexLayout = 'column';\n @HostBinding('attr.layout-align') flexLayoutAlign = 'start';\n\n @Input() value: number = 0\n @Output() valueChange: EventEmitter<number> = new EventEmitter(false)\n\n @Input() labelPosition: 'before' | 'after' | 'below' = 'before'\n @Input() disabled: boolean = false\n\n /**\n * Configuration Fields\n */\n @Input() label: string = ''\n @Output() labelChange: EventEmitter<string> = new EventEmitter(false)\n\n @Input() defaultValue: number = Date.now()\n @Output() defaultValueChange: EventEmitter<number> = new EventEmitter(false)\n\n @Input() defaultToNow: boolean = false\n @Output() defaultToNowChange: EventEmitter<boolean> = new EventEmitter(false)\n\n @Output() change: EventEmitter<any> = new EventEmitter(false)\n\n /**\n * Called when the spinner is blurred. Needed to properly implement ControlValueAccessor.\n * @docs-private\n */\n onTouched: () => any = () => { };\n private controlValueAccessorChangeFn: (value: any) => void = (value) => { };\n\n\n constructor(private changeDetectorRef: ChangeDetectorRef) {\n }\n\n\n ngOnInit() {\n Hacks.materialDesignPlaceholderText(this.changeDetectorRef)\n }\n\n ngOnChanges(changes: { config: SimpleChange, ival: SimpleChange }) {\n }\n\n emitChangeEvent(value: boolean, label: boolean) {\n this.controlValueAccessorChangeFn(this.value);\n this.change.emit(new DateTimeWidgetConfigureChange(this, this.value))\n if (value) {\n this.valueChange.emit(this.value);\n this.defaultValueChange.emit(this.defaultValue)\n }\n if (label) {\n this.labelChange.emit(this.label)\n }\n }\n\n /**\n * Boilerplate / required for Angular\n *\n */\n public writeValue(value: number): void {\n this.value = value\n }\n\n public registerOnChange(fn: any): void {\n this.controlValueAccessorChangeFn = fn;\n }\n\n public registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n /**\n * Sets the input's disabled state. Implemented as a part of ControlValueAccessor.\n * @param isDisabled Whether the input should be disabled.\n */\n setDisabledState(isDisabled: boolean) {\n this.disabled = isDisabled;\n }\n}\n","import {\n ChangeDetectorRef,\n Component,\n EventEmitter,\n forwardRef,\n HostBinding,\n Input,\n OnChanges,\n OnInit,\n Output, SimpleChanges,\n ViewEncapsulation\n} from '@angular/core'\nimport {\n ControlValueAccessor,\n NG_VALUE_ACCESSOR\n} from '@angular/forms'\nimport {Hacks} from '@tangential/core'\n\n\n/**\n * Provider Expression that allows this widget to register as a ControlValueAccessor.\n * This allows it to support [(ngModel)].\n * @docs-private\n */\nexport const TANJ_NUMBER_SPINNER_WIDGET_VIEW_CONTROL_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => NumberSpinnerWidgetComponent),\n multi: true\n};\n\nexport class NumberSpinnerWidgetChange {\n\n constructor(public source: NumberSpinnerWidgetComponent, public value: number) {\n }\n}\n\n\n@Component({\n selector: 'tanj-number-spinner-widget',\n template: `<!-- -->\n <div flex\n class=\"tanj-input-template tanj-mode-edit\"\n [ngClass]=\"{'tanj-disabled': disabled}\"\n layout=\"row\" layout-align=\"center center\">\n <span *ngIf=\"!hideLabel && labelPosition == 'before'\" class=\"tanj-label tanj-before tanj-number-spinner-label\">{{label}}</span>\n <div flex class=\"tanj-widget-input\" layout=\"column\" layout-align=\"start center\">\n <div *ngIf=\"!onlyLabel\"\n class=\"tanj-input-spinner-field\"\n layout=\"column\"\n layout-align=\"start\"\n (swipeUp)=\"swipeUp($event)\"\n (swipeDown)=\"swipeDown($event)\">\n <tanj-icon align=\"center\"\n font=\"material-icons\"\n ligature=\"arrow_drop_up\"\n (click)=\"$event.stopPropagation(); $event.preventDefault(); onNextValueRequest()\"></tanj-icon>\n <div class=\"tanj-spinner-value tanj-previous \">{{previousValue() | number:'1.0-0'}}</div>\n <div *ngIf=\"!keyboardInputToggled\"\n class=\"tanj-spinner-value tanj-current\"\n (click)=\"onKeyboardInputRequest($event)\">{{value | number:'1.0-0'}}\n </div>\n <input *ngIf=\"keyboardInputToggled\"\n class=\"tanj-spinner-value tanj-current tanj-spinner-keyboard-input-toggled tanj-raw-input tanj-number\"\n type=\"number\"\n min=\"{{min}}\"\n max=\"{{max}}\"\n step=\"{{step}}\"\n [(ngModel)]=\"value\"\n autofocus\n (blur)=\"keyboardInputToggled = false\">\n <div class=\"tanj-spinner-value tanj-next\">{{nextValue() | number:'1.0-0'}}</div>\n <tanj-icon align=\"center\"\n font=\"material-icons\"\n ligature=\"arrow_drop_down\"\n (click)=\"$event.stopPropagation(); $event.preventDefault(); onPreviousValueRequest()\"></tanj-icon>\n </div>\n <span *ngIf=\"!hideLabel && labelPosition == 'below'\" class=\"tanj-label tanj-below tanj-number-spinner-label\">{{label}}</span>\n </div>\n <span *ngIf=\"!hideLabel && labelPosition == 'after'\"\n class=\"tanj-label tanj-after tanj-number-spinner-label\">{{label}}</span>\n </div>\n `,\n providers: [TANJ_NUMBER_SPINNER_WIDGET_VIEW_CONTROL_VALUE_ACCESSOR],\n encapsulation: ViewEncapsulation.None\n})\nexport class NumberSpinnerWidgetComponent implements OnInit, OnChanges, ControlValueAccessor {\n\n // turn this into a class\n @HostBinding('attr.flex') flex = '';\n @HostBinding('attr.layout') flexLayout = 'column';\n @HostBinding('attr.layout-align') flexLayoutAlign = 'start';\n\n @Input() value: number = 0\n @Output() valueChange: EventEmitter<number> = new EventEmitter(false)\n\n @Input() labelPosition: 'before' | 'after' | 'below' = 'before'\n @Input() disabled: boolean = false\n @Input() hideLabel: boolean = false\n @Input() onlyLabel: boolean = false\n\n /**\n * Configuration Fields\n */\n @Input() label: string = ''\n @Input() defaultValue: number = 0\n @Input() max: number = 10\n @Input() min: number = 0\n @Input() step: number = 1\n /* end Configuration Fields */\n\n @Output() change: EventEmitter<any> = new EventEmitter(false)\n\n keyboardInputToggled = false\n\n onTouched: () => any = () => { };\n private controlValueAccessorChangeFn: (value: any) => void = (value) => { };\n\n constructor(private changeDetectorRef: ChangeDetectorRef) {\n }\n\n\n ngOnInit() {\n Hacks.materialDesignPlaceholderText(this.changeDetectorRef)\n }\n\n ngOnChanges(changes: SimpleChanges) {\n }\n\n handleValueChange(value: number) {\n if (!this.disabled) {\n this.value = value\n this.valueChange.emit(this.value)\n this.emitChangeEvent()\n }\n }\n\n\n onPreviousValueRequest() {\n if (!this.disabled) {\n const v = this.previousValue()\n if (v !== null) {\n this.handleValueChange(v)\n }\n }\n }\n\n onNextValueRequest() {\n if (!this.disabled) {\n const v = this.nextValue()\n if (v !== null) {\n this.handleValueChange(v)\n }\n }\n }\n\n nextValue(): number {\n let v = this.value + this.step\n if (v > this.max) {\n v = this.max\n }\n return v\n }\n\n previousValue(): number {\n let v = this.value - this.step\n if (v < this.min) {\n v = this.min\n }\n return v\n }\n\n swipeUp(event: any) {\n this.onNextValueRequest()\n }\n\n swipeDown(event: any) {\n this.onPreviousValueRequest()\n }\n\n onKeyboardInputRequest(event: any) {\n this.keyboardInputToggled = this.disabled ? false : !this.keyboardInputToggled\n }\n\n\n /**\n * Boilerplate / required for Angular\n */\n private emitChangeEvent() {\n this.controlValueAccessorChangeFn(this.value);\n this.change.emit(new NumberSpinnerWidgetChange(this, this.value))\n }\n\n public writeValue(value: number): void {\n this.value = value\n }\n\n public registerOnChange(fn: any): void {\n this.controlValueAccessorChangeFn = fn;\n }\n\n public registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n /**\n * Sets the input's disabled state. Implemented as a part of ControlValueAccessor.\n * @param isDisabled Whether the input should be disabled.\n */\n setDisabledState(isDisabled: boolean) {\n this.disabled = isDisabled;\n }\n}\n","import {Component, HostBinding, Inject, ViewEncapsulation} from '@angular/core'\nimport {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'\nimport {DurationPickerFieldsState, DurationPickerState} from './duration-picker-state'\n\nexport class DurationPickerDialogResult {\n success: boolean = false\n millis: number = 0\n}\n\n@Component({\n selector: 'duration-picker-dialog',\n templateUrl: './duration-picker-dialog.html',\n encapsulation: ViewEncapsulation.None\n})\nexport class DurationPickerDialog {\n\n @HostBinding('attr.flex') flex = '';\n @HostBinding('attr.layout') flexLayout = 'column';\n @HostBinding('attr.layout-align') flexLayoutAlign = 'start';\n\n\n state: DurationPickerState\n\n result = new DurationPickerDialogResult()\n\n\n constructor(public dialogRef: MatDialogRef<DurationPickerDialog>, @Inject(MAT_DIALOG_DATA) private data: any) {\n this.state = data.state\n }\n\n onValueChange(field: DurationPickerFieldsState) {\n console.log('DurationPickerDialog', 'onValueChange', field)\n }\n\n onCancelRequest() {\n this.dialogRef.close(this.result)\n }\n\n onOkRequest() {\n this.result.success = true\n this.result.millis = this.state.millis\n this.dialogRef.close(this.result)\n }\n}\n","<div flex class=\"tanj-duration-picker-dialog-body\" layout=\"column\" layout-align=\"start\">\n <div flex class=\"\" layout=\"row\" layout-align=\"space-around\">\n\n <tanj-number-spinner-widget flex *ngFor=\"let field of state.selectedFields()\"\n [(ngModel)]=\"field.value\"\n [label]=\"field.label\"\n [labelPosition]=\"'below'\"\n [max]=\"field.max\"\n [min]=\"0\"\n (change)=\"onValueChange(field)\"></tanj-number-spinner-widget>\n </div>\n</div>\n<div layout=\"column\" layout-align=\"end\">\n <div flex class='tanj-button-footer' layout=\"row\" layout-align=\"center\">\n <a flex mat-raised-button color=\"accent\" class=\"tanj-cancel\" (click)=\"onCancelRequest()\">Cancel</a>\n <a flex mat-raised-button color=\"primary\" class=\"tanj-ok\" (click)=\"onOkRequest()\">Set</a>\n </div>\n</div>\n\n","import {\n ObjMap,\n TimeUnit,\n TimeUnits\n} from '@tangential/core'\nimport {Duration} from 'moment'\nimport * as moment from 'moment/moment'\nexport class DurationPickerFieldsState {\n index: number = 0\n unit: TimeUnit = TimeUnits.h\n selected: boolean = false\n next: DurationPickerFieldsState | undefined\n previous: DurationPickerFieldsState | undefined\n\n constructor(public picker: DurationPickerState, unit: TimeUnit) {\n this.unit = unit\n this.selected = false\n }\n\n get label(): string {\n return this.unit.label\n }\n\n canSelect(): boolean {\n let can: boolean\n const count = this.picker.selectedCount()\n if (count >= 3) {\n can = false\n } else if (count === 0) {\n can = true\n } else {\n can = this.previous?.selected || this.next?.selected || false\n }\n return can\n }\n\n canDeselect(): boolean {\n /* If next and previous are selected then you cannot deselect this one. */\n return (!this.previous || !this.next || !this.previous.selected || !this.next.selected)\n }\n\n canToggleSelection() {\n return this.selected ? this.canDeselect() : this.canSelect()\n }\n\n\n get value(): number {\n let result: number\n if (this.previous && this.previous.selected) {\n result = this.picker.duration.get(this.unit.momentKey)\n } else {\n result = this.picker.duration.as(this.unit.momentKey)\n }\n return Math.floor(result)\n }\n\n set value(val: number) {\n if (val >= 0) {\n const prev = this.value\n this.picker.duration.add(val - prev, this.unit.momentKey)\n }\n }\n\n get separator(): string {\n return this.unit.separatorSuffix\n }\n\n get max(): number {\n return (this.previous && this.previous.selected) ? this.unit.logicalMax : 9999\n }\n}\n/** @todo: ggranum: Remove use of MomentJS if possible. */\nexport class DurationPickerState {\n\n public fields: DurationPickerFieldsState[] = []\n fieldsByKey: ObjMap<DurationPickerFieldsState> = {}\n duration: Duration = moment.duration(0)\n max: number = 100\n\n\n constructor() {\n this.fields = [\n new DurationPickerFieldsState(this, TimeUnits.day), new DurationPickerFieldsState(this, TimeUnits.h),\n new DurationPickerFieldsState(this, TimeUnits.min), new DurationPickerFieldsState(this, TimeUnits.s),\n new DurationPickerFieldsState(this, TimeUnits.ms), ]\n for (let i = 0; i < this.fields.length; i++) {\n const f = this.fields[i]\n f.next = this.fields[i + 1]\n f.previous = this.fields[i - 1]\n f.index = i\n this.fieldsByKey[f.unit.unitKey] = f\n\n }\n }\n\n selectedFields(): DurationPickerFieldsState[] {\n return this.fields.filter(f => f.selected)\n }\n\n selectedCount(): number {\n return this.selectedFields().length\n }\n\n\n setDuration(duration: Duration) {\n this.duration = duration\n }\n\n select(unit: TimeUnit) {\n this.fieldsByKey[unit.unitKey].selected = true\n }\n\n get millis(): number {\n return this.duration.asMilliseconds()\n }\n}\n","import {\n ChangeDetectorRef,\n Component,\n EventEmitter,\n forwardRef,\n HostBinding,\n Input,\n OnChanges,\n OnInit,\n Output,\n SimpleChange,\n ViewEncapsulation\n} from '@angular/core'\nimport {\n ControlValueAccessor,\n NG_VALUE_ACCESSOR\n} from '@angular/forms'\nimport {MatDialog} from '@angular/material/dialog';\nimport {\n Hacks,\n TimeUnits\n} from '@tangential/core'\nimport moment from 'moment'\nimport {\n DurationPickerDialog,\n DurationPickerDialogResult\n} from './duration-picker-dialog'\nimport {DurationPickerState} from './duration-picker-state'\n\n\n/**\n * Provider Expression that allows this widget to register as a ControlValueAccessor.\n * This allows it to support [(ngModel)].\n * @docs-private\n */\nexport const TANJ_DURATION_PICKER_WIDGET_VIEW_CONTROL_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => DurationPickerWidgetComponent),\n multi: true\n};\n\nexport class DurationPickerWidgetChange {\n\n constructor(public source: DurationPickerWidgetComponent, public value: number) {\n }\n}\n\n\nexport interface DurationFieldConfig {\n unitKey: string\n showing: boolean\n showingNext: boolean\n separator?: string\n label: string\n max: number\n value: number\n}\n@Component({\n selector: 'tanj-duration-picker-widget',\n template: `<!-- -->\n <div flex\n class=\"tanj-input-template tanj-mode-edit\"\n [ngClass]=\"{'tanj-disabled': disabled}\"\n layout=\"row\"\n layout-align=\"start center\"\n (click)=\"showEditDialog()\">\n <span *ngIf=\"!hideLabel && labelPosition == 'before'\"\n class=\"tanj-label tanj-icon-rating-widget-label\">{{label}}</span>\n <div flex class=\"tanj-widget-input\" layout=\"column\" layout-align=\"start center\">\n <div *ngIf=\"!onlyLabel\"\n class=\"tanj-widget-input\"\n layout=\"row\"\n layout-align=\"start\">\n\n <ng-container *ngFor=\"let field of state.fields\">\n <span *ngIf=\"field.selected\">{{field.value | number:'2.0-0'}}<span\n *ngIf=\"field.next?.selected\">{{field.separator || ':'}}</span></span>\n </ng-container>\n\n </div>\n <span *ngIf=\"!hideLabel && labelPosition == 'below'\" class=\"tanj-label tanj-below\">{{label}}</span>\n </div>\n <span *ngIf=\"!hideLabel && labelPosition == 'after'\" class=\"tanj-label tanj-after tanj-icon-rating-widget-label\">{{label}}</span>\n </div>\n\n `,\n providers: [TANJ_DURATION_PICKER_WIDGET_VIEW_CONTROL_VALUE_ACCESSOR],\n encapsulation: ViewEncapsulation.None\n})\nexport class DurationPickerWidgetComponent implements OnInit, OnChanges, ControlValueAccessor {\n\n // turn this into a class\n @HostBinding('attr.flex') flex = '';\n @HostBinding('attr.layout') flexLayout = 'column';\n @HostBinding('attr.layout-align') flexLayoutAlign = 'start';\n\n @Input() value: number = 0\n @Output() valueChange: EventEmitter<number> = new EventEmitter(false)\n\n @Input() labelPosition: 'before' | 'after' | 'below' = 'before'\n @Input() disabled: boolean = false\n @Input() hideLabel: boolean = false\n @Input() onlyLabel: boolean = false\n\n /**\n * Configuration Fields\n */\n @Input() label: string = ''\n @Input() defaultValue: number = 0\n /* end Configuration Fields */\n\n @Input() max: number = 10\n\n @Input() showDays: boolean = false\n @Input() showHours: boolean = false\n @Input() showMinutes: boolean = false\n @Input() showSeconds: boolean = false\n @Input() showMilliseconds: boolean = false\n\n @Output() change: EventEmitter<any> = new EventEmitter(false)\n\n state: DurationPickerState = new DurationPickerState()\n\n onTouched: () => any = () => { };\n private controlValueAccessorChangeFn: (value: any) => void = (value) => { };\n\n constructor(private changeDetectorRef: ChangeDetectorRef, private dialog: MatDialog) {\n }\n\n ngOnInit() {\n Hacks.materialDesignPlaceholderText(this.changeDetectorRef)\n }\n\n\n public ngOnChanges(changes: { value: SimpleChange }): void {\n if (changes.value) {\n this.state.setDuration(moment.duration(this.value))\n }\n this.updateFields()\n }\n\n private updateFields() {\n if (this.showDays) {\n this.state.select(TimeUnits.day)\n }\n if (this.showHours) {\n this.state.select(TimeUnits.h)\n }\n if (this.showMinutes) {\n this.state.select(TimeUnits.min)\n }\n if (this.showSeconds) {\n this.state.select(TimeUnits.s)\n }\n if (this.showMilliseconds) {\n this.state.select(TimeUnits.ms)\n }\n }\n\n\n showEditDialog() {\n const dialogRef = this.dialog.open(DurationPickerDialog, {\n disableClose: true,\n data: {state: this.state}\n })\n dialogRef.afterClosed().subscribe((result: DurationPickerDialogResult) => {\n if (result.success) {\n this.value = result.millis\n this.changeDetectorRef.detectChanges()\n this.emitChangeEvent()\n }\n })\n }\n\n\n private emitChangeEvent() {\n this.controlValueAccessorChangeFn(this.value);\n this.change.emit(new DurationPickerWidgetChange(this, this.value))\n this.valueChange.emit(this.value)\n console.log('DurationPickerWidgetComponent', 'emitChangeEvent')\n }\n\n /**\n * Boilerplate / required for Angular\n *\n */\n public writeValue(value: number): void {\n this.value = value\n }\n\n public registerOnChange(fn: any): void {\n this.controlValueAccessorChangeFn = fn;\n }\n\n public registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n /**\n * Sets the input's disabled state. Implemented as a part of ControlValueAccessor.\n * @param isDisabled Whether the input should be disabled.\n */\n setDisabledState(isDisabled: boolean) {\n this.disabled = isDisabled;\n }\n}\n\n","import {\n ChangeDetectorRef,\n Component,\n EventEmitter,\n forwardRef,\n HostBinding,\n Input,\n OnChanges,\n OnInit,\n Output,\n SimpleChange,\n ViewEncapsulation\n} from '@angular/core'\nimport {\n ControlValueAccessor,\n NG_VALUE_ACCESSOR\n} from '@angular/forms'\nimport {\n Hacks,\n TimeUnits\n} from '@tangential/core'\nimport moment from 'moment'\nimport {DurationPickerState} from './duration-picker-state'\n\n\n/**\n * Provider Expression that allows IconRatingWidget to register as a ControlValueAccessor.\n * This allows it to support [(ngModel)].\n * @docs-private\n */\nexport const TANJ_DURATION_WIDGET_CONFIG_CONTROL_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => DurationPickerWidgetConfigureComponent),\n multi: true\n};\n\nexport class DurationPickerWidgetConfigureChange {\n constructor(public source: DurationPickerWidgetConfigureComponent, public value: number) {\n }\n}\n\n\n@Component({\n selector: 'tanj-duration-picker-widget-configure',\n template: `<!-- -->\n <div class=\"tanj-input-template tanj-mode-configure\" flex layout=\"column\" layout-align=\"start\">\n <mat-form-field dividerColor=\"accent\">\n <input matInput\n class=\"tanj-input\"\n type=\"text\"\n maxlength=\"50\"\n placeholder=\"Enter a label for this input\"\n (change)=\"labelChange.emit(label)\"\n [(ngModel)]=\"label\"/>\n </mat-form-field>\n\n <ng-container *ngIf=\"label\">\n <fieldset flex layout=\"row\" layout-align=\"start\">\n <legend>For:</legend>\n <div flex class=\"tanj-choose-duration-fields-container\" layout=\"column\" layout-align=\"start\">\n <mat-checkbox *ngFor=\"let field of state.fields\"\n layout=\"row\" layout-align=\"start\"\n [disabled]=\"!field.canToggleSelection()\"\n [labelPosition]=\"'before'\"\n [checked]=\"field.selected\"\n (change)=\"field.selected = $event.checked\">\n {{field.unit.fullLabel}}\n </mat-checkbox>\n </div>\n </fieldset>\n\n <tanj-duration-picker-widget\n [(value)]=\"defaultValue\"\n (valueChange)=\"value = defaultValue; valueChange.emit(value); defaultValueChange.emit(defaultValue)\"\n [defaultValue]=\"defaultValue\"\n [showDays]=\"showDays\"\n [showHours]=\"showHours\"\n [showMinutes]=\"showMinutes\"\n [showSeconds]=\"showSeconds\"\n [showMilliseconds]=\"showMilliseconds\"\n [max]=\"max\"\n label=\"Default Value\"\n [labelPosition]=\"'before'\">\n </tanj-duration-picker-widget>\n </ng-container>\n\n </div>\n `,\n providers: [TANJ_DURATION_WIDGET_CONFIG_CONTROL_VALUE_ACCESSOR],\n encapsulation: ViewEncapsulation.None\n})\nexport class DurationPickerWidgetConfigureComponent implements OnInit, OnChanges, ControlValueAccessor {\n\n\n @HostBinding('attr.flex') flex = '';\n @HostBinding('attr.layout') flexLayout = 'column';\n @HostBinding('attr.layout-align') flexLayoutAlign = 'start';\n\n @Input() value: number = 0\n @Output() valueChange: EventEmitter<number> = new EventEmitter(false)\n\n @Input() labelPosition: 'before' | 'after' | 'below' = 'before'\n @Input() disabled: boolean = false\n\n /**\n * Configuration Fields\n */\n @Input() label: string = ''\n @Output() labelChange: EventEmitter<string> = new EventEmitter(false)\n\n @Input() defaultValue: number = 0\n @Output() defaultValueChange: EventEmitter<number> = new EventEmitter(false)\n\n @Input() max: number = 100\n @Output() maxChange: EventEmitter<number> = new EventEmitter(false)\n\n @Input() showDays: boolean = false\n @Output() showDaysChange: EventEmitter<boolean> = new EventEmitter(false)\n\n @Input() showHours: boolean = false\n @Output() showHoursChange: EventEmitter<boolean> = new EventEmitter(false)\n\n @Input() showMinutes: boolean = false\n @Output() showMinutesChange: EventEmitter<boolean> = new EventEmitter(false)\n\n @Input() showSeconds: boolean = false\n @Output() showSecondsChange: EventEmitter<boolean> = new EventEmitter(false)\n\n @Input() showMilliseconds: boolean = false\n @Output() showMillisecondsChange: EventEmitter<boolean> = new EventEmitter(false)\n\n /* end Configuration Fields */\n\n state: DurationPickerState = new DurationPickerState()\n\n @Output() change: EventEmitter<any> = new EventEmitter(false)\n\n /**\n * Called when the spinner is blurred. Needed to properly implement ControlValueAccessor.\n * @docs-private\n */\n onTouched: () => any = () => { };\n private controlValueAccessorChangeFn: (value: any) => void = (value) => { };\n\n constructor(private changeDetectorRef: ChangeDetectorRef) {\n }\n\n\n ngOnInit() {\n Hacks.materialDesignPlaceholderText(this.changeDetectorRef)\n }\n\n ngOnChanges(changes: { value: SimpleChange }) {\n if (changes.value) {\n this.state.setDuration(moment.duration(this.value))\n }\n this.updateFields()\n }\n\n private updateFields() {\n if (this.showDays) {\n this.state.select(TimeUnits.day)\n }\n if (this.showHours) {\n this.state.select(TimeUnits.h)\n }\n if (this.showMinutes) {\n this.state.select(TimeUnits.min)\n }\n if (this.showSeconds) {\n this.state.select(TimeUnits.s)\n }\n if (this.showMilliseconds) {\n this.state.select(TimeUnits.ms)\n }\n }\n\n\n emitChangeEvent() {\n this.controlValueAccessorChangeFn(this.value);\n this.change.emit(new DurationPickerWidgetConfigureChange(this, this.value))\n }\n\n /**\n * Boilerplate / required for Angular\n *\n */\n public writeValue(value: number): void {\n this.value = value\n }\n\n public registerOnChange(fn: any): void {\n this.controlValueAccessorChangeFn = fn;\n }\n\n public registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n /**\n * Sets the input's disabled state. Implemented as a part of ControlValueAccessor.\n * @param isDisabled Whether the input should be disabled.\n */\n setDisabledState(isDisabled: boolean) {\n this.disabled = isDisabled;\n }\n}\n\n","import {\n ChangeDetectorRef,\n Component,\n EventEmitter,\n forwardRef,\n HostBinding,\n Input,\n OnChanges,\n OnInit,\n Output,\n SimpleChange,\n ViewEncapsulation\n} from '@angular/core'\nimport {\n ControlValueAccessor,\n NG_VALUE_ACCESSOR\n} from '@angular/forms'\nimport {IconIF} from '@tangential/components'\nimport {Hacks} from '@tangential/core'\n\n\n/**\n * Provider Expression that allows this widget to register as a ControlValueAccessor.\n * This allows it to support [(ngModel)].\n * @docs-private\n */\nexport const TANJ_ICON_RATING_WIDGET_VIEW_CONTROL_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => IconRatingWidgetComponent),\n multi: true\n};\n\nexport class IconRatingWidgetChange {\n\n constructor(public source: IconRatingWidgetComponent, public value: number) {\n }\n}\n\n\n@Component({\n selector: 'tanj-icon-rating-widget',\n template: `<!-- -->\n <div flex\n class=\"tanj-input-template tanj-mode-edit\"\n [ngClass]=\"{'tanj-disabled': disabled}\"\n layout=\"row\"\n layout-align=\"center center\">\n <span *ngIf=\"!hideLabel && labelPosition == 'before'\"\n class=\"tanj-label tanj-icon-rating-widget-label\">{{label}}</span>\n <div flex class=\"tanj-widget-input\" layout=\"column\" layout-align=\"start center\">\n <div *ngIf=\"!onlyLabel\"\n class=\"tanj-icon-rating-stars tanj-widget-input\"\n layout=\"column\"\n layout-align=\"start\"\n (swipeRight)=\"swipeRight($event)\"\n (swipeLeft)=\"swipeLeft($event)\">\n\n <div flex class=\"tanj-icon-rating-icons-container\" layout=\"row\" layout-align=\"start\">\n <tanj-icon *ngFor=\"let icon of icons; let idx = index\" [icon]=\"icon\" (click)=\"onIconClick(idx)\"></tanj-icon>\n </div>\n\n </div>\n <span *ngIf=\"!hideLabel && labelPosition == 'below'\" class=\"tanj-label tanj-below\">{{label}}</span>\n </div>\n <span *ngIf=\"!hideLabel && labelPosition == 'after'\" class=\"tanj-label tanj-after tanj-icon-rating-widget-label\">{{label}}</span>\n </div>\n `,\n providers: [TANJ_ICON_RATING_WIDGET_VIEW_CONTROL_VALUE_ACCESSOR],\n encapsulation: ViewEncapsulation.None\n})\nexport class IconRatingWidgetComponent implements ControlValueAccessor, OnInit, OnChanges {\n\n // turn this into a class\n @HostBinding('attr.flex') flex = '';\n @HostBinding('attr.layout') flexLayout = 'column';\n @HostBinding('attr.layout-align') flexLayoutAlign = 'start';\n\n @Input() value: number = 0\n @Output() valueChange: EventEmitter<number> = new EventEmitter(false)\n\n @Input() labelPosition: 'before' | 'after' | 'below' = 'before'\n @Input() disabled: boolean = false\n @Input() hideLabel: boolean = false\n @Input() onlyLabel: boolean = false\n\n /**\n * Configuration Fields\n */\n @Input() label: string = ''\n @Input() defaultValue: number = 0\n @Input() max: number = 5\n @Input() iconFont: string | undefined\n @Input() offIconNames: string[] = []\n @Input() onIconNames: string[] = []\n /* end Configuration Fields */\n\n @Output() change: EventEmitter<any> = new EventEmitter(false)\n\n icons: IconIF[] = []\n\n onTouched: () => any = () => { };\n private controlValueAccessorChangeFn: (value: any) => void = (value) => { };\n\n\n constructor(private changeDetectorRef: ChangeDetectorRef) {\n }\n\n\n ngOnInit() {\n Hacks.materialDesignPlaceholderText(this.changeDetectorRef)\n }\n\n ngOnChanges(changes: { config: SimpleChange, ival: SimpleChange }) {\n if (this.max && this.iconFont && this.offIconNames && this.onIconNames) {\n this.icons = []\n for (let i = 0; i < this.max; i++) {\n const icon: IconIF = {\n font: this.iconFont,\n name: i <= this.value ? this.onIconNames[0] : this.offIconNames[0]\n // star star_border\n }\n this.icons.push(icon)\n }\n }\n }\n\n\n onIconClick(idx: number) {\n if (!this.disabled) {\n this.value = idx\n this.valueChange.emit(this.value)\n }\n }\n\n\n swipeRight(event: any) {\n }\n\n swipeLeft(event: any) {\n }\n\n\n emitChangeEvent() {\n this.controlValueAccessorChangeFn(this.value);\n this.change.emit(new IconRatingWidgetChange(this, this.value))\n }\n\n /**\n * Boilerplate / required for Angular\n *\n */\n public writeValue(value: number): void {\n this.value = value\n }\n\n public registerOnChange(fn: any): void {\n this.controlValueAccessorChangeFn = fn;\n }\n\n public registerOnTouched(fn: any): void {\n this.onTouched = fn;\n }\n\n /**\n * Sets the input's disabled state. Implemented as a part of ControlValueAccessor.\n * @param isDisabled Whether the input should be disabled.\n */\n setDisabledState(isDisabled: boolean) {\n this.disabled = isDisabled;\n }\n}\n","import {\n ChangeDetectorRef,\n Component,\n EventEmitter,\n forwardRef,\n HostBinding,\n Input,\n OnInit,\n Output,\n ViewEncapsulation\n} from '@angular/core'\nimport {\n ControlValueAccessor,\n NG_VALUE_ACCESSOR\n} from '@angular/forms'\nimport {Hacks} from '@tangential/core'\n\n\n/**\n * Provider Expression that allows IconRatingWidget to register as a ControlValueAccessor.\n * This allows it to support [(ngModel)].\n * @docs-private\n */\nexport const TANJ_ICON_RATING_WIDGET_CONFIG_CONTROL_VALUE_ACCESSOR: any = {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => IconRatingWidgetConfigureComponent),\n multi: true\n};\n\nexport class IconRatingWidgetConfigureChange {\n constructor(public source: IconRatingWidgetConfigureComponent, public value: number) {\n }\n}\n\n\n@Component({\n selector: 'tanj-icon-rating-widget-configure',\n template: `<!-- -->\n <div class=\"tanj-input-template tanj-mode-configure\" flex layout=\"column\" layout-align=\"start\">\n <mat-form-field dividerColor=\"accent\">\n <input matInput\n class=\"tanj-input\"\n type=\"text\"\n maxlength=\"50\"\n placeholder=\"Enter a label for this input\"\n (change)=\"labelChange.emit(label)\"\n [(ngModel)]=\"label\"/>\n