UNPKG

@inaccess-fang/ui-components

Version:

The Inaccess UI Components Library for the Front-end projects

1,061 lines (1,009 loc) 45.3 kB
import { Component, ViewEncapsulation, ChangeDetectionStrategy, Input, EventEmitter, ChangeDetectorRef, ContentChildren, Output, NgModule, Directive, HostBinding, ElementRef, HostListener, ComponentFactoryResolver, ViewContainerRef } from '@angular/core'; import { CommonModule } from '@angular/common'; import { HttpClientModule } from '@angular/common/http'; import { filter } from 'rxjs/operators'; import { ScrollDispatcher } from '@angular/cdk/overlay'; import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; import { FormsModule, NgModel } from '@angular/forms'; import tippy from 'tippy.js'; import { ReplaySubject, fromEvent, combineLatest } from 'rxjs'; import Popper from 'popper.js'; // @angular/core class FangTabComponent { constructor() { this.active = false; } // Ovveride ngOnInit() { console.log('FangTabComponent [ngOnInit]'); } } FangTabComponent.decorators = [ { type: Component, args: [{ selector: 'fang-tab', template: "<div [hidden]=\"!active\">\n\t<ng-content></ng-content>\n</div>\n", encapsulation: ViewEncapsulation.ShadowDom, changeDetection: ChangeDetectionStrategy.Default, styles: [":host{display:block;height:inherit}"] },] } ]; FangTabComponent.ctorParameters = () => []; FangTabComponent.propDecorators = { title: [{ type: Input, args: ['tabTitle',] }] }; // @angular/core class FangMultiTabsComponent { constructor(_changeDetectorRef) { this._changeDetectorRef = _changeDetectorRef; this.selectedTabChanged = new EventEmitter(); } // @Override ngOnInit() { console.log('FangMultiTabsComponent [ngOnInit]'); } // @Override ngAfterViewInit() { // Set initial active tab if (this.tabs.length && !this.tabs.first.active) { this.selectTab(this.tabs.first); } // Set selected Tab after each time child view changes on a single lifecycle this._changesSubscription$ = this.tabs.changes .pipe(filter((change) => change.first)) .subscribe(() => this.selectTab(this.tabs.first)); } // @Override ngOnDestroy() { this._changesSubscription$.unsubscribe(); } selectTab(tab) { console.log('FangMultiTabsComponent [selectTab]'); this.tabs.toArray().map(tab => tab.active = false); tab.active = true; this.selectedTabChanged.emit(); this._changeDetectorRef.detectChanges(); } } FangMultiTabsComponent.decorators = [ { type: Component, args: [{ selector: 'fang-multi-tabs', template: "<ul class=\"fang-multi-tabs\">\n\t<li *ngFor=\"let tab of tabs.toArray()\"\n\t\t[class.fang-tab-active]=\"tab.active\"\n\t\t(click)=\"selectTab(tab)\"\n\t\tclass=\"fang-tab\">\n\t\t<a class=\"fang-tab-header\">{{tab.title}}</a>\n\t</li>\n</ul>\n<ng-content></ng-content>\n", changeDetection: ChangeDetectionStrategy.Default, styles: [".fang-multi-tabs{display:flex;margin:0 8px;padding:0}.fang-tab{border-bottom:2px solid #ceeaf2;display:inline-flex;flex-grow:1;justify-content:space-around;padding:6px}.fang-tab-active,.fang-tab:focus{outline-color:transparent}.fang-tab-active{border-bottom:2px solid #519eae}.fang-tab-header{color:#6a6a6a;cursor:pointer;font-size:.85em;font-weight:600;text-transform:uppercase}"] },] } ]; FangMultiTabsComponent.ctorParameters = () => [ { type: ChangeDetectorRef } ]; FangMultiTabsComponent.propDecorators = { tabs: [{ type: ContentChildren, args: [FangTabComponent,] }], selectedTabChanged: [{ type: Output }] }; // @angular/core class FangMultiTabsModule { } FangMultiTabsModule.decorators = [ { type: NgModule, args: [{ declarations: [ FangMultiTabsComponent, FangTabComponent ], imports: [ CommonModule, HttpClientModule ], exports: [ FangMultiTabsComponent, FangTabComponent ], providers: [] },] } ]; // @angular/core class FangViewportAutoResizeDirective { constructor(cdkVirtualScrollViewport) { this.cdkVirtualScrollViewport = cdkVirtualScrollViewport; const ResizeObserver = window.ResizeObserver; if (ResizeObserver) { this.resizeObserver = new ResizeObserver(() => this.cdkVirtualScrollViewport.checkViewportSize()); this.resizeObserver.observe(this.cdkVirtualScrollViewport.elementRef.nativeElement); } } ngOnDestroy() { this.resizeObserver && this.resizeObserver.disconnect(); this.resizeObserver = null; } } FangViewportAutoResizeDirective.decorators = [ { type: Directive, args: [{ selector: 'cdk-virtual-scroll-viewport[viewport-auto-resize], fang-table-virtual-scroll-viewport[viewport-auto-resize]' },] } ]; FangViewportAutoResizeDirective.ctorParameters = () => [ { type: CdkVirtualScrollViewport } ]; // @angular/core const EXPORTED_DECLARATIONS = [ FangViewportAutoResizeDirective ]; class FangVirtualScrollingModule { } FangVirtualScrollingModule.decorators = [ { type: NgModule, args: [{ declarations: EXPORTED_DECLARATIONS, imports: [], exports: EXPORTED_DECLARATIONS, providers: [ScrollDispatcher] },] } ]; // Current version. var VERSION = '1.11.0'; // Establish the root object, `window` (`self`) in the browser, `global` // on the server, or `this` in some virtual machines. We use `self` // instead of `window` for `WebWorker` support. var root = typeof self == 'object' && self.self === self && self || typeof global == 'object' && global.global === global && global || Function('return this')() || {}; // Save bytes in the minified (but not gzipped) version: var ArrayProto = Array.prototype, ObjProto = Object.prototype; var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null; // Create quick reference variables for speed access to core prototypes. var push = ArrayProto.push, slice = ArrayProto.slice, toString = ObjProto.toString, hasOwnProperty = ObjProto.hasOwnProperty; // Modern feature detection. var supportsArrayBuffer = typeof ArrayBuffer !== 'undefined'; // All **ECMAScript 5+** native function implementations that we hope to use // are declared here. var nativeIsArray = Array.isArray, nativeKeys = Object.keys, nativeCreate = Object.create, nativeIsView = supportsArrayBuffer && ArrayBuffer.isView; // Create references to these builtin functions because we override them. var _isNaN = isNaN, _isFinite = isFinite; // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. var hasEnumBug = !{ toString: null }.propertyIsEnumerable('toString'); var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; // The largest integer that can be represented exactly. var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; function _(obj) { if (obj instanceof _) return obj; if (!(this instanceof _)) return new _(obj); this._wrapped = obj; } _.VERSION = VERSION; // Extracts the result from a wrapped and chained object. _.prototype.value = function () { return this._wrapped; }; // Provide unwrapping proxies for some methods used in engine operations // such as arithmetic and JSON stringification. _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; _.prototype.toString = function () { return String(this._wrapped); }; // Keep the identity function around for default iteratees. function identity(value) { return value; } // Internal function for creating a `toString`-based type tester. function tagTester(name) { return function (obj) { return toString.call(obj) === '[object ' + name + ']'; }; } var isFunction = tagTester('Function'); // Optimize `isFunction` if appropriate. Work around some `typeof` bugs in old // v8, IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236). var nodelist = root.document && root.document.childNodes; if (typeof /./ != 'function' && typeof Int8Array != 'object' && typeof nodelist != 'function') { isFunction = function (obj) { return typeof obj == 'function' || false; }; } var isFunction$1 = isFunction; // Is a given variable an object? function isObject(obj) { var type = typeof obj; return type === 'function' || type === 'object' && !!obj; } // Is a given value an array? // Delegates to ECMA5's native `Array.isArray`. var isArray = nativeIsArray || tagTester('Array'); // An internal function for creating assigner functions. function createAssigner(keysFunc, defaults) { return function (obj) { var length = arguments.length; if (defaults) obj = Object(obj); if (length < 2 || obj == null) return obj; for (var index = 1; index < length; index++) { var source = arguments[index], keys = keysFunc(source), l = keys.length; for (var i = 0; i < l; i++) { var key = keys[i]; if (!defaults || obj[key] === void 0) obj[key] = source[key]; } } return obj; }; } // Internal function to check whether `key` is an own property name of `obj`. function has(obj, key) { return obj != null && hasOwnProperty.call(obj, key); } // Internal helper to create a simple lookup structure. // `collectNonEnumProps` used to depend on `_.contains`, but this led to // circular imports. `emulatedSet` is a one-off solution that only works for // arrays of strings. function emulatedSet(keys) { var hash = {}; for (var l = keys.length, i = 0; i < l; ++i) hash[keys[i]] = true; return { contains: function (key) { return hash[key]; }, push: function (key) { hash[key] = true; return keys.push(key); } }; } // Internal helper. Checks `keys` for the presence of keys in IE < 9 that won't // be iterated by `for key in ...` and thus missed. Extends `keys` in place if // needed. function collectNonEnumProps(obj, keys) { keys = emulatedSet(keys); var nonEnumIdx = nonEnumerableProps.length; var constructor = obj.constructor; var proto = isFunction$1(constructor) && constructor.prototype || ObjProto; // Constructor is a special case. var prop = 'constructor'; if (has(obj, prop) && !keys.contains(prop)) keys.push(prop); while (nonEnumIdx--) { prop = nonEnumerableProps[nonEnumIdx]; if (prop in obj && obj[prop] !== proto[prop] && !keys.contains(prop)) { keys.push(prop); } } } // Retrieve the names of an object's own properties. // Delegates to **ECMAScript 5**'s native `Object.keys`. function keys(obj) { if (!isObject(obj)) return []; if (nativeKeys) return nativeKeys(obj); var keys = []; for (var key in obj) if (has(obj, key)) keys.push(key); // Ahem, IE < 9. if (hasEnumBug) collectNonEnumProps(obj, keys); return keys; } // Assigns a given object with all the own properties in the passed-in // object(s). // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) var extendOwn = createAssigner(keys); // Returns whether an object has a given set of `key:value` pairs. function isMatch(object, attrs) { var _keys = keys(attrs), length = _keys.length; if (object == null) return !length; var obj = Object(object); for (var i = 0; i < length; i++) { var key = _keys[i]; if (attrs[key] !== obj[key] || !(key in obj)) return false; } return true; } // Returns a predicate for checking whether an object has a given set of // `key:value` pairs. function matcher(attrs) { attrs = extendOwn({}, attrs); return function (obj) { return isMatch(obj, attrs); }; } // Internal function to obtain a nested property in `obj` along `path`. function deepGet(obj, path) { var length = path.length; for (var i = 0; i < length; i++) { if (obj == null) return void 0; obj = obj[path[i]]; } return length ? obj : void 0; } // Normalize a (deep) property `path` to array. // Like `_.iteratee`, this function can be customized. function toPath(path) { return isArray(path) ? path : [path]; } _.toPath = toPath; // Internal wrapper for `_.toPath` to enable minification. // Similar to `cb` for `_.iteratee`. function toPath$1(path) { return _.toPath(path); } // Creates a function that, when passed an object, will traverse that object’s // properties down the given `path`, specified as an array of keys or indices. function property(path) { path = toPath$1(path); return function (obj) { return deepGet(obj, path); }; } function optimizeCb(func, context, argCount) { if (context === void 0) return func; switch (argCount == null ? 3 : argCount) { case 1: return function (value) { return func.call(context, value); }; // The 2-argument case is omitted because we’re not using it. case 3: return function (value, index, collection) { return func.call(context, value, index, collection); }; case 4: return function (accumulator, value, index, collection) { return func.call(context, accumulator, value, index, collection); }; } return function () { return func.apply(context, arguments); }; } // An internal function to generate callbacks that can be applied to each // element in a collection, returning the desired result — either `_.identity`, // an arbitrary callback, a property matcher, or a property accessor. function baseIteratee(value, context, argCount) { if (value == null) return identity; if (isFunction$1(value)) return optimizeCb(value, context, argCount); if (isObject(value) && !isArray(value)) return matcher(value); return property(value); } // External wrapper for our callback generator. Users may customize // `_.iteratee` if they want additional predicate/iteratee shorthand styles. // This abstraction hides the internal-only `argCount` argument. function iteratee(value, context) { return baseIteratee(value, context, Infinity); } _.iteratee = iteratee; // The function we call internally to generate a callback. It invokes // `_.iteratee` if overridden, otherwise `baseIteratee`. function cb(value, context, argCount) { if (_.iteratee !== iteratee) return _.iteratee(value, context); return baseIteratee(value, context, argCount); } // Common internal logic for `isArrayLike` and `isBufferLike`. function createSizePropertyCheck(getSizeProperty) { return function (collection) { var sizeProperty = getSizeProperty(collection); return typeof sizeProperty == 'number' && sizeProperty >= 0 && sizeProperty <= MAX_ARRAY_INDEX; }; } // Internal helper to generate a function to obtain property `key` from `obj`. function shallowProperty(key) { return function (obj) { return obj == null ? void 0 : obj[key]; }; } // Internal helper to obtain the `length` property of an object. var getLength = shallowProperty('length'); // Internal helper for collection methods to determine whether a collection // should be iterated as an array or as an object. // Related: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 var isArrayLike = createSizePropertyCheck(getLength); // Return the results of applying the iteratee to each element. function map(obj, iteratee, context) { iteratee = cb(iteratee, context); var _keys = !isArrayLike(obj) && keys(obj), length = (_keys || obj).length, results = Array(length); for (var index = 0; index < length; index++) { var currentKey = _keys ? _keys[index] : index; results[index] = iteratee(obj[currentKey], currentKey, obj); } return results; } // Convenience version of a common use case of `_.map`: fetching a property. function pluck(obj, key) { return map(obj, property(key)); } // Sort the object's values by a criterion produced by an iteratee. function sortBy(obj, iteratee, context) { var index = 0; iteratee = cb(iteratee, context); return pluck(map(obj, function (value, key, list) { return { value: value, index: index++, criteria: iteratee(value, key, list) }; }).sort(function (left, right) { var a = left.criteria; var b = right.criteria; if (a !== b) { if (a > b || a === void 0) return 1; if (a < b || b === void 0) return -1; } return left.index - right.index; }), 'value'); } class FangChipGroupComponent { constructor() { this.dataChange = new EventEmitter(); this.chipGroupDataChange = new EventEmitter(); } ngOnChanges(changes) { if (changes['data']) { this.cursor = this.config.interaction === 'select' ? 'pointer' : 'default'; this.chipGroupData = this.data.reduce((acc, data, index) => { let selected; if (this.config.interaction !== 'select') { selected = true; } else { selected = this.chipGroupData && this.chipGroupData[index] && this.chipGroupData[index].selected; } acc.push({ displayValue: this.config.propertyAccessKey ? data[this.config.propertyAccessKey] : data, selected }); return acc; }, []); this.chipGroupData = this.sortData(this.chipGroupData); this.chipGroupDataChange.emit(this.chipGroupData); } } removeChip(event, chip) { event.stopPropagation(); this.chipGroupData = this.chipGroupData.filter(chipData => chipData.displayValue !== chip.displayValue); this.chipGroupData = this.sortData(this.chipGroupData); const chipToRemove = this.data.filter(data => this.config.propertyAccessKey ? data[this.config.propertyAccessKey] === chip.displayValue : data === chip.displayValue)[0]; this.dataChange.emit(chipToRemove); this.chipGroupDataChange.emit(this.chipGroupData); } toggleChipSelection(chipIndex) { this.chipGroupData[chipIndex].selected = !this.chipGroupData[chipIndex].selected; } sortData(data) { return sortBy(data, ['displayValue']); } } FangChipGroupComponent.decorators = [ { type: Component, args: [{ selector: 'fang-chip-group', template: "<div *ngIf=\"chipGroupData && chipGroupData.length\"\n\t [ngClass]=\"{'no-wrap': config.hasWrap !== undefined && !config.hasWrap}\"\n\t class=\"{{config.alignment ? config.alignment: 'group-inline'}}\n\t {{config.chipGroupBackground}}\"\n>\n\t<div *ngFor=\"let chip of chipGroupData; let chipIndex = index\"\n\t\t [ngClass]=\"{'selected': chip.selected}\"\n\t\t class=\"{{config.chipBackground ? config.chipBackground : 'chip-light'}}\"\n\t\t (click)=\"config.interaction === 'select' && toggleChipSelection(chipIndex)\">\n\n\t\t<p [ngClass]=\"{'text-truncate-100': config.hasTextTruncate}\"\n\t\t title=\"{{chip.displayValue}}\" style=\"pointer-events: auto;\">\n\t\t\t{{chip.displayValue}}\n\t\t</p>\n\n\t\t<i *ngIf=\"config.interaction && config.interaction === 'close'\"\n\t\t class=\"ic-close\"\n\t\t style=\"pointer-events: auto !important\"\n\t\t (click)=\"removeChip($event,chip)\">\n\t\t</i>\n\t</div>\n</div>\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{max-height:650px}::-webkit-scrollbar{background-color:#fff;border:none;border-left:1px solid hsla(0,0%,88.6%,.4);width:12px}"] },] } ]; FangChipGroupComponent.propDecorators = { cursor: [{ type: HostBinding, args: ['style.cursor',] }], data: [{ type: Input }], config: [{ type: Input }], dataChange: [{ type: Output }], chipGroupDataChange: [{ type: Output }] }; class FangChipGroupModule { } FangChipGroupModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule ], exports: [ FangChipGroupComponent ], declarations: [ FangChipGroupComponent ], providers: [], entryComponents: [FangChipGroupComponent] },] } ]; class FangSearchComponent { constructor() { this.config = {}; this.filteredDataChange = new EventEmitter(); this.inputTextChange = new EventEmitter(); this.inputText = ''; } filterInputElements() { if (this.data) { this.filteredData = this.data .filter(e => { return this.inputText.toLowerCase().split(' ').every(keyword => { return (this.config.searchBy ? e[this.config.searchBy] : e).toString().toLowerCase().includes(keyword); }); }); this.filteredDataChange.emit(this.filteredData); } this.inputTextChange.emit(this.inputText); } clearInputText(event) { event && event.stopPropagation(); this.inputText = ''; this.filterInputElements(); } } FangSearchComponent.decorators = [ { type: Component, args: [{ selector: 'fang-search', template: "<div class=\"input\">\n\t<input type=\"text\"\n\t\t [(ngModel)]=\"inputText\"\n\t\t (ngModelChange)=\"filterInputElements()\"\n\t\t placeholder=\"{{config?.placeholder ? config.placeholder : 'Search...'}}\"/>\n\t<i class=\"ic-close \" *ngIf=\"inputText.length\"\n\t (click)=\"clearInputText($event)\"\n\t></i>\n</div>\n\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [""] },] } ]; FangSearchComponent.propDecorators = { data: [{ type: Input }], config: [{ type: Input }], filteredDataChange: [{ type: Output }], inputTextChange: [{ type: Output }] }; class FangSearchModule { } FangSearchModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule, FormsModule ], exports: [ FangSearchComponent ], declarations: [ FangSearchComponent ], providers: [], entryComponents: [FangSearchComponent] },] } ]; const dropdownTypeMap = { 'default': 'dropdown-wrapper', 'compact': 'dropdown-wrapper-sm', 'large': 'dropdown-wrapper-lg' }; class FangDropdownComponent { constructor() { this.config = {}; this.selectedItemsChanged = new EventEmitter(); this.isDropdownOpen = false; this.selectedItems = []; this.searchInputText = ''; } ngOnChanges(changes) { if (changes['data']) { if (this.config.hasChipGroup && this.config.chipGroupConfig) { this.config.chipGroupConfig.propertyAccessKey = this.config.propertyAccessKey; this.config.chipGroupConfig.interaction = 'close'; } // Transform dropdownData to string[] this.dropdownData = [...this.data].map((el) => { return this.getPropertyValue(el); }); this.filteredDropdownData = [...this.dropdownData]; this.filteredDropdownData = this.sortData(this.filteredDropdownData); } if (changes['config'].isFirstChange()) { if (!this.config.type) { this.config.type = 'default'; } if (this.config.isGrowable === undefined) { this.config.isGrowable = true; } if (this.config.isPortfolio) { this.config.hasContainer = false; this.config.chipGroupConfig.alignment = 'group-inline'; this.config.chipGroupConfig.chipBackground = undefined; } } } selectItem(item) { if (this.config.hasMultiSelect) { const isElementSelected = this.selectedItems.find((el) => this.getPropertyValue(el) === item); if (!isElementSelected) { this.selectedItems = [...this.selectedItems, this.data.find((el) => this.getPropertyValue(el) === item)]; } else { this.selectedItems = this.selectedItems.filter((el) => this.getPropertyValue(el) !== item); } // Chip Group & portfolio if (this.config.hasChipGroup && this.config.chipGroupConfig) { this.dropdownData = this.dropdownData.filter((el) => el !== item); this.filteredDropdownData = this.filteredDropdownData.filter((el) => el !== item); this.filteredDropdownData = this.sortData(this.filteredDropdownData); } this.selectedItemsChanged.emit(this.selectedItems); // TODO Tree implementation } else { // single select this.selectedItems = [this.data.find((el) => this.getPropertyValue(el) === item)]; this.isDropdownOpen = false; this.selectedItemsChanged.emit(this.selectedItems); } } toggleDropdown(arrowPressed = false, event = undefined) { event && event.stopPropagation(); if (arrowPressed || !this.config.hasChipGroup || (this.config.hasChipGroup && !this.selectedItems.length && !arrowPressed)) { this.isDropdownOpen = !this.isDropdownOpen; } } getPropertyValue(element) { return this.config.propertyAccessKey ? element[this.config.propertyAccessKey] : element; } isItemSelected(item) { return this.selectedItems.find((el) => this.getPropertyValue(el) === item); } removeChip(item) { this.selectedItems = this.selectedItems.filter((el) => el !== item); // re-add chip to list only if its not portfolio if (this.config.hasChipGroup && this.config.chipGroupConfig) { this.dropdownData = [...this.dropdownData, this.getPropertyValue(item)]; this.filteredDropdownData = [...this.filteredDropdownData, this.getPropertyValue(item)]; this.filteredDropdownData = this.sortData(this.filteredDropdownData); } } getConcatSelectedItems(items) { return items.map(item => this.getPropertyValue(item)).join(', '); } selectAll() { this.selectedItems = [...this.data]; if (this.config.hasChipGroup) { this.dropdownData = []; this.filteredDropdownData = []; } else { this.dropdownData = this.selectedItems.map((selectedItem) => { return this.getPropertyValue(selectedItem); }); } } clearAll() { this.selectedItems = []; if (this.config.hasChipGroup) { this.dropdownData = [...this.data].map((dataEl) => { return this.getPropertyValue(dataEl); }); this.filteredDropdownData = [...this.dropdownData]; this.filteredDropdownData = this.sortData(this.filteredDropdownData); } } proceedToSelection(item, event = undefined) { event && event.stopPropagation(); if (!!this.selectedItems.find((el) => this.getPropertyValue(el) === item) || (this.config.multiActions && this.config.multiActions.selectLimit && this.config.multiActions.selectLimit > this.selectedItems.length) || (this.config.multiActions && !this.config.multiActions.selectLimit) || !this.config.multiActions) { this.selectItem(item); } } sortData(data) { return sortBy(data); } getDropdownSize() { return dropdownTypeMap[this.config.type]; } totalSelectedItems() { if (this.config.titleConfig && this.config.titleConfig.isTitleConcatenated) { if (this.config.multiActions && this.config.multiActions.selectLimit) { return `${this.getConcatSelectedItems(this.selectedItems)} (${this.selectedItems.length}/${this.config.multiActions.selectLimit})`; } return `${this.getConcatSelectedItems(this.selectedItems)} (${this.selectedItems.length})`; } else { if (this.config.multiActions && this.config.multiActions.selectLimit) { return `Total Selected (${this.selectedItems.length}/${this.config.multiActions.selectLimit})`; } return `Total Selected (${this.selectedItems.length})`; } } } FangDropdownComponent.decorators = [ { type: Component, args: [{ selector: 'fang-dropdown', template: "<div uds-ui class=\"light-theme\" (clickOutsideElement)=\"isDropdownOpen=false\">\n\t<div class=\" {{getDropdownSize()}}\"\n\t\t [ngClass]=\"{'no-container ': config.hasContainer !== undefined && !config.hasContainer,\n\t\t\t\t\t 'reverse': config.isPortfolio,\n\t\t\t\t\t 'grow': config.isGrowable && !config.isPortfolio}\"\n\t\t style=\"margin: 0 12px\">\n\t\t<div class=\"input\" (click)=\"toggleDropdown(false)\">\n\n\t\t\t<!-- Single Item Select -->\n\t\t\t<ng-container *ngIf=\"!config.hasMultiSelect\">\n\t\t\t\t<p *ngIf=\"!selectedItems.length\" class=\"text-placeholder\">\n\t\t\t\t\t{{config.titleConfig && config.titleConfig.placeholder ? config.titleConfig.placeholder : 'Select item...'}}\n\t\t\t\t</p>\n\t\t\t\t<p *ngIf=\"selectedItems.length\">{{getPropertyValue(selectedItems[0])}}</p>\n\t\t\t</ng-container>\n\n\t\t\t<!-- Multi Item Select -->\n\t\t\t<ng-container *ngIf=\"config.hasMultiSelect\">\n\t\t\t\t<!-- CheckList -->\n\t\t\t\t<p *ngIf=\"!selectedItems.length && !config.isPortfolio\" class=\"text-placeholder\">\n\t\t\t\t\t{{config.titleConfig && config.titleConfig.placeholder ? config.titleConfig.placeholder : 'Select items...'}}\n\t\t\t\t</p>\n\n\t\t\t\t<!-- Multi Select title -->\n\t\t\t\t<ng-container *ngIf=\"selectedItems.length && !config.hasChipGroup\">\n\t\t\t\t\t<p>{{totalSelectedItems()}}</p>\n\t\t\t\t</ng-container>\n\n\t\t\t\t<!-- Portfolio title -->\n\t\t\t\t<ng-container *ngIf=\"!selectedItems.length && config.isPortfolio\">\n\t\t\t\t\t<p>PORTFOLIOS</p>\n\t\t\t\t</ng-container>\n\n\t\t\t\t<!-- Chip Group & Portfolio -->\n\t\t\t\t<fang-chip-group *ngIf=\"config.hasChipGroup && this.selectedItems.length\"\n\t\t\t\t\t\t\t\t [data]=\"this.selectedItems\"\n\t\t\t\t\t\t\t\t [config]=\"config.chipGroupConfig\"\n\t\t\t\t\t\t\t\t (dataChange)=\"removeChip($event)\">\n\t\t\t\t</fang-chip-group>\n\t\t\t</ng-container>\n\n\t\t\t<!-- Arrow\t-->\n\t\t\t<button class=\"btn-icon grow\" (click)=\"toggleDropdown(true,$event)\">\n\t\t\t\t<i [ngClass]=\"{'ic-caret-down-sm': !isDropdownOpen, 'ic-caret-up-sm': isDropdownOpen}\"></i>\n\t\t\t</button>\n\t\t</div>\n\n\t\t<div class=\"dropdown-container\">\n\t\t\t<!-- Multi Actions -->\n\t\t\t<div class=\"dropdown-header\">\n\t\t\t\t<div class=\"dropdown-header-select\" *ngIf=\"isDropdownOpen && config.hasMultiActions && config.multiActions\">\n\t\t\t\t\t<button *ngIf=\"config.multiActions.hasClearAll\"\n\t\t\t\t\t\t\t[disabled]=\"!selectedItems.length\"\n\t\t\t\t\t\t\tclass=\"btn-secondary-sm\"\n\t\t\t\t\t\t\t(click)=\"clearAll()\">\n\t\t\t\t\t\tclearAll\n\t\t\t\t\t</button>\n\t\t\t\t\t<button [disabled]=\"!(dropdownData && dropdownData.length && ((dropdownData.length <= config.multiActions.selectLimit) || config.multiActions.selectLimit === undefined))\n\t\t\t\t\t\t\t\t\t\t|| (selectedItems.length === dropdownData.length)\"\n\t\t\t\t\t\t\tclass=\"btn-primary-sm\"\n\t\t\t\t\t\t\t(click)=\"(selectedItems.length !== dropdownData.length) && selectAll()\">\n\t\t\t\t\t\tselectAll\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\n\t\t\t\t<!-- Search field -->\n\t\t\t\t<div *ngIf=\"config.hasSearchField\"\n\t\t\t\t\t [hidden]=\"!isDropdownOpen || !dropdownData.length\"\n\t\t\t\t\t class=\"dropdown-header-search\">\n\t\t\t\t\t<fang-search [data]=\"dropdownData\"\n\t\t\t\t\t\t\t\t [config]=\"config.searchFieldConfig\"\n\t\t\t\t\t\t\t\t (filteredDataChange)=\"filteredDropdownData = $event\"\n\t\t\t\t\t\t\t\t (inputTextChange)=\"searchInputText = $event\">\n\t\t\t\t\t</fang-search>\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<!-- Dropdown List\t-->\n\t\t\t<div class=\"dropdown-body\" *ngIf=\"isDropdownOpen\">\n\t\t\t\t<div *ngFor=\"let item of filteredDropdownData\"\n\t\t\t\t\t class=\"dropdown-option\"\n\t\t\t\t\t [ngClass]=\"{'select': config.hasMultiSelect && isItemSelected(item)}\"\n\t\t\t\t\t (click)=\"proceedToSelection(item,$event)\">\n\t\t\t\t\t<p>{{item}}</p>\n\t\t\t\t\t<i *ngIf=\"config.hasMultiSelect && isItemSelected(item)\" class=\"ic-check\"> </i>\n\t\t\t\t</div>\n\t\t\t\t<p *ngIf=\"!filteredDropdownData.length && searchInputText.length\" class=\"no-options\">No results found</p>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n", changeDetection: ChangeDetectionStrategy.OnPush, styles: [""] },] } ]; FangDropdownComponent.propDecorators = { data: [{ type: Input }], config: [{ type: Input }], selectedItemsChanged: [{ type: Output }] }; tippy.setDefaultProps({ ignoreAttributes: true, arrow: false, maxWidth: '300px', trigger: 'mouseenter', zIndex: 99999, }); class FangPopoverDirective { constructor(el) { this.el = el; } ngOnChanges(changes) { if (changes['options']) { if (this.options && !this.instance) { this.instance = tippy(this.el.nativeElement, this.options); } else if (this.options && this.instance) { this.instance.setProps(this.options); } else if ((!this.options || !this.options.content) && this.instance) { this.instance.destroy(); this.instance = undefined; } } if (changes['content'] && this.instance) { this.instance.setContent(this.content); } } ngOnDestroy() { this.instance && this.instance.destroy(); } } FangPopoverDirective.decorators = [ { type: Directive, args: [{ selector: '[fang-popover]' },] } ]; FangPopoverDirective.ctorParameters = () => [ { type: ElementRef } ]; FangPopoverDirective.propDecorators = { options: [{ type: Input, args: ['fang-popover',] }], content: [{ type: Input, args: ['content',] }] }; class FangPopoverModule { } FangPopoverModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule ], exports: [ FangPopoverDirective ], declarations: [ FangPopoverDirective ], providers: [], entryComponents: [] },] } ]; // @angular/core class ClickOutsideElementDirective { constructor(_elementRef) { this._elementRef = _elementRef; this.clickOutsideElement = new EventEmitter(); } onClick(event, targetElement) { if (!targetElement) { return; } const clickedInsideElement = this._elementRef.nativeElement.contains(targetElement); if (!clickedInsideElement) { this.clickOutsideElement.emit(event); } } } ClickOutsideElementDirective.decorators = [ { type: Directive, args: [{ selector: '[clickOutsideElement]' },] } ]; ClickOutsideElementDirective.ctorParameters = () => [ { type: ElementRef } ]; ClickOutsideElementDirective.propDecorators = { clickOutsideElement: [{ type: Output }], onClick: [{ type: HostListener, args: ['document:click', ['$event', '$event.target'],] }] }; class ClickOutsideElementModule { } ClickOutsideElementModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule ], exports: [ ClickOutsideElementDirective ], declarations: [ ClickOutsideElementDirective ], providers: [], entryComponents: [] },] } ]; class FangDirectivesModule { } FangDirectivesModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule, FangPopoverModule, ClickOutsideElementModule ], exports: [ FangPopoverModule, ClickOutsideElementModule ], declarations: [], providers: [], entryComponents: [] },] } ]; class FangDropdownModule { } FangDropdownModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule, FangChipGroupModule, FangSearchModule, FangDirectivesModule ], exports: [ FangDropdownComponent ], declarations: [ FangDropdownComponent ], providers: [], entryComponents: [FangDropdownComponent] },] } ]; class FangAutocompleteDropdownComponent { constructor() { this.onSelect = new EventEmitter(); } selectElement(element) { this.onSelect.emit(element); } } FangAutocompleteDropdownComponent.decorators = [ { type: Component, args: [{ selector: 'autocomplete-dropdown', template: "<div class=\"dropdown-list\">\n\t<div *ngFor=\"let el of dropdownElements; let i=index\"\n\t\t class=\"dropdown-item\"\n\t\t (click)=\"selectElement(el)\">\n\t\t{{el}}\n\t</div>\n</div>\n", styles: [":host{background-clip:padding-box;border:1px solid #bdbdc3;border-radius:4px;border-top:0;box-shadow:4px 4px 4px rgba(0,0,0,.12),0 1px 4px rgba(0,0,0,.24);display:block;flex-direction:column;margin:2px 0 2px 1px;overflow:hidden;z-index:9999999999}.dropdown-list,:host{background-color:#fff}.dropdown-list{flex-grow:1;height:100%;max-height:20vh;overflow-x:hidden;overflow-y:auto;position:relative;width:100%;will-change:transform,scroll-position}.dropdown-item{align-items:center;color:#333;cursor:pointer;display:flex;flex-direction:row;justify-content:space-between;padding:8px}.dropdown-item:hover{background-color:#f5f5f5}"] },] } ]; FangAutocompleteDropdownComponent.propDecorators = { dropdownElements: [{ type: Input }], onSelect: [{ type: Output }] }; class FangAutocompleteInputDirective { constructor(element, factoryResolver, viewContainerRef, _changeDetectorRef, ngModel) { this.element = element; this.factoryResolver = factoryResolver; this.viewContainerRef = viewContainerRef; this._changeDetectorRef = _changeDetectorRef; this.ngModel = ngModel; this.dropdownElements$ = new ReplaySubject(1); this.popperConfig = { placement: 'bottom', positionFixed: true, modifiers: { preventOverflow: { enabled: true, boundariesElement: 'window' }, setWidth: { enabled: true, order: 840, fn(data) { data.offsets.popper.left = data.offsets.reference.left; data.offsets.popper.right = data.offsets.reference.right; data.offsets.popper.width = data.styles.width = Math.round(data.offsets.reference.width); return data; } } } }; } set dropdownElements(dropdownElements) { this.dropdownElements$.next(dropdownElements || []); } ; ngOnInit() { fromEvent(document, "click", { passive: true }).pipe(filter(() => !!this.componentRef && this.componentRef.location.nativeElement.style.display !== 'none')) .subscribe((e) => { if (!this.element.nativeElement.contains(e.target)) { this.componentRef.location.nativeElement.style.display = 'none'; } }); this._changeDetectorRef.detectChanges(); } ngAfterContentInit() { if (this.ngModel) { this.input = this.ngModel.control; this.autocompleteSubscription = combineLatest(this.dropdownElements$.asObservable(), fromEvent(this.element.nativeElement, "focus", { passive: true }), fromEvent(this.element.nativeElement, "keyup", { passive: true })) .subscribe(([arr, input, input2]) => { console.log(arr, input, input2); if (!this.componentRef) { const factory = this.factoryResolver.resolveComponentFactory(FangAutocompleteDropdownComponent); this.componentRef = this.viewContainerRef.createComponent(factory); this.componentRef.location.nativeElement.style.display = 'none'; this.dropdownPopper = new Popper(this.element.nativeElement, this.componentRef.location.nativeElement, this.popperConfig); this.inputChangesSubscription = this.componentRef.instance.onSelect.subscribe(v => { this.input.setValue(v); }); } const inputValue = input.target.value; const lowerCaseInput = inputValue && inputValue.toLocaleLowerCase(); const array = arr.slice().filter(e => e.toLowerCase().startsWith(lowerCaseInput)); const lowerCaseArray = arr.slice().map(a => a.toLowerCase()).filter(e => e.startsWith(lowerCaseInput)); if (inputValue && inputValue.length > 0 && (lowerCaseArray.length > 1 || !lowerCaseArray.includes(lowerCaseInput))) { this.componentRef.location.nativeElement.style.display = 'block'; this.componentRef.instance.dropdownElements = array; this.componentRef.changeDetectorRef.detectChanges(); this.dropdownPopper.scheduleUpdate(); } else { this.componentRef.location.nativeElement.style.display = 'none'; } }); } this._changeDetectorRef.detectChanges(); } ngOnDestroy() { this.dropdownPopper && this.dropdownPopper.destroy(); this.autocompleteSubscription && this.autocompleteSubscription.unsubscribe(); this.inputChangesSubscription && this.inputChangesSubscription.unsubscribe(); } } FangAutocompleteInputDirective.decorators = [ { type: Directive, args: [{ selector: '[autoComplete][ngModel]' },] } ]; FangAutocompleteInputDirective.ctorParameters = () => [ { type: ElementRef }, { type: ComponentFactoryResolver }, { type: ViewContainerRef }, { type: ChangeDetectorRef }, { type: NgModel } ]; FangAutocompleteInputDirective.propDecorators = { dropdownElements: [{ type: Input, args: ['autoComplete',] }] }; class FangAutocompleteModule { } FangAutocompleteModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule, FormsModule ], exports: [ FangAutocompleteInputDirective ], declarations: [ FangAutocompleteDropdownComponent, FangAutocompleteInputDirective ], providers: [], entryComponents: [FangAutocompleteDropdownComponent] },] } ]; /* * Public API Surface of fang-ui-components */ /** * Generated bundle index. Do not edit. */ export { FangAutocompleteModule, FangChipGroupComponent, FangChipGroupModule, FangDropdownComponent, FangDropdownModule, FangMultiTabsComponent, FangMultiTabsModule, FangSearchComponent, FangSearchModule, FangTabComponent, FangViewportAutoResizeDirective, FangVirtualScrollingModule, FangDirectivesModule as ɵa, FangPopoverModule as ɵb, FangPopoverDirective as ɵc, ClickOutsideElementModule as ɵd, ClickOutsideElementDirective as ɵe, FangAutocompleteInputDirective as ɵf, FangAutocompleteDropdownComponent as ɵg }; //# sourceMappingURL=inaccess-fang-ui-components.js.map