@piserve-tech/drop-down 1.2.108 → 1.2.110

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.
@@ -0,0 +1,374 @@
1
+ .dropdown {
2
+ background: white;
3
+ border-radius: 6px;
4
+ .dropdown-field {
5
+ background: white;
6
+ border-radius: 6px;
7
+ position: relative;
8
+ cursor: pointer;
9
+ .selected {
10
+ &.selectedList {
11
+ display: flex;
12
+ flex-wrap: wrap;
13
+ max-height: 80px;
14
+ overflow-y: auto;
15
+ overflow-x: hidden;
16
+ }
17
+ .selected-item {
18
+ background: #e3e3da;
19
+ display: inline;
20
+ margin: 5px;
21
+ padding: 2px;
22
+ border-radius: 5px;
23
+ font-size: small;
24
+ }
25
+ .remaining-items {
26
+ margin: 5px;
27
+ padding: 2px;
28
+ font-size: smaller;
29
+ display: block;
30
+ }
31
+ }
32
+ .input-field {
33
+ .dropdown_text {
34
+ width: 100%;
35
+ border: none;
36
+ padding: 2px;
37
+ margin-left: 3px;
38
+ margin-right: 3px;
39
+ outline: none;
40
+ box-sizing: border-box;
41
+ font-style: normal;
42
+ @media (max-width: 576px) {
43
+ width: 53%;
44
+ margin-left: 3px;
45
+ padding-left: 2px;
46
+ }
47
+ @media (max-width: 420px) {
48
+ width: 53%;
49
+ margin-left: 3px;
50
+ padding-left: 2px;
51
+ }
52
+ @media only screen and (min-width: 576px) {
53
+ height: 25px;
54
+ }
55
+ @media only screen and (min-width: 992px) {
56
+ height: 30px;
57
+ }
58
+ @media only screen and (min-width: 1200px) {
59
+ height: 35px;
60
+ }
61
+ }
62
+ }
63
+ &.closed {
64
+ border: 1px solid #d8d8d8;
65
+ }
66
+ &.opened {
67
+ border-bottom: 1px solid #d8d8d8;
68
+ }
69
+ }
70
+ .dropdown-items {
71
+ overflow-y: auto;
72
+ overflow-x: auto;
73
+ position: absolute !important;
74
+ top: 100%;
75
+ left: 0;
76
+ width: 100%;
77
+ background: white;
78
+ z-index: 9999999;
79
+ border: solid 1px #dbdbdb;
80
+ box-shadow: 0px 4px 4px -5px #00000040;
81
+ transition: transform 0.3s ease-out;
82
+ scroll-behavior: smooth;
83
+ cursor: pointer;
84
+ @media only screen and (min-width: 276px) {
85
+ max-height: 150px;
86
+ padding: 3px;
87
+ }
88
+ @media only screen and (min-width: 576px) {
89
+ max-height: 150px;
90
+ padding: 3px;
91
+ }
92
+ @media only screen and (min-width: 992px) {
93
+ max-height: 150px;
94
+ padding: 5px;
95
+ }
96
+ @media only screen and (min-width: 1441px) {
97
+ max-height: 200px;
98
+ padding: 7px;
99
+ }
100
+ .create_button {
101
+ text-decoration: none;
102
+ cursor: pointer;
103
+ @media only screen and (min-width: 576px) {
104
+ padding-left: 8px;
105
+ }
106
+ @media only screen and (min-width: 992px) {
107
+ padding-left: 8px;
108
+ }
109
+ @media only screen and (min-width: 1200px) {
110
+ padding-left: 8px;
111
+ }
112
+ }
113
+ .items {
114
+ text-decoration: none;
115
+ color: inherit;
116
+ // line-height: 41px;
117
+ position: relative;
118
+ cursor: pointer;
119
+ @media only screen and (min-width: 576px) {
120
+ padding-left: 8px;
121
+ font-size: small;
122
+ }
123
+ @media only screen and (min-width: 992px) {
124
+ padding-left: 8px;
125
+ }
126
+ @media only screen and (min-width: 1200px) {
127
+ padding-left: 8px;
128
+ font-size: small;
129
+ }
130
+ &:hover {
131
+ background: #ebedef;
132
+ border-radius: 6px;
133
+ }
134
+ &:hover button {
135
+ visibility: visible;
136
+ }
137
+ .dropdown_buttons {
138
+ display: inline;
139
+ }
140
+ button {
141
+ border: 0;
142
+ background: transparent;
143
+ visibility: hidden;
144
+ }
145
+ }
146
+ }
147
+ &.opened {
148
+ border: 1px #d8d8d8 solid;
149
+ }
150
+ }
151
+
152
+ ::-webkit-scrollbar {
153
+ width: 6px;
154
+ height: 6px;
155
+ }
156
+
157
+ ::-webkit-scrollbar-track {
158
+ background-color: transparent;
159
+ }
160
+
161
+ ::-webkit-scrollbar-thumb {
162
+ background-color: #b2b2b2;
163
+ border-radius: 6px;
164
+ }
165
+
166
+ .space {
167
+ width: 10px;
168
+ }
169
+
170
+ .item-details {
171
+ display: flex;
172
+ align-items: center;
173
+ justify-content: space-between;
174
+ }
175
+
176
+ .icon-size {
177
+ width: 30px;
178
+ height: 30px;
179
+ margin-right: 7px;
180
+ }
181
+ .smallSpace {
182
+ width: 3px;
183
+ }
184
+
185
+ .selected-icon-size {
186
+ width: 25px;
187
+ height: 20px;
188
+ margin-left: 10px;
189
+ @media (max-width: 576px) {
190
+ width: 21px;
191
+ height: 15px;
192
+ margin-right: 7px;
193
+ margin-bottom: 1px;
194
+ }
195
+ }
196
+
197
+ .multiSelected-icon-size {
198
+ width: 25px;
199
+ height: 20px;
200
+ margin-left: 1px;
201
+ margin-bottom: 1px;
202
+ margin-right: 3px;
203
+ }
204
+
205
+ .flexSection {
206
+ display: flex;
207
+ justify-content: space-between;
208
+ }
209
+
210
+ .dropdown-down-arrow,
211
+ .dropdown-up-arrow {
212
+ width: 20px;
213
+ height: 20px;
214
+ display: flex;
215
+ align-items: center;
216
+ justify-content: center;
217
+ cursor: pointer;
218
+ }
219
+
220
+ .deselect {
221
+ width: 20px;
222
+ height: 20px;
223
+ display: flex;
224
+ align-items: center;
225
+ justify-content: center;
226
+ cursor: pointer;
227
+ }
228
+
229
+ .dropdown-down-arrow {
230
+ cursor: pointer;
231
+ &.opened {
232
+ display: none;
233
+ }
234
+ &.closed {
235
+ display: block;
236
+ }
237
+ }
238
+ .dropdown-up-arrow {
239
+ cursor: pointer;
240
+ &.closed {
241
+ display: none;
242
+ }
243
+ }
244
+ .close-icon {
245
+ margin-left: 8px;
246
+ margin-right: 5px;
247
+ }
248
+
249
+ .iconSection {
250
+ display: flex;
251
+ flex-direction: row-reverse;
252
+ padding: 1px;
253
+ position: relative;
254
+ justify-content: center;
255
+ align-items: center;
256
+ }
257
+ .dropdown-icons-container {
258
+ display: flex;
259
+ gap: 10px;
260
+ }
261
+
262
+ .item-details {
263
+ display: flex;
264
+ align-items: center;
265
+ justify-content: space-between;
266
+ }
267
+
268
+ .content-wrapper {
269
+ display: flex;
270
+ align-items: center;
271
+ gap: 8px;
272
+ flex: 1;
273
+ }
274
+
275
+ .text-content {
276
+ display: flex;
277
+ flex-direction: column;
278
+ }
279
+
280
+ .item-label {
281
+ font-size: 14px;
282
+ font-weight: 400;
283
+ line-height: 1.3;
284
+ }
285
+
286
+ .item-sublabel {
287
+ font-size: 11px;
288
+ color: #666;
289
+ line-height: 1.2;
290
+ }
291
+
292
+ .dropdown_buttons {
293
+ display: flex;
294
+ gap: 4px;
295
+ }
296
+
297
+ .dropdown_buttons.empty::after {
298
+ content: "";
299
+ display: inline-block;
300
+ width: 4px;
301
+ height: 1px;
302
+ }
303
+
304
+ .compact {
305
+ line-height: 32px;
306
+ }
307
+
308
+ .expanded {
309
+ line-height: 41px;
310
+ }
311
+
312
+ .input-field {
313
+ width: 100%;
314
+ }
315
+
316
+ .input-with-icon {
317
+ display: flex;
318
+ align-items: center;
319
+ gap: 8px;
320
+ width: 100%;
321
+ }
322
+
323
+ .selected-icon-size {
324
+ width: 20px;
325
+ height: 20px;
326
+ flex-shrink: 0;
327
+ }
328
+
329
+ .dropdown_text.inline-input {
330
+ flex: 1;
331
+ border: none;
332
+ outline: none;
333
+ padding: 0;
334
+ background: transparent;
335
+ font-family: inherit;
336
+ font-size: inherit;
337
+ color: inherit;
338
+ }
339
+ .single-input {
340
+ width: 80%;
341
+ white-space: nowrap;
342
+ }
343
+
344
+ .item-label {
345
+ font-size: 14px;
346
+ line-height: 1.4;
347
+ color: #333;
348
+ }
349
+
350
+ .highlight-text {
351
+ font-weight: 600;
352
+ background-repeat: no-repeat;
353
+ background-size: 100% 0.3em;
354
+ background-position: 0 88%;
355
+ padding: 0.1em 0.05em;
356
+ border-radius: 2px;
357
+ color: #1a1a1a;
358
+ transition: all 0.2s ease-in-out;
359
+ }
360
+
361
+
362
+ .dropdown .dropdown-field .input-field .dropdown_text {
363
+ background: #ffff !important;
364
+ }
365
+
366
+ .dropdown.dropdown-disabled .dropdown-field .input-field .dropdown_text {
367
+ background: #e9ecef !important;
368
+ pointer-events: none;
369
+ }
370
+
371
+ .dropdown.dropdown-disabled .dropdown-field {
372
+ background: #e9ecef !important;
373
+ pointer-events: none;
374
+ }
@@ -0,0 +1,21 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { DropdownComponent } from './dropdown.component';
4
+
5
+ describe('DropdownComponent', () => {
6
+ let component: DropdownComponent;
7
+ let fixture: ComponentFixture<DropdownComponent>;
8
+
9
+ beforeEach(() => {
10
+ TestBed.configureTestingModule({
11
+ declarations: [DropdownComponent]
12
+ });
13
+ fixture = TestBed.createComponent(DropdownComponent);
14
+ component = fixture.componentInstance;
15
+ fixture.detectChanges();
16
+ });
17
+
18
+ it('should create', () => {
19
+ expect(component).toBeTruthy();
20
+ });
21
+ });
@@ -0,0 +1,226 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ ChangeDetectorRef,
4
+ Component,
5
+ ElementRef,
6
+ EventEmitter,
7
+ HostListener,
8
+ Input,
9
+ OnInit,
10
+ Output,
11
+ SimpleChanges,
12
+ ViewChild,
13
+ ViewEncapsulation,
14
+ } from "@angular/core";
15
+ import { DropdownItem } from "./dropdown.model";
16
+ import { v4 as uuidv4 } from 'uuid';
17
+
18
+ @Component({
19
+ selector: "lib-dropdown",
20
+ templateUrl: "./dropdown.component.html",
21
+ styleUrls: ["./dropdown.component.scss"],
22
+ encapsulation: ViewEncapsulation.None,
23
+ changeDetection: ChangeDetectionStrategy.OnPush,
24
+ })
25
+ export class DropdownComponent implements OnInit {
26
+ @Input() multiple!: boolean;
27
+ @Input() selectedItems: any[] = [];
28
+ @Input() placeholder: String = "";
29
+ @Input() showCreateNew!: boolean;
30
+ @Input() selectedValues: string = "";
31
+ @Input() customButtons: {
32
+ label: string;
33
+ icon: string;
34
+ color: string;
35
+ action: () => void;
36
+ }[] = [];
37
+ @Input() showBorder: boolean = true;
38
+ @Input() disable: boolean = false;
39
+ @Output() buttonClick: EventEmitter<Event> = new EventEmitter<Event>();
40
+ @Output() selectedItemsChange: EventEmitter<any[]> = new EventEmitter<
41
+ any[]
42
+ >();
43
+ @Output() onDropdownScroll: EventEmitter<Event> = new EventEmitter<Event>();
44
+ @Output() onCreateNew: EventEmitter<Event> = new EventEmitter<Event>();
45
+ @Output() onSearch: EventEmitter<string> = new EventEmitter<string>();
46
+ //subLabel
47
+ @Input() showSubLabel: boolean = false;
48
+ dropdownId = uuidv4();
49
+ dropdownOpened: boolean = false;
50
+ selectedItem: any;
51
+ selectedItemName: string = "";
52
+ selectedItemImage: string = "";
53
+ originalItems: DropdownItem[] = [];
54
+ searchTerm: string = "";
55
+ initialized: boolean = false;
56
+ searchText: string = "";
57
+ _filteredItems: DropdownItem[] = [];
58
+
59
+ private _items: DropdownItem[] = [];
60
+
61
+ @Input()
62
+ set items(value: DropdownItem[]) {
63
+ this._items = value || [];
64
+ this.originalItems = this._items.slice();
65
+ this._filteredItems = this._items.slice(); // use a separate variable for rendering
66
+ this.cdr.markForCheck();
67
+ }
68
+ get items(): DropdownItem[] {
69
+ return this._items;
70
+ }
71
+
72
+ constructor(private cdr: ChangeDetectorRef) {}
73
+
74
+ ngOnInit(): void {}
75
+
76
+
77
+
78
+ ngOnChanges(changes: SimpleChanges) {
79
+ if (changes["selectedItems"]) {
80
+ const item = changes["selectedItems"]["currentValue"];
81
+ this.selectedItems = item;
82
+ this.selectedItemName = this.selectedItems[0]?.label;
83
+ this.selectedItemImage = this.selectedItems[0]?.image;
84
+ }
85
+ if (changes["items"]) {
86
+ this.initialize();
87
+ this.originalItems = this.items.slice();
88
+ this.cdr.markForCheck();
89
+ }
90
+ if (changes["selectedValues"]) {
91
+ this.selectedItemName = this.selectedValues;
92
+ }
93
+ }
94
+
95
+ initialize() {
96
+ setTimeout(() => {
97
+ if (this.selectedItems && this.selectedItems.length > 0) {
98
+ if (!this.multiple) {
99
+ this.searchText = "";
100
+ this.selectedItemName = this.selectedItems[0]?.label;
101
+ this.selectedItemImage = this.selectedItems[0]?.image;
102
+ }
103
+ }
104
+ }, 1000);
105
+ const uniqueItems = this.items.filter(
106
+ (selected, index, self) =>
107
+ index === self.findIndex((t) => t.value === selected.value)
108
+ );
109
+
110
+ this.items = uniqueItems;
111
+ }
112
+
113
+ openDropdown() {
114
+ this.dropdownOpened = !this.dropdownOpened;
115
+ const inputId = `searchInput-${this.dropdownId}`;
116
+ const inputEl = document.getElementById(inputId);
117
+ setTimeout(() => {
118
+ inputEl?.focus();
119
+ }, 0);
120
+
121
+ }
122
+
123
+ @ViewChild("dropdownItems") dropdownitems!: ElementRef<any>;
124
+ dropdownScroll(event: any): void {
125
+ if (this.onDropdownScroll.observed) {
126
+ this.onDropdownScroll.emit(event);
127
+ this.cdr.markForCheck();
128
+ }
129
+ }
130
+
131
+ selectItem(item: any) {
132
+ if (this.multiple) {
133
+ if (!this.selectedItems.includes(item)) {
134
+ this.selectedItems.push(item);
135
+ this.selectedItemsChange.emit(this.selectedItems);
136
+ } else {
137
+ this.selectedItems = this.selectedItems.filter(
138
+ (selected: any) => selected !== item
139
+ );
140
+ this.selectedItemsChange.emit(this.selectedItems);
141
+ }
142
+ } else {
143
+ this.searchText = "";
144
+ this.selectedItems[0] = item;
145
+ this.selectedItemName = this.selectedItems[0]?.label;
146
+ this.selectedItemImage = this.selectedItems[0]?.image;
147
+ this.dropdownOpened = false;
148
+ this.selectedItemsChange.emit(this.selectedItems);
149
+ }
150
+ }
151
+
152
+ unselectItem(item: any): void {
153
+ this.selectedItems = this.selectedItems.filter(
154
+ (selected: any) => selected !== item
155
+ );
156
+ this.selectedItemsChange.emit(this.selectedItems);
157
+ }
158
+
159
+ unselectAll() {
160
+ this.selectedItems = [];
161
+ this.selectedItemName = "";
162
+ this.selectedItemImage = "";
163
+ this.selectedItemsChange.emit(this.selectedItems);
164
+ this.cdr.markForCheck();
165
+ }
166
+
167
+ @ViewChild("dropdown") dropdown!: ElementRef;
168
+ @HostListener("document:click", ["$event"])
169
+ onDocumentClick(event: Event): void {
170
+ const isClickInsideDropdown = this.dropdown.nativeElement.contains(
171
+ event.target
172
+ );
173
+
174
+ if (!isClickInsideDropdown) {
175
+ this.dropdownOpened = false;
176
+ }
177
+ }
178
+
179
+ createNew() {
180
+ this.onCreateNew.emit();
181
+ this.dropdownOpened = false;
182
+ }
183
+
184
+ search(event: any): void {
185
+ const keyCode = event.keyCode;
186
+ this.dropdownOpened = true;
187
+ this.searchTerm = event.target.value.toLowerCase();
188
+ if (!this.onSearch.observed) {
189
+ if (this.searchTerm.trim() === "") {
190
+ if (!this.multiple) {
191
+ this.unselectAll();
192
+ }
193
+ this._filteredItems = this.originalItems.slice();
194
+ } else {
195
+ const lowerCaseSearchTerm = this.searchTerm.toLowerCase();
196
+ this._filteredItems = this.originalItems.filter(
197
+ (item) =>
198
+ item.label.toLowerCase().includes(lowerCaseSearchTerm) ||
199
+ (item.value &&
200
+ item.value.toLowerCase().includes(lowerCaseSearchTerm))
201
+ );
202
+ }
203
+ } else {
204
+ this.onSearch.emit(this.searchTerm);
205
+ }
206
+ }
207
+
208
+ handleButtonClick(action: () => void): void {
209
+ action();
210
+ this.buttonClick.emit();
211
+ }
212
+
213
+ highlightMatch(text: string): string {
214
+ const search = this.searchText?.trim() || this.searchTerm?.trim();
215
+ if (!search || !text) return text;
216
+
217
+ const index = text.toLowerCase().indexOf(search.toLowerCase());
218
+ if (index === -1) return text;
219
+
220
+ const before = text.substring(0, index);
221
+ const match = text.substring(index, index + search.length);
222
+ const after = text.substring(index + search.length);
223
+
224
+ return `${before}<span class="highlight-text">${match}</span>${after}`;
225
+ }
226
+ }
@@ -1,6 +1,7 @@
1
- export interface DropdownItem {
2
- value: string;
3
- label: string;
4
- image: string;
5
- subLabel?: string;
6
- }
1
+ export interface DropdownItem {
2
+ value: string;
3
+ label: string;
4
+ image: string;
5
+ subLabel?: string
6
+ }
7
+
@@ -0,0 +1,20 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { DropdownComponent } from './dropdown.component';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { CommonModule } from '@angular/common';
5
+
6
+
7
+
8
+ @NgModule({
9
+ declarations: [
10
+ DropdownComponent
11
+ ],
12
+ imports: [
13
+ FormsModule,
14
+ CommonModule,
15
+ ],
16
+ exports: [
17
+ DropdownComponent
18
+ ]
19
+ })
20
+ export class DropdownModule { }
@@ -0,0 +1,16 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { DropdownService } from './dropdown.service';
4
+
5
+ describe('DropdownService', () => {
6
+ let service: DropdownService;
7
+
8
+ beforeEach(() => {
9
+ TestBed.configureTestingModule({});
10
+ service = TestBed.inject(DropdownService);
11
+ });
12
+
13
+ it('should be created', () => {
14
+ expect(service).toBeTruthy();
15
+ });
16
+ });
@@ -0,0 +1,9 @@
1
+ import { Injectable } from '@angular/core';
2
+
3
+ @Injectable({
4
+ providedIn: 'root'
5
+ })
6
+ export class DropdownService {
7
+
8
+ constructor() { }
9
+ }
@@ -1,3 +1,7 @@
1
- export * from './lib/dropdown.service';
2
- export * from './lib/dropdown.component';
3
- export * from './lib/dropdown.module';
1
+ /*
2
+ * Public API Surface of dropdown
3
+ */
4
+
5
+ export * from './lib/dropdown.service';
6
+ export * from './lib/dropdown.component';
7
+ export * from './lib/dropdown.module';
@@ -0,0 +1,14 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "../../tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "../../out-tsc/lib",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "inlineSources": true,
9
+ "types": []
10
+ },
11
+ "exclude": [
12
+ "**/*.spec.ts"
13
+ ]
14
+ }
@@ -0,0 +1,10 @@
1
+ /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
+ {
3
+ "extends": "./tsconfig.lib.json",
4
+ "compilerOptions": {
5
+ "declarationMap": false
6
+ },
7
+ "angularCompilerOptions": {
8
+ "compilationMode": "partial"
9
+ }
10
+ }