@revivejs/ng-multiselect-dropdown 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -0
- package/README.md +229 -0
- package/esm2022/click-outside.directive.mjs +32 -0
- package/esm2022/list-filter.pipe.mjs +28 -0
- package/esm2022/multiselect.component.mjs +342 -0
- package/esm2022/multiselect.model.mjs +17 -0
- package/esm2022/ng-multiselect-dropdown.module.mjs +27 -0
- package/esm2022/public_api.mjs +3 -0
- package/esm2022/revivejs-ng-multiselect-dropdown.mjs +5 -0
- package/fesm2022/revivejs-ng-multiselect-dropdown.mjs +440 -0
- package/fesm2022/revivejs-ng-multiselect-dropdown.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/package.json +71 -0
- package/themes/ng-multiselect-dropdown.theme.scss +210 -0
package/CHANGELOG.md
ADDED
|
File without changes
|
package/README.md
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# @revivejs/ng-multiselect-dropdown
|
|
2
|
+
|
|
3
|
+
> A polished **Angular 16 multi-select dropdown** for template-driven and reactive forms, with search, single or multiple selection, custom data binding, and theme support.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@revivejs/ng-multiselect-dropdown)
|
|
6
|
+
[](https://www.npmjs.com/package/@revivejs/ng-multiselect-dropdown)
|
|
7
|
+
[](https://www.npmjs.com/package/@revivejs/ng-multiselect-dropdown)
|
|
8
|
+
[](https://github.com/alexandroit/ng-multiselect-dropdown/blob/master/LICENSE)
|
|
9
|
+
[](https://angular.io)
|
|
10
|
+
[](https://www.typescriptlang.org)
|
|
11
|
+
[](https://github.com/alexandroit/ng-multiselect-dropdown/stargazers)
|
|
12
|
+
|
|
13
|
+
**[Documentation & Demo](https://alexandroit.github.io/ng-multiselect-dropdown/)** | **[Repository](https://github.com/alexandroit/ng-multiselect-dropdown)** | **[npm](https://www.npmjs.com/package/@revivejs/ng-multiselect-dropdown)** | **[Changelog](https://github.com/alexandroit/ng-multiselect-dropdown/blob/master/CHANGELOG.md)** | **[Custom Theme Guide](https://github.com/alexandroit/ng-multiselect-dropdown/blob/master/custom-theme.md)**
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
> **Credits:** This package is maintained and published from the official repository at [alexandroit/ng-multiselect-dropdown](https://github.com/alexandroit/ng-multiselect-dropdown). Historical credit remains with the original upstream authors who inspired and started the library line.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Why this library?
|
|
22
|
+
|
|
23
|
+
`@revivejs/ng-multiselect-dropdown` is the actively maintained scoped continuation of this component, prepared for modern Angular 16 applications and first-class npm publishing under the `@revivejs` scope.
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
| Feature | Supported |
|
|
28
|
+
| :--- | :---: |
|
|
29
|
+
| Angular 16 release line | ✅ |
|
|
30
|
+
| Single and multiple selection | ✅ |
|
|
31
|
+
| Search and filter | ✅ |
|
|
32
|
+
| Template-driven forms (`ngModel`) | ✅ |
|
|
33
|
+
| Reactive forms support | ✅ |
|
|
34
|
+
| Custom text and placeholders | ✅ |
|
|
35
|
+
| Select all and clear all | ✅ |
|
|
36
|
+
| Item selection limit | ✅ |
|
|
37
|
+
| Disabled items | ✅ |
|
|
38
|
+
| Remote search trigger (`allowRemoteDataSearch`) | ✅ |
|
|
39
|
+
| Custom theme support | ✅ |
|
|
40
|
+
|
|
41
|
+
## Table of Contents
|
|
42
|
+
|
|
43
|
+
1. [Angular Version Compatibility](#angular-version-compatibility)
|
|
44
|
+
2. [Installation](#installation)
|
|
45
|
+
3. [Setup](#setup)
|
|
46
|
+
4. [Basic Usage](#basic-usage)
|
|
47
|
+
5. [Settings](#settings)
|
|
48
|
+
6. [Events](#events)
|
|
49
|
+
7. [Theming](#theming)
|
|
50
|
+
8. [Run Locally](#run-locally)
|
|
51
|
+
9. [Publishing](#publishing)
|
|
52
|
+
10. [License](#license)
|
|
53
|
+
|
|
54
|
+
## Angular Version Compatibility
|
|
55
|
+
|
|
56
|
+
| Package | Angular | TypeScript | RxJS |
|
|
57
|
+
| :--- | :---: | :---: | :---: |
|
|
58
|
+
| `@revivejs/ng-multiselect-dropdown@1.x` | `16.x` | `4.9.x` | `7.x` |
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install @revivejs/ng-multiselect-dropdown
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Setup
|
|
67
|
+
|
|
68
|
+
### 1. Import the module
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { NgModule } from '@angular/core';
|
|
72
|
+
import { BrowserModule } from '@angular/platform-browser';
|
|
73
|
+
import { FormsModule } from '@angular/forms';
|
|
74
|
+
import { NgMultiSelectDropDownModule } from '@revivejs/ng-multiselect-dropdown';
|
|
75
|
+
|
|
76
|
+
@NgModule({
|
|
77
|
+
imports: [
|
|
78
|
+
BrowserModule,
|
|
79
|
+
FormsModule,
|
|
80
|
+
NgMultiSelectDropDownModule.forRoot()
|
|
81
|
+
]
|
|
82
|
+
})
|
|
83
|
+
export class AppModule {}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 2. Optional theme setup
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
"styles": [
|
|
90
|
+
"node_modules/@revivejs/ng-multiselect-dropdown/themes/ng-multiselect-dropdown.theme.scss"
|
|
91
|
+
]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 3. Use the package from the official repository
|
|
95
|
+
|
|
96
|
+
Repository URL:
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
https://github.com/alexandroit/ng-multiselect-dropdown
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Basic Usage
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { Component, OnInit } from '@angular/core';
|
|
106
|
+
import { IDropdownSettings } from '@revivejs/ng-multiselect-dropdown';
|
|
107
|
+
|
|
108
|
+
@Component({
|
|
109
|
+
selector: 'app-root',
|
|
110
|
+
templateUrl: './app.component.html'
|
|
111
|
+
})
|
|
112
|
+
export class AppComponent implements OnInit {
|
|
113
|
+
dropdownList = [];
|
|
114
|
+
selectedItems = [];
|
|
115
|
+
dropdownSettings: IDropdownSettings = {};
|
|
116
|
+
|
|
117
|
+
ngOnInit(): void {
|
|
118
|
+
this.dropdownList = [
|
|
119
|
+
{ item_id: 1, item_text: 'Mumbai' },
|
|
120
|
+
{ item_id: 2, item_text: 'Bangalore' },
|
|
121
|
+
{ item_id: 3, item_text: 'Pune' },
|
|
122
|
+
{ item_id: 4, item_text: 'Navsari' },
|
|
123
|
+
{ item_id: 5, item_text: 'New Delhi' }
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
this.selectedItems = [
|
|
127
|
+
{ item_id: 3, item_text: 'Pune' },
|
|
128
|
+
{ item_id: 4, item_text: 'Navsari' }
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
this.dropdownSettings = {
|
|
132
|
+
singleSelection: false,
|
|
133
|
+
idField: 'item_id',
|
|
134
|
+
textField: 'item_text',
|
|
135
|
+
selectAllText: 'Select All',
|
|
136
|
+
unSelectAllText: 'UnSelect All',
|
|
137
|
+
itemsShowLimit: 3,
|
|
138
|
+
allowSearchFilter: true
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
onItemSelect(item: unknown): void {
|
|
143
|
+
console.log(item);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
onSelectAll(items: unknown): void {
|
|
147
|
+
console.log(items);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
```html
|
|
153
|
+
<ng-multiselect-dropdown
|
|
154
|
+
[placeholder]="'Select options'"
|
|
155
|
+
[settings]="dropdownSettings"
|
|
156
|
+
[data]="dropdownList"
|
|
157
|
+
[(ngModel)]="selectedItems"
|
|
158
|
+
(onSelect)="onItemSelect($event)"
|
|
159
|
+
(onSelectAll)="onSelectAll($event)">
|
|
160
|
+
</ng-multiselect-dropdown>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Settings
|
|
164
|
+
|
|
165
|
+
| Setting | Type | Description | Default |
|
|
166
|
+
| :--- | :--- | :--- | :--- |
|
|
167
|
+
| `singleSelection` | `boolean` | Enables single-selection mode. | `false` |
|
|
168
|
+
| `placeholder` | `string` | Placeholder text shown when nothing is selected. | `'Select'` |
|
|
169
|
+
| `disabled` | `boolean` | Disables the dropdown. | `false` |
|
|
170
|
+
| `data` | `Array<any>` | Data source for the dropdown. | `[]` |
|
|
171
|
+
| `idField` | `string` | Field used as the item identifier. | `'id'` |
|
|
172
|
+
| `textField` | `string` | Field used as the item label. | `'text'` |
|
|
173
|
+
| `disabledField` | `string` | Field used to mark disabled items. | `'isDisabled'` |
|
|
174
|
+
| `enableCheckAll` | `boolean` | Shows the select-all option. | `true` |
|
|
175
|
+
| `selectAllText` | `string` | Label for the select-all option. | `'Select All'` |
|
|
176
|
+
| `unSelectAllText` | `string` | Label for the clear-all option. | `'UnSelect All'` |
|
|
177
|
+
| `allowSearchFilter` | `boolean` | Enables the search box. | `false` |
|
|
178
|
+
| `searchPlaceholderText` | `string` | Search input placeholder text. | `'Search'` |
|
|
179
|
+
| `clearSearchFilter` | `boolean` | Clears search text when the dropdown closes. | `true` |
|
|
180
|
+
| `maxHeight` | `number` | Max dropdown list height in pixels. | `197` |
|
|
181
|
+
| `itemsShowLimit` | `number` | Limits how many selected items appear in the control. | `999999999999` |
|
|
182
|
+
| `limitSelection` | `number` | Maximum allowed selected items. | `-1` |
|
|
183
|
+
| `noDataAvailablePlaceholderText` | `string` | Message shown when there is no data. | `'No data available'` |
|
|
184
|
+
| `noFilteredDataAvailablePlaceholderText` | `string` | Message shown when search returns no results. | `'No filtered data available'` |
|
|
185
|
+
| `closeDropDownOnSelection` | `boolean` | Closes the dropdown after selection in single mode. | `false` |
|
|
186
|
+
| `showSelectedItemsAtTop` | `boolean` | Moves selected items to the top of the list. | `false` |
|
|
187
|
+
| `defaultOpen` | `boolean` | Opens the dropdown by default. | `false` |
|
|
188
|
+
| `allowRemoteDataSearch` | `boolean` | Keeps remote search available even when data is empty. | `false` |
|
|
189
|
+
|
|
190
|
+
## Events
|
|
191
|
+
|
|
192
|
+
- `onSelect`: Fires when one item is selected.
|
|
193
|
+
- `onDeSelect`: Fires when one item is deselected.
|
|
194
|
+
- `onSelectAll`: Fires when all visible items are selected.
|
|
195
|
+
- `onDeSelectAll`: Fires when all items are deselected.
|
|
196
|
+
- `onFilterChange`: Fires when the search text changes.
|
|
197
|
+
- `onDropDownClose`: Fires when the dropdown closes.
|
|
198
|
+
|
|
199
|
+
## Theming
|
|
200
|
+
|
|
201
|
+
The package ships with a theme file at:
|
|
202
|
+
|
|
203
|
+
```text
|
|
204
|
+
node_modules/@revivejs/ng-multiselect-dropdown/themes/ng-multiselect-dropdown.theme.scss
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
For step-by-step theme customization, see [custom-theme.md](https://github.com/alexandroit/ng-multiselect-dropdown/blob/master/custom-theme.md).
|
|
208
|
+
|
|
209
|
+
## Run Locally
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
npm install
|
|
213
|
+
npm start
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The local demo runs at `http://localhost:4201/`.
|
|
217
|
+
|
|
218
|
+
## Publishing
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
npm run build:package
|
|
222
|
+
npm run pack:check
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
This prepares the publishable package in `dist-lib/` with the scoped package name `@revivejs/ng-multiselect-dropdown` and performs a dry-run tarball check without publishing.
|
|
226
|
+
|
|
227
|
+
## License
|
|
228
|
+
|
|
229
|
+
MIT License.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Directive, Output, EventEmitter, HostListener } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export class ClickOutsideDirective {
|
|
4
|
+
_elementRef;
|
|
5
|
+
constructor(_elementRef) {
|
|
6
|
+
this._elementRef = _elementRef;
|
|
7
|
+
}
|
|
8
|
+
clickOutside = new EventEmitter();
|
|
9
|
+
onClick(event, targetElement) {
|
|
10
|
+
if (!targetElement) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const clickedInside = this._elementRef.nativeElement.contains(targetElement);
|
|
14
|
+
if (!clickedInside) {
|
|
15
|
+
this.clickOutside.emit(event);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.7", ngImport: i0, type: ClickOutsideDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
19
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.1.7", type: ClickOutsideDirective, selector: "[clickOutside]", outputs: { clickOutside: "clickOutside" }, host: { listeners: { "document:click": "onClick($event,$event.target)" } }, ngImport: i0 });
|
|
20
|
+
}
|
|
21
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.7", ngImport: i0, type: ClickOutsideDirective, decorators: [{
|
|
22
|
+
type: Directive,
|
|
23
|
+
args: [{
|
|
24
|
+
selector: '[clickOutside]'
|
|
25
|
+
}]
|
|
26
|
+
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { clickOutside: [{
|
|
27
|
+
type: Output
|
|
28
|
+
}], onClick: [{
|
|
29
|
+
type: HostListener,
|
|
30
|
+
args: ['document:click', ['$event', '$event.target']]
|
|
31
|
+
}] } });
|
|
32
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpY2stb3V0c2lkZS5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbmctbXVsdGlzZWxlY3QtZHJvcGRvd24vc3JjL2NsaWNrLW91dHNpZGUuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxTQUFTLEVBQWMsTUFBTSxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUMsTUFBTSxlQUFlLENBQUM7O0FBS3hGLE1BQU0sT0FBTyxxQkFBcUI7SUFDVjtJQUFwQixZQUFvQixXQUF1QjtRQUF2QixnQkFBVyxHQUFYLFdBQVcsQ0FBWTtJQUMzQyxDQUFDO0lBR00sWUFBWSxHQUFHLElBQUksWUFBWSxFQUFjLENBQUM7SUFHOUMsT0FBTyxDQUFDLEtBQWlCLEVBQUUsYUFBMEI7UUFDeEQsSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUNoQixPQUFPO1NBQ1Y7UUFFRCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDN0UsSUFBSSxDQUFDLGFBQWEsRUFBRTtZQUNoQixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUNqQztJQUNMLENBQUM7dUdBakJRLHFCQUFxQjsyRkFBckIscUJBQXFCOzsyRkFBckIscUJBQXFCO2tCQUhqQyxTQUFTO21CQUFDO29CQUNQLFFBQVEsRUFBRSxnQkFBZ0I7aUJBQzdCO2lHQU1VLFlBQVk7c0JBRGxCLE1BQU07Z0JBSUEsT0FBTztzQkFEYixZQUFZO3VCQUFDLGdCQUFnQixFQUFFLENBQUMsUUFBUSxFQUFFLGVBQWUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7RGlyZWN0aXZlLCBFbGVtZW50UmVmLCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgSG9zdExpc3RlbmVyfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQERpcmVjdGl2ZSh7XG4gICAgc2VsZWN0b3I6ICdbY2xpY2tPdXRzaWRlXSdcbn0pXG5leHBvcnQgY2xhc3MgQ2xpY2tPdXRzaWRlRGlyZWN0aXZlIHtcbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9lbGVtZW50UmVmOiBFbGVtZW50UmVmKSB7XG4gICAgfVxuXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIGNsaWNrT3V0c2lkZSA9IG5ldyBFdmVudEVtaXR0ZXI8TW91c2VFdmVudD4oKTtcblxuICAgIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmNsaWNrJywgWyckZXZlbnQnLCAnJGV2ZW50LnRhcmdldCddKVxuICAgIHB1YmxpYyBvbkNsaWNrKGV2ZW50OiBNb3VzZUV2ZW50LCB0YXJnZXRFbGVtZW50OiBIVE1MRWxlbWVudCk6IHZvaWQge1xuICAgICAgICBpZiAoIXRhcmdldEVsZW1lbnQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNsaWNrZWRJbnNpZGUgPSB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuY29udGFpbnModGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIGlmICghY2xpY2tlZEluc2lkZSkge1xuICAgICAgICAgICAgdGhpcy5jbGlja091dHNpZGUuZW1pdChldmVudCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Pipe } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export class ListFilterPipe {
|
|
4
|
+
transform(items, filter) {
|
|
5
|
+
if (!items || !filter) {
|
|
6
|
+
return items;
|
|
7
|
+
}
|
|
8
|
+
return items.filter((item) => this.applyFilter(item, filter));
|
|
9
|
+
}
|
|
10
|
+
applyFilter(item, filter) {
|
|
11
|
+
if (typeof item.text === 'string' && typeof filter.text === 'string') {
|
|
12
|
+
return !(filter.text && item.text && item.text.toLowerCase().indexOf(filter.text.toLowerCase()) === -1);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
return !(filter.text && item.text && item.text.toString().toLowerCase().indexOf(filter.text.toString().toLowerCase()) === -1);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.7", ngImport: i0, type: ListFilterPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
19
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "16.1.7", ngImport: i0, type: ListFilterPipe, name: "multiSelectFilter", pure: false });
|
|
20
|
+
}
|
|
21
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.7", ngImport: i0, type: ListFilterPipe, decorators: [{
|
|
22
|
+
type: Pipe,
|
|
23
|
+
args: [{
|
|
24
|
+
name: 'multiSelectFilter',
|
|
25
|
+
pure: false
|
|
26
|
+
}]
|
|
27
|
+
}] });
|
|
28
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC1maWx0ZXIucGlwZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9uZy1tdWx0aXNlbGVjdC1kcm9wZG93bi9zcmMvbGlzdC1maWx0ZXIucGlwZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFpQixNQUFNLGVBQWUsQ0FBQzs7QUFRcEQsTUFBTSxPQUFPLGNBQWM7SUFDdkIsU0FBUyxDQUFDLEtBQWlCLEVBQUUsTUFBZ0I7UUFDekMsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNuQixPQUFPLEtBQUssQ0FBQztTQUNoQjtRQUNELE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQWMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUM1RSxDQUFDO0lBRUQsV0FBVyxDQUFDLElBQWMsRUFBRSxNQUFnQjtRQUN4QyxJQUFJLE9BQU8sSUFBSSxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksT0FBTyxNQUFNLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRTtZQUNsRSxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDM0c7YUFBTTtZQUNILE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNqSTtJQUNMLENBQUM7dUdBZFEsY0FBYztxR0FBZCxjQUFjOzsyRkFBZCxjQUFjO2tCQUoxQixJQUFJO21CQUFDO29CQUNGLElBQUksRUFBRSxtQkFBbUI7b0JBQ3pCLElBQUksRUFBRSxLQUFLO2lCQUNkIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGlwZSwgUGlwZVRyYW5zZm9ybSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBMaXN0SXRlbSB9IGZyb20gJy4vbXVsdGlzZWxlY3QubW9kZWwnO1xuXG5AUGlwZSh7XG4gICAgbmFtZTogJ211bHRpU2VsZWN0RmlsdGVyJyxcbiAgICBwdXJlOiBmYWxzZVxufSlcbmV4cG9ydCBjbGFzcyBMaXN0RmlsdGVyUGlwZSBpbXBsZW1lbnRzIFBpcGVUcmFuc2Zvcm0ge1xuICAgIHRyYW5zZm9ybShpdGVtczogTGlzdEl0ZW1bXSwgZmlsdGVyOiBMaXN0SXRlbSk6IExpc3RJdGVtW10ge1xuICAgICAgICBpZiAoIWl0ZW1zIHx8ICFmaWx0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBpdGVtcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXRlbXMuZmlsdGVyKChpdGVtOiBMaXN0SXRlbSkgPT4gdGhpcy5hcHBseUZpbHRlcihpdGVtLCBmaWx0ZXIpKTtcbiAgICB9XG5cbiAgICBhcHBseUZpbHRlcihpdGVtOiBMaXN0SXRlbSwgZmlsdGVyOiBMaXN0SXRlbSk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAodHlwZW9mIGl0ZW0udGV4dCA9PT0gJ3N0cmluZycgJiYgdHlwZW9mIGZpbHRlci50ZXh0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuICEoZmlsdGVyLnRleHQgJiYgaXRlbS50ZXh0ICYmIGl0ZW0udGV4dC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoZmlsdGVyLnRleHQudG9Mb3dlckNhc2UoKSkgPT09IC0xKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAhKGZpbHRlci50ZXh0ICYmIGl0ZW0udGV4dCAmJiBpdGVtLnRleHQudG9TdHJpbmcoKS50b0xvd2VyQ2FzZSgpLmluZGV4T2YoZmlsdGVyLnRleHQudG9TdHJpbmcoKS50b0xvd2VyQ2FzZSgpKSA9PT0gLTEpO1xuICAgICAgICB9XG4gICAgfVxufVxuIl19
|