@dso-design-system/ui 0.0.2 → 0.1.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/esm2022/lib/alert/alert.component.mjs +54 -0
- package/esm2022/lib/badge/badge.component.mjs +22 -0
- package/esm2022/lib/breadcrumb/breadcrumb.component.mjs +29 -0
- package/esm2022/lib/checkbox/checkbox.component.mjs +82 -0
- package/esm2022/lib/datepicker/datepicker.component.mjs +161 -0
- package/esm2022/lib/dialog/dialog.component.mjs +25 -0
- package/esm2022/lib/directives/truncate.directive.mjs +71 -0
- package/esm2022/lib/dropdown-list/dropdown-list.component.mjs +89 -0
- package/esm2022/lib/file-upload-items/file-upload-items.component.mjs +65 -0
- package/esm2022/lib/file-upload-multiple/file-upload-multiple.component.mjs +232 -0
- package/esm2022/lib/file-upload-multiple/upload-item.model.mjs +2 -0
- package/esm2022/lib/file-upload-multiple/upload-simulator.service.mjs +76 -0
- package/esm2022/lib/file-upload-single/file-upload-single.component.mjs +100 -0
- package/esm2022/lib/input-text/input-text.component.mjs +93 -0
- package/esm2022/lib/pagination/pagination.component.mjs +115 -0
- package/esm2022/lib/progress-bar/progress-bar.component.mjs +25 -0
- package/esm2022/lib/radio/radio.component.mjs +41 -0
- package/esm2022/lib/select-dropdown/select-dropdown.component.mjs +228 -0
- package/esm2022/lib/service/toast.service.mjs +20 -0
- package/esm2022/lib/side-navigation-bar/side-navigation-bar.component.mjs +113 -0
- package/esm2022/lib/spinner/spinner.component.mjs +60 -0
- package/esm2022/lib/table/table.component.mjs +136 -0
- package/esm2022/lib/tabs/tab.component.mjs +20 -0
- package/esm2022/lib/tabs/tabs.component.mjs +40 -0
- package/esm2022/lib/tag/tag.component.mjs +27 -0
- package/esm2022/lib/text-area/text-area.component.mjs +74 -0
- package/esm2022/lib/toast/toast.component.mjs +36 -0
- package/esm2022/lib/tooltip/tooltip.component.mjs +38 -0
- package/esm2022/lib/tooltip/tooltip.directive.mjs +105 -0
- package/esm2022/lib/top-navigation-bar/top-navigation-bar.component.mjs +24 -0
- package/esm2022/public-api.mjs +27 -2
- package/fesm2022/dso-design-system-ui.mjs +2056 -3
- package/fesm2022/dso-design-system-ui.mjs.map +1 -1
- package/lib/alert/alert.component.d.ts +20 -0
- package/lib/badge/badge.component.d.ts +8 -0
- package/lib/breadcrumb/breadcrumb.component.d.ts +15 -0
- package/lib/checkbox/checkbox.component.d.ts +42 -0
- package/lib/datepicker/datepicker.component.d.ts +48 -0
- package/lib/dialog/dialog.component.d.ts +10 -0
- package/lib/directives/truncate.directive.d.ts +23 -0
- package/lib/dropdown-list/dropdown-list.component.d.ts +33 -0
- package/lib/file-upload-items/file-upload-items.component.d.ts +27 -0
- package/lib/file-upload-multiple/file-upload-multiple.component.d.ts +44 -0
- package/lib/file-upload-multiple/upload-item.model.d.ts +7 -0
- package/lib/file-upload-multiple/upload-simulator.service.d.ts +34 -0
- package/lib/file-upload-single/file-upload-single.component.d.ts +28 -0
- package/lib/input-text/input-text.component.d.ts +24 -0
- package/lib/pagination/pagination.component.d.ts +31 -0
- package/lib/progress-bar/progress-bar.component.d.ts +11 -0
- package/lib/radio/radio.component.d.ts +14 -0
- package/lib/select-dropdown/select-dropdown.component.d.ts +78 -0
- package/lib/service/toast.service.d.ts +16 -0
- package/lib/side-navigation-bar/side-navigation-bar.component.d.ts +74 -0
- package/lib/spinner/spinner.component.d.ts +23 -0
- package/lib/table/table.component.d.ts +43 -0
- package/lib/tabs/tab.component.d.ts +9 -0
- package/lib/tabs/tabs.component.d.ts +15 -0
- package/lib/tag/tag.component.d.ts +10 -0
- package/lib/text-area/text-area.component.d.ts +21 -0
- package/lib/toast/toast.component.d.ts +13 -0
- package/lib/tooltip/tooltip.component.d.ts +15 -0
- package/lib/tooltip/tooltip.directive.d.ts +19 -0
- package/lib/top-navigation-bar/top-navigation-bar.component.d.ts +16 -0
- package/package.json +1 -1
- package/public-api.d.ts +25 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { IconComponent } from '../icon/icon.component';
|
|
4
|
+
import { TooltipDirective } from '../tooltip/tooltip.directive';
|
|
5
|
+
import { CheckboxComponent } from '../checkbox/checkbox.component';
|
|
6
|
+
import { ButtonComponent } from '../button/button.component';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
import * as i1 from "@angular/common";
|
|
9
|
+
export class TableComponent {
|
|
10
|
+
/* =====================
|
|
11
|
+
Inputs
|
|
12
|
+
===================== */
|
|
13
|
+
columns = [];
|
|
14
|
+
rows = [];
|
|
15
|
+
defaultSortColumn;
|
|
16
|
+
defaultSortDirection = 'asc';
|
|
17
|
+
stickyHeader = false;
|
|
18
|
+
maxTableHeight;
|
|
19
|
+
/* =====================
|
|
20
|
+
Outputs
|
|
21
|
+
===================== */
|
|
22
|
+
sortChange = new EventEmitter();
|
|
23
|
+
/* =====================
|
|
24
|
+
UI state only
|
|
25
|
+
===================== */
|
|
26
|
+
sortColumn = null;
|
|
27
|
+
sortDirection = 'asc';
|
|
28
|
+
/* =====================
|
|
29
|
+
Lifecycle
|
|
30
|
+
===================== */
|
|
31
|
+
ngOnChanges() {
|
|
32
|
+
// Initialize visual sort state ONLY
|
|
33
|
+
if (this.defaultSortColumn && !this.sortColumn) {
|
|
34
|
+
this.sortColumn = this.defaultSortColumn;
|
|
35
|
+
this.sortDirection = this.defaultSortDirection;
|
|
36
|
+
// Emit once so parent applies default sort
|
|
37
|
+
this.sortChange.emit({
|
|
38
|
+
column: this.sortColumn,
|
|
39
|
+
direction: this.sortDirection
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/* =====================
|
|
44
|
+
Sorting (emit only)
|
|
45
|
+
===================== */
|
|
46
|
+
sort(colKey) {
|
|
47
|
+
let direction = 'asc';
|
|
48
|
+
if (this.sortColumn === colKey) {
|
|
49
|
+
direction = this.sortDirection === 'asc' ? 'desc' : 'asc';
|
|
50
|
+
}
|
|
51
|
+
this.sortColumn = colKey;
|
|
52
|
+
this.sortDirection = direction;
|
|
53
|
+
this.sortChange.emit({ column: colKey, direction });
|
|
54
|
+
}
|
|
55
|
+
/* =====================
|
|
56
|
+
Column sizing
|
|
57
|
+
===================== */
|
|
58
|
+
getColumnStyle(col) {
|
|
59
|
+
return {
|
|
60
|
+
'min-width': col.minWidth || null,
|
|
61
|
+
'max-width': col.maxWidth || null,
|
|
62
|
+
'width': !col.minWidth && !col.maxWidth ? 'auto' : null,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/* =====================
|
|
66
|
+
Truncation
|
|
67
|
+
===================== */
|
|
68
|
+
shouldTruncateNative(cell) {
|
|
69
|
+
if (!cell)
|
|
70
|
+
return false;
|
|
71
|
+
const content = cell.querySelector('.cell-text');
|
|
72
|
+
if (!content)
|
|
73
|
+
return false;
|
|
74
|
+
return content.scrollWidth > content.clientWidth;
|
|
75
|
+
}
|
|
76
|
+
/* =====================
|
|
77
|
+
Selection (unchanged)
|
|
78
|
+
===================== */
|
|
79
|
+
selectedRows = new Set();
|
|
80
|
+
toggleRow(row) {
|
|
81
|
+
if (this.selectedRows.has(row)) {
|
|
82
|
+
this.selectedRows.delete(row);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
this.selectedRows.add(row);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
isRowSelected(row) {
|
|
89
|
+
return this.selectedRows.has(row);
|
|
90
|
+
}
|
|
91
|
+
get allSelected() {
|
|
92
|
+
return this.rows.length > 0 &&
|
|
93
|
+
this.selectedRows.size === this.rows.length;
|
|
94
|
+
}
|
|
95
|
+
toggleSelectAll() {
|
|
96
|
+
if (this.allSelected) {
|
|
97
|
+
this.selectedRows.clear();
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
this.rows.forEach(row => this.selectedRows.add(row));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
onEditRow(row) {
|
|
104
|
+
console.log('Edit clicked for row:', row);
|
|
105
|
+
}
|
|
106
|
+
onDeleteRow(row) {
|
|
107
|
+
console.log('Delete clicked for row:', row);
|
|
108
|
+
}
|
|
109
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
110
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: TableComponent, isStandalone: true, selector: "dso-table", inputs: { columns: "columns", rows: "rows", defaultSortColumn: "defaultSortColumn", defaultSortDirection: "defaultSortDirection", stickyHeader: "stickyHeader", maxTableHeight: "maxTableHeight" }, outputs: { sortChange: "sortChange" }, usesOnChanges: true, ngImport: i0, template: "<div #tableContainer class=\"dso-table-container\" [class.sticky-header]=\"stickyHeader\" [style.max-height]=\"maxTableHeight\">\r\n <table class=\"dso-table\">\r\n<thead>\r\n <tr>\r\n <th *ngFor=\"let col of columns\"\r\n [class.sticky]=\"stickyHeader || col.sticky\"\r\n [class.sticky-left]=\"stickyHeader && col.type === 'checkbox'\"\r\n [class.sticky-right]=\"stickyHeader && col.type === 'action'\"\r\n [ngStyle]=\"getColumnStyle(col)\"\r\n [class.active]=\"sortColumn === col.key\"\r\n class=\"sortable\"\r\n (click)=\"col.sortable !== false && col.type !== 'checkbox' && sort(col.key)\">\r\n\r\n <!-- If this column is a checkbox column -->\r\n <ng-container *ngIf=\"col.type === 'checkbox'; else normalHeader\">\r\n <dso-checkbox\r\n size=\"small\"\r\n [isChecked]=\"allSelected\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"toggleSelectAll()\">\r\n </dso-checkbox>\r\n </ng-container>\r\n\r\n <!-- Your original header stays EXACTLY as-is -->\r\n <ng-template #normalHeader>\r\n <div class=\"header-content\">\r\n {{ col.label }}\r\n\r\n <dso-icon\r\n *ngIf=\"col.sortable !== false && sortColumn === col.key\"\r\n [iconName]=\"sortDirection === 'asc'\r\n ? 'icon-van'\r\n : 'icon-chevron_down'\"\r\n size=\"small\"\r\n class=\"sort-icon\">\r\n </dso-icon>\r\n\r\n <dso-icon\r\n *ngIf=\"col.sortable !== false && sortColumn !== col.key\"\r\n iconName=\"icon-chevron_up\"\r\n size=\"small\"\r\n class=\"hover-indicator\">\r\n </dso-icon>\r\n </div>\r\n </ng-template>\r\n\r\n </th>\r\n </tr>\r\n</thead>\r\n\r\n\r\n<tbody>\r\n <tr *ngFor=\"let row of rows\">\r\n <td\r\n #cell\r\n *ngFor=\"let col of columns\"\r\n [class.sticky-left]=\"stickyHeader && col.type === 'checkbox'\"\r\n [class.sticky-right]=\"stickyHeader && col.type === 'action'\"\r\n [ngStyle]=\"getColumnStyle(col)\"\r\n [dsoDirectiveTooltip]=\"shouldTruncateNative(cell) ? row[col.key] : ''\">\r\n <div class=\"cell-wrapper\" style=\"display:flex; align-items:center;\">\r\n <dso-checkbox\r\n *ngIf=\"col.type==='checkbox'\"\r\n size=\"small\"\r\n [isChecked]=\"isRowSelected(row)\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"toggleRow(row)\">\r\n </dso-checkbox>\r\n\r\n <!-- Action button cell -->\r\n <ng-container *ngIf=\"col.type==='action'\">\r\n <dso-button\r\n btnType=\"filled\"\r\n btnSize=\"smBtn\"\r\n btnLabel=\"Edit\"\r\n (click)=\"onEditRow(row)\">\r\n </dso-button>\r\n <dso-button\r\n btnType=\"outlined\"\r\n btnSize=\"smBtn\"\r\n btnLabel=\"Delete\"\r\n (click)=\"onDeleteRow(row)\">\r\n </dso-button>\r\n </ng-container>\r\n\r\n <!-- Normal text cell -->\r\n <span *ngIf=\"!col.type || (col.type !== 'checkbox' && col.type !== 'action')\" class=\"cell-text\">\r\n {{ row[col.key] }}\r\n </span>\r\n </div>\r\n </td>\r\n </tr>\r\n</tbody>\r\n\r\n </table>\r\n</div>\r\n", styles: [".dso-table-container{overflow:auto;border:1px solid #ddd;position:relative}.dso-table{width:100%;border-collapse:collapse}.dso-table th,.dso-table td{padding:8px 12px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dso-table thead th{background:#2c2f36;color:#fff;font-weight:600}.dso-table-container.sticky-header .dso-table th.sticky{position:sticky;top:0}.dso-table th.sticky{top:0;z-index:20;box-shadow:0 2px 2px -1px #00000040}.dso-table thead th.sortable:hover{background:#3a3e46;cursor:pointer}.dso-table thead th.active{background:#464b54!important}.dso-table thead th:last-child{border-right:none}.truncate{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}td .cell-text{display:inline-block;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cell-wrapper{display:inline-flex;align-items:center;margin:0;padding:0;gap:8px}.sticky-left{position:sticky;left:0;z-index:15;background:#fff}.sticky-right{position:sticky;right:0;z-index:15;background:#fff}.dso-table thead th.sticky-left,.dso-table thead th.sticky-right{z-index:25}.sticky-left.scroll-shadow{box-shadow:4px 0 6px -3px #00000040}.sticky-right.scroll-shadow{box-shadow:-4px 0 6px -3px #00000040}.dso-table tbody tr:hover{background:#f5f7fa}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "dso-button", inputs: ["btnLabel", "btnType", "btnSize", "btnIconName", "isDisabled", "isActive"], outputs: ["onClick"] }, { kind: "component", type: CheckboxComponent, selector: "dso-checkbox", inputs: ["label", "isChecked", "disabled", "size", "error", "required", "errorMessage", "iconName"], outputs: ["change"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: IconComponent, selector: "dso-icon", inputs: ["iconName", "size"] }, { kind: "directive", type: TooltipDirective, selector: "[dsoDirectiveTooltip]", inputs: ["dsoDirectiveTooltip", "position", "tooltipWidth"] }] });
|
|
111
|
+
}
|
|
112
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TableComponent, decorators: [{
|
|
113
|
+
type: Component,
|
|
114
|
+
args: [{ selector: 'dso-table', standalone: true, imports: [
|
|
115
|
+
ButtonComponent,
|
|
116
|
+
CheckboxComponent,
|
|
117
|
+
CommonModule,
|
|
118
|
+
IconComponent,
|
|
119
|
+
TooltipDirective
|
|
120
|
+
], template: "<div #tableContainer class=\"dso-table-container\" [class.sticky-header]=\"stickyHeader\" [style.max-height]=\"maxTableHeight\">\r\n <table class=\"dso-table\">\r\n<thead>\r\n <tr>\r\n <th *ngFor=\"let col of columns\"\r\n [class.sticky]=\"stickyHeader || col.sticky\"\r\n [class.sticky-left]=\"stickyHeader && col.type === 'checkbox'\"\r\n [class.sticky-right]=\"stickyHeader && col.type === 'action'\"\r\n [ngStyle]=\"getColumnStyle(col)\"\r\n [class.active]=\"sortColumn === col.key\"\r\n class=\"sortable\"\r\n (click)=\"col.sortable !== false && col.type !== 'checkbox' && sort(col.key)\">\r\n\r\n <!-- If this column is a checkbox column -->\r\n <ng-container *ngIf=\"col.type === 'checkbox'; else normalHeader\">\r\n <dso-checkbox\r\n size=\"small\"\r\n [isChecked]=\"allSelected\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"toggleSelectAll()\">\r\n </dso-checkbox>\r\n </ng-container>\r\n\r\n <!-- Your original header stays EXACTLY as-is -->\r\n <ng-template #normalHeader>\r\n <div class=\"header-content\">\r\n {{ col.label }}\r\n\r\n <dso-icon\r\n *ngIf=\"col.sortable !== false && sortColumn === col.key\"\r\n [iconName]=\"sortDirection === 'asc'\r\n ? 'icon-van'\r\n : 'icon-chevron_down'\"\r\n size=\"small\"\r\n class=\"sort-icon\">\r\n </dso-icon>\r\n\r\n <dso-icon\r\n *ngIf=\"col.sortable !== false && sortColumn !== col.key\"\r\n iconName=\"icon-chevron_up\"\r\n size=\"small\"\r\n class=\"hover-indicator\">\r\n </dso-icon>\r\n </div>\r\n </ng-template>\r\n\r\n </th>\r\n </tr>\r\n</thead>\r\n\r\n\r\n<tbody>\r\n <tr *ngFor=\"let row of rows\">\r\n <td\r\n #cell\r\n *ngFor=\"let col of columns\"\r\n [class.sticky-left]=\"stickyHeader && col.type === 'checkbox'\"\r\n [class.sticky-right]=\"stickyHeader && col.type === 'action'\"\r\n [ngStyle]=\"getColumnStyle(col)\"\r\n [dsoDirectiveTooltip]=\"shouldTruncateNative(cell) ? row[col.key] : ''\">\r\n <div class=\"cell-wrapper\" style=\"display:flex; align-items:center;\">\r\n <dso-checkbox\r\n *ngIf=\"col.type==='checkbox'\"\r\n size=\"small\"\r\n [isChecked]=\"isRowSelected(row)\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"toggleRow(row)\">\r\n </dso-checkbox>\r\n\r\n <!-- Action button cell -->\r\n <ng-container *ngIf=\"col.type==='action'\">\r\n <dso-button\r\n btnType=\"filled\"\r\n btnSize=\"smBtn\"\r\n btnLabel=\"Edit\"\r\n (click)=\"onEditRow(row)\">\r\n </dso-button>\r\n <dso-button\r\n btnType=\"outlined\"\r\n btnSize=\"smBtn\"\r\n btnLabel=\"Delete\"\r\n (click)=\"onDeleteRow(row)\">\r\n </dso-button>\r\n </ng-container>\r\n\r\n <!-- Normal text cell -->\r\n <span *ngIf=\"!col.type || (col.type !== 'checkbox' && col.type !== 'action')\" class=\"cell-text\">\r\n {{ row[col.key] }}\r\n </span>\r\n </div>\r\n </td>\r\n </tr>\r\n</tbody>\r\n\r\n </table>\r\n</div>\r\n", styles: [".dso-table-container{overflow:auto;border:1px solid #ddd;position:relative}.dso-table{width:100%;border-collapse:collapse}.dso-table th,.dso-table td{padding:8px 12px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dso-table thead th{background:#2c2f36;color:#fff;font-weight:600}.dso-table-container.sticky-header .dso-table th.sticky{position:sticky;top:0}.dso-table th.sticky{top:0;z-index:20;box-shadow:0 2px 2px -1px #00000040}.dso-table thead th.sortable:hover{background:#3a3e46;cursor:pointer}.dso-table thead th.active{background:#464b54!important}.dso-table thead th:last-child{border-right:none}.truncate{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}td .cell-text{display:inline-block;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cell-wrapper{display:inline-flex;align-items:center;margin:0;padding:0;gap:8px}.sticky-left{position:sticky;left:0;z-index:15;background:#fff}.sticky-right{position:sticky;right:0;z-index:15;background:#fff}.dso-table thead th.sticky-left,.dso-table thead th.sticky-right{z-index:25}.sticky-left.scroll-shadow{box-shadow:4px 0 6px -3px #00000040}.sticky-right.scroll-shadow{box-shadow:-4px 0 6px -3px #00000040}.dso-table tbody tr:hover{background:#f5f7fa}\n"] }]
|
|
121
|
+
}], propDecorators: { columns: [{
|
|
122
|
+
type: Input
|
|
123
|
+
}], rows: [{
|
|
124
|
+
type: Input
|
|
125
|
+
}], defaultSortColumn: [{
|
|
126
|
+
type: Input
|
|
127
|
+
}], defaultSortDirection: [{
|
|
128
|
+
type: Input
|
|
129
|
+
}], stickyHeader: [{
|
|
130
|
+
type: Input
|
|
131
|
+
}], maxTableHeight: [{
|
|
132
|
+
type: Input
|
|
133
|
+
}], sortChange: [{
|
|
134
|
+
type: Output
|
|
135
|
+
}] } });
|
|
136
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdWkvc3JjL2xpYi90YWJsZS90YWJsZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS9zcmMvbGliL3RhYmxlL3RhYmxlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBYSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbEYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNuRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7OztBQTBCN0QsTUFBTSxPQUFPLGNBQWM7SUFFekI7OytCQUUyQjtJQUVsQixPQUFPLEdBQWtCLEVBQUUsQ0FBQztJQUM1QixJQUFJLEdBQVUsRUFBRSxDQUFDO0lBQ2pCLGlCQUFpQixDQUFVO0lBQzNCLG9CQUFvQixHQUFtQixLQUFLLENBQUM7SUFDN0MsWUFBWSxHQUFHLEtBQUssQ0FBQztJQUNyQixjQUFjLENBQVU7SUFFakM7OytCQUUyQjtJQUVqQixVQUFVLEdBQUcsSUFBSSxZQUFZLEVBR25DLENBQUM7SUFFTDs7K0JBRTJCO0lBRTNCLFVBQVUsR0FBa0IsSUFBSSxDQUFDO0lBQ2pDLGFBQWEsR0FBbUIsS0FBSyxDQUFDO0lBRXRDOzsrQkFFMkI7SUFFM0IsV0FBVztRQUNULG9DQUFvQztRQUNwQyxJQUFJLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUMvQyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztZQUN6QyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQyxvQkFBb0IsQ0FBQztZQUUvQywyQ0FBMkM7WUFDM0MsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7Z0JBQ25CLE1BQU0sRUFBRSxJQUFJLENBQUMsVUFBVTtnQkFDdkIsU0FBUyxFQUFFLElBQUksQ0FBQyxhQUFhO2FBQzlCLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0lBRUQ7OytCQUUyQjtJQUUzQixJQUFJLENBQUMsTUFBYztRQUNqQixJQUFJLFNBQVMsR0FBbUIsS0FBSyxDQUFDO1FBRXRDLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUMvQixTQUFTLEdBQUcsSUFBSSxDQUFDLGFBQWEsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO1FBQzVELENBQUM7UUFFRCxJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQztRQUN6QixJQUFJLENBQUMsYUFBYSxHQUFHLFNBQVMsQ0FBQztRQUUvQixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUN0RCxDQUFDO0lBRUQ7OytCQUUyQjtJQUUzQixjQUFjLENBQUMsR0FBZ0I7UUFDN0IsT0FBTztZQUNMLFdBQVcsRUFBRSxHQUFHLENBQUMsUUFBUSxJQUFJLElBQUk7WUFDakMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxRQUFRLElBQUksSUFBSTtZQUNqQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUMsUUFBUSxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJO1NBQ3hELENBQUM7SUFDSixDQUFDO0lBRUQ7OytCQUUyQjtJQUUzQixvQkFBb0IsQ0FBQyxJQUFpQjtRQUNwQyxJQUFJLENBQUMsSUFBSTtZQUFFLE9BQU8sS0FBSyxDQUFDO1FBRXhCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFnQixDQUFDO1FBQ2hFLElBQUksQ0FBQyxPQUFPO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFFM0IsT0FBTyxPQUFPLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUM7SUFDbkQsQ0FBQztJQUVEOzsrQkFFMkI7SUFFM0IsWUFBWSxHQUFHLElBQUksR0FBRyxFQUFPLENBQUM7SUFFOUIsU0FBUyxDQUFDLEdBQVE7UUFDaEIsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2hDLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDN0IsQ0FBQztJQUNILENBQUM7SUFFRCxhQUFhLENBQUMsR0FBUTtRQUNwQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRCxJQUFJLFdBQVc7UUFDYixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUM7WUFDcEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDckQsQ0FBQztJQUVELGVBQWU7UUFDYixJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNyQixJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzVCLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3ZELENBQUM7SUFDSCxDQUFDO0lBRUQsU0FBUyxDQUFDLEdBQVE7UUFDaEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBRUQsV0FBVyxDQUFDLEdBQVE7UUFDbEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM5QyxDQUFDO3dHQTlIVSxjQUFjOzRGQUFkLGNBQWMscVVDL0IzQix5eEdBZ0dBLDh5Q0QxRUksZUFBZSxrS0FDZixpQkFBaUIsa0xBQ2pCLFlBQVkscVZBQ1osYUFBYSxtRkFDYixnQkFBZ0I7OzRGQUtQLGNBQWM7a0JBYjFCLFNBQVM7K0JBQ0UsV0FBVyxjQUNULElBQUksV0FDUDt3QkFDUCxlQUFlO3dCQUNmLGlCQUFpQjt3QkFDakIsWUFBWTt3QkFDWixhQUFhO3dCQUNiLGdCQUFnQjtxQkFDakI7OEJBVVEsT0FBTztzQkFBZixLQUFLO2dCQUNHLElBQUk7c0JBQVosS0FBSztnQkFDRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0csb0JBQW9CO3NCQUE1QixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFNSSxVQUFVO3NCQUFuQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT3V0cHV0LCBPbkNoYW5nZXMsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBJY29uQ29tcG9uZW50IH0gZnJvbSAnLi4vaWNvbi9pY29uLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IFRvb2x0aXBEaXJlY3RpdmUgfSBmcm9tICcuLi90b29sdGlwL3Rvb2x0aXAuZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgQ2hlY2tib3hDb21wb25lbnQgfSBmcm9tICcuLi9jaGVja2JveC9jaGVja2JveC5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBCdXR0b25Db21wb25lbnQgfSBmcm9tICcuLi9idXR0b24vYnV0dG9uLmNvbXBvbmVudCc7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFRhYmxlQ29sdW1uIHtcclxuICBrZXk6IHN0cmluZztcclxuICBsYWJlbDogc3RyaW5nO1xyXG4gIG1pbldpZHRoPzogc3RyaW5nO1xyXG4gIG1heFdpZHRoPzogc3RyaW5nO1xyXG4gIHRydW5jYXRlPzogYm9vbGVhbjtcclxuICB0eXBlPzogJ3RleHQnIHwgJ2NoZWNrYm94JyB8ICdhY3Rpb24nO1xyXG4gIHNvcnRhYmxlPzogYm9vbGVhbjtcclxuICBzdGlja3k/OiBib29sZWFuO1xyXG59XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2Rzby10YWJsZScsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbXHJcbiAgICBCdXR0b25Db21wb25lbnQsXHJcbiAgICBDaGVja2JveENvbXBvbmVudCxcclxuICAgIENvbW1vbk1vZHVsZSxcclxuICAgIEljb25Db21wb25lbnQsXHJcbiAgICBUb29sdGlwRGlyZWN0aXZlXHJcbiAgXSxcclxuICB0ZW1wbGF0ZVVybDogJy4vdGFibGUuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL3RhYmxlLmNvbXBvbmVudC5zY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIFRhYmxlQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzIHtcclxuXHJcbiAgLyogPT09PT09PT09PT09PT09PT09PT09XHJcbiAgICAgSW5wdXRzXHJcbiAgICAgPT09PT09PT09PT09PT09PT09PT09ICovXHJcblxyXG4gIEBJbnB1dCgpIGNvbHVtbnM6IFRhYmxlQ29sdW1uW10gPSBbXTtcclxuICBASW5wdXQoKSByb3dzOiBhbnlbXSA9IFtdO1xyXG4gIEBJbnB1dCgpIGRlZmF1bHRTb3J0Q29sdW1uPzogc3RyaW5nO1xyXG4gIEBJbnB1dCgpIGRlZmF1bHRTb3J0RGlyZWN0aW9uOiAnYXNjJyB8ICdkZXNjJyA9ICdhc2MnO1xyXG4gIEBJbnB1dCgpIHN0aWNreUhlYWRlciA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIG1heFRhYmxlSGVpZ2h0Pzogc3RyaW5nO1xyXG5cclxuICAvKiA9PT09PT09PT09PT09PT09PT09PT1cclxuICAgICBPdXRwdXRzXHJcbiAgICAgPT09PT09PT09PT09PT09PT09PT09ICovXHJcblxyXG4gIEBPdXRwdXQoKSBzb3J0Q2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjx7XHJcbiAgICBjb2x1bW46IHN0cmluZztcclxuICAgIGRpcmVjdGlvbjogJ2FzYycgfCAnZGVzYyc7XHJcbiAgfT4oKTtcclxuXHJcbiAgLyogPT09PT09PT09PT09PT09PT09PT09XHJcbiAgICAgVUkgc3RhdGUgb25seVxyXG4gICAgID09PT09PT09PT09PT09PT09PT09PSAqL1xyXG5cclxuICBzb3J0Q29sdW1uOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcclxuICBzb3J0RGlyZWN0aW9uOiAnYXNjJyB8ICdkZXNjJyA9ICdhc2MnO1xyXG5cclxuICAvKiA9PT09PT09PT09PT09PT09PT09PT1cclxuICAgICBMaWZlY3ljbGVcclxuICAgICA9PT09PT09PT09PT09PT09PT09PT0gKi9cclxuXHJcbiAgbmdPbkNoYW5nZXMoKSB7XHJcbiAgICAvLyBJbml0aWFsaXplIHZpc3VhbCBzb3J0IHN0YXRlIE9OTFlcclxuICAgIGlmICh0aGlzLmRlZmF1bHRTb3J0Q29sdW1uICYmICF0aGlzLnNvcnRDb2x1bW4pIHtcclxuICAgICAgdGhpcy5zb3J0Q29sdW1uID0gdGhpcy5kZWZhdWx0U29ydENvbHVtbjtcclxuICAgICAgdGhpcy5zb3J0RGlyZWN0aW9uID0gdGhpcy5kZWZhdWx0U29ydERpcmVjdGlvbjtcclxuXHJcbiAgICAgIC8vIEVtaXQgb25jZSBzbyBwYXJlbnQgYXBwbGllcyBkZWZhdWx0IHNvcnRcclxuICAgICAgdGhpcy5zb3J0Q2hhbmdlLmVtaXQoe1xyXG4gICAgICAgIGNvbHVtbjogdGhpcy5zb3J0Q29sdW1uLFxyXG4gICAgICAgIGRpcmVjdGlvbjogdGhpcy5zb3J0RGlyZWN0aW9uXHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyogPT09PT09PT09PT09PT09PT09PT09XHJcbiAgICAgU29ydGluZyAoZW1pdCBvbmx5KVxyXG4gICAgID09PT09PT09PT09PT09PT09PT09PSAqL1xyXG5cclxuICBzb3J0KGNvbEtleTogc3RyaW5nKSB7XHJcbiAgICBsZXQgZGlyZWN0aW9uOiAnYXNjJyB8ICdkZXNjJyA9ICdhc2MnO1xyXG5cclxuICAgIGlmICh0aGlzLnNvcnRDb2x1bW4gPT09IGNvbEtleSkge1xyXG4gICAgICBkaXJlY3Rpb24gPSB0aGlzLnNvcnREaXJlY3Rpb24gPT09ICdhc2MnID8gJ2Rlc2MnIDogJ2FzYyc7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5zb3J0Q29sdW1uID0gY29sS2V5O1xyXG4gICAgdGhpcy5zb3J0RGlyZWN0aW9uID0gZGlyZWN0aW9uO1xyXG5cclxuICAgIHRoaXMuc29ydENoYW5nZS5lbWl0KHsgY29sdW1uOiBjb2xLZXksIGRpcmVjdGlvbiB9KTtcclxuICB9XHJcblxyXG4gIC8qID09PT09PT09PT09PT09PT09PT09PVxyXG4gICAgIENvbHVtbiBzaXppbmdcclxuICAgICA9PT09PT09PT09PT09PT09PT09PT0gKi9cclxuXHJcbiAgZ2V0Q29sdW1uU3R5bGUoY29sOiBUYWJsZUNvbHVtbikge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgJ21pbi13aWR0aCc6IGNvbC5taW5XaWR0aCB8fCBudWxsLFxyXG4gICAgICAnbWF4LXdpZHRoJzogY29sLm1heFdpZHRoIHx8IG51bGwsXHJcbiAgICAgICd3aWR0aCc6ICFjb2wubWluV2lkdGggJiYgIWNvbC5tYXhXaWR0aCA/ICdhdXRvJyA6IG51bGwsXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLyogPT09PT09PT09PT09PT09PT09PT09XHJcbiAgICAgVHJ1bmNhdGlvblxyXG4gICAgID09PT09PT09PT09PT09PT09PT09PSAqL1xyXG5cclxuICBzaG91bGRUcnVuY2F0ZU5hdGl2ZShjZWxsOiBIVE1MRWxlbWVudCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKCFjZWxsKSByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgY29uc3QgY29udGVudCA9IGNlbGwucXVlcnlTZWxlY3RvcignLmNlbGwtdGV4dCcpIGFzIEhUTUxFbGVtZW50O1xyXG4gICAgaWYgKCFjb250ZW50KSByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgcmV0dXJuIGNvbnRlbnQuc2Nyb2xsV2lkdGggPiBjb250ZW50LmNsaWVudFdpZHRoO1xyXG4gIH1cclxuXHJcbiAgLyogPT09PT09PT09PT09PT09PT09PT09XHJcbiAgICAgU2VsZWN0aW9uICh1bmNoYW5nZWQpXHJcbiAgICAgPT09PT09PT09PT09PT09PT09PT09ICovXHJcblxyXG4gIHNlbGVjdGVkUm93cyA9IG5ldyBTZXQ8YW55PigpO1xyXG5cclxuICB0b2dnbGVSb3cocm93OiBhbnkpIHtcclxuICAgIGlmICh0aGlzLnNlbGVjdGVkUm93cy5oYXMocm93KSkge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkUm93cy5kZWxldGUocm93KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRSb3dzLmFkZChyb3cpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgaXNSb3dTZWxlY3RlZChyb3c6IGFueSk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRSb3dzLmhhcyhyb3cpO1xyXG4gIH1cclxuXHJcbiAgZ2V0IGFsbFNlbGVjdGVkKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMucm93cy5sZW5ndGggPiAwICYmXHJcbiAgICAgICAgICAgdGhpcy5zZWxlY3RlZFJvd3Muc2l6ZSA9PT0gdGhpcy5yb3dzLmxlbmd0aDtcclxuICB9XHJcblxyXG4gIHRvZ2dsZVNlbGVjdEFsbCgpIHtcclxuICAgIGlmICh0aGlzLmFsbFNlbGVjdGVkKSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRSb3dzLmNsZWFyKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnJvd3MuZm9yRWFjaChyb3cgPT4gdGhpcy5zZWxlY3RlZFJvd3MuYWRkKHJvdykpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25FZGl0Um93KHJvdzogYW55KSB7XHJcbiAgICBjb25zb2xlLmxvZygnRWRpdCBjbGlja2VkIGZvciByb3c6Jywgcm93KTtcclxuICB9XHJcblxyXG4gIG9uRGVsZXRlUm93KHJvdzogYW55KSB7XHJcbiAgICBjb25zb2xlLmxvZygnRGVsZXRlIGNsaWNrZWQgZm9yIHJvdzonLCByb3cpO1xyXG4gIH1cclxufVxyXG4iLCI8ZGl2ICN0YWJsZUNvbnRhaW5lciBjbGFzcz1cImRzby10YWJsZS1jb250YWluZXJcIiBbY2xhc3Muc3RpY2t5LWhlYWRlcl09XCJzdGlja3lIZWFkZXJcIiBbc3R5bGUubWF4LWhlaWdodF09XCJtYXhUYWJsZUhlaWdodFwiPlxyXG4gIDx0YWJsZSBjbGFzcz1cImRzby10YWJsZVwiPlxyXG48dGhlYWQ+XHJcbiAgPHRyPlxyXG4gICAgPHRoICpuZ0Zvcj1cImxldCBjb2wgb2YgY29sdW1uc1wiXHJcbiAgICAgICAgW2NsYXNzLnN0aWNreV09XCJzdGlja3lIZWFkZXIgfHwgY29sLnN0aWNreVwiXHJcbiAgICAgICAgW2NsYXNzLnN0aWNreS1sZWZ0XT1cInN0aWNreUhlYWRlciAmJiBjb2wudHlwZSA9PT0gJ2NoZWNrYm94J1wiXHJcbiAgICAgICAgW2NsYXNzLnN0aWNreS1yaWdodF09XCJzdGlja3lIZWFkZXIgJiYgY29sLnR5cGUgPT09ICdhY3Rpb24nXCJcclxuICAgICAgICBbbmdTdHlsZV09XCJnZXRDb2x1bW5TdHlsZShjb2wpXCJcclxuICAgICAgICBbY2xhc3MuYWN0aXZlXT1cInNvcnRDb2x1bW4gPT09IGNvbC5rZXlcIlxyXG4gICAgICAgIGNsYXNzPVwic29ydGFibGVcIlxyXG4gICAgICAgIChjbGljayk9XCJjb2wuc29ydGFibGUgIT09IGZhbHNlICYmIGNvbC50eXBlICE9PSAnY2hlY2tib3gnICYmIHNvcnQoY29sLmtleSlcIj5cclxuXHJcbiAgICAgIDwhLS0gSWYgdGhpcyBjb2x1bW4gaXMgYSBjaGVja2JveCBjb2x1bW4gLS0+XHJcbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJjb2wudHlwZSA9PT0gJ2NoZWNrYm94JzsgZWxzZSBub3JtYWxIZWFkZXJcIj5cclxuICAgICAgICA8ZHNvLWNoZWNrYm94XHJcbiAgICAgICAgICBzaXplPVwic21hbGxcIlxyXG4gICAgICAgICAgW2lzQ2hlY2tlZF09XCJhbGxTZWxlY3RlZFwiXHJcbiAgICAgICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcclxuICAgICAgICAgIChjaGFuZ2UpPVwidG9nZ2xlU2VsZWN0QWxsKClcIj5cclxuICAgICAgICA8L2Rzby1jaGVja2JveD5cclxuICAgICAgPC9uZy1jb250YWluZXI+XHJcblxyXG4gICAgICA8IS0tIFlvdXIgb3JpZ2luYWwgaGVhZGVyIHN0YXlzIEVYQUNUTFkgYXMtaXMgLS0+XHJcbiAgICAgIDxuZy10ZW1wbGF0ZSAjbm9ybWFsSGVhZGVyPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJoZWFkZXItY29udGVudFwiPlxyXG4gICAgICAgICAge3sgY29sLmxhYmVsIH19XHJcblxyXG4gICAgICAgICAgPGRzby1pY29uXHJcbiAgICAgICAgICAgICpuZ0lmPVwiY29sLnNvcnRhYmxlICE9PSBmYWxzZSAmJiBzb3J0Q29sdW1uID09PSBjb2wua2V5XCJcclxuICAgICAgICAgICAgW2ljb25OYW1lXT1cInNvcnREaXJlY3Rpb24gPT09ICdhc2MnXHJcbiAgICAgICAgICAgICAgICA/ICdpY29uLXZhbidcclxuICAgICAgICAgICAgICAgIDogJ2ljb24tY2hldnJvbl9kb3duJ1wiXHJcbiAgICAgICAgICAgIHNpemU9XCJzbWFsbFwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwic29ydC1pY29uXCI+XHJcbiAgICAgICAgICA8L2Rzby1pY29uPlxyXG5cclxuICAgICAgICAgIDxkc28taWNvblxyXG4gICAgICAgICAgICAqbmdJZj1cImNvbC5zb3J0YWJsZSAhPT0gZmFsc2UgJiYgc29ydENvbHVtbiAhPT0gY29sLmtleVwiXHJcbiAgICAgICAgICAgIGljb25OYW1lPVwiaWNvbi1jaGV2cm9uX3VwXCJcclxuICAgICAgICAgICAgc2l6ZT1cInNtYWxsXCJcclxuICAgICAgICAgICAgY2xhc3M9XCJob3Zlci1pbmRpY2F0b3JcIj5cclxuICAgICAgICAgIDwvZHNvLWljb24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvbmctdGVtcGxhdGU+XHJcblxyXG4gICAgPC90aD5cclxuICA8L3RyPlxyXG48L3RoZWFkPlxyXG5cclxuXHJcbjx0Ym9keT5cclxuICA8dHIgKm5nRm9yPVwibGV0IHJvdyBvZiByb3dzXCI+XHJcbiAgICA8dGRcclxuICAgICNjZWxsXHJcbiAgICAqbmdGb3I9XCJsZXQgY29sIG9mIGNvbHVtbnNcIlxyXG4gICAgICAgIFtjbGFzcy5zdGlja3ktbGVmdF09XCJzdGlja3lIZWFkZXIgJiYgY29sLnR5cGUgPT09ICdjaGVja2JveCdcIlxyXG4gICAgICAgIFtjbGFzcy5zdGlja3ktcmlnaHRdPVwic3RpY2t5SGVhZGVyICYmIGNvbC50eXBlID09PSAnYWN0aW9uJ1wiXHJcbiAgICBbbmdTdHlsZV09XCJnZXRDb2x1bW5TdHlsZShjb2wpXCJcclxuICAgIFtkc29EaXJlY3RpdmVUb29sdGlwXT1cInNob3VsZFRydW5jYXRlTmF0aXZlKGNlbGwpID8gcm93W2NvbC5rZXldIDogJydcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJjZWxsLXdyYXBwZXJcIiBzdHlsZT1cImRpc3BsYXk6ZmxleDsgYWxpZ24taXRlbXM6Y2VudGVyO1wiPlxyXG4gICAgPGRzby1jaGVja2JveFxyXG4gICAgICAqbmdJZj1cImNvbC50eXBlPT09J2NoZWNrYm94J1wiXHJcbiAgICAgIHNpemU9XCJzbWFsbFwiXHJcbiAgICAgIFtpc0NoZWNrZWRdPVwiaXNSb3dTZWxlY3RlZChyb3cpXCJcclxuICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXHJcbiAgICAgIChjaGFuZ2UpPVwidG9nZ2xlUm93KHJvdylcIj5cclxuICAgIDwvZHNvLWNoZWNrYm94PlxyXG5cclxuICAgICAgICA8IS0tIEFjdGlvbiBidXR0b24gY2VsbCAtLT5cclxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiY29sLnR5cGU9PT0nYWN0aW9uJ1wiPlxyXG4gICAgICAgICAgPGRzby1idXR0b25cclxuICAgICAgICAgICAgYnRuVHlwZT1cImZpbGxlZFwiXHJcbiAgICAgICAgICAgIGJ0blNpemU9XCJzbUJ0blwiXHJcbiAgICAgICAgICAgIGJ0bkxhYmVsPVwiRWRpdFwiXHJcbiAgICAgICAgICAgIChjbGljayk9XCJvbkVkaXRSb3cocm93KVwiPlxyXG4gICAgICAgICAgPC9kc28tYnV0dG9uPlxyXG4gICAgICAgICAgPGRzby1idXR0b25cclxuICAgICAgICAgICAgYnRuVHlwZT1cIm91dGxpbmVkXCJcclxuICAgICAgICAgICAgYnRuU2l6ZT1cInNtQnRuXCJcclxuICAgICAgICAgICAgYnRuTGFiZWw9XCJEZWxldGVcIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwib25EZWxldGVSb3cocm93KVwiPlxyXG4gICAgICAgICAgPC9kc28tYnV0dG9uPlxyXG4gICAgICAgIDwvbmctY29udGFpbmVyPlxyXG5cclxuICAgICAgICA8IS0tIE5vcm1hbCB0ZXh0IGNlbGwgLS0+XHJcbiAgICAgICAgPHNwYW4gKm5nSWY9XCIhY29sLnR5cGUgfHwgKGNvbC50eXBlICE9PSAnY2hlY2tib3gnICYmIGNvbC50eXBlICE9PSAnYWN0aW9uJylcIiBjbGFzcz1cImNlbGwtdGV4dFwiPlxyXG4gICAgICAgICAge3sgcm93W2NvbC5rZXldIH19XHJcbiAgICAgICAgPC9zcGFuPlxyXG4gICAgPC9kaXY+XHJcbiAgICA8L3RkPlxyXG4gIDwvdHI+XHJcbjwvdGJvZHk+XHJcblxyXG4gIDwvdGFibGU+XHJcbjwvZGl2PlxyXG4iXX0=
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// tab.component.ts
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { Component, Input } from '@angular/core';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "@angular/common";
|
|
6
|
+
export class TabComponent {
|
|
7
|
+
/** Label for the tab shown in the tabs header */
|
|
8
|
+
label = '';
|
|
9
|
+
/** Is this tab currently active? Controlled by TabsComponent */
|
|
10
|
+
active = false;
|
|
11
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TabComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
12
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: TabComponent, isStandalone: true, selector: "dso-tab", inputs: { label: "label" }, ngImport: i0, template: "<!-- tab.component.html -->\r\n<!-- Only display the tab content if it is active -->\r\n<div *ngIf=\"active\" class=\"tab-content\">\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
13
|
+
}
|
|
14
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TabComponent, decorators: [{
|
|
15
|
+
type: Component,
|
|
16
|
+
args: [{ selector: 'dso-tab', imports: [CommonModule], standalone: true, template: "<!-- tab.component.html -->\r\n<!-- Only display the tab content if it is active -->\r\n<div *ngIf=\"active\" class=\"tab-content\">\r\n <ng-content></ng-content>\r\n</div>\r\n" }]
|
|
17
|
+
}], propDecorators: { label: [{
|
|
18
|
+
type: Input
|
|
19
|
+
}] } });
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFiLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3VpL3NyYy9saWIvdGFicy90YWIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdWkvc3JjL2xpYi90YWJzL3RhYi5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxtQkFBbUI7QUFDbkIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7QUFTakQsTUFBTSxPQUFPLFlBQVk7SUFDdkIsaURBQWlEO0lBQ3hDLEtBQUssR0FBVyxFQUFFLENBQUM7SUFFNUIsZ0VBQWdFO0lBQ2hFLE1BQU0sR0FBWSxLQUFLLENBQUM7d0dBTGIsWUFBWTs0RkFBWixZQUFZLCtGQ1h6QixtTEFLQSx5RERHYSxZQUFZOzs0RkFHWixZQUFZO2tCQVB4QixTQUFTOytCQUNFLFNBQVMsV0FHVixDQUFFLFlBQVksQ0FBRSxjQUNiLElBQUk7OEJBSVAsS0FBSztzQkFBYixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiLy8gdGFiLmNvbXBvbmVudC50c1xyXG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBDb21wb25lbnQsIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2Rzby10YWInLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi90YWIuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL3RhYi5jb21wb25lbnQuc2NzcyddLFxyXG4gIGltcG9ydHM6IFsgQ29tbW9uTW9kdWxlIF0sXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZVxyXG59KVxyXG5leHBvcnQgY2xhc3MgVGFiQ29tcG9uZW50IHtcclxuICAvKiogTGFiZWwgZm9yIHRoZSB0YWIgc2hvd24gaW4gdGhlIHRhYnMgaGVhZGVyICovXHJcbiAgQElucHV0KCkgbGFiZWw6IHN0cmluZyA9ICcnO1xyXG5cclxuICAvKiogSXMgdGhpcyB0YWIgY3VycmVudGx5IGFjdGl2ZT8gQ29udHJvbGxlZCBieSBUYWJzQ29tcG9uZW50ICovXHJcbiAgYWN0aXZlOiBib29sZWFuID0gZmFsc2U7XHJcbn1cclxuIiwiPCEtLSB0YWIuY29tcG9uZW50Lmh0bWwgLS0+XHJcbjwhLS0gT25seSBkaXNwbGF5IHRoZSB0YWIgY29udGVudCBpZiBpdCBpcyBhY3RpdmUgLS0+XHJcbjxkaXYgKm5nSWY9XCJhY3RpdmVcIiBjbGFzcz1cInRhYi1jb250ZW50XCI+XHJcbiAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG48L2Rpdj5cclxuIl19
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// tabs.component.ts
|
|
2
|
+
import { Component, ContentChildren, Input, Output, EventEmitter } from '@angular/core';
|
|
3
|
+
import { TabComponent } from './tab.component';
|
|
4
|
+
import { CommonModule } from '@angular/common';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
import * as i1 from "@angular/common";
|
|
7
|
+
export class TabsComponent {
|
|
8
|
+
/** Query all child tabs inside <dso-tabs> */
|
|
9
|
+
tabs;
|
|
10
|
+
/** Optional: two-way binding for active tab index */
|
|
11
|
+
tabIndex = 0;
|
|
12
|
+
tabIndexChange = new EventEmitter();
|
|
13
|
+
ngAfterContentInit() {
|
|
14
|
+
// Activate the default tab
|
|
15
|
+
this.selectTab(this.tabIndex);
|
|
16
|
+
}
|
|
17
|
+
/** When a tab header is clicked */
|
|
18
|
+
selectTab(index) {
|
|
19
|
+
if (!this.tabs)
|
|
20
|
+
return;
|
|
21
|
+
this.tabs.forEach((tab, i) => tab.active = i === index);
|
|
22
|
+
// Update internal tabIndex and emit event for two-way binding
|
|
23
|
+
this.tabIndex = index;
|
|
24
|
+
this.tabIndexChange.emit(this.tabIndex);
|
|
25
|
+
}
|
|
26
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
27
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: TabsComponent, isStandalone: true, selector: "dso-tabs", inputs: { tabIndex: "tabIndex" }, outputs: { tabIndexChange: "tabIndexChange" }, queries: [{ propertyName: "tabs", predicate: TabComponent }], ngImport: i0, template: "<!-- tabs.component.html -->\r\n<div class=\"tabs-container\">\r\n <!-- Tab headers -->\r\n <div class=\"tab-headers\">\r\n <button\r\n *ngFor=\"let tab of tabs; let i = index\"\r\n [class.active]=\"tab.active\"\r\n (click)=\"selectTab(i)\">\r\n {{ tab.label }}\r\n </button>\r\n </div>\r\n\r\n <!-- Tab content will render via ng-content inside TabComponent -->\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".tabs-container{border:1px solid #ccc;border-radius:4px}.tab-headers{display:flex;border-bottom:1px solid #ccc}.tab-headers button{flex:1;padding:8px 12px;background:none;border:none;cursor:pointer;font-weight:500}.tab-headers button.active{border-bottom:2px solid #007bff;font-weight:700}.tab-headers button:hover{background-color:#f5f5f5}.tab-content{padding:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
|
|
28
|
+
}
|
|
29
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TabsComponent, decorators: [{
|
|
30
|
+
type: Component,
|
|
31
|
+
args: [{ selector: 'dso-tabs', standalone: true, imports: [CommonModule, TabComponent], template: "<!-- tabs.component.html -->\r\n<div class=\"tabs-container\">\r\n <!-- Tab headers -->\r\n <div class=\"tab-headers\">\r\n <button\r\n *ngFor=\"let tab of tabs; let i = index\"\r\n [class.active]=\"tab.active\"\r\n (click)=\"selectTab(i)\">\r\n {{ tab.label }}\r\n </button>\r\n </div>\r\n\r\n <!-- Tab content will render via ng-content inside TabComponent -->\r\n <ng-content></ng-content>\r\n</div>\r\n", styles: [".tabs-container{border:1px solid #ccc;border-radius:4px}.tab-headers{display:flex;border-bottom:1px solid #ccc}.tab-headers button{flex:1;padding:8px 12px;background:none;border:none;cursor:pointer;font-weight:500}.tab-headers button.active{border-bottom:2px solid #007bff;font-weight:700}.tab-headers button:hover{background-color:#f5f5f5}.tab-content{padding:12px}\n"] }]
|
|
32
|
+
}], propDecorators: { tabs: [{
|
|
33
|
+
type: ContentChildren,
|
|
34
|
+
args: [TabComponent]
|
|
35
|
+
}], tabIndex: [{
|
|
36
|
+
type: Input
|
|
37
|
+
}], tabIndexChange: [{
|
|
38
|
+
type: Output
|
|
39
|
+
}] } });
|
|
40
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFicy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS9zcmMvbGliL3RhYnMvdGFicy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS9zcmMvbGliL3RhYnMvdGFicy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxvQkFBb0I7QUFDcEIsT0FBTyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQStCLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3JILE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7OztBQVMvQyxNQUFNLE9BQU8sYUFBYTtJQUN4Qiw2Q0FBNkM7SUFDZCxJQUFJLENBQTJCO0lBRTlELHFEQUFxRDtJQUM1QyxRQUFRLEdBQVcsQ0FBQyxDQUFDO0lBQ3BCLGNBQWMsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO0lBRXRELGtCQUFrQjtRQUNoQiwyQkFBMkI7UUFDM0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVELG1DQUFtQztJQUNuQyxTQUFTLENBQUMsS0FBYTtRQUNyQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUk7WUFBRSxPQUFPO1FBRXZCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLEtBQUssS0FBSyxDQUFDLENBQUM7UUFFeEQsOERBQThEO1FBQzlELElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ3RCLElBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMxQyxDQUFDO3dHQXRCVSxhQUFhOzRGQUFiLGFBQWEsMEtBRVAsWUFBWSw2QkNkL0IsdWJBZUEseWFETFksWUFBWTs7NEZBRVgsYUFBYTtrQkFQekIsU0FBUzsrQkFDRSxVQUFVLGNBR1IsSUFBSSxXQUNQLENBQUMsWUFBWSxFQUFFLFlBQVksQ0FBQzs4QkFJTixJQUFJO3NCQUFsQyxlQUFlO3VCQUFDLFlBQVk7Z0JBR3BCLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0ksY0FBYztzQkFBdkIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIHRhYnMuY29tcG9uZW50LnRzXHJcbmltcG9ydCB7IENvbXBvbmVudCwgQ29udGVudENoaWxkcmVuLCBRdWVyeUxpc3QsIEFmdGVyQ29udGVudEluaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBUYWJDb21wb25lbnQgfSBmcm9tICcuL3RhYi5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdkc28tdGFicycsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3RhYnMuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL3RhYnMuY29tcG9uZW50LnNjc3MnXSxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIFRhYkNvbXBvbmVudF1cclxufSlcclxuZXhwb3J0IGNsYXNzIFRhYnNDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlckNvbnRlbnRJbml0IHtcclxuICAvKiogUXVlcnkgYWxsIGNoaWxkIHRhYnMgaW5zaWRlIDxkc28tdGFicz4gKi9cclxuICBAQ29udGVudENoaWxkcmVuKFRhYkNvbXBvbmVudCkgdGFicyE6IFF1ZXJ5TGlzdDxUYWJDb21wb25lbnQ+O1xyXG5cclxuICAvKiogT3B0aW9uYWw6IHR3by13YXkgYmluZGluZyBmb3IgYWN0aXZlIHRhYiBpbmRleCAqL1xyXG4gIEBJbnB1dCgpIHRhYkluZGV4OiBudW1iZXIgPSAwO1xyXG4gIEBPdXRwdXQoKSB0YWJJbmRleENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xyXG5cclxuICBuZ0FmdGVyQ29udGVudEluaXQoKSB7XHJcbiAgICAvLyBBY3RpdmF0ZSB0aGUgZGVmYXVsdCB0YWJcclxuICAgIHRoaXMuc2VsZWN0VGFiKHRoaXMudGFiSW5kZXgpO1xyXG4gIH1cclxuXHJcbiAgLyoqIFdoZW4gYSB0YWIgaGVhZGVyIGlzIGNsaWNrZWQgKi9cclxuICBzZWxlY3RUYWIoaW5kZXg6IG51bWJlcikge1xyXG4gICAgaWYgKCF0aGlzLnRhYnMpIHJldHVybjtcclxuXHJcbiAgICB0aGlzLnRhYnMuZm9yRWFjaCgodGFiLCBpKSA9PiB0YWIuYWN0aXZlID0gaSA9PT0gaW5kZXgpO1xyXG5cclxuICAgIC8vIFVwZGF0ZSBpbnRlcm5hbCB0YWJJbmRleCBhbmQgZW1pdCBldmVudCBmb3IgdHdvLXdheSBiaW5kaW5nXHJcbiAgICB0aGlzLnRhYkluZGV4ID0gaW5kZXg7XHJcbiAgICB0aGlzLnRhYkluZGV4Q2hhbmdlLmVtaXQodGhpcy50YWJJbmRleCk7XHJcbiAgfVxyXG59XHJcbiIsIjwhLS0gdGFicy5jb21wb25lbnQuaHRtbCAtLT5cclxuPGRpdiBjbGFzcz1cInRhYnMtY29udGFpbmVyXCI+XHJcbiAgPCEtLSBUYWIgaGVhZGVycyAtLT5cclxuICA8ZGl2IGNsYXNzPVwidGFiLWhlYWRlcnNcIj5cclxuICAgIDxidXR0b25cclxuICAgICAgKm5nRm9yPVwibGV0IHRhYiBvZiB0YWJzOyBsZXQgaSA9IGluZGV4XCJcclxuICAgICAgW2NsYXNzLmFjdGl2ZV09XCJ0YWIuYWN0aXZlXCJcclxuICAgICAgKGNsaWNrKT1cInNlbGVjdFRhYihpKVwiPlxyXG4gICAgICB7eyB0YWIubGFiZWwgfX1cclxuICAgIDwvYnV0dG9uPlxyXG4gIDwvZGl2PlxyXG5cclxuICA8IS0tIFRhYiBjb250ZW50IHdpbGwgcmVuZGVyIHZpYSBuZy1jb250ZW50IGluc2lkZSBUYWJDb21wb25lbnQgLS0+XHJcbiAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxyXG48L2Rpdj5cclxuIl19
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Component, Input } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { ButtonComponent } from '../button/button.component';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "@angular/common";
|
|
6
|
+
export class TagComponent {
|
|
7
|
+
variant = 'neutral';
|
|
8
|
+
removable = false;
|
|
9
|
+
label = '';
|
|
10
|
+
removed = false;
|
|
11
|
+
removeTag() {
|
|
12
|
+
this.removed = true;
|
|
13
|
+
}
|
|
14
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TagComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
15
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: TagComponent, isStandalone: true, selector: "dso-tag", inputs: { variant: "variant", removable: "removable", label: "label" }, ngImport: i0, template: "<div\r\n *ngIf=\"!removed\"\r\n class=\"tag\"\r\n [ngClass]=\"'tag-' + variant\"\r\n>\r\n <span class=\"tag-label\">{{ label }}</span>\r\n <!-- <dso-button></dso-button> -->\r\n <button \r\n *ngIf=\"removable\" \r\n class=\"tag-remove-btn\" \r\n (click)=\"removeTag()\"\r\n aria-label=\"Remove tag\"\r\n >\r\n ×\r\n </button>\r\n</div>\r\n\r\n", styles: [".tag{display:inline-flex;align-items:center;padding:4px 12px;font-size:.875rem;border-radius:16px;font-weight:500;white-space:nowrap;background-color:#e0e0e0;color:#333;gap:2px}.tag-success{background-color:#d4edda;color:#155724}.tag-info{background-color:#d1ecf1;color:#0c5460}.tag-warning{background-color:#fff3cd;color:#856404}.tag-danger{background-color:#f8d7da;color:#721c24}.tag-neutral{background-color:#e2e3e5;color:#383d41}.tag-remove-btn{background:transparent;border:none;font-size:1rem;line-height:1;cursor:pointer;color:inherit}.tag-remove-btn:hover{opacity:.6}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
16
|
+
}
|
|
17
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TagComponent, decorators: [{
|
|
18
|
+
type: Component,
|
|
19
|
+
args: [{ selector: 'dso-tag', standalone: true, imports: [CommonModule, ButtonComponent], template: "<div\r\n *ngIf=\"!removed\"\r\n class=\"tag\"\r\n [ngClass]=\"'tag-' + variant\"\r\n>\r\n <span class=\"tag-label\">{{ label }}</span>\r\n <!-- <dso-button></dso-button> -->\r\n <button \r\n *ngIf=\"removable\" \r\n class=\"tag-remove-btn\" \r\n (click)=\"removeTag()\"\r\n aria-label=\"Remove tag\"\r\n >\r\n ×\r\n </button>\r\n</div>\r\n\r\n", styles: [".tag{display:inline-flex;align-items:center;padding:4px 12px;font-size:.875rem;border-radius:16px;font-weight:500;white-space:nowrap;background-color:#e0e0e0;color:#333;gap:2px}.tag-success{background-color:#d4edda;color:#155724}.tag-info{background-color:#d1ecf1;color:#0c5460}.tag-warning{background-color:#fff3cd;color:#856404}.tag-danger{background-color:#f8d7da;color:#721c24}.tag-neutral{background-color:#e2e3e5;color:#383d41}.tag-remove-btn{background:transparent;border:none;font-size:1rem;line-height:1;cursor:pointer;color:inherit}.tag-remove-btn:hover{opacity:.6}\n"] }]
|
|
20
|
+
}], propDecorators: { variant: [{
|
|
21
|
+
type: Input
|
|
22
|
+
}], removable: [{
|
|
23
|
+
type: Input
|
|
24
|
+
}], label: [{
|
|
25
|
+
type: Input
|
|
26
|
+
}] } });
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFnLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3VpL3NyYy9saWIvdGFnL3RhZy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS9zcmMvbGliL3RhZy90YWcuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQzs7O0FBUzdELE1BQU0sT0FBTyxZQUFZO0lBQ2QsT0FBTyxHQUEwRCxTQUFTLENBQUM7SUFDM0UsU0FBUyxHQUFZLEtBQUssQ0FBQztJQUMzQixLQUFLLEdBQVcsRUFBRSxDQUFDO0lBRTVCLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFFaEIsU0FBUztRQUNQLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO0lBQ3RCLENBQUM7d0dBVFUsWUFBWTs0RkFBWixZQUFZLDJJQ1h6QixzWEFpQkEsMG5CRFZZLFlBQVk7OzRGQUlYLFlBQVk7a0JBUHhCLFNBQVM7K0JBQ0UsU0FBUyxjQUNQLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxlQUFlLENBQUM7OEJBSy9CLE9BQU87c0JBQWYsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLEtBQUs7c0JBQWIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgQnV0dG9uQ29tcG9uZW50IH0gZnJvbSAnLi4vYnV0dG9uL2J1dHRvbi5jb21wb25lbnQnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdkc28tdGFnJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIEJ1dHRvbkNvbXBvbmVudF0sXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3RhZy5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vdGFnLmNvbXBvbmVudC5zY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIFRhZ0NvbXBvbmVudCB7XHJcbiAgQElucHV0KCkgdmFyaWFudDogJ25ldXRyYWwnIHwgJ3N1Y2Nlc3MnIHwgJ2luZm8nIHwgJ3dhcm5pbmcnIHwgJ2RhbmdlcicgPSAnbmV1dHJhbCc7XHJcbiAgQElucHV0KCkgcmVtb3ZhYmxlOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgbGFiZWw6IHN0cmluZyA9ICcnO1xyXG5cclxuICByZW1vdmVkID0gZmFsc2U7XHJcblxyXG4gIHJlbW92ZVRhZygpIHtcclxuICAgIHRoaXMucmVtb3ZlZCA9IHRydWU7XHJcbiAgfVxyXG59XHJcbiIsIjxkaXZcclxuICAqbmdJZj1cIiFyZW1vdmVkXCJcclxuICBjbGFzcz1cInRhZ1wiXHJcbiAgW25nQ2xhc3NdPVwiJ3RhZy0nICsgdmFyaWFudFwiXHJcbj5cclxuICA8c3BhbiBjbGFzcz1cInRhZy1sYWJlbFwiPnt7IGxhYmVsIH19PC9zcGFuPlxyXG4gIDwhLS0gPGRzby1idXR0b24+PC9kc28tYnV0dG9uPiAtLT5cclxuICA8YnV0dG9uIFxyXG4gICAgKm5nSWY9XCJyZW1vdmFibGVcIiBcclxuICAgIGNsYXNzPVwidGFnLXJlbW92ZS1idG5cIiBcclxuICAgIChjbGljayk9XCJyZW1vdmVUYWcoKVwiXHJcbiAgICBhcmlhLWxhYmVsPVwiUmVtb3ZlIHRhZ1wiXHJcbiAgPlxyXG4gICAgJnRpbWVzO1xyXG4gIDwvYnV0dG9uPlxyXG48L2Rpdj5cclxuXHJcbiJdfQ==
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { Component, Input } from '@angular/core';
|
|
3
|
+
import { FormsModule } from '@angular/forms';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "@angular/common";
|
|
6
|
+
import * as i2 from "@angular/forms";
|
|
7
|
+
export class TextAreaComponent {
|
|
8
|
+
inputLabel = ''; // Optional label for the textarea
|
|
9
|
+
placeholder = '';
|
|
10
|
+
value = ''; // Two-way binding for value
|
|
11
|
+
helperText = 'helpering '; // Optional helper text
|
|
12
|
+
errorText = 'tes test'; // Optional error text
|
|
13
|
+
isDisabled = false; // Optional disabled state
|
|
14
|
+
enableValidation = true; // Toggle validation
|
|
15
|
+
maxLength = 300; // Maximum character length (for example)
|
|
16
|
+
isTouched = false;
|
|
17
|
+
isInvalid = false; // Error state
|
|
18
|
+
charCount = 0; // To track character count
|
|
19
|
+
isExceeded = false; // To track if the limit is exceeded
|
|
20
|
+
onInputChange(event) {
|
|
21
|
+
const inputValue = event.target.value;
|
|
22
|
+
console.log(inputValue);
|
|
23
|
+
const charCount = inputValue.length;
|
|
24
|
+
// Check if the limit has been exceeded
|
|
25
|
+
this.isExceeded = charCount > this.maxLength;
|
|
26
|
+
this.isTouched = true;
|
|
27
|
+
this.checkValidity();
|
|
28
|
+
}
|
|
29
|
+
// Method to determine the style of the character count
|
|
30
|
+
getCharCountStyle() {
|
|
31
|
+
const charCount = this.value.length;
|
|
32
|
+
if (this.isExceeded) {
|
|
33
|
+
// this.isExceeded = true;
|
|
34
|
+
return 'char-count-error';
|
|
35
|
+
}
|
|
36
|
+
// If character count exceeds 50% of maxLength, change color to black
|
|
37
|
+
if (charCount > this.maxLength / 2) {
|
|
38
|
+
return '';
|
|
39
|
+
}
|
|
40
|
+
// Otherwise, keep it grey
|
|
41
|
+
return '';
|
|
42
|
+
}
|
|
43
|
+
onBlur() {
|
|
44
|
+
this.isTouched = true;
|
|
45
|
+
this.checkValidity();
|
|
46
|
+
}
|
|
47
|
+
checkValidity() {
|
|
48
|
+
// Set to invalid if it's required and empty
|
|
49
|
+
this.isInvalid = this.isTouched && !this.value.trim();
|
|
50
|
+
}
|
|
51
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TextAreaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
52
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: TextAreaComponent, isStandalone: true, selector: "dso-text-area", inputs: { inputLabel: "inputLabel", placeholder: "placeholder", value: "value", helperText: "helperText", errorText: "errorText", isDisabled: "isDisabled", enableValidation: "enableValidation", maxLength: "maxLength" }, ngImport: i0, template: "<div class=\"text-area-container\">\r\n <div class=\"text-wrapper\">\r\n <!-- Optional label -->\r\n <label *ngIf=\"inputLabel\">\r\n {{ inputLabel }}\r\n </label> \r\n <!-- Character count inside the container -->\r\n <div class=\"char-count\" [ngClass]=\"getCharCountStyle()\" *ngIf=\"maxLength\">\r\n <span>\r\n {{ value.length }}\r\n </span>\r\n / {{ maxLength }}\r\n </div>\r\n </div>\r\n\r\n <textarea\r\n [placeholder]=\"placeholder\"\r\n [(ngModel)]=\"value\"\r\n (input)=\"onInputChange($event)\"\r\n (blur)=\"onBlur()\"\r\n [disabled]=\"isDisabled\"\r\n [class.invalid]=\"(isInvalid && isTouched && enableValidation) || isExceeded\"\r\n [class.disabled]=\"isDisabled\"\r\n >\r\n </textarea>\r\n\r\n <!-- Helper Text \r\n This condition checks if the helper text should be displayed:\r\n - If the character limit is **not exceeded** and validation is **not enabled**, show the helper text.\r\n - If validation **is enabled**, show the helper text only if the input is **not invalid** and `helperText` is provided.\r\n - If the character limit is exceeded, the helper text will be replaced with an error message. -->\r\n <div *ngIf=\"!isExceeded && !enableValidation || ((!isInvalid && helperText) && !isExceeded)\" class=\"helper-text\">\r\n {{ helperText }}\r\n </div>\r\n\r\n <!-- Specified Error Text -->\r\n <div *ngIf=\"isInvalid && isTouched && enableValidation\" class=\"error-message\">\r\n {{ errorText }}\r\n </div>\r\n\r\n <!-- Error message if character limit exceeded -->\r\n <div *ngIf=\"isExceeded\" class=\"error-message\">\r\n Character limit exceeded.\r\n </div>\r\n</div>\r\n", styles: [".text-area-container{display:flex;flex-direction:column;width:500px;gap:8px}.text-wrapper{display:flex;justify-content:space-between}textarea{width:100%;height:160px;padding:12px 8px;font-size:1rem;resize:vertical;border:1px solid #ccc;border-radius:4px}textarea:hover{border:1px solid #071d35}textarea:focus{border-color:#007bff;outline:none}.char-count{font-size:12px;color:#666;align-self:flex-end}.char-count span,.char-count-error{font-size:12px;color:#666}.char-count-error span{font-size:12px;color:red}.helper-text{font-size:16px;color:#555}.error-message{font-size:16px;color:red}span .error-message{color:red;font-size:12px}textarea.invalid{border-color:red}textarea.disabled{background-color:#f0f0f0;cursor:not-allowed;border-color:#ccc}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
53
|
+
}
|
|
54
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TextAreaComponent, decorators: [{
|
|
55
|
+
type: Component,
|
|
56
|
+
args: [{ selector: 'dso-text-area', standalone: true, imports: [CommonModule, FormsModule], template: "<div class=\"text-area-container\">\r\n <div class=\"text-wrapper\">\r\n <!-- Optional label -->\r\n <label *ngIf=\"inputLabel\">\r\n {{ inputLabel }}\r\n </label> \r\n <!-- Character count inside the container -->\r\n <div class=\"char-count\" [ngClass]=\"getCharCountStyle()\" *ngIf=\"maxLength\">\r\n <span>\r\n {{ value.length }}\r\n </span>\r\n / {{ maxLength }}\r\n </div>\r\n </div>\r\n\r\n <textarea\r\n [placeholder]=\"placeholder\"\r\n [(ngModel)]=\"value\"\r\n (input)=\"onInputChange($event)\"\r\n (blur)=\"onBlur()\"\r\n [disabled]=\"isDisabled\"\r\n [class.invalid]=\"(isInvalid && isTouched && enableValidation) || isExceeded\"\r\n [class.disabled]=\"isDisabled\"\r\n >\r\n </textarea>\r\n\r\n <!-- Helper Text \r\n This condition checks if the helper text should be displayed:\r\n - If the character limit is **not exceeded** and validation is **not enabled**, show the helper text.\r\n - If validation **is enabled**, show the helper text only if the input is **not invalid** and `helperText` is provided.\r\n - If the character limit is exceeded, the helper text will be replaced with an error message. -->\r\n <div *ngIf=\"!isExceeded && !enableValidation || ((!isInvalid && helperText) && !isExceeded)\" class=\"helper-text\">\r\n {{ helperText }}\r\n </div>\r\n\r\n <!-- Specified Error Text -->\r\n <div *ngIf=\"isInvalid && isTouched && enableValidation\" class=\"error-message\">\r\n {{ errorText }}\r\n </div>\r\n\r\n <!-- Error message if character limit exceeded -->\r\n <div *ngIf=\"isExceeded\" class=\"error-message\">\r\n Character limit exceeded.\r\n </div>\r\n</div>\r\n", styles: [".text-area-container{display:flex;flex-direction:column;width:500px;gap:8px}.text-wrapper{display:flex;justify-content:space-between}textarea{width:100%;height:160px;padding:12px 8px;font-size:1rem;resize:vertical;border:1px solid #ccc;border-radius:4px}textarea:hover{border:1px solid #071d35}textarea:focus{border-color:#007bff;outline:none}.char-count{font-size:12px;color:#666;align-self:flex-end}.char-count span,.char-count-error{font-size:12px;color:#666}.char-count-error span{font-size:12px;color:red}.helper-text{font-size:16px;color:#555}.error-message{font-size:16px;color:red}span .error-message{color:red;font-size:12px}textarea.invalid{border-color:red}textarea.disabled{background-color:#f0f0f0;cursor:not-allowed;border-color:#ccc}\n"] }]
|
|
57
|
+
}], propDecorators: { inputLabel: [{
|
|
58
|
+
type: Input
|
|
59
|
+
}], placeholder: [{
|
|
60
|
+
type: Input
|
|
61
|
+
}], value: [{
|
|
62
|
+
type: Input
|
|
63
|
+
}], helperText: [{
|
|
64
|
+
type: Input
|
|
65
|
+
}], errorText: [{
|
|
66
|
+
type: Input
|
|
67
|
+
}], isDisabled: [{
|
|
68
|
+
type: Input
|
|
69
|
+
}], enableValidation: [{
|
|
70
|
+
type: Input
|
|
71
|
+
}], maxLength: [{
|
|
72
|
+
type: Input
|
|
73
|
+
}] } });
|
|
74
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC1hcmVhLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3VpL3NyYy9saWIvdGV4dC1hcmVhL3RleHQtYXJlYS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS9zcmMvbGliL3RleHQtYXJlYS90ZXh0LWFyZWEuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7OztBQVM3QyxNQUFNLE9BQU8saUJBQWlCO0lBQ25CLFVBQVUsR0FBVyxFQUFFLENBQUMsQ0FBQyxrQ0FBa0M7SUFDM0QsV0FBVyxHQUFXLEVBQUUsQ0FBQztJQUN6QixLQUFLLEdBQVcsRUFBRSxDQUFDLENBQUUsNEJBQTRCO0lBQ2pELFVBQVUsR0FBVyxZQUFZLENBQUMsQ0FBRSx1QkFBdUI7SUFDM0QsU0FBUyxHQUFXLFVBQVUsQ0FBQyxDQUFFLHNCQUFzQjtJQUN2RCxVQUFVLEdBQVksS0FBSyxDQUFDLENBQUUsMEJBQTBCO0lBQ3hELGdCQUFnQixHQUFZLElBQUksQ0FBQyxDQUFFLG9CQUFvQjtJQUN2RCxTQUFTLEdBQVcsR0FBRyxDQUFDLENBQUUseUNBQXlDO0lBRTVFLFNBQVMsR0FBWSxLQUFLLENBQUM7SUFDM0IsU0FBUyxHQUFZLEtBQUssQ0FBQyxDQUFFLGNBQWM7SUFDM0MsU0FBUyxHQUFXLENBQUMsQ0FBQyxDQUFDLDJCQUEyQjtJQUNsRCxVQUFVLEdBQVksS0FBSyxDQUFDLENBQUMsb0NBQW9DO0lBRWpFLGFBQWEsQ0FBQyxLQUFZO1FBQ3hCLE1BQU0sVUFBVSxHQUFJLEtBQUssQ0FBQyxNQUE4QixDQUFDLEtBQUssQ0FBQztRQUMvRCxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3hCLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUM7UUFFcEMsdUNBQXVDO1FBQ3ZDLElBQUksQ0FBQyxVQUFVLEdBQUcsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7UUFFN0MsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7UUFDdEIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCx1REFBdUQ7SUFDdkQsaUJBQWlCO1FBQ2YsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFFcEMsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDcEIsMEJBQTBCO1lBQzFCLE9BQU8sa0JBQWtCLENBQUM7UUFDNUIsQ0FBQztRQUNELHFFQUFxRTtRQUNyRSxJQUFJLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ25DLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUVELDBCQUEwQjtRQUMxQixPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCxNQUFNO1FBQ0osSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7UUFDdEIsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxhQUFhO1FBQ1gsNENBQTRDO1FBQzVDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDeEQsQ0FBQzt3R0FwRFUsaUJBQWlCOzRGQUFqQixpQkFBaUIscVNDWDlCLDAwREE2Q0EsdXlCRHBDYSxZQUFZLGdPQUFFLFdBQVc7OzRGQUV6QixpQkFBaUI7a0JBUDdCLFNBQVM7K0JBQ0UsZUFBZSxjQUNiLElBQUksV0FHUCxDQUFFLFlBQVksRUFBRSxXQUFXLENBQUU7OEJBRzdCLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBDb21wb25lbnQsIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdkc28tdGV4dC1hcmVhJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi90ZXh0LWFyZWEuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL3RleHQtYXJlYS5jb21wb25lbnQuc2NzcyddLFxyXG4gIGltcG9ydHM6IFsgQ29tbW9uTW9kdWxlLCBGb3Jtc01vZHVsZSBdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBUZXh0QXJlYUNvbXBvbmVudCB7XHJcbiAgQElucHV0KCkgaW5wdXRMYWJlbDogc3RyaW5nID0gJyc7IC8vIE9wdGlvbmFsIGxhYmVsIGZvciB0aGUgdGV4dGFyZWFcclxuICBASW5wdXQoKSBwbGFjZWhvbGRlcjogc3RyaW5nID0gJyc7XHJcbiAgQElucHV0KCkgdmFsdWU6IHN0cmluZyA9ICcnOyAgLy8gVHdvLXdheSBiaW5kaW5nIGZvciB2YWx1ZVxyXG4gIEBJbnB1dCgpIGhlbHBlclRleHQ6IHN0cmluZyA9ICdoZWxwZXJpbmcgJzsgIC8vIE9wdGlvbmFsIGhlbHBlciB0ZXh0XHJcbiAgQElucHV0KCkgZXJyb3JUZXh0OiBzdHJpbmcgPSAndGVzIHRlc3QnOyAgLy8gT3B0aW9uYWwgZXJyb3IgdGV4dFxyXG4gIEBJbnB1dCgpIGlzRGlzYWJsZWQ6IGJvb2xlYW4gPSBmYWxzZTsgIC8vIE9wdGlvbmFsIGRpc2FibGVkIHN0YXRlXHJcbiAgQElucHV0KCkgZW5hYmxlVmFsaWRhdGlvbjogYm9vbGVhbiA9IHRydWU7ICAvLyBUb2dnbGUgdmFsaWRhdGlvblxyXG4gIEBJbnB1dCgpIG1heExlbmd0aDogbnVtYmVyID0gMzAwOyAgLy8gTWF4aW11bSBjaGFyYWN0ZXIgbGVuZ3RoIChmb3IgZXhhbXBsZSlcclxuXHJcbiAgaXNUb3VjaGVkOiBib29sZWFuID0gZmFsc2U7XHJcbiAgaXNJbnZhbGlkOiBib29sZWFuID0gZmFsc2U7ICAvLyBFcnJvciBzdGF0ZVxyXG4gIGNoYXJDb3VudDogbnVtYmVyID0gMDsgLy8gVG8gdHJhY2sgY2hhcmFjdGVyIGNvdW50XHJcbiAgaXNFeGNlZWRlZDogYm9vbGVhbiA9IGZhbHNlOyAvLyBUbyB0cmFjayBpZiB0aGUgbGltaXQgaXMgZXhjZWVkZWRcclxuXHJcbiAgb25JbnB1dENoYW5nZShldmVudDogRXZlbnQpOiB2b2lkIHtcclxuICAgIGNvbnN0IGlucHV0VmFsdWUgPSAoZXZlbnQudGFyZ2V0IGFzIEhUTUxUZXh0QXJlYUVsZW1lbnQpLnZhbHVlO1xyXG4gICAgY29uc29sZS5sb2coaW5wdXRWYWx1ZSk7XHJcbiAgICBjb25zdCBjaGFyQ291bnQgPSBpbnB1dFZhbHVlLmxlbmd0aDtcclxuXHJcbiAgICAvLyBDaGVjayBpZiB0aGUgbGltaXQgaGFzIGJlZW4gZXhjZWVkZWRcclxuICAgIHRoaXMuaXNFeGNlZWRlZCA9IGNoYXJDb3VudCA+IHRoaXMubWF4TGVuZ3RoO1xyXG4gICAgIFxyXG4gICAgdGhpcy5pc1RvdWNoZWQgPSB0cnVlO1xyXG4gICAgdGhpcy5jaGVja1ZhbGlkaXR5KCk7XHJcbiAgfVxyXG5cclxuICAvLyBNZXRob2QgdG8gZGV0ZXJtaW5lIHRoZSBzdHlsZSBvZiB0aGUgY2hhcmFjdGVyIGNvdW50XHJcbiAgZ2V0Q2hhckNvdW50U3R5bGUoKSB7XHJcbiAgICBjb25zdCBjaGFyQ291bnQgPSB0aGlzLnZhbHVlLmxlbmd0aDtcclxuXHJcbiAgICBpZiAodGhpcy5pc0V4Y2VlZGVkKSB7XHJcbiAgICAgIC8vIHRoaXMuaXNFeGNlZWRlZCA9IHRydWU7XHJcbiAgICAgIHJldHVybiAnY2hhci1jb3VudC1lcnJvcic7XHJcbiAgICB9XHJcbiAgICAvLyBJZiBjaGFyYWN0ZXIgY291bnQgZXhjZWVkcyA1MCUgb2YgbWF4TGVuZ3RoLCBjaGFuZ2UgY29sb3IgdG8gYmxhY2tcclxuICAgIGlmIChjaGFyQ291bnQgPiB0aGlzLm1heExlbmd0aCAvIDIpIHtcclxuICAgICAgcmV0dXJuICcnO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIE90aGVyd2lzZSwga2VlcCBpdCBncmV5XHJcbiAgICByZXR1cm4gJyc7XHJcbiAgfVxyXG5cclxuICBvbkJsdXIoKTogdm9pZCB7XHJcbiAgICB0aGlzLmlzVG91Y2hlZCA9IHRydWU7XHJcbiAgICB0aGlzLmNoZWNrVmFsaWRpdHkoKTtcclxuICB9XHJcblxyXG4gIGNoZWNrVmFsaWRpdHkoKTogdm9pZCB7XHJcbiAgICAvLyBTZXQgdG8gaW52YWxpZCBpZiBpdCdzIHJlcXVpcmVkIGFuZCBlbXB0eVxyXG4gICAgdGhpcy5pc0ludmFsaWQgPSB0aGlzLmlzVG91Y2hlZCAmJiAhdGhpcy52YWx1ZS50cmltKCk7XHJcbiAgfVxyXG59XHJcbiIsIjxkaXYgY2xhc3M9XCJ0ZXh0LWFyZWEtY29udGFpbmVyXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwidGV4dC13cmFwcGVyXCI+XHJcbiAgICAgICAgPCEtLSBPcHRpb25hbCBsYWJlbCAtLT5cclxuICAgICAgICA8bGFiZWwgKm5nSWY9XCJpbnB1dExhYmVsXCI+XHJcbiAgICAgICAgICAgIHt7IGlucHV0TGFiZWwgfX1cclxuICAgICAgICA8L2xhYmVsPiAgXHJcbiAgICAgICAgPCEtLSBDaGFyYWN0ZXIgY291bnQgaW5zaWRlIHRoZSBjb250YWluZXIgLS0+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImNoYXItY291bnRcIiBbbmdDbGFzc109XCJnZXRDaGFyQ291bnRTdHlsZSgpXCIgKm5nSWY9XCJtYXhMZW5ndGhcIj5cclxuICAgICAgICAgICAgPHNwYW4+XHJcbiAgICAgICAgICAgICAgICB7eyB2YWx1ZS5sZW5ndGggfX1cclxuICAgICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgICAgICAvIHt7IG1heExlbmd0aCB9fVxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPHRleHRhcmVhXHJcbiAgICAgICAgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyXCJcclxuICAgICAgICBbKG5nTW9kZWwpXT1cInZhbHVlXCJcclxuICAgICAgICAoaW5wdXQpPVwib25JbnB1dENoYW5nZSgkZXZlbnQpXCJcclxuICAgICAgICAoYmx1cik9XCJvbkJsdXIoKVwiXHJcbiAgICAgICAgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIlxyXG4gICAgICAgIFtjbGFzcy5pbnZhbGlkXT1cIihpc0ludmFsaWQgJiYgaXNUb3VjaGVkICYmIGVuYWJsZVZhbGlkYXRpb24pIHx8IGlzRXhjZWVkZWRcIlxyXG4gICAgICAgIFtjbGFzcy5kaXNhYmxlZF09XCJpc0Rpc2FibGVkXCJcclxuICAgICAgICA+XHJcbiAgICA8L3RleHRhcmVhPlxyXG5cclxuICAgICA8IS0tIEhlbHBlciBUZXh0IFxyXG4gICAgICAgICAgVGhpcyBjb25kaXRpb24gY2hlY2tzIGlmIHRoZSBoZWxwZXIgdGV4dCBzaG91bGQgYmUgZGlzcGxheWVkOlxyXG4gICAgICAgICAgICAtIElmIHRoZSBjaGFyYWN0ZXIgbGltaXQgaXMgKipub3QgZXhjZWVkZWQqKiBhbmQgdmFsaWRhdGlvbiBpcyAqKm5vdCBlbmFibGVkKiosIHNob3cgdGhlIGhlbHBlciB0ZXh0LlxyXG4gICAgICAgICAgICAtIElmIHZhbGlkYXRpb24gKippcyBlbmFibGVkKiosIHNob3cgdGhlIGhlbHBlciB0ZXh0IG9ubHkgaWYgdGhlIGlucHV0IGlzICoqbm90IGludmFsaWQqKiBhbmQgYGhlbHBlclRleHRgIGlzIHByb3ZpZGVkLlxyXG4gICAgICAgICAgICAtIElmIHRoZSBjaGFyYWN0ZXIgbGltaXQgaXMgZXhjZWVkZWQsIHRoZSBoZWxwZXIgdGV4dCB3aWxsIGJlIHJlcGxhY2VkIHdpdGggYW4gZXJyb3IgbWVzc2FnZS4gLS0+XHJcbiAgICA8ZGl2ICpuZ0lmPVwiIWlzRXhjZWVkZWQgJiYgIWVuYWJsZVZhbGlkYXRpb24gfHwgKCghaXNJbnZhbGlkICYmIGhlbHBlclRleHQpICYmICFpc0V4Y2VlZGVkKVwiIGNsYXNzPVwiaGVscGVyLXRleHRcIj5cclxuICAgICAgICB7eyBoZWxwZXJUZXh0IH19XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIFNwZWNpZmllZCBFcnJvciBUZXh0IC0tPlxyXG4gICAgPGRpdiAqbmdJZj1cImlzSW52YWxpZCAmJiBpc1RvdWNoZWQgJiYgZW5hYmxlVmFsaWRhdGlvblwiIGNsYXNzPVwiZXJyb3ItbWVzc2FnZVwiPlxyXG4gICAgICAgIHt7IGVycm9yVGV4dCB9fVxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPCEtLSBFcnJvciBtZXNzYWdlIGlmIGNoYXJhY3RlciBsaW1pdCBleGNlZWRlZCAtLT5cclxuICAgIDxkaXYgKm5nSWY9XCJpc0V4Y2VlZGVkXCIgY2xhc3M9XCJlcnJvci1tZXNzYWdlXCI+XHJcbiAgICAgICAgQ2hhcmFjdGVyIGxpbWl0IGV4Y2VlZGVkLlxyXG4gICAgPC9kaXY+XHJcbjwvZGl2PlxyXG4iXX0=
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { Component, Input } from '@angular/core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "../service/toast.service";
|
|
5
|
+
import * as i2 from "@angular/common";
|
|
6
|
+
export class ToastComponent {
|
|
7
|
+
toastService;
|
|
8
|
+
toasts = [];
|
|
9
|
+
position = 'top-right';
|
|
10
|
+
toastData; // Stores the current toast being displayed
|
|
11
|
+
constructor(toastService) {
|
|
12
|
+
this.toastService = toastService;
|
|
13
|
+
} // Inject toast service
|
|
14
|
+
ngOnInit() {
|
|
15
|
+
// Subscribe to toast messages from the service
|
|
16
|
+
this.toastService.toast$.subscribe((toast) => {
|
|
17
|
+
console.log('Toast Child Listening:', toast); // Add this debug log!
|
|
18
|
+
this.toasts.push(toast); // Add the new toast to the array for display
|
|
19
|
+
// Auto-hide after specified duration (default 3000ms)
|
|
20
|
+
setTimeout(() => {
|
|
21
|
+
// this.visible = false; // Hide toast
|
|
22
|
+
this.toasts.shift(); // Remove first toast from the array
|
|
23
|
+
}, toast.duration || 3000);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ToastComponent, deps: [{ token: i1.ToastService }], target: i0.ɵɵFactoryTarget.Component });
|
|
27
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ToastComponent, isStandalone: true, selector: "dso-toast", inputs: { position: "position" }, ngImport: i0, template: "<div class=\"toast-wrapper\" \r\n [ngClass]=\"['toast-' + (position || 'top-right')]\">\r\n <div\r\n *ngFor=\"let toast of toasts; let i = index\"\r\n class=\"toast-container\"\r\n [ngClass]=\"['toast-' + (toast.variant || 'neutral')]\"\r\n >\r\n \r\n <div class=\"toast-header\" *ngIf=\"toast.header\">{{ toast.header }}</div>\r\n <div class=\"toast-body\">\r\n <div class=\"toast-message\">{{ toast.message }}</div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \r\n[ngStyle]=\"{\r\n animation: 'fadeInOut ' + (toast.duration || 3000) + 'ms ease forwards'}\"> -->", styles: [".toast-wrapper{position:fixed;display:flex;flex-direction:column;z-index:1000;gap:16px}.toast-container{padding:12px 16px;border-radius:8px;box-shadow:0 4px 12px #0003;color:#fff;width:280px;font-family:sans-serif;animation:fadeIn .3s ease forwards}.toast-top-right{top:20px;right:20px;align-items:flex-end}.toast-top-left{top:20px;left:20px;align-items:flex-start}.toast-bottom-right{bottom:20px;right:20px;align-items:flex-end}.toast-bottom-left{bottom:20px;left:20px;align-items:flex-start}.toast-top-center{top:20px;left:50%;transform:translate(-50%)}.toast-bottom-center{bottom:20px;left:50%;transform:translate(-50%)}.toast-success{background-color:#28a745}.toast-info{background-color:#17a2b8}.toast-warning{background-color:#ffc107;color:#333}.toast-danger{background-color:#dc3545}.toast-neutral{background-color:#6c757d}.toast-header{font-weight:600;margin-bottom:4px}.toast-subtext{font-size:.85rem;opacity:.8}@keyframes fadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeOut{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-10px)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
28
|
+
}
|
|
29
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ToastComponent, decorators: [{
|
|
30
|
+
type: Component,
|
|
31
|
+
args: [{ selector: 'dso-toast', standalone: true, imports: [CommonModule] // Import CommonModule for ngIf, ngFor etc.
|
|
32
|
+
, template: "<div class=\"toast-wrapper\" \r\n [ngClass]=\"['toast-' + (position || 'top-right')]\">\r\n <div\r\n *ngFor=\"let toast of toasts; let i = index\"\r\n class=\"toast-container\"\r\n [ngClass]=\"['toast-' + (toast.variant || 'neutral')]\"\r\n >\r\n \r\n <div class=\"toast-header\" *ngIf=\"toast.header\">{{ toast.header }}</div>\r\n <div class=\"toast-body\">\r\n <div class=\"toast-message\">{{ toast.message }}</div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- \r\n[ngStyle]=\"{\r\n animation: 'fadeInOut ' + (toast.duration || 3000) + 'ms ease forwards'}\"> -->", styles: [".toast-wrapper{position:fixed;display:flex;flex-direction:column;z-index:1000;gap:16px}.toast-container{padding:12px 16px;border-radius:8px;box-shadow:0 4px 12px #0003;color:#fff;width:280px;font-family:sans-serif;animation:fadeIn .3s ease forwards}.toast-top-right{top:20px;right:20px;align-items:flex-end}.toast-top-left{top:20px;left:20px;align-items:flex-start}.toast-bottom-right{bottom:20px;right:20px;align-items:flex-end}.toast-bottom-left{bottom:20px;left:20px;align-items:flex-start}.toast-top-center{top:20px;left:50%;transform:translate(-50%)}.toast-bottom-center{bottom:20px;left:50%;transform:translate(-50%)}.toast-success{background-color:#28a745}.toast-info{background-color:#17a2b8}.toast-warning{background-color:#ffc107;color:#333}.toast-danger{background-color:#dc3545}.toast-neutral{background-color:#6c757d}.toast-header{font-weight:600;margin-bottom:4px}.toast-subtext{font-size:.85rem;opacity:.8}@keyframes fadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeOut{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-10px)}}\n"] }]
|
|
33
|
+
}], ctorParameters: () => [{ type: i1.ToastService }], propDecorators: { position: [{
|
|
34
|
+
type: Input
|
|
35
|
+
}] } });
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9hc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdWkvc3JjL2xpYi90b2FzdC90b2FzdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS9zcmMvbGliL3RvYXN0L3RvYXN0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBVSxNQUFNLGVBQWUsQ0FBQzs7OztBQVl6RCxNQUFNLE9BQU8sY0FBYztJQU1MO0lBTHBCLE1BQU0sR0FBbUIsRUFBRSxDQUFDO0lBQ25CLFFBQVEsR0FBK0YsV0FBVyxDQUFDO0lBRTVILFNBQVMsQ0FBZ0IsQ0FBUSwyQ0FBMkM7SUFFNUUsWUFBb0IsWUFBMEI7UUFBMUIsaUJBQVksR0FBWixZQUFZLENBQWM7SUFBRyxDQUFDLENBQUMsdUJBQXVCO0lBRTFFLFFBQVE7UUFDTiwrQ0FBK0M7UUFDL0MsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsS0FBbUIsRUFBRSxFQUFFO1lBQzNELE9BQU8sQ0FBQyxHQUFHLENBQUMsd0JBQXdCLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBRSxzQkFBc0I7WUFFckUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyw2Q0FBNkM7WUFFcEUsc0RBQXNEO1lBQ3RELFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2QsdUNBQXVDO2dCQUN2QyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUcsb0NBQW9DO1lBQzdELENBQUMsRUFBRSxLQUFLLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxDQUFDO1FBQzdCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzt3R0FyQlUsY0FBYzs0RkFBZCxjQUFjLHVHQ2IzQiwwbEJBaUJvRix1cENEUnZFLFlBQVk7OzRGQUlaLGNBQWM7a0JBVDFCLFNBQVM7K0JBQ0UsV0FBVyxjQUNULElBQUksV0FHUCxDQUFFLFlBQVksQ0FBRSxDQUFPLDJDQUEyQzs7aUZBTWxFLFFBQVE7c0JBQWhCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgVG9hc3RTZXJ2aWNlLCBUb2FzdE1lc3NhZ2UgfSBmcm9tICcuLi9zZXJ2aWNlL3RvYXN0LnNlcnZpY2UnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdkc28tdG9hc3QnLCAgICAgICAgICAgLy8gQ29tcG9uZW50IHNlbGVjdG9yIHVzZWQgaW4gSFRNTFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsICAgICAgICAgICAgICAgIC8vIFN0YW5kYWxvbmUgY29tcG9uZW50LCBubyBtb2R1bGUgbmVlZGVkXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3RvYXN0LmNvbXBvbmVudC5odG1sJywgXHJcbiAgc3R5bGVVcmxzOiBbJy4vdG9hc3QuY29tcG9uZW50LnNjc3MnXSwgXHJcbiAgaW1wb3J0czogWyBDb21tb25Nb2R1bGUgXSAgICAgICAvLyBJbXBvcnQgQ29tbW9uTW9kdWxlIGZvciBuZ0lmLCBuZ0ZvciBldGMuXHJcbn0pXHJcblxyXG5cclxuZXhwb3J0IGNsYXNzIFRvYXN0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcclxuICB0b2FzdHM6IFRvYXN0TWVzc2FnZVtdID0gW107ICAgIFxyXG4gIEBJbnB1dCgpIHBvc2l0aW9uOiAndG9wLXJpZ2h0JyB8ICdib3R0b20tcmlnaHQnIHwgJ3RvcC1sZWZ0JyB8ICdib3R0b20tbGVmdCcgfCAndG9wLWNlbnRlcicgfCAnYm90dG9tLWNlbnRlcicgPSAndG9wLXJpZ2h0JztcclxuXHJcbiAgdG9hc3REYXRhITogVG9hc3RNZXNzYWdlOyAgICAgICAgLy8gU3RvcmVzIHRoZSBjdXJyZW50IHRvYXN0IGJlaW5nIGRpc3BsYXllZFxyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHRvYXN0U2VydmljZTogVG9hc3RTZXJ2aWNlKSB7fSAvLyBJbmplY3QgdG9hc3Qgc2VydmljZVxyXG5cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIC8vIFN1YnNjcmliZSB0byB0b2FzdCBtZXNzYWdlcyBmcm9tIHRoZSBzZXJ2aWNlXHJcbiAgICB0aGlzLnRvYXN0U2VydmljZS50b2FzdCQuc3Vic2NyaWJlKCh0b2FzdDogVG9hc3RNZXNzYWdlKSA9PiB7XHJcbiAgICBjb25zb2xlLmxvZygnVG9hc3QgQ2hpbGQgTGlzdGVuaW5nOicsIHRvYXN0KTsgIC8vIEFkZCB0aGlzIGRlYnVnIGxvZyFcclxuXHJcbiAgICB0aGlzLnRvYXN0cy5wdXNoKHRvYXN0KTsgLy8gQWRkIHRoZSBuZXcgdG9hc3QgdG8gdGhlIGFycmF5IGZvciBkaXNwbGF5XHJcblxyXG4gICAgICAvLyBBdXRvLWhpZGUgYWZ0ZXIgc3BlY2lmaWVkIGR1cmF0aW9uIChkZWZhdWx0IDMwMDBtcylcclxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgLy8gdGhpcy52aXNpYmxlID0gZmFsc2U7ICAvLyBIaWRlIHRvYXN0XHJcbiAgICAgICAgdGhpcy50b2FzdHMuc2hpZnQoKTsgICAvLyBSZW1vdmUgZmlyc3QgdG9hc3QgZnJvbSB0aGUgYXJyYXlcclxuICAgICAgfSwgdG9hc3QuZHVyYXRpb24gfHwgMzAwMCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG5cclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwidG9hc3Qtd3JhcHBlclwiIFxyXG4gIFtuZ0NsYXNzXT1cIlsndG9hc3QtJyArIChwb3NpdGlvbiB8fCAndG9wLXJpZ2h0JyldXCI+XHJcbiAgPGRpdlxyXG4gICAgKm5nRm9yPVwibGV0IHRvYXN0IG9mIHRvYXN0czsgbGV0IGkgPSBpbmRleFwiXHJcbiAgICBjbGFzcz1cInRvYXN0LWNvbnRhaW5lclwiXHJcbiAgICBbbmdDbGFzc109XCJbJ3RvYXN0LScgKyAodG9hc3QudmFyaWFudCB8fCAnbmV1dHJhbCcpXVwiXHJcbiAgICA+XHJcbiAgICBcclxuICAgIDxkaXYgY2xhc3M9XCJ0b2FzdC1oZWFkZXJcIiAqbmdJZj1cInRvYXN0LmhlYWRlclwiPnt7IHRvYXN0LmhlYWRlciB9fTwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cInRvYXN0LWJvZHlcIj5cclxuICAgICAgPGRpdiBjbGFzcz1cInRvYXN0LW1lc3NhZ2VcIj57eyB0b2FzdC5tZXNzYWdlIH19PC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcblxyXG48IS0tIFxyXG5bbmdTdHlsZV09XCJ7XHJcbiAgICAgIGFuaW1hdGlvbjogJ2ZhZGVJbk91dCAnICsgKHRvYXN0LmR1cmF0aW9uIHx8IDMwMDApICsgJ21zIGVhc2UgZm9yd2FyZHMnfVwiPiAtLT4iXX0=
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { Component, Input } from '@angular/core';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "@angular/common";
|
|
5
|
+
export class TooltipComponent {
|
|
6
|
+
el;
|
|
7
|
+
text; // Tooltip text to display
|
|
8
|
+
position = 'top'; // Position of the tooltip (default is 'top')
|
|
9
|
+
tooltipWidth = '300px'; // Default width, can be overridden
|
|
10
|
+
constructor(el) {
|
|
11
|
+
this.el = el;
|
|
12
|
+
}
|
|
13
|
+
showTooltip = false; // This flag controls the visibility of the tooltip
|
|
14
|
+
isHovered = false; // This flag checks if the mouse is over the tooltip
|
|
15
|
+
// Triggered when the mouse enters the wrapper area (button + tooltip)
|
|
16
|
+
onMouseEnter() {
|
|
17
|
+
// console.log('Mouse entered');
|
|
18
|
+
this.showTooltip = true; // Show tooltip
|
|
19
|
+
}
|
|
20
|
+
// Triggered when the mouse leaves the wrapper area (button + tooltip)
|
|
21
|
+
onMouseLeave() {
|
|
22
|
+
// console.log('Mouse left');
|
|
23
|
+
this.showTooltip = false; // Hide tooltip
|
|
24
|
+
}
|
|
25
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
26
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: TooltipComponent, isStandalone: true, selector: "dso-tooltip", inputs: { text: "text", position: "position", tooltipWidth: "tooltipWidth" }, ngImport: i0, template: "<!-- Tooltip wrapper: listens for mouse enter/leave -->\r\n<div class=\"tooltip-wrapper\" (mouseenter)=\"onMouseEnter()\" (mouseleave)=\"onMouseLeave()\">\r\n <ng-content></ng-content> <!-- This will allow the button or other content to be passed inside -->\r\n\r\n <!-- Tooltip box -->\r\n <div \r\n class=\"tooltip\" \r\n *ngIf=\"showTooltip\" \r\n [ngClass]=\"position\"\r\n [ngStyle]=\"{ 'width': tooltipWidth }\"\r\n >\r\n {{ text }}\r\n </div>\r\n</div>", styles: [".tooltip-wrapper{position:relative}.tooltip{position:absolute;background-color:#000;color:#fff;display:block;white-space:normal;word-break:break-word;border-radius:4px;pointer-events:auto;padding:12px;font-size:12px;z-index:100}.tooltip.top{bottom:calc(100% + 4px);transform:translate(-25%)}.tooltip.bottom{top:calc(100% + 4px);transform:translate(-25%)}.tooltip.left{top:0%;right:calc(100% + 4px);transform:translateY(-25%)}.tooltip.right{bottom:0%;left:calc(100% + 4px);transform:translateY(25%)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
27
|
+
}
|
|
28
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TooltipComponent, decorators: [{
|
|
29
|
+
type: Component,
|
|
30
|
+
args: [{ selector: 'dso-tooltip', standalone: true, imports: [CommonModule], template: "<!-- Tooltip wrapper: listens for mouse enter/leave -->\r\n<div class=\"tooltip-wrapper\" (mouseenter)=\"onMouseEnter()\" (mouseleave)=\"onMouseLeave()\">\r\n <ng-content></ng-content> <!-- This will allow the button or other content to be passed inside -->\r\n\r\n <!-- Tooltip box -->\r\n <div \r\n class=\"tooltip\" \r\n *ngIf=\"showTooltip\" \r\n [ngClass]=\"position\"\r\n [ngStyle]=\"{ 'width': tooltipWidth }\"\r\n >\r\n {{ text }}\r\n </div>\r\n</div>", styles: [".tooltip-wrapper{position:relative}.tooltip{position:absolute;background-color:#000;color:#fff;display:block;white-space:normal;word-break:break-word;border-radius:4px;pointer-events:auto;padding:12px;font-size:12px;z-index:100}.tooltip.top{bottom:calc(100% + 4px);transform:translate(-25%)}.tooltip.bottom{top:calc(100% + 4px);transform:translate(-25%)}.tooltip.left{top:0%;right:calc(100% + 4px);transform:translateY(-25%)}.tooltip.right{bottom:0%;left:calc(100% + 4px);transform:translateY(25%)}\n"] }]
|
|
31
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { text: [{
|
|
32
|
+
type: Input
|
|
33
|
+
}], position: [{
|
|
34
|
+
type: Input
|
|
35
|
+
}], tooltipWidth: [{
|
|
36
|
+
type: Input
|
|
37
|
+
}] } });
|
|
38
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbHRpcC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS9zcmMvbGliL3Rvb2x0aXAvdG9vbHRpcC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS9zcmMvbGliL3Rvb2x0aXAvdG9vbHRpcC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFNBQVMsRUFBYyxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7OztBQVM1RCxNQUFNLE9BQU8sZ0JBQWdCO0lBS1I7SUFKWCxJQUFJLENBQVUsQ0FBRSwwQkFBMEI7SUFDMUMsUUFBUSxHQUFXLEtBQUssQ0FBQyxDQUFFLDZDQUE2QztJQUN4RSxZQUFZLEdBQVcsT0FBTyxDQUFDLENBQUksbUNBQW1DO0lBRS9FLFlBQW9CLEVBQWM7UUFBZCxPQUFFLEdBQUYsRUFBRSxDQUFZO0lBQUcsQ0FBQztJQUl0QyxXQUFXLEdBQUcsS0FBSyxDQUFDLENBQUUsbURBQW1EO0lBQ3pFLFNBQVMsR0FBRyxLQUFLLENBQUMsQ0FBSSxvREFBb0Q7SUFFMUUsc0VBQXNFO0lBQ3RFLFlBQVk7UUFDVixnQ0FBZ0M7UUFDaEMsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsQ0FBQyxlQUFlO0lBQzFDLENBQUM7SUFFRCxzRUFBc0U7SUFDdEUsWUFBWTtRQUNWLDZCQUE2QjtRQUM3QixJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQyxDQUFDLGVBQWU7SUFDM0MsQ0FBQzt3R0F0QlcsZ0JBQWdCOzRGQUFoQixnQkFBZ0IscUpDVjlCLGdlQWFNLDZpQkRMTyxZQUFZOzs0RkFFWCxnQkFBZ0I7a0JBUDdCLFNBQVM7K0JBQ0UsYUFBYSxjQUNYLElBQUksV0FHUCxDQUFFLFlBQVksQ0FBRTsrRUFHaEIsSUFBSTtzQkFBWixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnZHNvLXRvb2x0aXAnLFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3Rvb2x0aXAuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL3Rvb2x0aXAuY29tcG9uZW50LnNjc3MnXSxcclxuICBpbXBvcnRzOiBbIENvbW1vbk1vZHVsZSBdXHJcbn0pXHJcbiBleHBvcnQgY2xhc3MgVG9vbHRpcENvbXBvbmVudCB7XHJcbiAgQElucHV0KCkgdGV4dCE6IHN0cmluZzsgIC8vIFRvb2x0aXAgdGV4dCB0byBkaXNwbGF5XHJcbiAgQElucHV0KCkgcG9zaXRpb246IHN0cmluZyA9ICd0b3AnOyAgLy8gUG9zaXRpb24gb2YgdGhlIHRvb2x0aXAgKGRlZmF1bHQgaXMgJ3RvcCcpXHJcbiAgQElucHV0KCkgdG9vbHRpcFdpZHRoOiBzdHJpbmcgPSAnMzAwcHgnOyAgICAvLyBEZWZhdWx0IHdpZHRoLCBjYW4gYmUgb3ZlcnJpZGRlblxyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGVsOiBFbGVtZW50UmVmKSB7fVxyXG5cclxuXHJcblxyXG4gIHNob3dUb29sdGlwID0gZmFsc2U7ICAvLyBUaGlzIGZsYWcgY29udHJvbHMgdGhlIHZpc2liaWxpdHkgb2YgdGhlIHRvb2x0aXBcclxuICBpc0hvdmVyZWQgPSBmYWxzZTsgICAgLy8gVGhpcyBmbGFnIGNoZWNrcyBpZiB0aGUgbW91c2UgaXMgb3ZlciB0aGUgdG9vbHRpcFxyXG5cclxuICAvLyBUcmlnZ2VyZWQgd2hlbiB0aGUgbW91c2UgZW50ZXJzIHRoZSB3cmFwcGVyIGFyZWEgKGJ1dHRvbiArIHRvb2x0aXApXHJcbiAgb25Nb3VzZUVudGVyKCkge1xyXG4gICAgLy8gY29uc29sZS5sb2coJ01vdXNlIGVudGVyZWQnKTtcclxuICAgIHRoaXMuc2hvd1Rvb2x0aXAgPSB0cnVlOyAvLyBTaG93IHRvb2x0aXBcclxuICB9XHJcblxyXG4gIC8vIFRyaWdnZXJlZCB3aGVuIHRoZSBtb3VzZSBsZWF2ZXMgdGhlIHdyYXBwZXIgYXJlYSAoYnV0dG9uICsgdG9vbHRpcClcclxuICBvbk1vdXNlTGVhdmUoKSB7XHJcbiAgICAvLyBjb25zb2xlLmxvZygnTW91c2UgbGVmdCcpO1xyXG4gICAgdGhpcy5zaG93VG9vbHRpcCA9IGZhbHNlOyAvLyBIaWRlIHRvb2x0aXBcclxuICB9XHJcblxyXG5cclxufVxyXG4iLCI8IS0tIFRvb2x0aXAgd3JhcHBlcjogbGlzdGVucyBmb3IgbW91c2UgZW50ZXIvbGVhdmUgLS0+XHJcbjxkaXYgY2xhc3M9XCJ0b29sdGlwLXdyYXBwZXJcIiAobW91c2VlbnRlcik9XCJvbk1vdXNlRW50ZXIoKVwiIChtb3VzZWxlYXZlKT1cIm9uTW91c2VMZWF2ZSgpXCI+XHJcbiAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PiAgPCEtLSBUaGlzIHdpbGwgYWxsb3cgdGhlIGJ1dHRvbiBvciBvdGhlciBjb250ZW50IHRvIGJlIHBhc3NlZCBpbnNpZGUgLS0+XHJcblxyXG4gIDwhLS0gVG9vbHRpcCBib3ggLS0+XHJcbiAgPGRpdiBcclxuICAgIGNsYXNzPVwidG9vbHRpcFwiIFxyXG4gICAgKm5nSWY9XCJzaG93VG9vbHRpcFwiIFxyXG4gICAgW25nQ2xhc3NdPVwicG9zaXRpb25cIlxyXG4gICAgW25nU3R5bGVdPVwieyAnd2lkdGgnOiB0b29sdGlwV2lkdGggfVwiXHJcbiAgPlxyXG4gIHt7IHRleHQgfX1cclxuICA8L2Rpdj5cclxuPC9kaXY+Il19
|