(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('@wm/components/base'), require('@wm/components/basic/search'), require('@angular/forms'), require('@wm/core'), require('@wm/components/input'), require('lodash-es')) :
    typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@angular/common', '@wm/components/base', '@wm/components/basic/search', '@angular/forms', '@wm/core', '@wm/components/input', 'lodash-es'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.wm = global.wm || {}, global.wm.components = global.wm.components || {}, global.wm.components.input = global.wm.components.input || {}, global.wm.components.input.chips = {}), global.ng.core, global.ng.common, global.wm.components.base, global.wm.components.basic.search, global.ng.forms, global.wm.core, global.wm.components.input, global._));
})(this, (function (exports, i0, i1, i3, i2, forms, core, input, lodashEs) { 'use strict';

    function _interopNamespaceDefault(e) {
        var n = Object.create(null);
        if (e) {
            Object.keys(e).forEach(function (k) {
                if (k !== 'default') {
                    var d = Object.getOwnPropertyDescriptor(e, k);
                    Object.defineProperty(n, k, d.get ? d : {
                        enumerable: true,
                        get: function () { return e[k]; }
                    });
                }
            });
        }
        n.default = e;
        return Object.freeze(n);
    }

    var i0__namespace = /*#__PURE__*/_interopNamespaceDefault(i0);
    var i1__namespace = /*#__PURE__*/_interopNamespaceDefault(i1);
    var i3__namespace = /*#__PURE__*/_interopNamespaceDefault(i3);
    var i2__namespace = /*#__PURE__*/_interopNamespaceDefault(i2);

    const chipsProps = new Map([
        ['allowonlyselect', i3.PROP_BOOLEAN],
        ['autofocus', i3.PROP_BOOLEAN],
        ['chipclass', i3.PROP_STRING],
        ['class', i3.PROP_STRING],
        ['compareby', i3.PROP_STRING],
        ['datafield', i3.PROP_STRING],
        ['dataoptions', i3.PROP_ANY],
        ['dataset', { value: 'Option 1, Option 2, Option 3', ...i3.PROP_ANY }],
        ['datasource', i3.PROP_ANY],
        ['datavalue', i3.PROP_ANY],
        ['datavaluesource', i3.PROP_ANY],
        ['dateformat', i3.PROP_STRING],
        ['disabled', i3.PROP_BOOLEAN],
        ['displayexpression', i3.PROP_STRING],
        ['displayfield', i3.PROP_STRING],
        ['displayimagesrc', i3.PROP_STRING],
        ['enablereorder', i3.PROP_BOOLEAN],
        ['groupby', i3.PROP_STRING],
        ['inputposition', { value: 'last', ...i3.PROP_STRING }],
        ['inputwidth', { value: 'default', ...i3.PROP_STRING }],
        ['limit', i3.PROP_NUMBER],
        ['loadingdatamsg', { value: 'Loading items...', ...i3.PROP_STRING }],
        ['match', i3.PROP_STRING],
        ['matchmode', i3.PROP_STRING],
        ['maxsize', i3.PROP_NUMBER],
        ['minchars', { value: 1, ...i3.PROP_NUMBER }],
        ['name', i3.PROP_STRING],
        ['navsearchbar', { value: false, ...i3.PROP_BOOLEAN }],
        ['orderby', i3.PROP_STRING],
        ['placeholder', { value: 'Type here..', ...i3.PROP_STRING }],
        ['query', i3.PROP_STRING],
        ['readonly', i3.PROP_BOOLEAN],
        ['searchkey', i3.PROP_STRING],
        ['shortcutkey', i3.PROP_STRING],
        ['show', { value: true, ...i3.PROP_BOOLEAN }],
        ['showsearchicon', i3.PROP_BOOLEAN],
        ['tabindex', { value: 0, ...i3.PROP_NUMBER }],
        ['type', { value: 'search', ...i3.PROP_STRING }],
        ['debouncetime', { value: 250, ...i3.PROP_NUMBER }],
        ['datacompletemsg', { value: 'No more data to load', ...i3.PROP_STRING }],
    ]);
    const registerProps = () => {
        i3.register('wm-chips', chipsProps);
        i3.registerFormWidget(core.FormWidgetType.CHIPS, new Map(chipsProps));
    };

    const _c0 = ["wmChips", ""];
    const _c1 = a0 => ({ "full-width": a0 });
    const _c2 = (a0, a1) => ({ "active": a0, "disabled": a1 });
    const _c3 = (a0, a1, a2) => ({ "no-drag": a0, "chip-duplicate bg-danger": a1, "chip-picture": a2 });
    function ChipsComponent_li_0_img_2_Template(rf, ctx) { if (rf & 1) {
        i0__namespace.ɵɵelement(0, "img", 9);
    } if (rf & 2) {
        const item_r3 = i0__namespace.ɵɵnextContext().$implicit;
        i0__namespace.ɵɵproperty("src", item_r3.imgSrc, i0__namespace.ɵɵsanitizeUrl);
    } }
    function ChipsComponent_li_0_button_4_Template(rf, ctx) { if (rf & 1) {
        const _r10 = i0__namespace.ɵɵgetCurrentView();
        i0__namespace.ɵɵelementStart(0, "button", 10);
        i0__namespace.ɵɵlistener("click", function ChipsComponent_li_0_button_4_Template_button_click_0_listener($event) { i0__namespace.ɵɵrestoreView(_r10); const ctx_r10 = i0__namespace.ɵɵnextContext(); const item_r3 = ctx_r10.$implicit; const $index_r6 = ctx_r10.index; const ctx_r3 = i0__namespace.ɵɵnextContext(); return i0__namespace.ɵɵresetView(ctx_r3.removeItem($event, item_r3, $index_r6)); });
        i0__namespace.ɵɵelement(1, "i", 11);
        i0__namespace.ɵɵelementEnd();
    } if (rf & 2) {
        const item_r3 = i0__namespace.ɵɵnextContext().$implicit;
        i0__namespace.ɵɵattribute("aria-label", "Clear " + item_r3.label);
    } }
    function ChipsComponent_li_0_Template(rf, ctx) { if (rf & 1) {
        const _r2 = i0__namespace.ɵɵgetCurrentView();
        i0__namespace.ɵɵelementStart(0, "li", 4)(1, "a", 5);
        i0__namespace.ɵɵlistener("click", function ChipsComponent_li_0_Template_a_click_1_listener($event) { const item_r3 = i0__namespace.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0__namespace.ɵɵnextContext(); return i0__namespace.ɵɵresetView(ctx_r3.handleChipClick($event, item_r3)); })("keydown.delete", function ChipsComponent_li_0_Template_a_keydown_delete_1_listener($event) { const ctx_r4 = i0__namespace.ɵɵrestoreView(_r2); const item_r3 = ctx_r4.$implicit; const $index_r6 = ctx_r4.index; const ctx_r3 = i0__namespace.ɵɵnextContext(); return i0__namespace.ɵɵresetView(ctx_r3.onDelete($event, item_r3, $index_r6)); })("keydown.backspace", function ChipsComponent_li_0_Template_a_keydown_backspace_1_listener($event) { const ctx_r6 = i0__namespace.ɵɵrestoreView(_r2); const item_r3 = ctx_r6.$implicit; const $index_r6 = ctx_r6.index; const ctx_r3 = i0__namespace.ɵɵnextContext(); return i0__namespace.ɵɵresetView(ctx_r3.onBackspace($event, item_r3, $index_r6)); })("keydown.arrowleft", function ChipsComponent_li_0_Template_a_keydown_arrowleft_1_listener() { const ctx_r7 = i0__namespace.ɵɵrestoreView(_r2); const item_r3 = ctx_r7.$implicit; const $index_r6 = ctx_r7.index; const ctx_r3 = i0__namespace.ɵɵnextContext(); return i0__namespace.ɵɵresetView(ctx_r3.onArrowLeft(item_r3, $index_r6)); })("keydown.arrowright", function ChipsComponent_li_0_Template_a_keydown_arrowright_1_listener() { const ctx_r8 = i0__namespace.ɵɵrestoreView(_r2); const item_r3 = ctx_r8.$implicit; const $index_r6 = ctx_r8.index; const ctx_r3 = i0__namespace.ɵɵnextContext(); return i0__namespace.ɵɵresetView(ctx_r3.onArrowRight(item_r3, $index_r6)); })("focus", function ChipsComponent_li_0_Template_a_focus_1_listener($event) { const item_r3 = i0__namespace.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0__namespace.ɵɵnextContext(); return i0__namespace.ɵɵresetView(ctx_r3.handleChipFocus($event, item_r3)); })("blur", function ChipsComponent_li_0_Template_a_blur_1_listener() { const item_r3 = i0__namespace.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0__namespace.ɵɵnextContext(); return i0__namespace.ɵɵresetView(ctx_r3.readonly ? 0 : item_r3.active = false); });
        i0__namespace.ɵɵtemplate(2, ChipsComponent_li_0_img_2_Template, 1, 1, "img", 6);
        i0__namespace.ɵɵelement(3, "span", 7);
        i0__namespace.ɵɵtemplate(4, ChipsComponent_li_0_button_4_Template, 2, 1, "button", 8);
        i0__namespace.ɵɵelementEnd()();
    } if (rf & 2) {
        const item_r3 = ctx.$implicit;
        const ctx_r3 = i0__namespace.ɵɵnextContext();
        i0__namespace.ɵɵclassMapInterpolate1("chip-item ", ctx_r3.chipclass && !ctx_r3.bindChipclass ? ctx_r3.chipclass : "", "");
        i0__namespace.ɵɵproperty("ngClass", i0__namespace.ɵɵpureFunction2(9, _c2, item_r3.active, ctx_r3.disabled));
        i0__namespace.ɵɵadvance();
        i0__namespace.ɵɵproperty("ngClass", i0__namespace.ɵɵpureFunction3(12, _c3, !ctx_r3.enablereorder, item_r3.isDuplicate, item_r3.imgSrc));
        i0__namespace.ɵɵadvance();
        i0__namespace.ɵɵproperty("ngIf", item_r3.imgSrc);
        i0__namespace.ɵɵadvance();
        i0__namespace.ɵɵproperty("textContent", item_r3.label)("title", item_r3.label);
        i0__namespace.ɵɵadvance();
        i0__namespace.ɵɵproperty("ngIf", !ctx_r3.readonly);
    } }
    const WIDGET_CONFIG = {
        widgetType: 'wm-chips',
        hostClass: 'app-chips nav nav-pills list-inline'
    };
    class ChipsComponent extends input.DatasetAwareFormComponent {
        static { this.initializeProps = registerProps(); }
        // getter setter is added to pass the datasource to searchcomponent.
        get datasource() {
            return this._datasource;
        }
        set datasource(nv) {
            this._datasource = nv;
            this.searchComponent.datasource = nv;
            this._debounceUpdateQueryModel(this.datavalue || this.toBeProcessedDatavalue);
        }
        constructor(inj, bindDisplayField, bindDisplayExpr, bindDisplayImgSrc, bindDataField, bindDataSet, bindChipclass, explicitContext) {
            super(inj, WIDGET_CONFIG, explicitContext);
            this.bindDisplayField = bindDisplayField;
            this.bindDisplayExpr = bindDisplayExpr;
            this.bindDisplayImgSrc = bindDisplayImgSrc;
            this.bindDataField = bindDataField;
            this.bindDataSet = bindDataSet;
            this.bindChipclass = bindChipclass;
            this.chipsList = [];
            this.maxSizeReached = 'Max size reached';
            this._unsubscribeDv = false;
            i3.styler(this.nativeElement, this);
            // set the showsearchicon as false by default.
            if (!core.isDefined(this.showsearchicon)) {
                this.showsearchicon = false;
            }
            this.multiple = true;
            this.nextItemIndex = 0; // default chip index
            this._debounceUpdateQueryModel = core.debounce((val) => {
                this.updateQueryModel(val).then(() => {
                    if (this.bindChipclass) {
                        lodashEs.forEach(this.chipsList, (item, index) => {
                            this.registerChipItemClass(item, index);
                        });
                    }
                });
            }, 150);
            const datasetSubscription = this.dataset$.subscribe(() => {
                this.searchComponent.dataset = this.dataset;
                // clearing the last results when dataset is reassigned
                this.searchComponent._lastResult = undefined;
                this.nextItemIndex = this.datasetItems.length;
                this._debounceUpdateQueryModel(this.datavalue || this.toBeProcessedDatavalue);
            });
            this.registerDestroyListener(() => datasetSubscription.unsubscribe());
            const datavalueSubscription = this.datavalue$.subscribe((val) => {
                // update queryModel only when parentRef is available.
                if (!this._unsubscribeDv) {
                    this.chipsList = [];
                    // if the datafield is ALLFILEDS do not fetch the records
                    // update the query model with the values we have
                    this._debounceUpdateQueryModel(val);
                }
            });
            this.registerDestroyListener(() => datavalueSubscription.unsubscribe());
        }
        ngOnInit() {
            super.ngOnInit();
            this.searchComponent.multiple = true;
            this.searchComponent.binddisplayimagesrc = this.bindDisplayImgSrc;
            this.searchComponent.displayimagesrc = this.displayimagesrc;
            this.searchComponent.binddisplaylabel = this.bindDisplayExpr;
            this.searchComponent.displaylabel = this.displayfield;
            this.searchComponent.datafield = this.bindDataField || this.datafield;
            this.searchComponent.binddataset = this.bindDataSet;
            this.searchComponent.dataset = this.dataset;
            this.searchComponent.searchkey = this.searchkey;
            this.searchComponent.limit = this.limit;
            this.searchComponent.debouncetime = this.debouncetime;
            this.searchComponent.matchmode = this.matchmode;
            this.getTransformedData = (val, isCustom) => {
                return this.searchComponent.getTransformedData([val], this.nextItemIndex++, isCustom);
            };
        }
        ngAfterViewInit() {
            super.ngAfterViewInit();
            if (this.enablereorder) {
                this.configureDnD();
            }
        }
        /**
         * This method returns the evaluated class expression.
         * @param $index index of the chip
         * @param item chip object containing the key, value, label
         * @returns {any} evaluated class expression value
         */
        registerChipItemClass(item, $index) {
            if (this.bindChipclass) {
                const watchName = `${this.widgetId}_chipItemClass_${$index}`;
                core.$unwatch(watchName);
                //[Todo-CSP]: same as list item class
                this.registerDestroyListener(core.$watch(this.bindChipclass, this.viewParent, { item, $index }, (nv, ov) => {
                    this.applyItemClass(i3.getConditionalClasses(nv, ov), $index);
                }, watchName));
            }
        }
        applyItemClass(val, index) {
            const chipItem = this.nativeElement.querySelectorAll('.chip-item').item(index);
            $(chipItem).removeClass(val.toRemove).addClass(val.toAdd);
        }
        removeDuplicates() {
            this.chipsList = i3.getUniqObjsByDataField(this.chipsList, this.datafield, this.displayfield || this.displaylabel);
        }
        // This method updates the queryModel.
        // default call to get the default data can be done only when defaultQuery is true.
        updateQueryModel(data) {
            const promises = [];
            if (!data) {
                this.chipsList = [];
                return Promise.resolve();
            }
            // clone the data as the updations on data will change the datavalue.
            let dataValue = lodashEs.clone(data);
            const prevChipsList = this.chipsList;
            this.chipsList = [];
            // update the model when model has items more than maxsize
            if (this.maxsize && dataValue.length > this.maxsize) {
                this._modelByValue = dataValue = lodashEs.slice(dataValue, 0, this.maxsize);
                data = dataValue;
            }
            const searchQuery = [];
            /**
             * For each value in datavalue,
             * 1. check whether value is in datasetItems, if item is found, addd to the chipsList.
             * 2. else make a default query to the filter and get the record.
             * 3. In step 2, if datavalue is not ALLFIELDS, then make a query. Extract the chipsList from the query response.
             * 4. If there is no response for the value and allowonlyselect is true, remove the value from the datavalue. So that datavalue just contains the valid values.
             * 5. In step 2, if datavalue is ALLFIELDS and value is object, then just prepare the datasetItem from the value.
             * 6. If value is not object and allowonlyselect is false, then create a customModel and replace this value with customModel and prepare datasetItem from this value
             */
            dataValue.forEach((val, i) => {
                const itemFound = lodashEs.find(this.datasetItems, item => {
                    return lodashEs.isObject(item.value) ? lodashEs.isEqual(item.value, val) : lodashEs.toString(item.value) === lodashEs.toString(val);
                });
                if (itemFound) {
                    this.chipsList.push(itemFound);
                }
                else if (this.datafield !== i3.ALLFIELDS) {
                    searchQuery.push(val);
                }
                else if (this.datafield === i3.ALLFIELDS) {
                    let dataObj, isCustom = false;
                    if (!lodashEs.isObject(val)) {
                        dataObj = this.createCustomDataModel(val);
                        isCustom = true;
                        if (dataObj) {
                            data.splice(i, 1, dataObj);
                        }
                    }
                    else {
                        // if custom chips is already generated, val will be object as {'dataField_val': 'entered_val'}
                        // Hence check this val in previous chipList and assign the iscustom flag
                        const prevChipObj = prevChipsList.find(obj => {
                            return lodashEs.isEqual(obj.value, val);
                        });
                        if (prevChipObj) {
                            isCustom = prevChipObj.iscustom;
                        }
                    }
                    dataObj = dataObj || val;
                    const transformedData = this.getTransformedData(dataObj, isCustom);
                    const chipObj = transformedData[0];
                    if (isCustom) {
                        chipObj.iscustom = isCustom;
                    }
                    this.chipsList.push(chipObj);
                }
            });
            // make default query with all the values and if response for the value is not in datavalue then add a custom chip object.
            if (searchQuery.length) {
                promises.push(this.getDefaultModel(searchQuery, this.nextItemIndex)
                    .then(response => {
                    this.chipsList = this.chipsList.concat(response || []);
                    dataValue.forEach((val, i) => {
                        const isExists = lodashEs.find(this.chipsList, (obj) => {
                            return obj.value.toString() === val.toString();
                        });
                        if (!isExists) {
                            if (this.allowonlyselect) {
                                const index = data.indexOf(val);
                                if (index > -1) {
                                    data.splice(index, 1);
                                }
                                return;
                            }
                            const transformedData = this.getTransformedData(val, true);
                            const chipObj = transformedData[0];
                            chipObj.iscustom = true;
                            this.chipsList.push(chipObj);
                        }
                    });
                }));
            }
            // default chip data is adding focus on to the search input. Hence this flag helps not to focus.
            this.resetSearchModel(true);
            return Promise.all(promises).then(() => {
                this._modelByValue = data;
                this.removeDuplicates();
                this.updateMaxSize();
                core.$appDigest();
            });
        }
        resetSearchModel(defaultQuery) {
            this._unsubscribeDv = true;
            // clear search will empty the query model and gets the data when minchars is 0 (i.e. autocomplete) on focus
            // defaultQuery flag is set when widget is not active. This will only load the autocomplete dropup with minchars as 0 when widget is focused/active
            this.searchComponent.clearSearch(undefined, !this.minchars && !defaultQuery);
            this._unsubscribeDv = false;
        }
        // Add the newItem to the list
        addItem($event, widget) {
            const searchComponent = widget;
            let allowAdd;
            let chipObj;
            if (searchComponent && core.isDefined(searchComponent.datavalue) && searchComponent.queryModel !== '') {
                if (!searchComponent.query || !lodashEs.trim(searchComponent.query)) {
                    return;
                }
                chipObj = searchComponent.queryModel;
            }
            else {
                if (this.allowonlyselect) {
                    return;
                }
                let dataObj;
                if (this.datafield === i3.ALLFIELDS) {
                    if (!lodashEs.isObject(this.searchComponent.query) && lodashEs.trim(this.searchComponent.query)) {
                        dataObj = this.createCustomDataModel(this.searchComponent.query);
                        // return if the custom chip is empty
                        if (!dataObj) {
                            this.resetSearchModel();
                            return;
                        }
                    }
                }
                const data = dataObj || lodashEs.trim(this.searchComponent.query);
                if (data) {
                    const transformedData = this.getTransformedData(data, true);
                    chipObj = transformedData[0];
                    chipObj.iscustom = true;
                }
            }
            if (!core.isDefined(chipObj) || chipObj === '') {
                return;
            }
            allowAdd = this.invokeEventCallback('beforeadd', { $event, newItem: chipObj });
            if (core.isDefined(allowAdd) && !core.toBoolean(allowAdd)) {
                return;
            }
            if (this.isDuplicate(chipObj)) {
                this.resetSearchModel();
                return;
            }
            this.registerChipItemClass(chipObj, this.chipsList.length);
            this.chipsList.push(chipObj);
            if (!this.datavalue) {
                this._modelByValue = [chipObj.value];
            }
            else {
                this._modelByValue = [...this._modelByValue, chipObj.value];
            }
            this._unsubscribeDv = true;
            this.invokeOnTouched();
            this.invokeOnChange(this._modelByValue, $event || {}, true);
            this.invokeEventCallback('add', { $event, $item: chipObj });
            this.updateMaxSize();
            // reset input box when item is added.
            this.resetSearchModel();
            // stop the event to not to call the submit event on enter press.
            if ($event && ($event.key === 'Enter' || $event.keyCode === 13)) {
                this.stopEvent($event);
            }
        }
        // Prepare datavalue object from a string(junk) value when datafield is allFields.
        createCustomDataModel(val) {
            const key = this.displayfield || (this.datafield !== i3.ALLFIELDS ? this.datafield : undefined);
            if (key) {
                const customObj = {};
                customObj[key] = val;
                return customObj;
            }
        }
        // Check if newItem already exists
        isDuplicate(item) {
            if (this.datafield === i3.ALLFIELDS) {
                return lodashEs.findIndex(this.chipsList, { value: item.value }) > -1;
            }
            return lodashEs.findIndex(this.chipsList, { key: item.key }) > -1;
        }
        // Check if max size is reached
        updateMaxSize() {
            this.saturate = this.maxsize > 0 && this.chipsList.length === this.maxsize;
        }
        // Makes call to searchComponent to filter the dataSource based on the query.
        getDefaultModel(query, index) {
            this.nextItemIndex++;
            return this.searchComponent.getDataSource(query, true, index)
                .then((response) => {
                // @ts-ignore
                return lodashEs.filter(query, queryVal => {
                    lodashEs.find(response, { value: queryVal });
                });
            });
        }
        handleChipClick($event, chip) {
            if (this.readonly) {
                return;
            }
            $event.currentTarget.focus();
            this.invokeEventCallback('chipclick', { $event, $item: chip });
        }
        handleChipFocus($event, chip) {
            if (this.readonly) {
                return;
            }
            chip.active = true;
            this.invokeEventCallback('chipselect', { $event, $item: chip });
        }
        // To avoid form submit on pressing enter key
        stopEvent($event) {
            $event.stopPropagation();
            $event.preventDefault();
        }
        onTextDelete($event) {
            if (core.isAppleProduct) {
                this.onInputClear($event);
            }
        }
        onInputClear($event) {
            if (!this.chipsList || !this.chipsList.length || this.searchComponent.query) {
                return;
            }
            this.$element.find('li.chip-item > a.app-chip').last().focus();
            this.stopEvent($event);
        }
        onBackspace($event, $item, $index) {
            if (this.readonly) {
                return;
            }
            this.removeItem($event, $item, $index, true);
        }
        onDelete($event, $item, $index) {
            if (this.readonly) {
                return;
            }
            this.removeItem($event, $item, $index);
        }
        onArrowLeft($item, $index) {
            if (this.readonly) {
                return;
            }
            // On left arrow click when search input query is empty.
            if (!this.searchComponent.query && !core.isDefined($index) && !core.isDefined($item)) {
                this.$element.find('li.chip-item > a.app-chip').last().focus();
                return;
            }
            if ($index > 0) {
                this.$element.find('li.chip-item > a.app-chip').get($index - 1).focus();
            }
            else {
                this.focusSearchBox();
            }
        }
        onArrowRight($item, $index) {
            if (this.readonly) {
                return;
            }
            // On right arrow click when search input query is empty.
            if (!this.searchComponent.query && !core.isDefined($index) && !core.isDefined($item)) {
                this.$element.find('li.chip-item > a.app-chip').first().focus();
                return;
            }
            if ($index < (this.chipsList.length - 1)) {
                this.$element.find('li.chip-item > a.app-chip').get($index + 1).focus();
            }
            else {
                this.focusSearchBox();
            }
        }
        // focus search box.
        focusSearchBox() {
            this.$element.find('.app-chip-input > input.app-textbox').focus();
        }
        // Remove the item from list
        removeItem($event, item, index, canFocus) {
            $event.stopPropagation();
            const indexes = lodashEs.isArray(index) ? index : [index];
            const focusIndex = lodashEs.max(indexes);
            const items = lodashEs.reduce(indexes, (result, i) => {
                result.push(this.chipsList[i]);
                return result;
            }, []);
            // prevent deletion if the before-remove event callback returns false
            const allowRemove = this.invokeEventCallback('beforeremove', { $event, $item: items.length === 1 ? items[0] : items });
            if (core.isDefined(allowRemove) && !core.toBoolean(allowRemove)) {
                return;
            }
            const prevDatavalue = lodashEs.clone(this.datavalue);
            // focus next chip after deletion.
            // if there are no chips in the list focus search box
            setTimeout(() => {
                const chipsLength = this.chipsList.length;
                const $chipsList = this.$element.find('li.chip-item > a.app-chip');
                if (!chipsLength || !canFocus) {
                    this.focusSearchBox();
                }
                else if ((chipsLength - 1) < focusIndex) {
                    // if focus index is greater than chips length select last chip
                    $chipsList.get(chipsLength - 1).focus();
                }
                else {
                    // manually set the succeeding chip as active if there is a chip next to the current chip.
                    this.chipsList[focusIndex].active = true;
                    $chipsList.get(focusIndex).focus();
                }
            });
            const pulledItems = lodashEs.pullAt(this.chipsList, indexes);
            pulledItems.forEach(datasetItem => {
                this._modelByValue = lodashEs.filter(this._modelByValue, val => {
                    return !(lodashEs.isObject(val) ? lodashEs.isEqual(val, datasetItem.value) : lodashEs.toString(val) === lodashEs.toString(datasetItem.value));
                });
            });
            this._unsubscribeDv = false;
            this.invokeOnChange(this._modelByValue, $event, true);
            this.invokeEventCallback('change', { $event, newVal: this.datavalue, oldVal: prevDatavalue });
            this.updateMaxSize();
            this.invokeEventCallback('remove', { $event, $item: items.length === 1 ? items[0] : items });
        }
        /**
         * Swaps items in an array if provided with indexes.
         * @param data :- array to be swapped
         * @param newIndex :- new index for the element to be placed
         * @param currentIndex :- the current index of the element.
         */
        swapElementsInArray(data, newIndex, currentIndex) {
            const draggedItem = lodashEs.pullAt(data, currentIndex)[0];
            data.splice(newIndex, 0, draggedItem);
        }
        /**
         * Cancels the reorder by reseting the elements to the original position.
         */
        resetReorder() {
            this.$element.removeData('oldIndex');
        }
        invokeOnBeforeServiceCall(inputData) {
            this.invokeEventCallback('beforeservicecall', { inputData });
        }
        handleEvent(node, eventName, eventCallback, locals) {
            if (eventName === 'remove' || eventName === 'beforeremove' || eventName === 'chipselect'
                || eventName === 'chipclick' || eventName === 'add' || eventName === 'reorder' || eventName === 'change') {
                return;
            }
            super.handleEvent(node, eventName, eventCallback, locals);
        }
        // Configures the reordable feature in chips widgets.
        configureDnD() {
            const options = {
                items: '> li:not(.app-chip-search)',
                placeholder: 'chip-placeholder'
            };
            i3.configureDnD(this.$element, options, this.onReorderStart.bind(this), this.update.bind(this));
        }
        // Triggered on drag start while reordering.
        onReorderStart(evt, ui) {
            const helper = ui.helper;
            // increasing the width of the dragged item by 1
            helper.width(helper.width() + 1);
            this.$element.data('oldIndex', ui.item.index() - (this.inputposition === 'first' ? 1 : 0));
        }
        // updates the chipsList and datavalue on reorder.
        update($event, ui) {
            let changedItem, newIndex, oldIndex;
            // Get the index of the item at position before drag and after the reorder.
            newIndex = ui.item.index() - (this.inputposition === 'first' ? 1 : 0);
            oldIndex = this.$element.data('oldIndex');
            newIndex = this.chipsList.length === newIndex ? newIndex - 1 : newIndex;
            changedItem = {
                oldIndex: oldIndex,
                newIndex: newIndex,
                item: this.chipsList[oldIndex]
            };
            if (newIndex === oldIndex) {
                this.resetReorder();
                return;
            }
            changedItem.item = this.chipsList[oldIndex];
            const allowReorder = this.invokeEventCallback('beforereorder', { $event, $data: this.chipsList, $changedItem: changedItem });
            if (core.isDefined(allowReorder) && core.toBoolean(allowReorder) === false) {
                this.resetReorder();
                return;
            }
            // modify the chipsList and datavalue after the reorder.
            this.swapElementsInArray(this.chipsList, newIndex, oldIndex);
            this.swapElementsInArray(this._modelByValue, newIndex, oldIndex);
            changedItem.item = this.chipsList[newIndex];
            this.chipsList = [...this.chipsList];
            this.resetReorder();
            this.invokeEventCallback('reorder', { $event, $data: this.chipsList, $changedItem: changedItem });
        }
        onPropertyChange(key, nv, ov) {
            if (key === 'tabindex') {
                return;
            }
            if (key === 'dataoptions') {
                this.searchComponent.dataoptions = nv;
            }
            if (key === 'datafield') {
                this.searchComponent.datafield = this.datafield;
            }
            if (key === 'displayfield') {
                this.searchComponent.displaylabel = this.displayfield;
            }
            if (key === 'displayexpression') {
                this.searchComponent.binddisplaylabel = this.binddisplayexpression ? this.binddisplayexpression : this.displayexpression;
            }
            if (key === 'displayimagesrc') {
                this.searchComponent.binddisplayimagesrc = this.binddisplayimagesrc ? this.binddisplayimagesrc : this.displayimagesrc;
            }
            if (key === 'limit') {
                this.searchComponent.limit = this.limit;
            }
            if (key === 'matchmode') {
                this.searchComponent.matchmode = this.matchmode;
            }
            if (key === 'groupby') {
                this.searchComponent.groupby = this.groupby;
            }
            if (key === 'enablereorder') {
                if (this.$element.hasClass('ui-sortable')) {
                    this.$element.sortable('option', 'disabled', !nv);
                }
                else if (nv) {
                    this.configureDnD();
                }
                // Add this block to handle drag prevention
                const chipElements = this.$element.find('.chip-item a.app-chip');
                if (!nv) {
                    chipElements.addClass('no-drag');
                    // Prevent default drag behavior
                    chipElements.on('dragstart', (e) => {
                        e.preventDefault();
                        return false;
                    });
                }
                else {
                    chipElements.removeClass('no-drag');
                    chipElements.off('dragstart');
                }
            }
            if (key === 'readonly') {
                if (nv) {
                    this.$element.addClass('readonly');
                }
                else {
                    this.$element.removeClass('readonly');
                }
            }
            if (key === 'inputposition') {
                const $inputEl = this.$element.find('li.app-chip-search');
                if (nv === 'first') {
                    this.$element.prepend($inputEl);
                }
                else {
                    this.$element.append($inputEl);
                }
            }
            if (key === 'autofocus' && nv) {
                // setting the autofocus on the input once after dom is updated
                setTimeout(() => {
                    const $chipsList = this.$element.find('.app-chip-input > input.app-textbox');
                    if ($chipsList && $chipsList.length) {
                        this.focusSearchBox();
                    }
                });
            }
            super.onPropertyChange(key, nv, ov);
        }
        static { this.ɵfac = function ChipsComponent_Factory(t) { return new (t || ChipsComponent)(i0__namespace.ɵɵdirectiveInject(i0__namespace.Injector), i0__namespace.ɵɵinjectAttribute('displayfield.bind'), i0__namespace.ɵɵinjectAttribute('displayexpression.bind'), i0__namespace.ɵɵinjectAttribute('displayimagesrc.bind'), i0__namespace.ɵɵinjectAttribute('datafield.bind'), i0__namespace.ɵɵinjectAttribute('dataset.bind'), i0__namespace.ɵɵinjectAttribute('chipclass.bind'), i0__namespace.ɵɵdirectiveInject('EXPLICIT_CONTEXT', 8)); }; }
        static { this.ɵcmp = /*@__PURE__*/ i0__namespace.ɵɵdefineComponent({ type: ChipsComponent, selectors: [["", "wmChips", ""]], viewQuery: function ChipsComponent_Query(rf, ctx) { if (rf & 1) {
                i0__namespace.ɵɵviewQuery(i2.SearchComponent, 7);
            } if (rf & 2) {
                let _t;
                i0__namespace.ɵɵqueryRefresh(_t = i0__namespace.ɵɵloadQuery()) && (ctx.searchComponent = _t.first);
            } }, features: [i0__namespace.ɵɵProvidersFeature([
                    i3.provideAs(ChipsComponent, forms.NG_VALUE_ACCESSOR, true),
                    i3.provideAsWidgetRef(ChipsComponent)
                ]), i0__namespace.ɵɵInheritDefinitionFeature], attrs: _c0, decls: 4, vars: 4, consts: [["search", ""], [3, "class", "ngClass", 4, "ngFor", "ngForOf"], [1, "app-chip-search", 3, "ngClass"], ["wmSearch", "", "name", "app-chip-search", "submit.event", "addItem($event, widget)", "beforeservicecall.event", "invokeOnBeforeServiceCall(inputData)", "disabled.bind", "disabled || readonly || saturate", "datafield.bind", "datafield", "allowonlyselect.bind", "allowonlyselect", "searchkey.bind", "searchkey", "orderby.bind", "orderby", "placeholder.bind", "saturate ? maxSizeReached : placeholder", "showsearchicon.bind", "showsearchicon", "tabindex.bind", "tabindex", "minchars.bind", "minchars", "debouncetime.bind", "debouncetime", "matchmode.bind", "matchmode", "datacompletemsg.bind", "datacompletemsg", "groupby.bind", "groupby", "match.bind", "match", "dateformat.bind", "dateformat", 1, "app-chip-input", 3, "keydown.enter", "keydown.delete", "keydown.backspace", "keydown.arrowleft", "keydown.arrowright"], [3, "ngClass"], ["href", "javascript:void(0)", 1, "app-chip", 3, "click", "keydown.delete", "keydown.backspace", "keydown.arrowleft", "keydown.arrowright", "focus", "blur", "ngClass"], ["data-identifier", "img", "alt", "Chip Image", "class", "button-image-icon", 3, "src", 4, "ngIf"], [1, "app-chip-title", 3, "textContent", "title"], ["type", "button", "class", "btn btn-transparent", 3, "click", 4, "ngIf"], ["data-identifier", "img", "alt", "Chip Image", 1, "button-image-icon", 3, "src"], ["type", "button", 1, "btn", "btn-transparent", 3, "click"], [1, "app-icon", "wi", "wi-close"]], template: function ChipsComponent_Template(rf, ctx) { if (rf & 1) {
                const _r1 = i0__namespace.ɵɵgetCurrentView();
                i0__namespace.ɵɵtemplate(0, ChipsComponent_li_0_Template, 5, 16, "li", 1);
                i0__namespace.ɵɵelementStart(1, "li", 2)(2, "div", 3, 0);
                i0__namespace.ɵɵlistener("keydown.enter", function ChipsComponent_Template_div_keydown_enter_2_listener($event) { i0__namespace.ɵɵrestoreView(_r1); return i0__namespace.ɵɵresetView(ctx.stopEvent($event)); })("keydown.delete", function ChipsComponent_Template_div_keydown_delete_2_listener($event) { i0__namespace.ɵɵrestoreView(_r1); return i0__namespace.ɵɵresetView(ctx.onTextDelete($event)); })("keydown.backspace", function ChipsComponent_Template_div_keydown_backspace_2_listener($event) { i0__namespace.ɵɵrestoreView(_r1); return i0__namespace.ɵɵresetView(ctx.onInputClear($event)); })("keydown.arrowleft", function ChipsComponent_Template_div_keydown_arrowleft_2_listener() { i0__namespace.ɵɵrestoreView(_r1); return i0__namespace.ɵɵresetView(ctx.onArrowLeft()); })("keydown.arrowright", function ChipsComponent_Template_div_keydown_arrowright_2_listener() { i0__namespace.ɵɵrestoreView(_r1); return i0__namespace.ɵɵresetView(ctx.onArrowRight()); });
                i0__namespace.ɵɵelementEnd()();
            } if (rf & 2) {
                i0__namespace.ɵɵproperty("ngForOf", ctx.chipsList);
                i0__namespace.ɵɵadvance();
                i0__namespace.ɵɵproperty("ngClass", i0__namespace.ɵɵpureFunction1(2, _c1, ctx.inputwidth === "full"));
            } }, dependencies: [i1__namespace.NgClass, i1__namespace.NgForOf, i1__namespace.NgIf, i2__namespace.SearchComponent, i3__namespace.TextContentDirective], encapsulation: 2 }); }
    }
    (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(ChipsComponent, [{
            type: i0.Component,
            args: [{ selector: '[wmChips]', providers: [
                        i3.provideAs(ChipsComponent, forms.NG_VALUE_ACCESSOR, true),
                        i3.provideAsWidgetRef(ChipsComponent)
                    ], template: "<li class=\"chip-item {{chipclass && !bindChipclass ? chipclass : ''}}\"\n    *ngFor=\"let item of chipsList; let $index = index;\"\n    [ngClass]=\"{'active': item.active, 'disabled': disabled}\">\n    <a href=\"javascript:void(0)\" class=\"app-chip\"\n       (click)=\"handleChipClick($event, item)\"\n       (keydown.delete)=\"onDelete($event, item, $index)\"\n       (keydown.backspace)=\"onBackspace($event, item, $index)\"\n       (keydown.arrowleft)=\"onArrowLeft(item, $index)\"\n       (keydown.arrowright)=\"onArrowRight(item, $index)\"\n       (focus)=\"handleChipFocus($event, item)\"\n       (blur)=\"readonly ? 0 : item.active = false\"\n       [ngClass]=\"{'no-drag': !enablereorder,'chip-duplicate bg-danger': item.isDuplicate, 'chip-picture': item.imgSrc}\">\n        <img data-identifier=\"img\" alt=\"Chip Image\" class=\"button-image-icon\" [src]=\"item.imgSrc\" *ngIf=\"item.imgSrc\"/>\n        <span class=\"app-chip-title\" [textContent]=\"item.label\" [title]=\"item.label\"></span>\n        <button type=\"button\" [attr.aria-label]=\"'Clear ' + item.label\" class=\"btn btn-transparent\"\n                (click)=\"removeItem($event, item, $index);\" *ngIf=\"!readonly\">\n            <i class=\"app-icon wi wi-close\"></i>\n        </button>\n    </a>\n</li>\n<li class=\"app-chip-search\" [ngClass]=\"{'full-width': inputwidth === 'full'}\">\n    <div #search wmSearch class=\"app-chip-input\"\n         name=\"app-chip-search\"\n         submit.event=\"addItem($event, widget)\"\n         beforeservicecall.event=\"invokeOnBeforeServiceCall(inputData)\"\n         disabled.bind=\"disabled || readonly || saturate\"\n         datafield.bind=\"datafield\"\n         allowonlyselect.bind=\"allowonlyselect\"\n         searchkey.bind=\"searchkey\"\n         orderby.bind=\"orderby\"\n         placeholder.bind=\"saturate ? maxSizeReached : placeholder\"\n         showsearchicon.bind=\"showsearchicon\"\n         tabindex.bind=\"tabindex\"\n         minchars.bind=\"minchars\"\n         debouncetime.bind=\"debouncetime\"\n         matchmode.bind=\"matchmode\"\n         datacompletemsg.bind = \"datacompletemsg\"\n         groupby.bind=\"groupby\"\n         match.bind=\"match\"\n         dateformat.bind=\"dateformat\"\n         (keydown.enter)=\"stopEvent($event)\"\n         (keydown.delete)=\"onTextDelete($event)\"\n         (keydown.backspace)=\"onInputClear($event)\"\n         (keydown.arrowleft)=\"onArrowLeft()\"\n         (keydown.arrowright)=\"onArrowRight()\">\n    </div>\n</li>\n" }]
        }], () => [{ type: i0__namespace.Injector }, { type: undefined, decorators: [{
                    type: i0.Attribute,
                    args: ['displayfield.bind']
                }] }, { type: undefined, decorators: [{
                    type: i0.Attribute,
                    args: ['displayexpression.bind']
                }] }, { type: undefined, decorators: [{
                    type: i0.Attribute,
                    args: ['displayimagesrc.bind']
                }] }, { type: undefined, decorators: [{
                    type: i0.Attribute,
                    args: ['datafield.bind']
                }] }, { type: undefined, decorators: [{
                    type: i0.Attribute,
                    args: ['dataset.bind']
                }] }, { type: undefined, decorators: [{
                    type: i0.Attribute,
                    args: ['chipclass.bind']
                }] }, { type: undefined, decorators: [{
                    type: i0.Inject,
                    args: ['EXPLICIT_CONTEXT']
                }, {
                    type: i0.Optional
                }] }], { searchComponent: [{
                type: i0.ViewChild,
                args: [i2.SearchComponent, /* TODO: add static flag */ { static: true }]
            }] }); })();
    (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassDebugInfo(ChipsComponent, { className: "ChipsComponent", filePath: "chips.component.ts", lineNumber: 53 }); })();

    const components = [
        ChipsComponent
    ];
    class ChipsModule {
        static { this.ɵfac = function ChipsModule_Factory(t) { return new (t || ChipsModule)(); }; }
        static { this.ɵmod = /*@__PURE__*/ i0__namespace.ɵɵdefineNgModule({ type: ChipsModule }); }
        static { this.ɵinj = /*@__PURE__*/ i0__namespace.ɵɵdefineInjector({ imports: [i1.CommonModule,
                i2.SearchModule,
                i3.WmComponentsModule] }); }
    }
    (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(ChipsModule, [{
            type: i0.NgModule,
            args: [{
                    imports: [
                        i1.CommonModule,
                        i2.SearchModule,
                        i3.WmComponentsModule
                    ],
                    declarations: [...components],
                    exports: [...components]
                }]
        }], null, null); })();
    (function () { (typeof ngJitMode === "undefined" || ngJitMode) && i0__namespace.ɵɵsetNgModuleScope(ChipsModule, { declarations: [ChipsComponent], imports: [i1.CommonModule,
            i2.SearchModule,
            i3.WmComponentsModule], exports: [ChipsComponent] }); })();

    exports.ChipsComponent = ChipsComponent;
    exports.ChipsModule = ChipsModule;

}));
