verben-ng-ui 0.0.1
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/README.md +24 -0
- package/ng-package.json +10 -0
- package/package.json +34 -0
- package/src/lib/Verbena-input/error.service.ts +23 -0
- package/src/lib/Verbena-input/verbena-input.component.css +59 -0
- package/src/lib/Verbena-input/verbena-input.component.html +64 -0
- package/src/lib/Verbena-input/verbena-input.component.spec.ts +25 -0
- package/src/lib/Verbena-input/verbena-input.component.ts +162 -0
- package/src/lib/Verbena-input/verbena-input.module.ts +12 -0
- package/src/lib/components/TemplateDirective.directive.ts +10 -0
- package/src/lib/components/card/card.component.css +20 -0
- package/src/lib/components/card/card.component.html +23 -0
- package/src/lib/components/card/card.component.spec.ts +23 -0
- package/src/lib/components/card/card.component.ts +33 -0
- package/src/lib/components/card/card.module.ts +10 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.css +3 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.html +1 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.ts +10 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.css +7 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.html +1 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.ts +10 -0
- package/src/lib/components/card-data-view/card-data-view.component.css +39 -0
- package/src/lib/components/card-data-view/card-data-view.component.html +29 -0
- package/src/lib/components/card-data-view/card-data-view.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/card-data-view.component.ts +66 -0
- package/src/lib/components/card-data-view/card-data-view.module.ts +20 -0
- package/src/lib/components/card-data-view/card-data.ts +7 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.css +15 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.html +4 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/left-card-data/left-card-data.component.ts +19 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.css +0 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.html +4 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.ts +12 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.css +3 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.html +1 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.spec.ts +23 -0
- package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.ts +10 -0
- package/src/lib/components/chip/ChipChangeEvent.ts +4 -0
- package/src/lib/components/chip/chip.component.css +94 -0
- package/src/lib/components/chip/chip.component.html +49 -0
- package/src/lib/components/chip/chip.component.spec.ts +23 -0
- package/src/lib/components/chip/chip.component.ts +209 -0
- package/src/lib/components/chip/chip.module.ts +24 -0
- package/src/lib/components/chip/documentation.md +26 -0
- package/src/lib/components/data-export/data-export.component.css +0 -0
- package/src/lib/components/data-export/data-export.component.html +90 -0
- package/src/lib/components/data-export/data-export.component.spec.ts +23 -0
- package/src/lib/components/data-export/data-export.component.ts +158 -0
- package/src/lib/components/data-export/data-export.module.ts +13 -0
- package/src/lib/components/data-export/data-export.service.spec.ts +16 -0
- package/src/lib/components/data-export/data-export.service.ts +152 -0
- package/src/lib/components/data-export/data-export.types.ts +21 -0
- package/src/lib/components/data-table/column.directive.spec.ts +8 -0
- package/src/lib/components/data-table/column.directive.ts +19 -0
- package/src/lib/components/data-table/data-table.component.css +0 -0
- package/src/lib/components/data-table/data-table.component.html +55 -0
- package/src/lib/components/data-table/data-table.component.spec.ts +21 -0
- package/src/lib/components/data-table/data-table.component.ts +336 -0
- package/src/lib/components/data-table/data-table.module.ts +11 -0
- package/src/lib/components/data-table/data-table.types.ts +13 -0
- package/src/lib/components/data-table/style.types.ts +55 -0
- package/src/lib/components/data-view/data-view-click-outside.directive.ts +44 -0
- package/src/lib/components/data-view/data-view.component.css +74 -0
- package/src/lib/components/data-view/data-view.component.html +161 -0
- package/src/lib/components/data-view/data-view.component.spec.ts +23 -0
- package/src/lib/components/data-view/data-view.component.ts +136 -0
- package/src/lib/components/data-view/data-view.module.ts +16 -0
- package/src/lib/components/date-picker/date-picker.component.css +65 -0
- package/src/lib/components/date-picker/date-picker.component.html +60 -0
- package/src/lib/components/date-picker/date-picker.component.specs.ts +23 -0
- package/src/lib/components/date-picker/date-picker.component.ts +143 -0
- package/src/lib/components/date-picker/date-picker.module.ts +12 -0
- package/src/lib/components/drop-down/DropdownChangeEvent.ts +4 -0
- package/src/lib/components/drop-down/DropdownLoadEvent.ts +19 -0
- package/src/lib/components/drop-down/DropdownMenuItem.ts +42 -0
- package/src/lib/components/drop-down/documentation.md +69 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.css +123 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.html +133 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.spec.ts +23 -0
- package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.ts +88 -0
- package/src/lib/components/drop-down/drop-down.component.css +317 -0
- package/src/lib/components/drop-down/drop-down.component.html +177 -0
- package/src/lib/components/drop-down/drop-down.component.spec.ts +23 -0
- package/src/lib/components/drop-down/drop-down.component.ts +757 -0
- package/src/lib/components/drop-down/drop-down.module.ts +24 -0
- package/src/lib/components/image/image.component.css +12 -0
- package/src/lib/components/image/image.component.html +18 -0
- package/src/lib/components/image/image.component.spec.ts +23 -0
- package/src/lib/components/image/image.component.ts +45 -0
- package/src/lib/components/image/image.module.ts +11 -0
- package/src/lib/components/notification/notification.component.css +3 -0
- package/src/lib/components/notification/notification.component.html +19 -0
- package/src/lib/components/notification/notification.component.spec.ts +23 -0
- package/src/lib/components/notification/notification.component.ts +77 -0
- package/src/lib/components/notification/notification.module.ts +14 -0
- package/src/lib/components/shared.module.ts +9 -0
- package/src/lib/components/sort-table/sort-table.component.css +67 -0
- package/src/lib/components/sort-table/sort-table.component.html +164 -0
- package/src/lib/components/sort-table/sort-table.component.spec.ts +23 -0
- package/src/lib/components/sort-table/sort-table.component.ts +204 -0
- package/src/lib/components/sort-table/sort-table.module.ts +11 -0
- package/src/lib/components/svg/svg.component.css +0 -0
- package/src/lib/components/svg/svg.component.html +1 -0
- package/src/lib/components/svg/svg.component.spec.ts +23 -0
- package/src/lib/components/svg/svg.component.ts +64 -0
- package/src/lib/components/svg/svg.module.ts +10 -0
- package/src/lib/components/table-filter/table-filter.component.css +93 -0
- package/src/lib/components/table-filter/table-filter.component.html +293 -0
- package/src/lib/components/table-filter/table-filter.component.spec.ts +23 -0
- package/src/lib/components/table-filter/table-filter.component.ts +221 -0
- package/src/lib/components/table-filter/table-filter.module.ts +25 -0
- package/src/lib/components/tooltip/tooltip.component.css +8 -0
- package/src/lib/components/tooltip/tooltip.component.html +13 -0
- package/src/lib/components/tooltip/tooltip.component.spec.ts +23 -0
- package/src/lib/components/tooltip/tooltip.component.ts +84 -0
- package/src/lib/components/tooltip/tooltip.module.ts +11 -0
- package/src/lib/components/verben-mail/verben-mail.component.config.ts +11 -0
- package/src/lib/components/verben-mail/verben-mail.component.css +71 -0
- package/src/lib/components/verben-mail/verben-mail.component.html +139 -0
- package/src/lib/components/verben-mail/verben-mail.component.ts +151 -0
- package/src/lib/components/verben-mail/verben-mail.module.ts +18 -0
- package/src/lib/components/visible-column/visible-column.component.css +83 -0
- package/src/lib/components/visible-column/visible-column.component.html +77 -0
- package/src/lib/components/visible-column/visible-column.component.spec.ts +23 -0
- package/src/lib/components/visible-column/visible-column.component.ts +106 -0
- package/src/lib/components/visible-column/visible-column.module.ts +11 -0
- package/src/lib/config.ts +37 -0
- package/src/lib/control-options/control-options.directive.ts +129 -0
- package/src/lib/control-options/control-options.module.ts +10 -0
- package/src/lib/convert-to-integer/convert-to-integer.directive.ts +28 -0
- package/src/lib/convert-to-integer/convert-to-integer.module.ts +10 -0
- package/src/lib/convert-to-integer/public-api.ts +1 -0
- package/src/lib/convert-to-number/convert-to-number.directive.ts +22 -0
- package/src/lib/convert-to-number/convert-to-number.module.ts +8 -0
- package/src/lib/convert-to-number/public-api.ts +1 -0
- package/src/lib/email-validator/email-validator.directive.ts +24 -0
- package/src/lib/email-validator/email-validator.module.ts +14 -0
- package/src/lib/models/column-filter.ts +5 -0
- package/src/lib/models/data-filter.ts +8 -0
- package/src/lib/models/mail-model.ts +8 -0
- package/src/lib/models/sort-filter.ts +0 -0
- package/src/lib/models/table-filter.ts +34 -0
- package/src/lib/number-range/number-range.directive.ts +35 -0
- package/src/lib/number-range/number-range.module.ts +11 -0
- package/src/lib/phone-number/phone-number.directive.ts +22 -0
- package/src/lib/phone-number/phone-number.module.ts +10 -0
- package/src/lib/phone-number/public-api.ts +1 -0
- package/src/lib/required-input/required-input.directive.ts +18 -0
- package/src/lib/required-input/required-input.module.ts +8 -0
- package/src/lib/theme-switcher/theme-switcher.directive.spec.ts +8 -0
- package/src/lib/theme-switcher/theme-switcher.directive.ts +70 -0
- package/src/lib/theme-switcher/theme-switcher.module.ts +8 -0
- package/src/lib/validate/error-message.service.ts +104 -0
- package/src/lib/validate/validate.directive.ts +110 -0
- package/src/lib/validate/validate.module.ts +17 -0
- package/src/lib/validate-input/validate-input.directive.ts +8 -0
- package/src/lib/validate-input/validate-input.module.ts +8 -0
- package/src/lib/verben-ng-ui.component.spec.ts +23 -0
- package/src/lib/verben-ng-ui.component.ts +16 -0
- package/src/lib/verben-ng-ui.service.spec.ts +16 -0
- package/src/lib/verben-ng-ui.service.ts +9 -0
- package/src/lib/verbena-badge/verbena-badge.component.css +16 -0
- package/src/lib/verbena-badge/verbena-badge.component.html +13 -0
- package/src/lib/verbena-badge/verbena-badge.component.spec.ts +25 -0
- package/src/lib/verbena-badge/verbena-badge.component.ts +18 -0
- package/src/lib/verbena-badge/verbena-badge.module.ts +10 -0
- package/src/lib/verbena-button/verbena-button.component.css +20 -0
- package/src/lib/verbena-button/verbena-button.component.html +25 -0
- package/src/lib/verbena-button/verbena-button.component.spec.ts +25 -0
- package/src/lib/verbena-button/verbena-button.component.ts +92 -0
- package/src/lib/verbena-button/verbena-button.module.ts +11 -0
- package/src/lib/verbena-switch/verbena-switch.component.css +45 -0
- package/src/lib/verbena-switch/verbena-switch.component.html +8 -0
- package/src/lib/verbena-switch/verbena-switch.component.spec.ts +25 -0
- package/src/lib/verbena-switch/verbena-switch.component.ts +31 -0
- package/src/lib/verbena-switch/verbena-switch.module.ts +10 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.css +0 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.html +19 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.spec.ts +33 -0
- package/src/lib/verbena-textarea/verbena-textarea.component.ts +44 -0
- package/src/lib/verbena-textarea/verbena-textarea.module.ts +11 -0
- package/src/public-api.ts +122 -0
- package/src/styles.css +103 -0
- package/tsconfig.lib.json +15 -0
- package/tsconfig.lib.prod.json +11 -0
- package/tsconfig.spec.json +15 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
2
|
+
import { DropdownChangeEvent } from '../drop-down/DropdownChangeEvent';
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: 'app-date-picker',
|
|
6
|
+
templateUrl: './date-picker.component.html',
|
|
7
|
+
styleUrls: ['./date-picker.component.css'],
|
|
8
|
+
})
|
|
9
|
+
export class DatePickerComponent {
|
|
10
|
+
@Input() placeholder = 'Select date';
|
|
11
|
+
@Input() format = 'MM/DD/YYYY';
|
|
12
|
+
@Input() minDate: Date | undefined;
|
|
13
|
+
@Input() maxDate: Date | undefined;
|
|
14
|
+
@Input() useDropdowns: boolean = true;
|
|
15
|
+
@Input() yearPlaceholder:string="Select a year"
|
|
16
|
+
@Input() monthPlaceholder:string="Select a year"
|
|
17
|
+
@Output() dateChange = new EventEmitter<Date>();
|
|
18
|
+
|
|
19
|
+
selectedDate: Date = new Date();
|
|
20
|
+
tempSelectedDate: Date = new Date();
|
|
21
|
+
showCalendar = false;
|
|
22
|
+
|
|
23
|
+
weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
24
|
+
months = [
|
|
25
|
+
'January',
|
|
26
|
+
'February',
|
|
27
|
+
'March',
|
|
28
|
+
'April',
|
|
29
|
+
'May',
|
|
30
|
+
'June',
|
|
31
|
+
'July',
|
|
32
|
+
'August',
|
|
33
|
+
'September',
|
|
34
|
+
'October',
|
|
35
|
+
'November',
|
|
36
|
+
'December',
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
yearRange: number[] = Array.from(
|
|
40
|
+
{ length: new Date().getFullYear() - 1960 + 1 },
|
|
41
|
+
(_, i) => 1960 + i
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
selectedMonth: number =1|| this.selectedDate.getMonth();
|
|
45
|
+
selectedYear: number = this.selectedDate.getFullYear();
|
|
46
|
+
|
|
47
|
+
get displayDate(): string {
|
|
48
|
+
return this.selectedDate
|
|
49
|
+
? this.formatDate(this.selectedDate, this.format)
|
|
50
|
+
: '';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
toggleCalendar() {
|
|
54
|
+
this.showCalendar = !this.showCalendar;
|
|
55
|
+
this.tempSelectedDate = new Date(this.selectedDate);
|
|
56
|
+
this.selectedMonth = this.tempSelectedDate.getMonth();
|
|
57
|
+
this.selectedYear = this.tempSelectedDate.getFullYear();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
previousMonth() {
|
|
61
|
+
this.selectedMonth--;
|
|
62
|
+
if (this.selectedMonth < 0) {
|
|
63
|
+
this.selectedMonth = 11;
|
|
64
|
+
this.selectedYear--;
|
|
65
|
+
}
|
|
66
|
+
this.updateTempSelectedDate();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
nextMonth() {
|
|
70
|
+
this.selectedMonth++;
|
|
71
|
+
if (this.selectedMonth > 11) {
|
|
72
|
+
this.selectedMonth = 0;
|
|
73
|
+
this.selectedYear++;
|
|
74
|
+
}
|
|
75
|
+
this.updateTempSelectedDate();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
onDropdownYearChange(event: DropdownChangeEvent): void {
|
|
79
|
+
this.selectedYear = event.value;
|
|
80
|
+
this.updateTempSelectedDate();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
onDropdownMonthChange(event: DropdownChangeEvent): void {
|
|
84
|
+
this.selectedMonth = event.value;
|
|
85
|
+
this.updateTempSelectedDate();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
updateTempSelectedDate() {
|
|
89
|
+
this.tempSelectedDate.setMonth(this.selectedMonth);
|
|
90
|
+
this.tempSelectedDate.setFullYear(this.selectedYear);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
getDaysInMonth(): Date[] {
|
|
94
|
+
const days = [];
|
|
95
|
+
const year = this.tempSelectedDate.getFullYear();
|
|
96
|
+
const month = this.tempSelectedDate.getMonth();
|
|
97
|
+
const firstDay = new Date(year, month, 1);
|
|
98
|
+
const lastDay = new Date(year, month + 1, 0);
|
|
99
|
+
|
|
100
|
+
for (let i = firstDay.getDate(); i <= lastDay.getDate(); i++) {
|
|
101
|
+
days.push(new Date(year, month, i));
|
|
102
|
+
}
|
|
103
|
+
return days;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
selectTemporaryDate(day: Date) {
|
|
107
|
+
this.tempSelectedDate = day; // Set the temporary date when user clicks on a day
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
isSelected(day: Date): boolean {
|
|
111
|
+
return (
|
|
112
|
+
day.getDate() === this.tempSelectedDate.getDate() &&
|
|
113
|
+
day.getMonth() === this.tempSelectedDate.getMonth() &&
|
|
114
|
+
day.getFullYear() === this.tempSelectedDate.getFullYear()
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
formatDate(date: Date, format: string): string {
|
|
119
|
+
const day = date.getDate().toString().padStart(2, '0');
|
|
120
|
+
const month = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
121
|
+
const year = date.getFullYear();
|
|
122
|
+
|
|
123
|
+
switch (format) {
|
|
124
|
+
case 'DD/MM/YYYY':
|
|
125
|
+
return `${day}/${month}/${year}`;
|
|
126
|
+
case 'MM/DD/YYYY':
|
|
127
|
+
default:
|
|
128
|
+
return `${month}/${day}/${year}`;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
confirm() {
|
|
133
|
+
// When OK is clicked, confirm the selected date
|
|
134
|
+
this.selectedDate = new Date(this.tempSelectedDate);
|
|
135
|
+
this.showCalendar = false;
|
|
136
|
+
this.dateChange.emit(this.selectedDate);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
cancel() {
|
|
140
|
+
// When Cancel is clicked, close the calendar without changing the date
|
|
141
|
+
this.showCalendar = false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { FormsModule } from '@angular/forms'
|
|
3
|
+
import { CommonModule } from '@angular/common';
|
|
4
|
+
import { DatePickerComponent } from './date-picker.component';
|
|
5
|
+
import { SvgModule } from "../svg/svg.module";
|
|
6
|
+
import { DropDownModule } from '../drop-down/drop-down.module';
|
|
7
|
+
@NgModule({
|
|
8
|
+
declarations:[DatePickerComponent],
|
|
9
|
+
imports: [FormsModule, CommonModule, SvgModule,DropDownModule],
|
|
10
|
+
exports: [DatePickerComponent]
|
|
11
|
+
})
|
|
12
|
+
export class DatePickerModule {}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class DropdownLoadEvent {
|
|
2
|
+
private _loadTimes: number;
|
|
3
|
+
|
|
4
|
+
get loadTimes(): number {
|
|
5
|
+
return this._loadTimes;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
this._loadTimes = 0;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
increaseLoadTime() {
|
|
13
|
+
this._loadTimes += 1;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
reset() {
|
|
17
|
+
this._loadTimes = 0;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DropdownLoadEvent } from './DropdownLoadEvent';
|
|
2
|
+
|
|
3
|
+
// interface BaseMenuItem {
|
|
4
|
+
// label: string;
|
|
5
|
+
// subLabel?: string;
|
|
6
|
+
// value: any;
|
|
7
|
+
// lazyLoad?: false;
|
|
8
|
+
// }
|
|
9
|
+
|
|
10
|
+
// interface GroupMenuItem {
|
|
11
|
+
// label: string;
|
|
12
|
+
// subLabel?: string;
|
|
13
|
+
// value: any;
|
|
14
|
+
// items: DropdownMenuItem[];
|
|
15
|
+
// lazyLoad: true;
|
|
16
|
+
// loadMore: (context: DropdownLoadEvent) => Promise<DropdownMenuItem[]>;
|
|
17
|
+
// loadTimes: DropdownLoadEvent;
|
|
18
|
+
// }
|
|
19
|
+
|
|
20
|
+
// var item: DropdownMenuItem = {
|
|
21
|
+
// label: "",
|
|
22
|
+
// value: "",
|
|
23
|
+
// lazyLoad: true,
|
|
24
|
+
// }
|
|
25
|
+
|
|
26
|
+
// export type DropdownMenuItem = BaseMenuItem | GroupMenuItem
|
|
27
|
+
|
|
28
|
+
// type DropdownMenuItem = BaseMenuItem & (BaseMenuItem['lazyLoad'] extends true ? Required<Pick<BaseMenuItem, 'loadMore' | 'loadTimes'>>: {})
|
|
29
|
+
|
|
30
|
+
export interface DropdownMenuItem {
|
|
31
|
+
label: string;
|
|
32
|
+
subLabel?: string;
|
|
33
|
+
value: any;
|
|
34
|
+
items?: DropdownMenuItem[];
|
|
35
|
+
lazyLoad?: boolean;
|
|
36
|
+
filterBy?: string;
|
|
37
|
+
search?: (
|
|
38
|
+
param: string,
|
|
39
|
+
context: DropdownLoadEvent
|
|
40
|
+
) => Promise<DropdownMenuItem[]>;
|
|
41
|
+
loadMore?: (context: DropdownLoadEvent) => Promise<DropdownMenuItem[]>;
|
|
42
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
SELECTOR - <verbena-drop-down></verbena-drop-down>
|
|
2
|
+
|
|
3
|
+
INPUTS
|
|
4
|
+
options: any[] | DropdownMenuItem[] - List containing selectable options. Can be 2-way bound to capture internal changes to the options state.
|
|
5
|
+
|
|
6
|
+
width: string- sets the width of the dropdown.
|
|
7
|
+
showHorizontalLine: boolean - Configures whether or not the horizontal line should show. Default is true.
|
|
8
|
+
horizontalLineColor: string- Configure the color of the horizontal line if shown.
|
|
9
|
+
optionLabel: string (Represents a valid property on the object type passed) - Can be set if options is a list of Objects and you want to configure what gets displayed for users to select and the value displayed when selected.
|
|
10
|
+
optionSubLabel: string (Represents a valid property on the object type passed) - Can also be set if options is a list of Objects and you want to show another property as additional information that would like to display under the label.
|
|
11
|
+
optionValue: string (Represents a valid property on the object type passed or in the case of a DropdownMenuItem array, a valid property on the value property if it's an object type) - Can be set if options is a list of Objects or a DropdownMenuItem array for which the value property is an object and you want to set what value formControls or ngModel bindings are mapped to.
|
|
12
|
+
styleClass: string - Optional class addition that would be added to the dropdown.
|
|
13
|
+
placeholder: string - Any value you want the dropdown to display when nothing has been selected.
|
|
14
|
+
invalidMessage: string - Specifies message to be shown when the dropdown is invalid. If not set, no message is shown.
|
|
15
|
+
errorPosition: string - Specifies the position you want the dropdown's invalid message to show relative to the dropdown. Has 3 options - 'top', 'left' and 'right'. If none of these is set, it defaults to bottom.
|
|
16
|
+
showClear: boolean (default = false) - Configures whether to show a clear icon to remove the current selected value or values.
|
|
17
|
+
lazyLoad: boolean (default = false) - Configures whether or not more items can be loaded aynchronously and added to the options list.
|
|
18
|
+
loadMoreCaption: string - Configures the caption of the button that is used to load more items. Only displays when lazyLoad is set to true.
|
|
19
|
+
group: boolean (default = false) - Configures whether the dropdown items are nested. Requires an options type of DropdownMenuItem[] as input.
|
|
20
|
+
multiselect: boolean (default = false)- Configures whether the dropdown allows multiple selections or not.
|
|
21
|
+
display: string - Only valid in multiselect contexts. Displays selected items as a chip. Default look is comma seperated.
|
|
22
|
+
filter: boolean (default = false) - Configures whether items in the dropdown are searchable, in a lazyload context, it calls a dedicated function 'search'. Otherwise it performs string based search.
|
|
23
|
+
filterBy: string - Only valid in non lazyload contexts. Specifies properties that are used for reference when searching.
|
|
24
|
+
debounceTime: number (default = 500) - Configures the delay allowed between user input when searching before search endpoint is called. Only valid in lazyload contexts.
|
|
25
|
+
minChar: number (default = 0) - Configures the minimum characters necessary before search endpoint is called. Only valid in lazyload contexts.
|
|
26
|
+
disabled: boolean (default = false) - Sets the disabled state of the dropdown.
|
|
27
|
+
required: boolean (default = false) - If set as true, display visual cues when no item is selected and the dropdown is marked as touched.
|
|
28
|
+
load: (context: DropdownLoadEvent) => Promise<any[]> - This is a function variable that is set to a function that accepts a DropdownLoadEvent as a parameter and returns an array. This is only valid for a lazyLoad context and is called once 'see more' or whatever loadMoreCaption set is clicked. It needs to be set for see more to work properly. What should be returned should be of the same type as the options array.
|
|
29
|
+
asyncLabel: (context: any) => string | null - For lazyLoad contexts where the optionValue for example is 'Id', there's a chance that the item doesn't currently exist in the options array, and you might want to display the proper label so it shows that something is selected in the dropdown. So this function variable can be set. If your dropdown is bound to a variable 'selectedItem' and you set the value to 'mock-id' we call this function sending that id to you, so you can return the proper label property to set the dropdown display state. Note though that if there's no optionValue set and you pass in an object when setting 'selectedItem', it uses the current set optionLabel to display properly and this function might not need to be set in such contexts.
|
|
30
|
+
search: ( data: any, context: DropdownLoadEvent) => Promise<any[]> - For lazyLoad contexts, is called when the user is searching and the debounce time has elapsed, sends to your registered function, the search param and a DropdownLoadEvent that tells you the number of pages loaded prior to the call. Once a search query is active, 'see more' being clicked still calls the search function passing in the search param and the updated DropdownLoadEvent.
|
|
31
|
+
|
|
32
|
+
OUTPUTS
|
|
33
|
+
optionsChange: EventEmitter<any[]> - enables options to be two-way bound.
|
|
34
|
+
onChange: EventEmitter<DropdownChangeEvent> - emitted when changes are made to the selected option or options.
|
|
35
|
+
onClick: EventEmitter<Event> - emitted when the dropdown is clicked.
|
|
36
|
+
onClear: EventEmitter<Event> - emitted when the selected item or items is cleared.
|
|
37
|
+
|
|
38
|
+
TEMPLATING
|
|
39
|
+
selected - Configure how selected items look.
|
|
40
|
+
item - Configure how selectable items look.
|
|
41
|
+
group - Configure how group header items look.
|
|
42
|
+
|
|
43
|
+
<ng-template let-item vTemplate="selected">
|
|
44
|
+
{{item}} Test Selected Template
|
|
45
|
+
</ng-template>
|
|
46
|
+
<ng-template let-item vTemplate="item">
|
|
47
|
+
{{item}} Test Item Template
|
|
48
|
+
</ng-template>
|
|
49
|
+
<ng-template let-item vTemplate="group">
|
|
50
|
+
{{item}} Test Group Template
|
|
51
|
+
</ng-template>
|
|
52
|
+
|
|
53
|
+
OBJECTS
|
|
54
|
+
DropdownChangeEvent - Sent when the dropdown selected option or options changes
|
|
55
|
+
originalEvent: Event - Event captured.
|
|
56
|
+
value: any - Selected option or options.
|
|
57
|
+
|
|
58
|
+
DropdownLoadEvent - Sent when the loadMore function is called
|
|
59
|
+
loadTimes: number of times the context has been loaded prior to the event being sent.
|
|
60
|
+
|
|
61
|
+
DropdownMenuItem - The Object type passed as an array, when group is set to true. Used for nested Dropdowns
|
|
62
|
+
label: string - optionLabel isn't used when group is true. Defaults to the value set here.
|
|
63
|
+
subLabel?: string - optionSubLabel isn't used when group is true. Defaults to the value set here if set.
|
|
64
|
+
value: any - Whatever is set here decides the default value on ngModel bindings and formControl bindings when optionValue isn't set. If optionValue is set, it looks on this value property for the property that matches the optionValue set.
|
|
65
|
+
items?: DropdownMenuItem[] - Decides whether or not this DropdownMenuItem itself would be a group. If it going to have items under it, needs to be initialized.
|
|
66
|
+
lazyLoad?: boolean - Configures whether or not more items under can be loaded aynchronously and added to the items list.
|
|
67
|
+
filterBy?: string - Only valid in non lazyload contexts and when items is not null. Specifies properties that are used for reference when searching through items list.
|
|
68
|
+
search?: (param: string, context: DropdownLoadEvent) => Promise<DropdownMenuItem[]> - For lazyLoad contexts, is called when the user is searching and the debounce time has elapsed, sends to your registered function, the search param and a DropdownLoadEvent that tells you the number of pages loaded prior to the call. Once a search query is active, 'see more' being clicked still calls the search function passing in the search param and the updated DropdownLoadEvent.
|
|
69
|
+
loadMore?: (context: DropdownLoadEvent) => Promise<DropdownMenuItem[]> - This is a function variable that is set to a function that accepts a DropdownLoadEvent as a parameter and returns an array of DropdownMenuItems. This is only valid for a lazyLoad context and is called once the item is expanded or when 'see more' or whatever loadMoreCaption set is clicked. It needs to be set for see more to work properly. What should be returned should be a DropdownMenuItem array.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
@import '../../../../styles.css';
|
|
2
|
+
|
|
3
|
+
.option-items-container {
|
|
4
|
+
gap: 5px;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.see-more-container {
|
|
8
|
+
padding: 5px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.see-more-caption {
|
|
12
|
+
font-size: 12px;
|
|
13
|
+
color: #3b82f6;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.item-wrapper {
|
|
17
|
+
padding: 10px;
|
|
18
|
+
border-radius: 4px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.item-wrapper.multi-select {
|
|
22
|
+
align-items: center;
|
|
23
|
+
gap: 5px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.item-wrapper:hover {
|
|
27
|
+
background-color: rgba(180, 205, 245, 0.24)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.item-wrapper.active-item {
|
|
31
|
+
background-color: rgba(59, 130, 246, 0.24);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.item-wrapper.multi-select-active-item {
|
|
35
|
+
background-color: rgba(180, 205, 245, 0.24)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.item-wrapper.active-item>div {
|
|
39
|
+
color: #1D4ED8;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.group-wrapper {
|
|
43
|
+
padding: 5px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.group-wrapper-items {
|
|
47
|
+
padding-left: 15px;
|
|
48
|
+
position: relative;
|
|
49
|
+
z-index: 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.item-label {
|
|
53
|
+
font-weight: 500;
|
|
54
|
+
white-space: normal;
|
|
55
|
+
word-wrap: break-word;
|
|
56
|
+
word-break: break-all;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.item-label.has-sub-label {
|
|
60
|
+
font-weight: 600;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.item-sub-label {
|
|
64
|
+
font-size: 12px;
|
|
65
|
+
color: rgb(77, 77, 77);
|
|
66
|
+
/* white-space: normal;
|
|
67
|
+
word-wrap: break-word;
|
|
68
|
+
word-break: break-all; */
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.default-group {
|
|
72
|
+
gap: 5px;
|
|
73
|
+
align-items: center;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.default-item {
|
|
77
|
+
flex: 1 1 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.plus-minus-icon {
|
|
81
|
+
color: #5d6674;
|
|
82
|
+
width: 0.8rem;
|
|
83
|
+
height: 0.8rem;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.loading-overlay {
|
|
87
|
+
position: absolute;
|
|
88
|
+
top: 0;
|
|
89
|
+
left: 0;
|
|
90
|
+
width: 100%;
|
|
91
|
+
height: 100%;
|
|
92
|
+
background-color: rgba(77, 75, 75, 0.5);
|
|
93
|
+
/* Semi-transparent shade */
|
|
94
|
+
z-index: 10;
|
|
95
|
+
/* Make sure it's on top */
|
|
96
|
+
display: flex;
|
|
97
|
+
justify-content: center;
|
|
98
|
+
align-items: center;
|
|
99
|
+
pointer-events: none;
|
|
100
|
+
/* Prevents interactions below */
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.loader {
|
|
104
|
+
width: 50px;
|
|
105
|
+
padding: 8px;
|
|
106
|
+
aspect-ratio: 1;
|
|
107
|
+
border-radius: 50%;
|
|
108
|
+
background: #3b82f6;
|
|
109
|
+
--_m:
|
|
110
|
+
conic-gradient(#0000 10%, #000),
|
|
111
|
+
linear-gradient(#000 0 0) content-box;
|
|
112
|
+
-webkit-mask: var(--_m);
|
|
113
|
+
mask: var(--_m);
|
|
114
|
+
-webkit-mask-composite: source-out;
|
|
115
|
+
mask-composite: subtract;
|
|
116
|
+
animation: l3 1s infinite linear;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@keyframes l3 {
|
|
120
|
+
to {
|
|
121
|
+
transform: rotate(1turn)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
<!-- If group mode is false, display a flat list -->
|
|
2
|
+
<ng-container *ngIf="!group">
|
|
3
|
+
|
|
4
|
+
<div class="option-items-container flex flex-col">
|
|
5
|
+
<ng-container *ngFor="let item of options">
|
|
6
|
+
<ng-container *ngIf="itemTemplate; else defaultItem">
|
|
7
|
+
<div *ngIf="!multiselect" [ngClass]="{'active-item': isEqual(this.activeItem, this.getValue(item))}"
|
|
8
|
+
(click)="onSelect && onSelect(item, $event)" class="item-wrapper">
|
|
9
|
+
<ng-container *ngTemplateOutlet="itemTemplate; context: { $implicit: item }"></ng-container>
|
|
10
|
+
</div>
|
|
11
|
+
<div *ngIf="multiselect"
|
|
12
|
+
[ngClass]="{'multi-select-active-item': isSelected(this.activeItems, this.getValue(item))}"
|
|
13
|
+
(click)="onSelect && onSelect(item, $event)" class="item-wrapper multi-select flex">
|
|
14
|
+
<input type="checkbox" [checked]="isSelected(this.activeItems, this.getValue(item))"
|
|
15
|
+
class="custom-checkbox" />
|
|
16
|
+
<ng-container *ngTemplateOutlet="itemTemplate; context: { $implicit: item }"></ng-container>
|
|
17
|
+
</div>
|
|
18
|
+
</ng-container>
|
|
19
|
+
|
|
20
|
+
<ng-template #defaultItem>
|
|
21
|
+
<div *ngIf="!multiselect" [ngClass]="{'active-item': isEqual(this.activeItem, this.getValue(item))}"
|
|
22
|
+
(click)="onSelect && onSelect(item, $event)" class="default-item item-wrapper flex flex-col">
|
|
23
|
+
<div [ngClass]="{'has-sub-label': optionSubLabel}" class="item-label">{{this.getOptionLabel(item)}}</div>
|
|
24
|
+
<div *ngIf="optionSubLabel || (group && item.subLabel)" class="item-sub-label">
|
|
25
|
+
{{this.getOptionSubLabel(item)}}</div>
|
|
26
|
+
</div>
|
|
27
|
+
<div *ngIf="multiselect"
|
|
28
|
+
[ngClass]="{'multi-select-active-item': isSelected(this.activeItems, this.getValue(item))}"
|
|
29
|
+
(click)="onSelect && onSelect(item, $event)" class="default-item item-wrapper multi-select flex">
|
|
30
|
+
<input type="checkbox" [checked]="isSelected(this.activeItems, this.getValue(item))"
|
|
31
|
+
class="custom-checkbox" />
|
|
32
|
+
<div class="flex flex-col">
|
|
33
|
+
<div [ngClass]="{'has-sub-label': optionSubLabel}" class="item-label">{{this.getOptionLabel(item)}}</div>
|
|
34
|
+
<div *ngIf="optionSubLabel || (group && item.subLabel)" class="item-sub-label">
|
|
35
|
+
{{this.getOptionSubLabel(item)}}</div>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</ng-template>
|
|
39
|
+
</ng-container>
|
|
40
|
+
</div>
|
|
41
|
+
</ng-container>
|
|
42
|
+
|
|
43
|
+
<!-- If group mode is true, display groups and sub-groups recursively -->
|
|
44
|
+
<ng-container *ngIf="group">
|
|
45
|
+
<div class="option-items-container flex flex-col">
|
|
46
|
+
<ng-container *ngFor="let item of options">
|
|
47
|
+
<!-- Display as group header if the item has children -->
|
|
48
|
+
<div *ngIf="!item.items">
|
|
49
|
+
<ng-container *ngIf="itemTemplate; else defaultItem">
|
|
50
|
+
<div *ngIf="!multiselect" [ngClass]="{'active-item': isEqual(this.activeItem, this.getValue(item))}"
|
|
51
|
+
(click)="onSelect && onSelect(item, $event)" class="item-wrapper">
|
|
52
|
+
<ng-container *ngTemplateOutlet="itemTemplate; context: { $implicit: item }"></ng-container>
|
|
53
|
+
</div>
|
|
54
|
+
<div *ngIf="multiselect"
|
|
55
|
+
[ngClass]="{'multi-select-active-item': isSelected(this.activeItems, this.getValue(item))}"
|
|
56
|
+
(click)="onSelect && onSelect(item, $event)" class="item-wrapper multi-select flex">
|
|
57
|
+
<input type="checkbox" [checked]="isSelected(this.activeItems, this.getValue(item))"
|
|
58
|
+
class="custom-checkbox" />
|
|
59
|
+
<ng-container *ngTemplateOutlet="itemTemplate; context: { $implicit: item }"></ng-container>
|
|
60
|
+
</div>
|
|
61
|
+
</ng-container>
|
|
62
|
+
|
|
63
|
+
<ng-template #defaultItem>
|
|
64
|
+
<div *ngIf="!multiselect" [ngClass]="{'active-item': isEqual(this.activeItem, this.getValue(item))}"
|
|
65
|
+
(click)="onSelect && onSelect(item, $event)" class="default-item item-wrapper flex flex-col">
|
|
66
|
+
<div [ngClass]="{'has-sub-label': item.subLabel}" class="item-label">{{item.label}}</div>
|
|
67
|
+
<div *ngIf="item.subLabel" class="item-sub-label">{{item.subLabel}}</div>
|
|
68
|
+
</div>
|
|
69
|
+
<div *ngIf="multiselect"
|
|
70
|
+
[ngClass]="{'multi-select-active-item': isSelected(this.activeItems, this.getValue(item))}"
|
|
71
|
+
(click)="onSelect && onSelect(item, $event)" class="default-item item-wrapper multi-select flex">
|
|
72
|
+
<input type="checkbox" [checked]="isSelected(this.activeItems, this.getValue(item))"
|
|
73
|
+
class="custom-checkbox" />
|
|
74
|
+
<div class="flex flex-col">
|
|
75
|
+
<div [ngClass]="{'has-sub-label': item.subLabel}" class="item-label">{{item.label}}</div>
|
|
76
|
+
<div *ngIf="item.subLabel" class="item-sub-label">{{item.subLabel}}</div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
</ng-template>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<!-- Display as normal item if it doesn't have children -->
|
|
83
|
+
<div class="flex flex-col" *ngIf="item.items">
|
|
84
|
+
<ng-container *ngIf="groupTemplate; else defaultGroup">
|
|
85
|
+
<div class="group-wrapper" (click)="onExpand && onExpand(item, options)">
|
|
86
|
+
<ng-container *ngTemplateOutlet="groupTemplate; context: { $implicit: item }"></ng-container>
|
|
87
|
+
</div>
|
|
88
|
+
</ng-container>
|
|
89
|
+
|
|
90
|
+
<ng-template #defaultGroup>
|
|
91
|
+
<div (click)="onExpand && onExpand(item, options)" class="default-group group-wrapper flex">
|
|
92
|
+
<span *ngIf="!item.expanded">
|
|
93
|
+
<verben-svg icon="plus" fill="#5d6674" [width]="15" [height]="15"></verben-svg>
|
|
94
|
+
<!-- <svg class="plus-minus-icon" width="12" height="12" viewBox="0 0 12 12" fill="none"
|
|
95
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
96
|
+
<path
|
|
97
|
+
d="M5.33214 6.66578H5.26102C3.95858 6.66578 2.65614 6.6663 1.35371 6.66544C1.06528 6.66527 0.850553 6.53571 0.728192 6.27369C0.525115 5.83859 0.844383 5.33734 1.32491 5.33322C1.64624 5.33031 1.96756 5.33271 2.28889 5.33271C3.28285 5.33271 4.27682 5.33271 5.27079 5.33271H5.33214V5.27633C5.33214 3.96674 5.33214 2.65714 5.33214 1.34755C5.33214 1.03086 5.53162 0.767472 5.82998 0.688643C6.25515 0.576225 6.66577 0.896512 6.66645 1.34327C6.66748 1.96311 6.66679 2.58294 6.66679 3.20278C6.66679 3.89254 6.66679 4.58229 6.66679 5.27222V5.33305H6.7242C8.0323 5.33305 9.34056 5.33305 10.6487 5.33305C10.933 5.33305 11.1737 5.48848 11.2788 5.73902C11.4659 6.18527 11.1431 6.66475 10.6533 6.66595C10.1549 6.66698 9.6564 6.66612 9.15805 6.66612C8.34968 6.66612 7.54148 6.66612 6.73311 6.66612H6.66679V6.72713C6.66679 8.03535 6.66679 9.34357 6.66679 10.6516C6.66679 10.9808 6.45343 11.2475 6.13485 11.3177C5.75989 11.4003 5.38252 11.1309 5.33899 10.749C5.33471 10.7107 5.33231 10.6722 5.33231 10.6336C5.33197 9.33123 5.33197 8.02867 5.33197 6.72627V6.66612L5.33214 6.66578Z"
|
|
98
|
+
fill="currentColor" />
|
|
99
|
+
</svg> -->
|
|
100
|
+
</span>
|
|
101
|
+
<span *ngIf="item.expanded">
|
|
102
|
+
<verben-svg icon="minus" fill="#5d6674" [width]="15" [height]="2"></verben-svg>
|
|
103
|
+
<!-- <svg class="plus-minus-icon" width="10" height="2" viewBox="0 0 10 2" fill="none"
|
|
104
|
+
xmlns="http://www.w3.org/2000/svg">
|
|
105
|
+
<path d="M0.333984 0.332031H9.66732V1.66536H0.333984V0.332031Z" fill="currentColor" />
|
|
106
|
+
</svg> -->
|
|
107
|
+
</span>
|
|
108
|
+
<div class="default-item flex flex-col">
|
|
109
|
+
<div [ngClass]="{'has-sub-label': item.subLabel}" class="item-label">{{item.label}}</div>
|
|
110
|
+
<div *ngIf="item.subLabel" class="item-sub-label">{{item.subLabel}}</div>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
</ng-template>
|
|
114
|
+
<!-- Recursive rendering of sub-items (groups or individual items) -->
|
|
115
|
+
<ng-container *ngIf="item.expanded">
|
|
116
|
+
<div class="group-wrapper-items flex flex-col">
|
|
117
|
+
<drop-down-item [itemTemplate]="itemTemplate" [groupTemplate]="groupTemplate" [activeItem]="activeItem"
|
|
118
|
+
[activeItems]="activeItems" [multiselect]="multiselect" [optionValue]="optionValue"
|
|
119
|
+
[optionLabel]="optionLabel" [optionSubLabel]="optionSubLabel" [loadMoreCaption]="loadMoreCaption"
|
|
120
|
+
[options]="item.items" [group]="group" [onExpand]="onExpand" [onLoadMore]="onLoadMore"
|
|
121
|
+
[onSelect]="onSelect"></drop-down-item>
|
|
122
|
+
<div *ngIf="item.lazyLoad" class="see-more-container flex">
|
|
123
|
+
<span class="see-more-caption" (click)="onLoadMore && onLoadMore(item)">{{loadMoreCaption}}</span>
|
|
124
|
+
</div>
|
|
125
|
+
<div *ngIf="item.isLoading" class="loading-overlay">
|
|
126
|
+
<div class="loader"></div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
</ng-container>
|
|
130
|
+
</div>
|
|
131
|
+
</ng-container>
|
|
132
|
+
</div>
|
|
133
|
+
</ng-container>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
|
|
3
|
+
import { DropDownItemComponent } from './drop-down-item.component';
|
|
4
|
+
|
|
5
|
+
describe('DropDownItemComponent', () => {
|
|
6
|
+
let component: DropDownItemComponent;
|
|
7
|
+
let fixture: ComponentFixture<DropDownItemComponent>;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
await TestBed.configureTestingModule({
|
|
11
|
+
imports: [DropDownItemComponent]
|
|
12
|
+
})
|
|
13
|
+
.compileComponents();
|
|
14
|
+
|
|
15
|
+
fixture = TestBed.createComponent(DropDownItemComponent);
|
|
16
|
+
component = fixture.componentInstance;
|
|
17
|
+
fixture.detectChanges();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should create', () => {
|
|
21
|
+
expect(component).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AfterContentInit,
|
|
3
|
+
Component,
|
|
4
|
+
ContentChildren,
|
|
5
|
+
Input,
|
|
6
|
+
OnInit,
|
|
7
|
+
QueryList,
|
|
8
|
+
SimpleChanges,
|
|
9
|
+
TemplateRef,
|
|
10
|
+
} from '@angular/core';
|
|
11
|
+
import { TemplateDirective } from '../../TemplateDirective.directive';
|
|
12
|
+
import { DropdownMenuItemWrapper } from '../drop-down.component';
|
|
13
|
+
import { CommonModule } from '@angular/common';
|
|
14
|
+
import { isEqual } from 'lodash';
|
|
15
|
+
import { FormsModule } from '@angular/forms';
|
|
16
|
+
// import { SvgModule } from 'verben-ng-ui/src/public-api';
|
|
17
|
+
import {SvgModule} from '../../../components/svg/svg.module'
|
|
18
|
+
|
|
19
|
+
@Component({
|
|
20
|
+
selector: 'drop-down-item',
|
|
21
|
+
standalone: true,
|
|
22
|
+
imports: [CommonModule, FormsModule, SvgModule],
|
|
23
|
+
templateUrl: './drop-down-item.component.html',
|
|
24
|
+
styleUrl: './drop-down-item.component.css',
|
|
25
|
+
})
|
|
26
|
+
export class DropDownItemComponent implements OnInit {
|
|
27
|
+
@Input() itemTemplate: TemplateRef<any> | null = null; // Allow null for custom item template
|
|
28
|
+
@Input() groupTemplate: TemplateRef<any> | null = null;
|
|
29
|
+
|
|
30
|
+
@Input() activeItem?: any;
|
|
31
|
+
@Input() activeItems?: any;
|
|
32
|
+
@Input() optionValue?: string;
|
|
33
|
+
@Input() optionLabel?: string;
|
|
34
|
+
@Input() optionSubLabel?: string;
|
|
35
|
+
@Input() loadMoreCaption?: string;
|
|
36
|
+
@Input() multiselect: boolean = false;
|
|
37
|
+
@Input() options: any[] = [];
|
|
38
|
+
@Input() group: boolean = false;
|
|
39
|
+
@Input() onExpand?: (
|
|
40
|
+
item: DropdownMenuItemWrapper,
|
|
41
|
+
siblings: DropdownMenuItemWrapper[]
|
|
42
|
+
) => Promise<void>;
|
|
43
|
+
@Input() onLoadMore?: (item: DropdownMenuItemWrapper) => Promise<void>;
|
|
44
|
+
@Input() onSelect?: (value: any, event: Event) => void;
|
|
45
|
+
|
|
46
|
+
constructor() {}
|
|
47
|
+
ngOnInit(): void {}
|
|
48
|
+
|
|
49
|
+
isEqual(value: any, other: any): boolean {
|
|
50
|
+
return isEqual(value, other);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
isSelected(value: any[], other: any): boolean {
|
|
54
|
+
for (let val of value) {
|
|
55
|
+
if (isEqual(val, other)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
getValue(item: any): any {
|
|
63
|
+
if (!this.optionValue) {
|
|
64
|
+
return this.group ? item.value : item;
|
|
65
|
+
}
|
|
66
|
+
return this.group ? item.value[this.optionValue] : item[this.optionValue];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
getOptionLabel(item: any): any {
|
|
70
|
+
if (this.group) {
|
|
71
|
+
return item.label;
|
|
72
|
+
}
|
|
73
|
+
if (!this.optionLabel) {
|
|
74
|
+
return item;
|
|
75
|
+
}
|
|
76
|
+
return typeof item === 'string' ? item : item[this.optionLabel];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
getOptionSubLabel(item: any): any {
|
|
80
|
+
if (this.group) {
|
|
81
|
+
return item.subLabel;
|
|
82
|
+
}
|
|
83
|
+
if (!this.optionSubLabel) {
|
|
84
|
+
return item;
|
|
85
|
+
}
|
|
86
|
+
return typeof item === 'string' ? item : item[this.optionSubLabel];
|
|
87
|
+
}
|
|
88
|
+
}
|