@webilix/ngx-helper-m3 0.0.11 → 0.0.13

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, makeEnvironmentProviders, Injector, Component, HostBinding, Input, Injectable, Optional, Inject, EventEmitter, Output, inject, Directive, Pipe } from '@angular/core';
2
+ import { InjectionToken, makeEnvironmentProviders, Injector, Component, HostBinding, Input, Pipe, Injectable, Optional, Inject, EventEmitter, Output, inject, Directive, HostListener, createComponent } from '@angular/core';
3
3
  import { NgComponentOutlet, NgClass } from '@angular/common';
4
4
  import * as i1$2 from '@angular/material/button';
5
5
  import { MatButton, MatIconButton, MatButtonModule } from '@angular/material/button';
@@ -9,15 +9,18 @@ import { MatIcon, MatIconModule } from '@angular/material/icon';
9
9
  import * as i2 from '@angular/material/menu';
10
10
  import { MatMenuModule } from '@angular/material/menu';
11
11
  import { Helper } from '@webilix/helper-library';
12
+ import { JalaliDateTime } from '@webilix/jalali-date-time';
12
13
  import * as i1 from '@angular/router';
13
14
  import * as i3 from '@angular/cdk/clipboard';
14
15
  import { ClipboardModule } from '@angular/cdk/clipboard';
15
- import { JalaliDateTime } from '@webilix/jalali-date-time';
16
16
  import * as i1$1 from '@angular/platform-browser';
17
17
  import * as i2$1 from '@angular/material/dialog';
18
18
  import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
19
19
  import * as i1$3 from '@angular/material/bottom-sheet';
20
20
  import { MAT_BOTTOM_SHEET_DATA } from '@angular/material/bottom-sheet';
21
+ import { trigger, transition, style, animate } from '@angular/animations';
22
+ import * as i1$4 from '@angular/common/http';
23
+ import { HttpHeaders, HttpEventType } from '@angular/common/http';
21
24
 
22
25
  const NGX_HELPER_CONFIG = new InjectionToken('NGX-HELPER-CONFIG');
23
26
  const provideNgxHelperConfig = (config) => {
@@ -76,214 +79,526 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImpor
76
79
  args: [{ required: false }]
77
80
  }] } });
78
81
 
79
- class ComponentService {
80
- getComponentConfig(config) {
81
- const getStickyView = (config) => {
82
- return {
83
- desktopView: typeof config === 'string' ? config : config.desktopView,
84
- mobileView: typeof config === 'string' ? config : config.mobileView,
85
- };
86
- };
87
- return {
88
- mobileWidth: config?.mobileWidth || 600,
89
- pageGroupSidebarWidth: config?.pageGroupSidebarWidth || '200px',
90
- stickyView: config?.stickyView
91
- ? {
92
- top: config.stickyView.top ? getStickyView(config.stickyView.top) : undefined,
93
- bottom: config.stickyView.bottom ? getStickyView(config.stickyView.bottom) : undefined,
94
- }
95
- : undefined,
96
- };
82
+ class NgxHelperBankCardPipe {
83
+ transform(value, options) {
84
+ if (value === undefined || value === null || !Helper.IS.string(value) || value === '')
85
+ return '';
86
+ switch (options?.view) {
87
+ case 'BANK':
88
+ return Helper.BANK.findCard(value)?.title || '';
89
+ default:
90
+ return Helper.STRING.getBankCardView(value, options?.join || '-');
91
+ }
97
92
  }
98
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: ComponentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
99
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: ComponentService });
93
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperBankCardPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
94
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperBankCardPipe, isStandalone: true, name: "ngxHelperBankCard" });
100
95
  }
101
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: ComponentService, decorators: [{
102
- type: Injectable
96
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperBankCardPipe, decorators: [{
97
+ type: Pipe,
98
+ args: [{ name: 'ngxHelperBankCard' }]
103
99
  }] });
104
100
 
105
- class NgxHelperCardComponent {
106
- componentService;
107
- config;
108
- className = 'ngx-helper-m3-card';
109
- title;
110
- subTitle;
111
- icon;
112
- actions = [];
113
- padding = '1rem';
114
- backgroundColor;
115
- hasShadow = false;
116
- isMobile = false;
117
- buttons = [];
118
- componentConfig;
119
- constructor(componentService, config) {
120
- this.componentService = componentService;
121
- this.config = config;
101
+ class NgxHelperDatePipe {
102
+ transform(value, options) {
103
+ if (value === undefined || value === null || (!Helper.IS.date(value) && !Helper.IS.number(value)))
104
+ return '';
105
+ const date = typeof value === 'number' ? new Date(value) : value;
106
+ const jalali = JalaliDateTime();
107
+ const timezone = options?.timezone && jalali.timezones().includes(options?.timezone) ? options?.timezone : 'Asia/Tehran';
108
+ switch (options?.format || 'DATE') {
109
+ case 'FULL':
110
+ return jalali.toFullText(date, { format: 'W، d N Y H:I', timezone });
111
+ case 'SHORT':
112
+ return jalali.toFullText(date, { format: 'Y/M/D', timezone });
113
+ case 'DATE':
114
+ return jalali.toFullText(date, { format: 'W، d N Y', timezone });
115
+ case 'TIME':
116
+ return jalali.toFullText(date, { format: 'H:I', timezone });
117
+ case 'WEEK':
118
+ const { from, to } = jalali.periodWeek(1, date, timezone);
119
+ return Helper.DATE.jalaliPeriod(from, to, timezone);
120
+ case 'MONTH':
121
+ return jalali.toFullText(date, { format: 'N Y', timezone });
122
+ case 'YEAR':
123
+ return jalali.toFullText(date, { format: 'Y', timezone });
124
+ default:
125
+ return jalali.toFullText(date, { format: options?.format, timezone });
126
+ }
122
127
  }
123
- ngOnInit() {
124
- this.componentConfig = this.componentService.getComponentConfig(this.config);
125
- this.onResize();
128
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
129
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDatePipe, isStandalone: true, name: "ngxHelperDate" });
130
+ }
131
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDatePipe, decorators: [{
132
+ type: Pipe,
133
+ args: [{ name: 'ngxHelperDate' }]
134
+ }] });
135
+
136
+ class NgxHelperDurationPipe {
137
+ transform(value, options) {
138
+ if (value === undefined || value === null)
139
+ return '';
140
+ let seconds = 0;
141
+ if (Helper.IS.number(value))
142
+ seconds = Math.abs(value);
143
+ else if (Helper.IS.date(value))
144
+ seconds = Math.floor(Math.abs(new Date().getTime() - value.getTime()) / 1000);
145
+ else if (Helper.IS.object(value)) {
146
+ const from = 'from' in value ? value.from : new Date();
147
+ const to = 'to' in value ? value.to : new Date();
148
+ seconds = Math.floor(Math.abs(from.getTime() - to.getTime()) / 1000);
149
+ }
150
+ const days = Math.floor(seconds / (24 * 60 * 60));
151
+ seconds -= days * (24 * 60 * 60);
152
+ const hours = Math.floor(seconds / (60 * 60));
153
+ seconds -= hours * (60 * 60);
154
+ const minutes = Math.floor(seconds / 60);
155
+ seconds -= minutes * 60;
156
+ const hasDays = days !== 0;
157
+ const time = [hours, minutes, seconds].map((v) => v.toString().padStart(2, '0')).join(':');
158
+ switch (options?.format || 'TEXT') {
159
+ case 'TEXT':
160
+ const hasTime = !!hours || !!minutes || !!seconds;
161
+ const day = hasDays
162
+ ? Helper.NUMBER.format(days, 'EN') + (!!options?.english ? (days === 1 ? ' day' : ' days') : ' روز')
163
+ : '';
164
+ const join = hasDays && hasTime ? (!!options?.english ? ', ' : ' و ') : '';
165
+ return (day + join + (!hasDays || hasTime ? time : '')).trim();
166
+ case 'FULL':
167
+ return (hasDays ? Helper.NUMBER.format(days, 'EN') + ':' : '') + time;
168
+ case 'DAY':
169
+ return Helper.NUMBER.format(days + (hours !== 0 || minutes !== 0 ? 1 : 0), !!options?.english ? 'EN' : 'FA');
170
+ case 'HOUR':
171
+ return Helper.NUMBER.format(days * 24 + hours + (minutes !== 0 ? 1 : 0), !!options?.english ? 'EN' : 'FA');
172
+ case 'MINUTE':
173
+ return Helper.NUMBER.format(days * 24 * 60 + hours * 60 + minutes, !!options?.english ? 'EN' : 'FA');
174
+ case 'SECOND':
175
+ return Helper.NUMBER.format(days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds, !!options?.english ? 'EN' : 'FA');
176
+ }
126
177
  }
127
- ngOnChanges(changes) {
128
- this.className = `ngx-helper-m3-card${this.hasShadow ? ' has-shadow' : ''}`;
129
- this.buttons = this.actions.map((action) => {
130
- return 'buttons' in action ? { type: 'MENU', ...action } : { type: 'BUTTON', ...action };
131
- });
178
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDurationPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
179
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDurationPipe, isStandalone: true, name: "ngxHelperDuration" });
180
+ }
181
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDurationPipe, decorators: [{
182
+ type: Pipe,
183
+ args: [{ name: 'ngxHelperDuration' }]
184
+ }] });
185
+
186
+ class NgxHelperFileSizePipe {
187
+ transform(value, options) {
188
+ if (value === undefined || value === null || !Helper.IS.number(value))
189
+ return '';
190
+ return Helper.NUMBER.toFileSize(value, !!options?.english ? 'EN' : 'FA');
132
191
  }
133
- onResize() {
134
- this.isMobile = window.innerWidth <= this.componentConfig.mobileWidth;
192
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperFileSizePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
193
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperFileSizePipe, isStandalone: true, name: "ngxHelperFileSize" });
194
+ }
195
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperFileSizePipe, decorators: [{
196
+ type: Pipe,
197
+ args: [{ name: 'ngxHelperFileSize' }]
198
+ }] });
199
+
200
+ class NgxHelperMobilePipe {
201
+ transform(value, options) {
202
+ if (value === undefined || value === null || !Helper.IS.string(value) || value === '')
203
+ return '';
204
+ return Helper.STRING.getMobileView(value, options?.join || '-');
135
205
  }
136
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperCardComponent, deps: [{ token: ComponentService }, { token: NGX_HELPER_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Component });
137
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.4", type: NgxHelperCardComponent, isStandalone: true, selector: "ngx-helper-card", inputs: { title: "title", subTitle: "subTitle", icon: "icon", actions: "actions", padding: "padding", backgroundColor: "backgroundColor", hasShadow: "hasShadow" }, host: { listeners: { "window:resize": "onResize($event)" }, properties: { "className": "this.className" } }, providers: [ComponentService], usesOnChanges: true, ngImport: i0, template: "<div class=\"card-header\" [class.has-sub-title]=\"subTitle\">\n <!-- ICON -->\n @if (icon) { <mat-icon>{{ icon }}</mat-icon> }\n\n <!-- TITLE -->\n <div class=\"content\">\n <div class=\"title\">{{ title }}</div>\n <!-- SUB TITLE -->\n @if (subTitle) {\n <div class=\"sub-title\">{{ subTitle }}</div>\n }\n </div>\n\n <!-- BUTTONS -->\n @if (buttons.length > 0) {\n <div class=\"buttons\" [ngClass]=\"isMobile ? 'mobile-view' : ''\">\n @for (item of buttons; track $index) {\n <!-- TYPE -->\n @switch (item.type) {\n\n <!-- BUTTON -->\n @case('BUTTON') {\n <button mat-button type=\"button\" [style.color]=\"item.color\" (click)=\"item.action()\">\n @if (!isMobile) {\n <div class=\"title\">{{ item.title }}</div>\n }\n <!-- ICON -->\n @if (isMobile || item.showIcon) {\n <mat-icon>{{ item.icon }}</mat-icon>\n }\n </button>\n }\n\n <!-- MENU -->\n @case('MENU') {\n <button mat-button type=\"button\" [style.color]=\"item.color\" [matMenuTriggerFor]=\"actionMenu\">\n @if (!isMobile) {\n <div class=\"title\">{{ item.title }}</div>\n }\n <!-- ICON -->\n @if (isMobile || item.showIcon) {\n <mat-icon>{{ item.icon }}</mat-icon>\n }\n </button>\n <mat-menu #actionMenu=\"matMenu\" class=\"ngx-helper-card-action-menu\">\n @for (menu of item.buttons; track $index) {\n <!-- DIVIDER -->\n @if (menu === 'DIVIDER') { <mat-divider></mat-divider> }\n <!-- BUTTON -->\n @else {\n <button mat-menu-item type=\"button\" (click)=\"menu.action()\" [style.color]=\"menu.color\">\n <div class=\"title\">{{ menu.title }}</div>\n <mat-icon [style.color]=\"menu.color\">{{ menu.icon }}</mat-icon>\n </button>\n } }\n </mat-menu>\n } } }\n </div>\n }\n</div>\n\n<div class=\"card-content\" [style.padding]=\"padding\" [style.background-color]=\"backgroundColor\">\n <ng-content></ng-content>\n</div>\n", styles: ["::ng-deep .ngx-helper-card-action-menu button mat-icon{font-size:115%;margin:0 0 0 .75rem!important}::ng-deep .ngx-helper-card-action-menu button .title{font-size:90%!important}::ng-deep .ngx-helper-card-action-menu .mat-mdc-menu-content{padding:0}::ng-deep .ngx-helper-card-action-menu .mat-mdc-menu-item{direction:rtl;text-align:right}::ng-deep .ngx-helper-card-action-menu .mat-divider{margin:0;border-top-color:var(--outline-variant)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }] });
206
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperMobilePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
207
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperMobilePipe, isStandalone: true, name: "ngxHelperMobile" });
138
208
  }
139
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperCardComponent, decorators: [{
140
- type: Component,
141
- args: [{ selector: 'ngx-helper-card', host: { '(window:resize)': 'onResize($event)' }, imports: [NgClass, MatButton, MatDivider, MatIcon, MatMenuModule], providers: [ComponentService], template: "<div class=\"card-header\" [class.has-sub-title]=\"subTitle\">\n <!-- ICON -->\n @if (icon) { <mat-icon>{{ icon }}</mat-icon> }\n\n <!-- TITLE -->\n <div class=\"content\">\n <div class=\"title\">{{ title }}</div>\n <!-- SUB TITLE -->\n @if (subTitle) {\n <div class=\"sub-title\">{{ subTitle }}</div>\n }\n </div>\n\n <!-- BUTTONS -->\n @if (buttons.length > 0) {\n <div class=\"buttons\" [ngClass]=\"isMobile ? 'mobile-view' : ''\">\n @for (item of buttons; track $index) {\n <!-- TYPE -->\n @switch (item.type) {\n\n <!-- BUTTON -->\n @case('BUTTON') {\n <button mat-button type=\"button\" [style.color]=\"item.color\" (click)=\"item.action()\">\n @if (!isMobile) {\n <div class=\"title\">{{ item.title }}</div>\n }\n <!-- ICON -->\n @if (isMobile || item.showIcon) {\n <mat-icon>{{ item.icon }}</mat-icon>\n }\n </button>\n }\n\n <!-- MENU -->\n @case('MENU') {\n <button mat-button type=\"button\" [style.color]=\"item.color\" [matMenuTriggerFor]=\"actionMenu\">\n @if (!isMobile) {\n <div class=\"title\">{{ item.title }}</div>\n }\n <!-- ICON -->\n @if (isMobile || item.showIcon) {\n <mat-icon>{{ item.icon }}</mat-icon>\n }\n </button>\n <mat-menu #actionMenu=\"matMenu\" class=\"ngx-helper-card-action-menu\">\n @for (menu of item.buttons; track $index) {\n <!-- DIVIDER -->\n @if (menu === 'DIVIDER') { <mat-divider></mat-divider> }\n <!-- BUTTON -->\n @else {\n <button mat-menu-item type=\"button\" (click)=\"menu.action()\" [style.color]=\"menu.color\">\n <div class=\"title\">{{ menu.title }}</div>\n <mat-icon [style.color]=\"menu.color\">{{ menu.icon }}</mat-icon>\n </button>\n } }\n </mat-menu>\n } } }\n </div>\n }\n</div>\n\n<div class=\"card-content\" [style.padding]=\"padding\" [style.background-color]=\"backgroundColor\">\n <ng-content></ng-content>\n</div>\n", styles: ["::ng-deep .ngx-helper-card-action-menu button mat-icon{font-size:115%;margin:0 0 0 .75rem!important}::ng-deep .ngx-helper-card-action-menu button .title{font-size:90%!important}::ng-deep .ngx-helper-card-action-menu .mat-mdc-menu-content{padding:0}::ng-deep .ngx-helper-card-action-menu .mat-mdc-menu-item{direction:rtl;text-align:right}::ng-deep .ngx-helper-card-action-menu .mat-divider{margin:0;border-top-color:var(--outline-variant)}\n"] }]
142
- }], ctorParameters: () => [{ type: ComponentService }, { type: undefined, decorators: [{
143
- type: Optional
144
- }, {
145
- type: Inject,
146
- args: [NGX_HELPER_CONFIG]
147
- }] }], propDecorators: { className: [{
148
- type: HostBinding,
149
- args: ['className']
150
- }], title: [{
151
- type: Input,
152
- args: [{ required: true }]
153
- }], subTitle: [{
154
- type: Input,
155
- args: [{ required: false }]
156
- }], icon: [{
157
- type: Input,
158
- args: [{ required: false }]
159
- }], actions: [{
160
- type: Input,
161
- args: [{ required: false }]
162
- }], padding: [{
163
- type: Input,
164
- args: [{ required: false }]
165
- }], backgroundColor: [{
166
- type: Input,
167
- args: [{ required: false }]
168
- }], hasShadow: [{
169
- type: Input,
170
- args: [{ required: false }]
171
- }] } });
209
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperMobilePipe, decorators: [{
210
+ type: Pipe,
211
+ args: [{ name: 'ngxHelperMobile' }]
212
+ }] });
172
213
 
173
- class NgxHelperLoaderComponent {
174
- loaderSize;
175
- loaderColor;
176
- mode;
177
- size;
178
- color;
179
- padding;
180
- ngOnChanges(changes) {
181
- this.loaderSize = `${this.size || 25}px`;
182
- this.loaderColor = this.color || `var(--secondary)`;
214
+ class NgxHelperNumberPipe {
215
+ transform(value, options) {
216
+ if (value === undefined || value === null || !Helper.IS.number(value))
217
+ return '';
218
+ value = options?.fractionDigits ? +value.toFixed(options?.fractionDigits) : value;
219
+ return Helper.NUMBER.format(value, options?.english ? 'EN' : 'FA');
183
220
  }
184
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
185
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.4", type: NgxHelperLoaderComponent, isStandalone: true, selector: "ngx-helper-loader", inputs: { mode: "mode", size: "size", color: "color", padding: "padding" }, host: { properties: { "style.--loader-size": "this.loaderSize", "style.--loader-color": "this.loaderColor" } }, usesOnChanges: true, ngImport: i0, template: "<div [style.padding]=\"padding || '0'\">\n <div [class]=\"mode.toLowerCase()\"></div>\n</div>\n", styles: [".spinner{--size: calc(var(--loader-size) / 7);width:var(--loader-size);aspect-ratio:1;border-radius:50%;background:radial-gradient(farthest-side,var(--loader-color) 94%,rgba(0,0,0,0)) top/var(--size) var(--size) no-repeat,conic-gradient(rgba(0,0,0,0) 30%,var(--loader-color));mask:radial-gradient(farthest-side,rgba(0,0,0,0) calc(100% - var(--size)),#000 0);animation:spinner 1s infinite linear}@keyframes spinner{to{transform:rotate(1turn)}}.dots-spinner{--dot: no-repeat radial-gradient(farthest-side, var(--loader-color) 92%, #0000);--size: calc(var(--loader-size) / 4);width:var(--loader-size);aspect-ratio:1;background:var(--dot) top,var(--dot) left,var(--dot) right,var(--dot) bottom;background-size:var(--size) var(--size);animation:dots-spinner 1s infinite}@keyframes dots-spinner{to{transform:rotate(.5turn)}}.wheel-spinner{--size: calc(var(--loader-size) / 9);width:var(--loader-size);aspect-ratio:1;border-radius:50%;background:var(--loader-color);mask:repeating-conic-gradient(rgba(0,0,0,0) 0deg,#000 1deg 70deg,rgba(0,0,0,0) 71deg 90deg),radial-gradient(farthest-side,rgba(0,0,0,0) calc(100% - var(--size) - 1px),#000 calc(100% - var(--size)));-webkit-mask-composite:destination-in;mask-composite:intersect;animation:wheel-spinner 1s infinite}@keyframes wheel-spinner{to{transform:rotate(.5turn)}}\n"] });
221
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperNumberPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
222
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperNumberPipe, isStandalone: true, name: "ngxHelperNumber" });
186
223
  }
187
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperLoaderComponent, decorators: [{
188
- type: Component,
189
- args: [{ selector: 'ngx-helper-loader', imports: [], template: "<div [style.padding]=\"padding || '0'\">\n <div [class]=\"mode.toLowerCase()\"></div>\n</div>\n", styles: [".spinner{--size: calc(var(--loader-size) / 7);width:var(--loader-size);aspect-ratio:1;border-radius:50%;background:radial-gradient(farthest-side,var(--loader-color) 94%,rgba(0,0,0,0)) top/var(--size) var(--size) no-repeat,conic-gradient(rgba(0,0,0,0) 30%,var(--loader-color));mask:radial-gradient(farthest-side,rgba(0,0,0,0) calc(100% - var(--size)),#000 0);animation:spinner 1s infinite linear}@keyframes spinner{to{transform:rotate(1turn)}}.dots-spinner{--dot: no-repeat radial-gradient(farthest-side, var(--loader-color) 92%, #0000);--size: calc(var(--loader-size) / 4);width:var(--loader-size);aspect-ratio:1;background:var(--dot) top,var(--dot) left,var(--dot) right,var(--dot) bottom;background-size:var(--size) var(--size);animation:dots-spinner 1s infinite}@keyframes dots-spinner{to{transform:rotate(.5turn)}}.wheel-spinner{--size: calc(var(--loader-size) / 9);width:var(--loader-size);aspect-ratio:1;border-radius:50%;background:var(--loader-color);mask:repeating-conic-gradient(rgba(0,0,0,0) 0deg,#000 1deg 70deg,rgba(0,0,0,0) 71deg 90deg),radial-gradient(farthest-side,rgba(0,0,0,0) calc(100% - var(--size) - 1px),#000 calc(100% - var(--size)));-webkit-mask-composite:destination-in;mask-composite:intersect;animation:wheel-spinner 1s infinite}@keyframes wheel-spinner{to{transform:rotate(.5turn)}}\n"] }]
190
- }], propDecorators: { loaderSize: [{
191
- type: HostBinding,
192
- args: ['style.--loader-size']
193
- }], loaderColor: [{
194
- type: HostBinding,
195
- args: ['style.--loader-color']
196
- }], mode: [{
197
- type: Input,
198
- args: [{ required: true }]
199
- }], size: [{
200
- type: Input,
201
- args: [{ required: false }]
202
- }], color: [{
203
- type: Input,
204
- args: [{ required: false }]
205
- }], padding: [{
206
- type: Input,
207
- args: [{ required: false }]
208
- }] } });
224
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperNumberPipe, decorators: [{
225
+ type: Pipe,
226
+ args: [{ name: 'ngxHelperNumber' }]
227
+ }] });
209
228
 
210
- const NGX_HELPER_PAGE_GROUP_ITEM = new InjectionToken('NGX-HELPER-PAGE-GROUP-ITEM');
211
- const NGX_HELPER_PAGE_GROUP_DATA = new InjectionToken('NGX-HELPER-PAGE-GROUP-DATA');
212
- const NGX_HELPER_PAGE_GROUP_DATA_CHANGE = new InjectionToken('NGX-HELPER-PAGE-GROUP-DATA-CHANGE');
229
+ class NgxHelperPeriodPipe {
230
+ transform(value, options) {
231
+ if (value === undefined || value === null)
232
+ return '';
233
+ const from = Helper.IS.date(value) ? value : 'from' in value ? value.from : new Date();
234
+ const to = Helper.IS.date(value) ? new Date() : 'to' in value ? value.to : new Date();
235
+ return Helper.DATE.jalaliPeriod(from, to, options?.timezone || '');
236
+ }
237
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPeriodPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
238
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPeriodPipe, isStandalone: true, name: "ngxHelperPeriod" });
239
+ }
240
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPeriodPipe, decorators: [{
241
+ type: Pipe,
242
+ args: [{ name: 'ngxHelperPeriod' }]
243
+ }] });
213
244
 
214
- class NgxHelperPageGroupComponent {
215
- activatedRoute;
216
- router;
245
+ class NgxHelperPricePipe {
246
+ transform(value, options) {
247
+ if (value === undefined || value === null || !Helper.IS.number(value) || value < 0)
248
+ return '';
249
+ const getPrice = (...titles) => {
250
+ if (value === undefined || value === null)
251
+ return '';
252
+ const price = Helper.NUMBER.format(+value.toFixed(2), !!options?.english ? 'EN' : 'FA');
253
+ const unit = titles[options?.short ? 0 : 1][options?.english ? 0 : 1];
254
+ const currency = options?.currency ? ' ' + options?.currency : '';
255
+ return `${price} ${unit}${currency}`;
256
+ };
257
+ if (value < 1000)
258
+ return getPrice(['', ''], ['', '']);
259
+ value /= 1000;
260
+ if (value < 1000)
261
+ return getPrice(['T', 'ه'], ['Thousand', 'هزار']);
262
+ value /= 1000;
263
+ if (value < 1000)
264
+ return getPrice(['M', 'م'], ['Million', 'میلیون']);
265
+ value /= 1000;
266
+ return getPrice(['B', 'د'], ['Billion', 'میلیارد']);
267
+ }
268
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPricePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
269
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPricePipe, isStandalone: true, name: "ngxHelperPrice" });
270
+ }
271
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPricePipe, decorators: [{
272
+ type: Pipe,
273
+ args: [{ name: 'ngxHelperPrice' }]
274
+ }] });
275
+
276
+ class NgxHelperVolumePipe {
277
+ transform(value, options) {
278
+ if (value === undefined || value === null || !Helper.IS.number(value) || value < 0)
279
+ return '';
280
+ const getVolume = (...titles) => {
281
+ if (value === undefined || value === null)
282
+ return '';
283
+ const volume = Helper.NUMBER.format(+value.toFixed(2), options?.english ? 'EN' : 'FA');
284
+ const shortIndex = options?.short ? 0 : 1;
285
+ const titleIndex = options?.english ? 0 : 1;
286
+ return `${volume} ${titles[shortIndex][titleIndex]}`;
287
+ };
288
+ if (value === 0)
289
+ return getVolume(['', ''], ['', '']);
290
+ if (value < 1000)
291
+ return getVolume(['ML', 'م'], ['Milliliter', 'میلی لیتر']);
292
+ value /= 1000;
293
+ return getVolume(['L', 'ل'], ['Liter', 'لیتر']);
294
+ }
295
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperVolumePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
296
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperVolumePipe, isStandalone: true, name: "ngxHelperVolume" });
297
+ }
298
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperVolumePipe, decorators: [{
299
+ type: Pipe,
300
+ args: [{ name: 'ngxHelperVolume' }]
301
+ }] });
302
+
303
+ class NgxHelperWeightPipe {
304
+ transform(value, options) {
305
+ if (value === undefined || value === null || !Helper.IS.number(value) || value < 0)
306
+ return '';
307
+ const getWeight = (...titles) => {
308
+ if (value === undefined || value === null)
309
+ return '';
310
+ const weight = Helper.NUMBER.format(+value.toFixed(2), options?.english ? 'EN' : 'FA');
311
+ const shortIndex = options?.short ? 0 : 1;
312
+ const titleIndex = options?.english ? 0 : 1;
313
+ return `${weight} ${titles[shortIndex][titleIndex]}`;
314
+ };
315
+ if (value === 0)
316
+ return getWeight(['', ''], ['', '']);
317
+ if (value < 1000)
318
+ return getWeight(['G', 'گ'], ['Gram', 'گرم']);
319
+ value /= 1000;
320
+ if (value < 1000)
321
+ return getWeight(['K', 'ک'], ['Kilogram', 'کیلو']);
322
+ value /= 1000;
323
+ if (value < 1000)
324
+ return getWeight(['T', 'ت'], ['Tonne', 'تن']);
325
+ value /= 1000;
326
+ return getWeight(['KT', 'ه'], ['Kilotonne', 'هزار تن']);
327
+ }
328
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperWeightPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
329
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperWeightPipe, isStandalone: true, name: "ngxHelperWeight" });
330
+ }
331
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperWeightPipe, decorators: [{
332
+ type: Pipe,
333
+ args: [{ name: 'ngxHelperWeight' }]
334
+ }] });
335
+
336
+ class NgxHelperValuePipe {
337
+ transform(value, options) {
338
+ const emptyText = options?.emptyText || '';
339
+ if (value === undefined || Helper.IS.empty(value))
340
+ return emptyText;
341
+ switch (value.type) {
342
+ case 'BANK-CARD':
343
+ return new NgxHelperBankCardPipe().transform(value.value, value) || emptyText;
344
+ case 'DATE':
345
+ return new NgxHelperDatePipe().transform(value.value, value) || emptyText;
346
+ case 'DURATION':
347
+ return new NgxHelperDurationPipe().transform(value.value, value) || emptyText;
348
+ case 'FILE-SIZE':
349
+ return new NgxHelperFileSizePipe().transform(value.value, value) || emptyText;
350
+ case 'MOBILE':
351
+ return new NgxHelperMobilePipe().transform(value.value, value) || emptyText;
352
+ case 'NUMBER':
353
+ return new NgxHelperNumberPipe().transform(value.value, value) || emptyText;
354
+ case 'PERIOD':
355
+ return new NgxHelperPeriodPipe().transform(value.value, value) || emptyText;
356
+ case 'PRICE':
357
+ return new NgxHelperPricePipe().transform(value.value, value) || emptyText;
358
+ case 'STRING':
359
+ return Helper.IS.string(value.value) ? value.value : emptyText;
360
+ case 'VOLUME':
361
+ return new NgxHelperVolumePipe().transform(value.value, value) || emptyText;
362
+ case 'WEIGHT':
363
+ return new NgxHelperWeightPipe().transform(value.value, value) || emptyText;
364
+ }
365
+ }
366
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
367
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperValuePipe, isStandalone: true, name: "ngxHelperValue" });
368
+ }
369
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperValuePipe, decorators: [{
370
+ type: Pipe,
371
+ args: [{ name: 'ngxHelperValue' }]
372
+ }] });
373
+
374
+ class ComponentService {
375
+ getComponentConfig(config) {
376
+ const getStickyView = (config) => {
377
+ return {
378
+ desktopView: typeof config === 'string' ? config : config.desktopView,
379
+ mobileView: typeof config === 'string' ? config : config.mobileView,
380
+ };
381
+ };
382
+ return {
383
+ mobileWidth: config?.mobileWidth || 600,
384
+ pageGroupSidebarWidth: config?.pageGroupSidebarWidth || '200px',
385
+ stickyView: config?.stickyView
386
+ ? {
387
+ top: config.stickyView.top ? getStickyView(config.stickyView.top) : undefined,
388
+ bottom: config.stickyView.bottom ? getStickyView(config.stickyView.bottom) : undefined,
389
+ }
390
+ : undefined,
391
+ };
392
+ }
393
+ getValueData(values) {
394
+ const pipeTransform = new NgxHelperValuePipe().transform;
395
+ const ltrValues = ['BANK-CARD', 'MOBILE', 'NUMBER'];
396
+ return values.map((item) => {
397
+ const value = item.value;
398
+ return value === undefined
399
+ ? { title: item.title, value: '' }
400
+ : typeof value === 'string'
401
+ ? { title: item.title, value: value.trim(), color: item.color }
402
+ : {
403
+ title: item.title,
404
+ value: pipeTransform(value),
405
+ color: item.color,
406
+ action: item.action,
407
+ copyToClipboard: item.copyToClipboard,
408
+ ltr: ltrValues.includes(value.type),
409
+ english: 'english' in value && !!value.english,
410
+ };
411
+ });
412
+ }
413
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: ComponentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
414
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: ComponentService });
415
+ }
416
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: ComponentService, decorators: [{
417
+ type: Injectable
418
+ }] });
419
+
420
+ class NgxHelperCardComponent {
217
421
  componentService;
218
422
  config;
219
- className = 'ngx-helper-m3-page-group';
220
- display = 'none';
221
- pageGroup;
222
- pageId;
223
- data;
224
- pageChanged = new EventEmitter();
225
- dataChanged = new EventEmitter();
423
+ className = 'ngx-helper-m3-card';
424
+ title;
425
+ subTitle;
426
+ icon;
427
+ actions = [];
428
+ padding = '1rem';
429
+ backgroundColor;
430
+ hasShadow = false;
226
431
  isMobile = false;
227
- pages = [];
228
- injector;
229
- sidebarWidth;
432
+ buttons = [];
230
433
  componentConfig;
231
- constructor(activatedRoute, router, componentService, config) {
232
- this.activatedRoute = activatedRoute;
233
- this.router = router;
434
+ constructor(componentService, config) {
234
435
  this.componentService = componentService;
235
436
  this.config = config;
236
437
  }
237
438
  ngOnInit() {
238
- this.pages = Object.keys(this.pageGroup.pages);
239
- this.display = this.pages.length === 0 ? 'none' : 'flex';
240
- if (this.pages.length === 0)
241
- return;
242
439
  this.componentConfig = this.componentService.getComponentConfig(this.config);
243
- this.sidebarWidth = this.pageGroup.sidebarWidth || this.componentConfig.pageGroupSidebarWidth;
244
- if (!this.pageGroup.pages[this.pageId])
245
- this.pageId = this.pages[0];
246
- const queryParams = { ...this.activatedRoute.snapshot.queryParams };
247
- if (!!this.pageGroup.route && Helper.IS.string(queryParams['ngx-helper-page-group'])) {
248
- const id = queryParams['ngx-helper-page-group'];
249
- if (this.pageId !== id && this.pages.includes(id)) {
250
- this.pageId = id;
251
- this.triggerPageChanged();
252
- }
253
- }
254
440
  this.onResize();
255
- this.setInjector();
256
441
  }
257
442
  ngOnChanges(changes) {
258
- this.setInjector();
443
+ this.className = `ngx-helper-m3-card${this.hasShadow ? ' has-shadow' : ''}`;
444
+ this.buttons = this.actions.map((action) => {
445
+ return 'buttons' in action ? { type: 'MENU', ...action } : { type: 'BUTTON', ...action };
446
+ });
259
447
  }
260
448
  onResize() {
261
449
  this.isMobile = window.innerWidth <= this.componentConfig.mobileWidth;
262
- this.className = `ngx-helper-m3-page-group${this.isMobile ? ' mobile-view' : ''}`;
263
- }
264
- setInjector() {
265
- if (this.pages.length === 0)
266
- return;
267
- const item = {
268
- index: this.pages.findIndex((page) => page === this.pageId),
269
- id: this.pageId,
270
- title: this.pageGroup.pages[this.pageId].title,
271
- icon: this.pageGroup.pages[this.pageId].icon,
272
- };
273
- this.injector = Injector.create({
274
- providers: [
275
- { provide: NGX_HELPER_PAGE_GROUP_ITEM, useValue: item },
276
- { provide: NGX_HELPER_PAGE_GROUP_DATA, useValue: this.data },
277
- { provide: NGX_HELPER_PAGE_GROUP_DATA_CHANGE, useValue: (data) => this.dataChanged.next(data) },
278
- ],
279
- });
280
450
  }
281
- setPage(id) {
282
- if (this.pages.length === 0 || this.pageId == id)
283
- return;
284
- const page = this.pageGroup.pages[id];
285
- const index = this.pages.findIndex((p) => p === id);
286
- if (!page || index === -1)
451
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperCardComponent, deps: [{ token: ComponentService }, { token: NGX_HELPER_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Component });
452
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.4", type: NgxHelperCardComponent, isStandalone: true, selector: "ngx-helper-card", inputs: { title: "title", subTitle: "subTitle", icon: "icon", actions: "actions", padding: "padding", backgroundColor: "backgroundColor", hasShadow: "hasShadow" }, host: { listeners: { "window:resize": "onResize($event)" }, properties: { "className": "this.className" } }, providers: [ComponentService], usesOnChanges: true, ngImport: i0, template: "<div class=\"card-header\" [class.has-sub-title]=\"subTitle\">\n <!-- ICON -->\n @if (icon) { <mat-icon>{{ icon }}</mat-icon> }\n\n <!-- TITLE -->\n <div class=\"content\">\n <div class=\"title\">{{ title }}</div>\n <!-- SUB TITLE -->\n @if (subTitle) {\n <div class=\"sub-title\">{{ subTitle }}</div>\n }\n </div>\n\n <!-- BUTTONS -->\n @if (buttons.length > 0) {\n <div class=\"buttons\" [ngClass]=\"isMobile ? 'mobile-view' : ''\">\n @for (item of buttons; track $index) {\n <!-- TYPE -->\n @switch (item.type) {\n\n <!-- BUTTON -->\n @case('BUTTON') {\n <button mat-button type=\"button\" [style.color]=\"item.color\" (click)=\"item.action()\">\n @if (!isMobile) {\n <div class=\"title\">{{ item.title }}</div>\n }\n <!-- ICON -->\n @if (isMobile || item.showIcon) {\n <mat-icon>{{ item.icon }}</mat-icon>\n }\n </button>\n }\n\n <!-- MENU -->\n @case('MENU') {\n <button mat-button type=\"button\" [style.color]=\"item.color\" [matMenuTriggerFor]=\"actionMenu\">\n @if (!isMobile) {\n <div class=\"title\">{{ item.title }}</div>\n }\n <!-- ICON -->\n @if (isMobile || item.showIcon) {\n <mat-icon>{{ item.icon }}</mat-icon>\n }\n </button>\n <mat-menu #actionMenu=\"matMenu\" class=\"ngx-helper-card-action-menu\">\n @for (menu of item.buttons; track $index) {\n <!-- DIVIDER -->\n @if (menu === 'DIVIDER') { <mat-divider></mat-divider> }\n <!-- BUTTON -->\n @else {\n <button mat-menu-item type=\"button\" (click)=\"menu.action()\" [style.color]=\"menu.color\">\n <div class=\"title\">{{ menu.title }}</div>\n <mat-icon [style.color]=\"menu.color\">{{ menu.icon }}</mat-icon>\n </button>\n } }\n </mat-menu>\n } } }\n </div>\n }\n</div>\n\n<div class=\"card-content\" [style.padding]=\"padding\" [style.background-color]=\"backgroundColor\">\n <ng-content></ng-content>\n</div>\n", styles: ["::ng-deep .ngx-helper-card-action-menu button mat-icon{font-size:115%;margin:0 0 0 .75rem!important}::ng-deep .ngx-helper-card-action-menu button .title{font-size:90%!important}::ng-deep .ngx-helper-card-action-menu .mat-mdc-menu-content{padding:0}::ng-deep .ngx-helper-card-action-menu .mat-mdc-menu-item{direction:rtl;text-align:right}::ng-deep .ngx-helper-card-action-menu .mat-divider{margin:0;border-top-color:var(--outline-variant)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i2.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }] });
453
+ }
454
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperCardComponent, decorators: [{
455
+ type: Component,
456
+ args: [{ selector: 'ngx-helper-card', host: { '(window:resize)': 'onResize($event)' }, imports: [NgClass, MatButton, MatDivider, MatIcon, MatMenuModule], providers: [ComponentService], template: "<div class=\"card-header\" [class.has-sub-title]=\"subTitle\">\n <!-- ICON -->\n @if (icon) { <mat-icon>{{ icon }}</mat-icon> }\n\n <!-- TITLE -->\n <div class=\"content\">\n <div class=\"title\">{{ title }}</div>\n <!-- SUB TITLE -->\n @if (subTitle) {\n <div class=\"sub-title\">{{ subTitle }}</div>\n }\n </div>\n\n <!-- BUTTONS -->\n @if (buttons.length > 0) {\n <div class=\"buttons\" [ngClass]=\"isMobile ? 'mobile-view' : ''\">\n @for (item of buttons; track $index) {\n <!-- TYPE -->\n @switch (item.type) {\n\n <!-- BUTTON -->\n @case('BUTTON') {\n <button mat-button type=\"button\" [style.color]=\"item.color\" (click)=\"item.action()\">\n @if (!isMobile) {\n <div class=\"title\">{{ item.title }}</div>\n }\n <!-- ICON -->\n @if (isMobile || item.showIcon) {\n <mat-icon>{{ item.icon }}</mat-icon>\n }\n </button>\n }\n\n <!-- MENU -->\n @case('MENU') {\n <button mat-button type=\"button\" [style.color]=\"item.color\" [matMenuTriggerFor]=\"actionMenu\">\n @if (!isMobile) {\n <div class=\"title\">{{ item.title }}</div>\n }\n <!-- ICON -->\n @if (isMobile || item.showIcon) {\n <mat-icon>{{ item.icon }}</mat-icon>\n }\n </button>\n <mat-menu #actionMenu=\"matMenu\" class=\"ngx-helper-card-action-menu\">\n @for (menu of item.buttons; track $index) {\n <!-- DIVIDER -->\n @if (menu === 'DIVIDER') { <mat-divider></mat-divider> }\n <!-- BUTTON -->\n @else {\n <button mat-menu-item type=\"button\" (click)=\"menu.action()\" [style.color]=\"menu.color\">\n <div class=\"title\">{{ menu.title }}</div>\n <mat-icon [style.color]=\"menu.color\">{{ menu.icon }}</mat-icon>\n </button>\n } }\n </mat-menu>\n } } }\n </div>\n }\n</div>\n\n<div class=\"card-content\" [style.padding]=\"padding\" [style.background-color]=\"backgroundColor\">\n <ng-content></ng-content>\n</div>\n", styles: ["::ng-deep .ngx-helper-card-action-menu button mat-icon{font-size:115%;margin:0 0 0 .75rem!important}::ng-deep .ngx-helper-card-action-menu button .title{font-size:90%!important}::ng-deep .ngx-helper-card-action-menu .mat-mdc-menu-content{padding:0}::ng-deep .ngx-helper-card-action-menu .mat-mdc-menu-item{direction:rtl;text-align:right}::ng-deep .ngx-helper-card-action-menu .mat-divider{margin:0;border-top-color:var(--outline-variant)}\n"] }]
457
+ }], ctorParameters: () => [{ type: ComponentService }, { type: undefined, decorators: [{
458
+ type: Optional
459
+ }, {
460
+ type: Inject,
461
+ args: [NGX_HELPER_CONFIG]
462
+ }] }], propDecorators: { className: [{
463
+ type: HostBinding,
464
+ args: ['className']
465
+ }], title: [{
466
+ type: Input,
467
+ args: [{ required: true }]
468
+ }], subTitle: [{
469
+ type: Input,
470
+ args: [{ required: false }]
471
+ }], icon: [{
472
+ type: Input,
473
+ args: [{ required: false }]
474
+ }], actions: [{
475
+ type: Input,
476
+ args: [{ required: false }]
477
+ }], padding: [{
478
+ type: Input,
479
+ args: [{ required: false }]
480
+ }], backgroundColor: [{
481
+ type: Input,
482
+ args: [{ required: false }]
483
+ }], hasShadow: [{
484
+ type: Input,
485
+ args: [{ required: false }]
486
+ }] } });
487
+
488
+ class NgxHelperLoaderComponent {
489
+ loaderSize;
490
+ loaderColor;
491
+ mode;
492
+ size;
493
+ color;
494
+ padding;
495
+ ngOnChanges(changes) {
496
+ this.loaderSize = `${this.size || 25}px`;
497
+ this.loaderColor = this.color || `var(--secondary)`;
498
+ }
499
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
500
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.4", type: NgxHelperLoaderComponent, isStandalone: true, selector: "ngx-helper-loader", inputs: { mode: "mode", size: "size", color: "color", padding: "padding" }, host: { properties: { "style.--loader-size": "this.loaderSize", "style.--loader-color": "this.loaderColor" } }, usesOnChanges: true, ngImport: i0, template: "<div [style.padding]=\"padding || '0'\">\n <div [class]=\"mode.toLowerCase()\"></div>\n</div>\n", styles: [".spinner{--size: calc(var(--loader-size) / 7);width:var(--loader-size);aspect-ratio:1;border-radius:50%;background:radial-gradient(farthest-side,var(--loader-color) 94%,rgba(0,0,0,0)) top/var(--size) var(--size) no-repeat,conic-gradient(rgba(0,0,0,0) 30%,var(--loader-color));mask:radial-gradient(farthest-side,rgba(0,0,0,0) calc(100% - var(--size)),#000 0);animation:spinner 1s infinite linear}@keyframes spinner{to{transform:rotate(1turn)}}.dots-spinner{--dot: no-repeat radial-gradient(farthest-side, var(--loader-color) 92%, #0000);--size: calc(var(--loader-size) / 4);width:var(--loader-size);aspect-ratio:1;background:var(--dot) top,var(--dot) left,var(--dot) right,var(--dot) bottom;background-size:var(--size) var(--size);animation:dots-spinner 1s infinite}@keyframes dots-spinner{to{transform:rotate(.5turn)}}.wheel-spinner{--size: calc(var(--loader-size) / 9);width:var(--loader-size);aspect-ratio:1;border-radius:50%;background:var(--loader-color);mask:repeating-conic-gradient(rgba(0,0,0,0) 0deg,#000 1deg 70deg,rgba(0,0,0,0) 71deg 90deg),radial-gradient(farthest-side,rgba(0,0,0,0) calc(100% - var(--size) - 1px),#000 calc(100% - var(--size)));-webkit-mask-composite:destination-in;mask-composite:intersect;animation:wheel-spinner 1s infinite}@keyframes wheel-spinner{to{transform:rotate(.5turn)}}\n"] });
501
+ }
502
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperLoaderComponent, decorators: [{
503
+ type: Component,
504
+ args: [{ selector: 'ngx-helper-loader', imports: [], template: "<div [style.padding]=\"padding || '0'\">\n <div [class]=\"mode.toLowerCase()\"></div>\n</div>\n", styles: [".spinner{--size: calc(var(--loader-size) / 7);width:var(--loader-size);aspect-ratio:1;border-radius:50%;background:radial-gradient(farthest-side,var(--loader-color) 94%,rgba(0,0,0,0)) top/var(--size) var(--size) no-repeat,conic-gradient(rgba(0,0,0,0) 30%,var(--loader-color));mask:radial-gradient(farthest-side,rgba(0,0,0,0) calc(100% - var(--size)),#000 0);animation:spinner 1s infinite linear}@keyframes spinner{to{transform:rotate(1turn)}}.dots-spinner{--dot: no-repeat radial-gradient(farthest-side, var(--loader-color) 92%, #0000);--size: calc(var(--loader-size) / 4);width:var(--loader-size);aspect-ratio:1;background:var(--dot) top,var(--dot) left,var(--dot) right,var(--dot) bottom;background-size:var(--size) var(--size);animation:dots-spinner 1s infinite}@keyframes dots-spinner{to{transform:rotate(.5turn)}}.wheel-spinner{--size: calc(var(--loader-size) / 9);width:var(--loader-size);aspect-ratio:1;border-radius:50%;background:var(--loader-color);mask:repeating-conic-gradient(rgba(0,0,0,0) 0deg,#000 1deg 70deg,rgba(0,0,0,0) 71deg 90deg),radial-gradient(farthest-side,rgba(0,0,0,0) calc(100% - var(--size) - 1px),#000 calc(100% - var(--size)));-webkit-mask-composite:destination-in;mask-composite:intersect;animation:wheel-spinner 1s infinite}@keyframes wheel-spinner{to{transform:rotate(.5turn)}}\n"] }]
505
+ }], propDecorators: { loaderSize: [{
506
+ type: HostBinding,
507
+ args: ['style.--loader-size']
508
+ }], loaderColor: [{
509
+ type: HostBinding,
510
+ args: ['style.--loader-color']
511
+ }], mode: [{
512
+ type: Input,
513
+ args: [{ required: true }]
514
+ }], size: [{
515
+ type: Input,
516
+ args: [{ required: false }]
517
+ }], color: [{
518
+ type: Input,
519
+ args: [{ required: false }]
520
+ }], padding: [{
521
+ type: Input,
522
+ args: [{ required: false }]
523
+ }] } });
524
+
525
+ const NGX_HELPER_PAGE_GROUP_ITEM = new InjectionToken('NGX-HELPER-PAGE-GROUP-ITEM');
526
+ const NGX_HELPER_PAGE_GROUP_DATA = new InjectionToken('NGX-HELPER-PAGE-GROUP-DATA');
527
+ const NGX_HELPER_PAGE_GROUP_DATA_CHANGE = new InjectionToken('NGX-HELPER-PAGE-GROUP-DATA-CHANGE');
528
+
529
+ class NgxHelperPageGroupComponent {
530
+ activatedRoute;
531
+ router;
532
+ componentService;
533
+ config;
534
+ className = 'ngx-helper-m3-page-group';
535
+ display = 'none';
536
+ pageGroup;
537
+ pageId;
538
+ data;
539
+ pageChanged = new EventEmitter();
540
+ dataChanged = new EventEmitter();
541
+ isMobile = false;
542
+ pages = [];
543
+ injector;
544
+ sidebarWidth;
545
+ componentConfig;
546
+ constructor(activatedRoute, router, componentService, config) {
547
+ this.activatedRoute = activatedRoute;
548
+ this.router = router;
549
+ this.componentService = componentService;
550
+ this.config = config;
551
+ }
552
+ ngOnInit() {
553
+ this.pages = Object.keys(this.pageGroup.pages);
554
+ this.display = this.pages.length === 0 ? 'none' : 'flex';
555
+ if (this.pages.length === 0)
556
+ return;
557
+ this.componentConfig = this.componentService.getComponentConfig(this.config);
558
+ this.sidebarWidth = this.pageGroup.sidebarWidth || this.componentConfig.pageGroupSidebarWidth;
559
+ if (!this.pageGroup.pages[this.pageId])
560
+ this.pageId = this.pages[0];
561
+ const queryParams = { ...this.activatedRoute.snapshot.queryParams };
562
+ if (!!this.pageGroup.route && Helper.IS.string(queryParams['ngx-helper-page-group'])) {
563
+ const id = queryParams['ngx-helper-page-group'];
564
+ if (this.pageId !== id && this.pages.includes(id)) {
565
+ this.pageId = id;
566
+ this.triggerPageChanged();
567
+ }
568
+ }
569
+ this.onResize();
570
+ this.setInjector();
571
+ }
572
+ ngOnChanges(changes) {
573
+ this.setInjector();
574
+ }
575
+ onResize() {
576
+ this.isMobile = window.innerWidth <= this.componentConfig.mobileWidth;
577
+ this.className = `ngx-helper-m3-page-group${this.isMobile ? ' mobile-view' : ''}`;
578
+ }
579
+ setInjector() {
580
+ if (this.pages.length === 0)
581
+ return;
582
+ const item = {
583
+ index: this.pages.findIndex((page) => page === this.pageId),
584
+ id: this.pageId,
585
+ title: this.pageGroup.pages[this.pageId].title,
586
+ icon: this.pageGroup.pages[this.pageId].icon,
587
+ };
588
+ this.injector = Injector.create({
589
+ providers: [
590
+ { provide: NGX_HELPER_PAGE_GROUP_ITEM, useValue: item },
591
+ { provide: NGX_HELPER_PAGE_GROUP_DATA, useValue: this.data },
592
+ { provide: NGX_HELPER_PAGE_GROUP_DATA_CHANGE, useValue: (data) => this.dataChanged.next(data) },
593
+ ],
594
+ });
595
+ }
596
+ setPage(id) {
597
+ if (this.pages.length === 0 || this.pageId == id)
598
+ return;
599
+ const page = this.pageGroup.pages[id];
600
+ const index = this.pages.findIndex((p) => p === id);
601
+ if (!page || index === -1)
287
602
  return;
288
603
  this.pageId = id;
289
604
  this.triggerPageChanged();
@@ -398,372 +713,78 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImpor
398
713
  }], ngxHelperSectionZIndex: [{
399
714
  type: Input,
400
715
  args: [{ required: false }]
401
- }] } });
402
-
403
- class NgxHelperSectionComponent {
404
- componentService;
405
- config;
406
- gap;
407
- gapSize;
408
- componentConfig;
409
- isMobile = false;
410
- constructor(componentService, config) {
411
- this.componentService = componentService;
412
- this.config = config;
413
- }
414
- ngOnInit() {
415
- this.componentConfig = this.componentService.getComponentConfig(this.config);
416
- this.gap = this.gapSize || '1rem';
417
- this.onResize();
418
- }
419
- onResize() {
420
- this.isMobile = window.innerWidth <= this.componentConfig.mobileWidth;
421
- }
422
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperSectionComponent, deps: [{ token: ComponentService }, { token: NGX_HELPER_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Component });
423
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.4", type: NgxHelperSectionComponent, isStandalone: true, selector: "ngx-helper-section", inputs: { gapSize: "gapSize" }, host: { listeners: { "window:resize": "onResize($event)" }, properties: { "style.--section-gap": "this.gap" } }, providers: [ComponentService], ngImport: i0, template: "<div class=\"section-columns\" [class.section-columns-mobile]=\"isMobile\">\n <ng-content></ng-content>\n</div>\n", styles: [":host{display:block;direction:rtl}:host .section-columns{display:flex;align-items:flex-start;column-gap:var(--section-gap)}:host ::ng-deep ngx-helper-section-column{flex:1;display:flex;flex-direction:column;row-gap:var(--section-gap)}:host .section-columns-mobile{flex-direction:column;column-gap:0;row-gap:var(--section-gap)}:host .section-columns-mobile ::ng-deep ngx-helper-section-column{width:100%!important}\n"] });
424
- }
425
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperSectionComponent, decorators: [{
426
- type: Component,
427
- args: [{ selector: 'ngx-helper-section', host: { '(window:resize)': 'onResize($event)' }, imports: [], providers: [ComponentService], template: "<div class=\"section-columns\" [class.section-columns-mobile]=\"isMobile\">\n <ng-content></ng-content>\n</div>\n", styles: [":host{display:block;direction:rtl}:host .section-columns{display:flex;align-items:flex-start;column-gap:var(--section-gap)}:host ::ng-deep ngx-helper-section-column{flex:1;display:flex;flex-direction:column;row-gap:var(--section-gap)}:host .section-columns-mobile{flex-direction:column;column-gap:0;row-gap:var(--section-gap)}:host .section-columns-mobile ::ng-deep ngx-helper-section-column{width:100%!important}\n"] }]
428
- }], ctorParameters: () => [{ type: ComponentService }, { type: undefined, decorators: [{
429
- type: Optional
430
- }, {
431
- type: Inject,
432
- args: [NGX_HELPER_CONFIG]
433
- }] }], propDecorators: { gap: [{
434
- type: HostBinding,
435
- args: ['style.--section-gap']
436
- }], gapSize: [{
437
- type: Input,
438
- args: [{ required: false }]
439
- }] } });
440
-
441
- class NgxHelperSectionColumnComponent {
442
- flexStyle = '1';
443
- widthStyle = '*';
444
- flex;
445
- width;
446
- sticky;
447
- ngOnChanges(changes) {
448
- this.flexStyle = this.width ? 'unset' : this.flex?.toString() || '1';
449
- this.widthStyle = this.width || '*';
450
- }
451
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperSectionColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
452
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.4", type: NgxHelperSectionColumnComponent, isStandalone: true, selector: "ngx-helper-section-column", inputs: { flex: "flex", width: "width", sticky: "sticky" }, host: { properties: { "style.flex": "this.flexStyle", "style.width": "this.widthStyle" } }, usesOnChanges: true, ngImport: i0, template: "<ng-content></ng-content>\n", styles: [""] });
453
- }
454
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperSectionColumnComponent, decorators: [{
455
- type: Component,
456
- args: [{ selector: 'ngx-helper-section-column', imports: [], template: "<ng-content></ng-content>\n" }]
457
- }], propDecorators: { flexStyle: [{
458
- type: HostBinding,
459
- args: ['style.flex']
460
- }], widthStyle: [{
461
- type: HostBinding,
462
- args: ['style.width']
463
- }], flex: [{
464
- type: Input,
465
- args: [{ required: false }]
466
- }], width: [{
467
- type: Input,
468
- args: [{ required: false }]
469
- }], sticky: [{
470
- type: Input,
471
- args: [{ required: false }]
472
- }] } });
473
-
474
- const ltrValues = ['BANK-CARD', 'MOBILE', 'NUMBER'];
475
-
476
- class NgxHelperBankCardPipe {
477
- transform(value, options) {
478
- if (value === undefined || value === null || !Helper.IS.string(value) || value === '')
479
- return '';
480
- switch (options?.view) {
481
- case 'BANK':
482
- return Helper.BANK.findCard(value)?.title || '';
483
- default:
484
- return Helper.STRING.getBankCardView(value, options?.join || '-');
485
- }
486
- }
487
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperBankCardPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
488
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperBankCardPipe, isStandalone: true, name: "ngxHelperBankCard" });
489
- }
490
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperBankCardPipe, decorators: [{
491
- type: Pipe,
492
- args: [{ name: 'ngxHelperBankCard' }]
493
- }] });
494
-
495
- class NgxHelperDatePipe {
496
- transform(value, options) {
497
- if (value === undefined || value === null || (!Helper.IS.date(value) && !Helper.IS.number(value)))
498
- return '';
499
- const date = typeof value === 'number' ? new Date(value) : value;
500
- const jalali = JalaliDateTime();
501
- const timezone = options?.timezone && jalali.timezones().includes(options?.timezone) ? options?.timezone : 'Asia/Tehran';
502
- switch (options?.format || 'DATE') {
503
- case 'FULL':
504
- return jalali.toFullText(date, { format: 'W، d N Y H:I', timezone });
505
- case 'SHORT':
506
- return jalali.toFullText(date, { format: 'Y/M/D', timezone });
507
- case 'DATE':
508
- return jalali.toFullText(date, { format: 'W، d N Y', timezone });
509
- case 'TIME':
510
- return jalali.toFullText(date, { format: 'H:I', timezone });
511
- case 'WEEK':
512
- const { from, to } = jalali.periodWeek(1, date, timezone);
513
- return Helper.DATE.jalaliPeriod(from, to, timezone);
514
- case 'MONTH':
515
- return jalali.toFullText(date, { format: 'N Y', timezone });
516
- case 'YEAR':
517
- return jalali.toFullText(date, { format: 'Y', timezone });
518
- default:
519
- return jalali.toFullText(date, { format: options?.format, timezone });
520
- }
521
- }
522
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
523
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDatePipe, isStandalone: true, name: "ngxHelperDate" });
524
- }
525
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDatePipe, decorators: [{
526
- type: Pipe,
527
- args: [{ name: 'ngxHelperDate' }]
528
- }] });
529
-
530
- class NgxHelperDurationPipe {
531
- transform(value, options) {
532
- if (value === undefined || value === null)
533
- return '';
534
- let seconds = 0;
535
- if (Helper.IS.number(value))
536
- seconds = Math.abs(value);
537
- else if (Helper.IS.date(value))
538
- seconds = Math.floor(Math.abs(new Date().getTime() - value.getTime()) / 1000);
539
- else if (Helper.IS.object(value)) {
540
- const from = 'from' in value ? value.from : new Date();
541
- const to = 'to' in value ? value.to : new Date();
542
- seconds = Math.floor(Math.abs(from.getTime() - to.getTime()) / 1000);
543
- }
544
- const days = Math.floor(seconds / (24 * 60 * 60));
545
- seconds -= days * (24 * 60 * 60);
546
- const hours = Math.floor(seconds / (60 * 60));
547
- seconds -= hours * (60 * 60);
548
- const minutes = Math.floor(seconds / 60);
549
- seconds -= minutes * 60;
550
- const hasDays = days !== 0;
551
- const time = [hours, minutes, seconds].map((v) => v.toString().padStart(2, '0')).join(':');
552
- switch (options?.format || 'TEXT') {
553
- case 'TEXT':
554
- const hasTime = !!hours || !!minutes || !!seconds;
555
- const day = hasDays
556
- ? Helper.NUMBER.format(days, 'EN') + (!!options?.english ? (days === 1 ? ' day' : ' days') : ' روز')
557
- : '';
558
- const join = hasDays && hasTime ? (!!options?.english ? ', ' : ' و ') : '';
559
- return (day + join + (!hasDays || hasTime ? time : '')).trim();
560
- case 'FULL':
561
- return (hasDays ? Helper.NUMBER.format(days, 'EN') + ':' : '') + time;
562
- case 'DAY':
563
- return Helper.NUMBER.format(days + (hours !== 0 || minutes !== 0 ? 1 : 0), !!options?.english ? 'EN' : 'FA');
564
- case 'HOUR':
565
- return Helper.NUMBER.format(days * 24 + hours + (minutes !== 0 ? 1 : 0), !!options?.english ? 'EN' : 'FA');
566
- case 'MINUTE':
567
- return Helper.NUMBER.format(days * 24 * 60 + hours * 60 + minutes, !!options?.english ? 'EN' : 'FA');
568
- case 'SECOND':
569
- return Helper.NUMBER.format(days * 24 * 3600 + hours * 3600 + minutes * 60 + seconds, !!options?.english ? 'EN' : 'FA');
570
- }
571
- }
572
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDurationPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
573
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDurationPipe, isStandalone: true, name: "ngxHelperDuration" });
574
- }
575
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperDurationPipe, decorators: [{
576
- type: Pipe,
577
- args: [{ name: 'ngxHelperDuration' }]
578
- }] });
579
-
580
- class NgxHelperFileSizePipe {
581
- transform(value, options) {
582
- if (value === undefined || value === null || !Helper.IS.number(value))
583
- return '';
584
- return Helper.NUMBER.toFileSize(value, !!options?.english ? 'EN' : 'FA');
585
- }
586
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperFileSizePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
587
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperFileSizePipe, isStandalone: true, name: "ngxHelperFileSize" });
588
- }
589
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperFileSizePipe, decorators: [{
590
- type: Pipe,
591
- args: [{ name: 'ngxHelperFileSize' }]
592
- }] });
593
-
594
- class NgxHelperMobilePipe {
595
- transform(value, options) {
596
- if (value === undefined || value === null || !Helper.IS.string(value) || value === '')
597
- return '';
598
- return Helper.STRING.getMobileView(value, options?.join || '-');
599
- }
600
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperMobilePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
601
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperMobilePipe, isStandalone: true, name: "ngxHelperMobile" });
602
- }
603
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperMobilePipe, decorators: [{
604
- type: Pipe,
605
- args: [{ name: 'ngxHelperMobile' }]
606
- }] });
607
-
608
- class NgxHelperNumberPipe {
609
- transform(value, options) {
610
- if (value === undefined || value === null || !Helper.IS.number(value))
611
- return '';
612
- value = options?.fractionDigits ? +value.toFixed(options?.fractionDigits) : value;
613
- return Helper.NUMBER.format(value, options?.english ? 'EN' : 'FA');
614
- }
615
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperNumberPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
616
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperNumberPipe, isStandalone: true, name: "ngxHelperNumber" });
617
- }
618
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperNumberPipe, decorators: [{
619
- type: Pipe,
620
- args: [{ name: 'ngxHelperNumber' }]
621
- }] });
622
-
623
- class NgxHelperPeriodPipe {
624
- transform(value, options) {
625
- if (value === undefined || value === null)
626
- return '';
627
- const from = Helper.IS.date(value) ? value : 'from' in value ? value.from : new Date();
628
- const to = Helper.IS.date(value) ? new Date() : 'to' in value ? value.to : new Date();
629
- return Helper.DATE.jalaliPeriod(from, to, options?.timezone || '');
630
- }
631
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPeriodPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
632
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPeriodPipe, isStandalone: true, name: "ngxHelperPeriod" });
633
- }
634
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPeriodPipe, decorators: [{
635
- type: Pipe,
636
- args: [{ name: 'ngxHelperPeriod' }]
637
- }] });
638
-
639
- class NgxHelperPricePipe {
640
- transform(value, options) {
641
- if (value === undefined || value === null || !Helper.IS.number(value) || value < 0)
642
- return '';
643
- const getPrice = (...titles) => {
644
- if (value === undefined || value === null)
645
- return '';
646
- const price = Helper.NUMBER.format(+value.toFixed(2), !!options?.english ? 'EN' : 'FA');
647
- const unit = titles[options?.short ? 0 : 1][options?.english ? 0 : 1];
648
- const currency = options?.currency ? ' ' + options?.currency : '';
649
- return `${price} ${unit}${currency}`;
650
- };
651
- if (value < 1000)
652
- return getPrice(['', ''], ['', '']);
653
- value /= 1000;
654
- if (value < 1000)
655
- return getPrice(['T', 'ه'], ['Thousand', 'هزار']);
656
- value /= 1000;
657
- if (value < 1000)
658
- return getPrice(['M', 'م'], ['Million', 'میلیون']);
659
- value /= 1000;
660
- return getPrice(['B', 'د'], ['Billion', 'میلیارد']);
661
- }
662
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPricePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
663
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPricePipe, isStandalone: true, name: "ngxHelperPrice" });
664
- }
665
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperPricePipe, decorators: [{
666
- type: Pipe,
667
- args: [{ name: 'ngxHelperPrice' }]
668
- }] });
669
-
670
- class NgxHelperVolumePipe {
671
- transform(value, options) {
672
- if (value === undefined || value === null || !Helper.IS.number(value) || value < 0)
673
- return '';
674
- const getVolume = (...titles) => {
675
- if (value === undefined || value === null)
676
- return '';
677
- const volume = Helper.NUMBER.format(+value.toFixed(2), options?.english ? 'EN' : 'FA');
678
- const shortIndex = options?.short ? 0 : 1;
679
- const titleIndex = options?.english ? 0 : 1;
680
- return `${volume} ${titles[shortIndex][titleIndex]}`;
681
- };
682
- if (value === 0)
683
- return getVolume(['', ''], ['', '']);
684
- if (value < 1000)
685
- return getVolume(['ML', 'م'], ['Milliliter', 'میلی لیتر']);
686
- value /= 1000;
687
- return getVolume(['L', 'ل'], ['Liter', 'لیتر']);
688
- }
689
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperVolumePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
690
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperVolumePipe, isStandalone: true, name: "ngxHelperVolume" });
691
- }
692
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperVolumePipe, decorators: [{
693
- type: Pipe,
694
- args: [{ name: 'ngxHelperVolume' }]
695
- }] });
716
+ }] } });
696
717
 
697
- class NgxHelperWeightPipe {
698
- transform(value, options) {
699
- if (value === undefined || value === null || !Helper.IS.number(value) || value < 0)
700
- return '';
701
- const getWeight = (...titles) => {
702
- if (value === undefined || value === null)
703
- return '';
704
- const weight = Helper.NUMBER.format(+value.toFixed(2), options?.english ? 'EN' : 'FA');
705
- const shortIndex = options?.short ? 0 : 1;
706
- const titleIndex = options?.english ? 0 : 1;
707
- return `${weight} ${titles[shortIndex][titleIndex]}`;
708
- };
709
- if (value === 0)
710
- return getWeight(['', ''], ['', '']);
711
- if (value < 1000)
712
- return getWeight(['G', 'گ'], ['Gram', 'گرم']);
713
- value /= 1000;
714
- if (value < 1000)
715
- return getWeight(['K', 'ک'], ['Kilogram', 'کیلو']);
716
- value /= 1000;
717
- if (value < 1000)
718
- return getWeight(['T', 'ت'], ['Tonne', 'تن']);
719
- value /= 1000;
720
- return getWeight(['KT', 'ه'], ['Kilotonne', 'هزار تن']);
718
+ class NgxHelperSectionComponent {
719
+ componentService;
720
+ config;
721
+ gap;
722
+ gapSize;
723
+ componentConfig;
724
+ isMobile = false;
725
+ constructor(componentService, config) {
726
+ this.componentService = componentService;
727
+ this.config = config;
721
728
  }
722
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperWeightPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
723
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperWeightPipe, isStandalone: true, name: "ngxHelperWeight" });
729
+ ngOnInit() {
730
+ this.componentConfig = this.componentService.getComponentConfig(this.config);
731
+ this.gap = this.gapSize || '1rem';
732
+ this.onResize();
733
+ }
734
+ onResize() {
735
+ this.isMobile = window.innerWidth <= this.componentConfig.mobileWidth;
736
+ }
737
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperSectionComponent, deps: [{ token: ComponentService }, { token: NGX_HELPER_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Component });
738
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.4", type: NgxHelperSectionComponent, isStandalone: true, selector: "ngx-helper-section", inputs: { gapSize: "gapSize" }, host: { listeners: { "window:resize": "onResize($event)" }, properties: { "style.--section-gap": "this.gap" } }, providers: [ComponentService], ngImport: i0, template: "<div class=\"section-columns\" [class.section-columns-mobile]=\"isMobile\">\n <ng-content></ng-content>\n</div>\n", styles: [":host{display:block;direction:rtl}:host .section-columns{display:flex;align-items:flex-start;column-gap:var(--section-gap)}:host ::ng-deep ngx-helper-section-column{flex:1;display:flex;flex-direction:column;row-gap:var(--section-gap)}:host .section-columns-mobile{flex-direction:column;column-gap:0;row-gap:var(--section-gap)}:host .section-columns-mobile ::ng-deep ngx-helper-section-column{width:100%!important}\n"] });
724
739
  }
725
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperWeightPipe, decorators: [{
726
- type: Pipe,
727
- args: [{ name: 'ngxHelperWeight' }]
728
- }] });
740
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperSectionComponent, decorators: [{
741
+ type: Component,
742
+ args: [{ selector: 'ngx-helper-section', host: { '(window:resize)': 'onResize($event)' }, imports: [], providers: [ComponentService], template: "<div class=\"section-columns\" [class.section-columns-mobile]=\"isMobile\">\n <ng-content></ng-content>\n</div>\n", styles: [":host{display:block;direction:rtl}:host .section-columns{display:flex;align-items:flex-start;column-gap:var(--section-gap)}:host ::ng-deep ngx-helper-section-column{flex:1;display:flex;flex-direction:column;row-gap:var(--section-gap)}:host .section-columns-mobile{flex-direction:column;column-gap:0;row-gap:var(--section-gap)}:host .section-columns-mobile ::ng-deep ngx-helper-section-column{width:100%!important}\n"] }]
743
+ }], ctorParameters: () => [{ type: ComponentService }, { type: undefined, decorators: [{
744
+ type: Optional
745
+ }, {
746
+ type: Inject,
747
+ args: [NGX_HELPER_CONFIG]
748
+ }] }], propDecorators: { gap: [{
749
+ type: HostBinding,
750
+ args: ['style.--section-gap']
751
+ }], gapSize: [{
752
+ type: Input,
753
+ args: [{ required: false }]
754
+ }] } });
729
755
 
730
- class NgxHelperValuePipe {
731
- transform(value, options) {
732
- const emptyText = options?.emptyText || '';
733
- if (value === undefined || Helper.IS.empty(value))
734
- return emptyText;
735
- switch (value.type) {
736
- case 'BANK-CARD':
737
- return new NgxHelperBankCardPipe().transform(value.value, value) || emptyText;
738
- case 'DATE':
739
- return new NgxHelperDatePipe().transform(value.value, value) || emptyText;
740
- case 'DURATION':
741
- return new NgxHelperDurationPipe().transform(value.value, value) || emptyText;
742
- case 'FILE-SIZE':
743
- return new NgxHelperFileSizePipe().transform(value.value, value) || emptyText;
744
- case 'MOBILE':
745
- return new NgxHelperMobilePipe().transform(value.value, value) || emptyText;
746
- case 'NUMBER':
747
- return new NgxHelperNumberPipe().transform(value.value, value) || emptyText;
748
- case 'PERIOD':
749
- return new NgxHelperPeriodPipe().transform(value.value, value) || emptyText;
750
- case 'PRICE':
751
- return new NgxHelperPricePipe().transform(value.value, value) || emptyText;
752
- case 'STRING':
753
- return Helper.IS.string(value.value) ? value.value : emptyText;
754
- case 'VOLUME':
755
- return new NgxHelperVolumePipe().transform(value.value, value) || emptyText;
756
- case 'WEIGHT':
757
- return new NgxHelperWeightPipe().transform(value.value, value) || emptyText;
758
- }
756
+ class NgxHelperSectionColumnComponent {
757
+ flexStyle = '1';
758
+ widthStyle = '*';
759
+ flex;
760
+ width;
761
+ sticky;
762
+ ngOnChanges(changes) {
763
+ this.flexStyle = this.width ? 'unset' : this.flex?.toString() || '1';
764
+ this.widthStyle = this.width || '*';
759
765
  }
760
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
761
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperValuePipe, isStandalone: true, name: "ngxHelperValue" });
766
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperSectionColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
767
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.4", type: NgxHelperSectionColumnComponent, isStandalone: true, selector: "ngx-helper-section-column", inputs: { flex: "flex", width: "width", sticky: "sticky" }, host: { properties: { "style.flex": "this.flexStyle", "style.width": "this.widthStyle" } }, usesOnChanges: true, ngImport: i0, template: "<ng-content></ng-content>\n", styles: [""] });
762
768
  }
763
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperValuePipe, decorators: [{
764
- type: Pipe,
765
- args: [{ name: 'ngxHelperValue' }]
766
- }] });
769
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperSectionColumnComponent, decorators: [{
770
+ type: Component,
771
+ args: [{ selector: 'ngx-helper-section-column', imports: [], template: "<ng-content></ng-content>\n" }]
772
+ }], propDecorators: { flexStyle: [{
773
+ type: HostBinding,
774
+ args: ['style.flex']
775
+ }], widthStyle: [{
776
+ type: HostBinding,
777
+ args: ['style.width']
778
+ }], flex: [{
779
+ type: Input,
780
+ args: [{ required: false }]
781
+ }], width: [{
782
+ type: Input,
783
+ args: [{ required: false }]
784
+ }], sticky: [{
785
+ type: Input,
786
+ args: [{ required: false }]
787
+ }] } });
767
788
 
768
789
  class NgxHelperValueBoxComponent {
769
790
  router;
@@ -782,7 +803,6 @@ class NgxHelperValueBoxComponent {
782
803
  copyIndex;
783
804
  copyTimeout;
784
805
  componentConfig;
785
- pipeTransform = new NgxHelperValuePipe().transform;
786
806
  constructor(router, componentService, config) {
787
807
  this.router = router;
788
808
  this.componentService = componentService;
@@ -795,21 +815,7 @@ class NgxHelperValueBoxComponent {
795
815
  ngOnChanges(changes) {
796
816
  this.boxGap = this.gapSize;
797
817
  this.className = `ngx-helper-m3-value-box${this.hideShadow ? ' hide-shadow' : ''}`;
798
- this.data = this.values.map((item) => {
799
- const value = item.value;
800
- return value === undefined
801
- ? { title: item.title, value: '' }
802
- : typeof value === 'string'
803
- ? { title: item.title, value: value.trim() }
804
- : {
805
- title: item.title,
806
- value: this.pipeTransform(value),
807
- action: item.action,
808
- copyToClipboard: item.copyToClipboard,
809
- ltr: ltrValues.includes(value.type),
810
- english: 'english' in value && !!value.english,
811
- };
812
- });
818
+ this.data = this.componentService.getValueData(this.values);
813
819
  }
814
820
  onResize() {
815
821
  if (this.values.length === 0)
@@ -843,11 +849,11 @@ class NgxHelperValueBoxComponent {
843
849
  }, 2000);
844
850
  }
845
851
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperValueBoxComponent, deps: [{ token: i1.Router }, { token: ComponentService }, { token: NGX_HELPER_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Component });
846
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.4", type: NgxHelperValueBoxComponent, isStandalone: true, selector: "ngx-helper-value-box", inputs: { values: "values", column: "column", clearBox: "clearBox", emptyText: "emptyText", gapSize: "gapSize", hideShadow: "hideShadow" }, host: { listeners: { "window:resize": "onResize($event)" }, properties: { "className": "this.className", "style.grid-template-columns": "this.gridTemplateColumns", "style.--gap-size": "this.boxGap" } }, providers: [ComponentService], usesOnChanges: true, ngImport: i0, template: "@for (item of data; track $index) {\n<div class=\"value-box\" [class.clear]=\"clearBox\" [class.click]=\"!!item.action\">\n <div class=\"title\" (click)=\"onClick(item.action)\">{{ item.title }}</div>\n <div\n class=\"value\"\n [style.display]=\"'inline-block'\"\n [style.direction]=\"item.ltr ? 'ltr' : '*'\"\n [class.en]=\"item.english\"\n [class.empty]=\"!item.value\"\n (click)=\"onClick(item.action)\"\n >\n {{ item.value || emptyText }}\n </div>\n <!-- COPY TO CLIPBOARD -->\n @if (item.copyToClipboard && item.value) {\n <button mat-icon-button type=\"button\" [cdkCopyToClipboard]=\"item.value\" (click)=\"onCopy($event, $index)\">\n <mat-icon>{{ copyIndex === $index ? 'done_all' : 'copy' }}</mat-icon>\n </button>\n }\n</div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ClipboardModule }, { kind: "directive", type: i3.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }] });
852
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.4", type: NgxHelperValueBoxComponent, isStandalone: true, selector: "ngx-helper-value-box", inputs: { values: "values", column: "column", clearBox: "clearBox", emptyText: "emptyText", gapSize: "gapSize", hideShadow: "hideShadow" }, host: { listeners: { "window:resize": "onResize($event)" }, properties: { "className": "this.className", "style.grid-template-columns": "this.gridTemplateColumns", "style.--gap-size": "this.boxGap" } }, providers: [ComponentService], usesOnChanges: true, ngImport: i0, template: "@for (item of data; track $index) {\n<div class=\"value-box\" [class.clear]=\"clearBox\" [class.click]=\"!!item.action\">\n <div class=\"title\" (click)=\"onClick(item.action)\">{{ item.title }}</div>\n <div\n class=\"value\"\n [style.display]=\"'inline-block'\"\n [style.direction]=\"item.ltr ? 'ltr' : '*'\"\n [style.color]=\"item.color\"\n [class.en]=\"item.english\"\n [class.empty]=\"!item.value\"\n (click)=\"onClick(item.action)\"\n >\n {{ item.value || emptyText }}\n </div>\n <!-- COPY TO CLIPBOARD -->\n @if (item.copyToClipboard && item.value) {\n <button mat-icon-button type=\"button\" [cdkCopyToClipboard]=\"item.value\" (click)=\"onCopy($event, $index)\">\n <mat-icon>{{ copyIndex === $index ? 'done_all' : 'copy' }}</mat-icon>\n </button>\n }\n</div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ClipboardModule }, { kind: "directive", type: i3.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }] });
847
853
  }
848
854
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperValueBoxComponent, decorators: [{
849
855
  type: Component,
850
- args: [{ selector: 'ngx-helper-value-box', host: { '(window:resize)': 'onResize($event)' }, imports: [ClipboardModule, MatIcon, MatIconButton], providers: [ComponentService], template: "@for (item of data; track $index) {\n<div class=\"value-box\" [class.clear]=\"clearBox\" [class.click]=\"!!item.action\">\n <div class=\"title\" (click)=\"onClick(item.action)\">{{ item.title }}</div>\n <div\n class=\"value\"\n [style.display]=\"'inline-block'\"\n [style.direction]=\"item.ltr ? 'ltr' : '*'\"\n [class.en]=\"item.english\"\n [class.empty]=\"!item.value\"\n (click)=\"onClick(item.action)\"\n >\n {{ item.value || emptyText }}\n </div>\n <!-- COPY TO CLIPBOARD -->\n @if (item.copyToClipboard && item.value) {\n <button mat-icon-button type=\"button\" [cdkCopyToClipboard]=\"item.value\" (click)=\"onCopy($event, $index)\">\n <mat-icon>{{ copyIndex === $index ? 'done_all' : 'copy' }}</mat-icon>\n </button>\n }\n</div>\n}\n" }]
856
+ args: [{ selector: 'ngx-helper-value-box', host: { '(window:resize)': 'onResize($event)' }, imports: [ClipboardModule, MatIcon, MatIconButton], providers: [ComponentService], template: "@for (item of data; track $index) {\n<div class=\"value-box\" [class.clear]=\"clearBox\" [class.click]=\"!!item.action\">\n <div class=\"title\" (click)=\"onClick(item.action)\">{{ item.title }}</div>\n <div\n class=\"value\"\n [style.display]=\"'inline-block'\"\n [style.direction]=\"item.ltr ? 'ltr' : '*'\"\n [style.color]=\"item.color\"\n [class.en]=\"item.english\"\n [class.empty]=\"!item.value\"\n (click)=\"onClick(item.action)\"\n >\n {{ item.value || emptyText }}\n </div>\n <!-- COPY TO CLIPBOARD -->\n @if (item.copyToClipboard && item.value) {\n <button mat-icon-button type=\"button\" [cdkCopyToClipboard]=\"item.value\" (click)=\"onCopy($event, $index)\">\n <mat-icon>{{ copyIndex === $index ? 'done_all' : 'copy' }}</mat-icon>\n </button>\n }\n</div>\n}\n" }]
851
857
  }], ctorParameters: () => [{ type: i1.Router }, { type: ComponentService }, { type: undefined, decorators: [{
852
858
  type: Optional
853
859
  }, {
@@ -884,6 +890,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImpor
884
890
 
885
891
  class NgxHelperValueListComponent {
886
892
  router;
893
+ componentService;
887
894
  className = 'ngx-helper-m3-value-list';
888
895
  values;
889
896
  titleWidth = '20%';
@@ -891,26 +898,12 @@ class NgxHelperValueListComponent {
891
898
  data = [];
892
899
  copyIndex;
893
900
  copyTimeout;
894
- pipeTransform = new NgxHelperValuePipe().transform;
895
- constructor(router) {
901
+ constructor(router, componentService) {
896
902
  this.router = router;
903
+ this.componentService = componentService;
897
904
  }
898
905
  ngOnChanges(changes) {
899
- this.data = this.values.map((item) => {
900
- const value = item.value;
901
- return value === undefined
902
- ? { title: item.title, value: '' }
903
- : typeof value === 'string'
904
- ? { title: item.title, value: value.trim() }
905
- : {
906
- title: item.title,
907
- value: this.pipeTransform(value),
908
- action: item.action,
909
- copyToClipboard: item.copyToClipboard,
910
- ltr: ltrValues.includes(value.type),
911
- english: 'english' in value && !!value.english,
912
- };
913
- });
906
+ this.data = this.componentService.getValueData(this.values);
914
907
  }
915
908
  onClick(action) {
916
909
  if (!action)
@@ -929,13 +922,13 @@ class NgxHelperValueListComponent {
929
922
  this.copyTimeout = undefined;
930
923
  }, 2000);
931
924
  }
932
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperValueListComponent, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
933
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.4", type: NgxHelperValueListComponent, isStandalone: true, selector: "ngx-helper-value-list", inputs: { values: "values", titleWidth: "titleWidth", emptyText: "emptyText" }, host: { properties: { "className": "this.className" } }, usesOnChanges: true, ngImport: i0, template: "@for (item of data; track $index) {\n<div class=\"value-list-item\" [class.even]=\"$index % 2 === 0\" [class.odd]=\"$index % 2 === 1\">\n <div class=\"title\" [style.width]=\"titleWidth\">{{ item.title }}:</div>\n <div class=\"value\">\n <div\n [style.display]=\"'inline-block'\"\n [style.direction]=\"item.ltr ? 'ltr' : '*'\"\n [class.en]=\"item.english\"\n [class.empty]=\"!item.value\"\n [class.click]=\"!!item.action\"\n (click)=\"onClick(item.action)\"\n >\n {{ item.value || emptyText }}\n </div>\n <!-- ACTION -->\n @if (item.action) {\n <button mat-icon-button type=\"button\" (click)=\"onClick(item.action)\">\n <mat-icon>open_in_new</mat-icon>\n </button>\n\n }\n </div>\n <!-- COPY TO CLIPBOARD -->\n @if (item.copyToClipboard && item.value) {\n <button mat-icon-button type=\"button\" [cdkCopyToClipboard]=\"item.value\" (click)=\"onCopy($event, $index)\">\n <mat-icon>{{ copyIndex === $index ? 'done_all' : 'copy' }}</mat-icon>\n </button>\n }\n</div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ClipboardModule }, { kind: "directive", type: i3.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }] });
925
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperValueListComponent, deps: [{ token: i1.Router }, { token: ComponentService }], target: i0.ɵɵFactoryTarget.Component });
926
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.4", type: NgxHelperValueListComponent, isStandalone: true, selector: "ngx-helper-value-list", inputs: { values: "values", titleWidth: "titleWidth", emptyText: "emptyText" }, host: { properties: { "className": "this.className" } }, providers: [ComponentService], usesOnChanges: true, ngImport: i0, template: "@for (item of data; track $index) {\n<div class=\"value-list-item\" [class.even]=\"$index % 2 === 0\" [class.odd]=\"$index % 2 === 1\">\n <div class=\"title\" [style.width]=\"titleWidth\">{{ item.title }}:</div>\n <div class=\"value\">\n <div\n [style.display]=\"'inline-block'\"\n [style.direction]=\"item.ltr ? 'ltr' : '*'\"\n [style.color]=\"item.color\"\n [class.en]=\"item.english\"\n [class.empty]=\"!item.value\"\n [class.click]=\"!!item.action\"\n (click)=\"onClick(item.action)\"\n >\n {{ item.value || emptyText }}\n </div>\n <!-- ACTION -->\n @if (item.action) {\n <button mat-icon-button type=\"button\" (click)=\"onClick(item.action)\">\n <mat-icon [style.color]=\"item.color\">open_in_new</mat-icon>\n </button>\n\n }\n </div>\n <!-- COPY TO CLIPBOARD -->\n @if (item.copyToClipboard && item.value) {\n <button mat-icon-button type=\"button\" [cdkCopyToClipboard]=\"item.value\" (click)=\"onCopy($event, $index)\">\n <mat-icon>{{ copyIndex === $index ? 'done_all' : 'copy' }}</mat-icon>\n </button>\n }\n</div>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: ClipboardModule }, { kind: "directive", type: i3.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }] });
934
927
  }
935
928
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperValueListComponent, decorators: [{
936
929
  type: Component,
937
- args: [{ selector: 'ngx-helper-value-list', imports: [ClipboardModule, MatIcon, MatIconButton], template: "@for (item of data; track $index) {\n<div class=\"value-list-item\" [class.even]=\"$index % 2 === 0\" [class.odd]=\"$index % 2 === 1\">\n <div class=\"title\" [style.width]=\"titleWidth\">{{ item.title }}:</div>\n <div class=\"value\">\n <div\n [style.display]=\"'inline-block'\"\n [style.direction]=\"item.ltr ? 'ltr' : '*'\"\n [class.en]=\"item.english\"\n [class.empty]=\"!item.value\"\n [class.click]=\"!!item.action\"\n (click)=\"onClick(item.action)\"\n >\n {{ item.value || emptyText }}\n </div>\n <!-- ACTION -->\n @if (item.action) {\n <button mat-icon-button type=\"button\" (click)=\"onClick(item.action)\">\n <mat-icon>open_in_new</mat-icon>\n </button>\n\n }\n </div>\n <!-- COPY TO CLIPBOARD -->\n @if (item.copyToClipboard && item.value) {\n <button mat-icon-button type=\"button\" [cdkCopyToClipboard]=\"item.value\" (click)=\"onCopy($event, $index)\">\n <mat-icon>{{ copyIndex === $index ? 'done_all' : 'copy' }}</mat-icon>\n </button>\n }\n</div>\n}\n" }]
938
- }], ctorParameters: () => [{ type: i1.Router }], propDecorators: { className: [{
930
+ args: [{ selector: 'ngx-helper-value-list', imports: [ClipboardModule, MatIcon, MatIconButton], providers: [ComponentService], template: "@for (item of data; track $index) {\n<div class=\"value-list-item\" [class.even]=\"$index % 2 === 0\" [class.odd]=\"$index % 2 === 1\">\n <div class=\"title\" [style.width]=\"titleWidth\">{{ item.title }}:</div>\n <div class=\"value\">\n <div\n [style.display]=\"'inline-block'\"\n [style.direction]=\"item.ltr ? 'ltr' : '*'\"\n [style.color]=\"item.color\"\n [class.en]=\"item.english\"\n [class.empty]=\"!item.value\"\n [class.click]=\"!!item.action\"\n (click)=\"onClick(item.action)\"\n >\n {{ item.value || emptyText }}\n </div>\n <!-- ACTION -->\n @if (item.action) {\n <button mat-icon-button type=\"button\" (click)=\"onClick(item.action)\">\n <mat-icon [style.color]=\"item.color\">open_in_new</mat-icon>\n </button>\n\n }\n </div>\n <!-- COPY TO CLIPBOARD -->\n @if (item.copyToClipboard && item.value) {\n <button mat-icon-button type=\"button\" [cdkCopyToClipboard]=\"item.value\" (click)=\"onCopy($event, $index)\">\n <mat-icon>{{ copyIndex === $index ? 'done_all' : 'copy' }}</mat-icon>\n </button>\n }\n</div>\n}\n" }]
931
+ }], ctorParameters: () => [{ type: i1.Router }, { type: ComponentService }], propDecorators: { className: [{
939
932
  type: HostBinding,
940
933
  args: ['className']
941
934
  }], values: [{
@@ -1283,6 +1276,533 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImpor
1283
1276
  args: [{ providedIn: 'root' }]
1284
1277
  }], ctorParameters: () => [{ type: i1$3.MatBottomSheet }, { type: i2$1.MatDialog }] });
1285
1278
 
1279
+ class ToastComponent {
1280
+ elementRef;
1281
+ onClick = () => this.close();
1282
+ host = true;
1283
+ className = 'ngx-helper-m3-toast';
1284
+ top = '1rem';
1285
+ textColor;
1286
+ borderColor;
1287
+ backgroundColor;
1288
+ id;
1289
+ icon;
1290
+ messages = [];
1291
+ config;
1292
+ init;
1293
+ close;
1294
+ timeout;
1295
+ showClose;
1296
+ animation;
1297
+ progress = 0;
1298
+ start = 0;
1299
+ interval;
1300
+ constructor(elementRef) {
1301
+ this.elementRef = elementRef;
1302
+ }
1303
+ ngOnInit() {
1304
+ this.borderColor = this.backgroundColor;
1305
+ const xPosition = this.config.helper?.toastXPosition || 'CENTER';
1306
+ this.className = `ngx-helper-m3-toast ${xPosition.toLowerCase()}`;
1307
+ const toastTimeout = this.config.helper?.toastTimeout === undefined || this.config.helper?.toastTimeout < 0
1308
+ ? 4000
1309
+ : this.config.helper?.toastTimeout;
1310
+ this.timeout =
1311
+ this.config.toast.timeout === undefined || this.config.toast.timeout < 0
1312
+ ? toastTimeout
1313
+ : this.config.toast.timeout;
1314
+ this.showClose = this.config.toast.showClose || this.timeout === 0;
1315
+ this.animation = this.config.helper?.toastProgressAnimation || 'DECREASE';
1316
+ if (this.timeout) {
1317
+ this.start = new Date().getTime();
1318
+ this.interval = setInterval(() => {
1319
+ const timer = new Date().getTime();
1320
+ this.progress = ((timer - this.start) * 100) / this.timeout;
1321
+ this.progress = this.progress < 100 ? +this.progress.toFixed(2) : 100;
1322
+ if (this.progress === 100)
1323
+ this.close();
1324
+ }, 25);
1325
+ }
1326
+ }
1327
+ ngOnDestroy() {
1328
+ if (this.interval)
1329
+ clearInterval(this.interval);
1330
+ }
1331
+ ngAfterViewInit() {
1332
+ this.init();
1333
+ }
1334
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: ToastComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1335
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.4", type: ToastComponent, isStandalone: true, selector: "ng-component", host: { attributes: { "selector": "toast" }, listeners: { "click": "onClick()" }, properties: { "@host": "this.host", "className": "this.className", "style.top": "this.top", "style.color": "this.textColor", "style.border-color": "this.borderColor", "style.background-color": "this.backgroundColor" } }, ngImport: i0, template: "<div class=\"content\">\n <div class=\"toast\">\n <mat-icon [style.color]=\"textColor\" class=\"icon\">{{ icon }}</mat-icon>\n <ul>\n @for (message of messages; track $index) {\n <li [innerHTML]=\"message | ngxHelperMultiLine\"></li>\n }\n </ul>\n </div>\n <!-- CLOSE ICON -->\n @if (showClose) {\n <mat-icon [style.color]=\"textColor\" class=\"close\">close</mat-icon>\n }\n</div>\n\n<div class=\"progress-container\" [style.background-color]=\"backgroundColor\">\n @if (timeout !== 0) {\n <div\n class=\"progress-value\"\n [style.background-color]=\"'color-mix(in srgb, ' + backgroundColor + ', black 25%)'\"\n [style.width]=\"(animation === 'DECREASE' ? 100 - progress : progress) + '%'\"\n ></div>\n }\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: NgxHelperMultiLinePipe, name: "ngxHelperMultiLine" }], animations: [
1336
+ trigger('host', [
1337
+ transition(':enter', [
1338
+ style({ top: 0, opacity: 0 }),
1339
+ animate('350ms ease-in-out', style({ top: '*', opacity: 1 })),
1340
+ ]),
1341
+ ]),
1342
+ ] });
1343
+ }
1344
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: ToastComponent, decorators: [{
1345
+ type: Component,
1346
+ args: [{ host: { selector: 'toast' }, imports: [MatIcon, NgxHelperMultiLinePipe], animations: [
1347
+ trigger('host', [
1348
+ transition(':enter', [
1349
+ style({ top: 0, opacity: 0 }),
1350
+ animate('350ms ease-in-out', style({ top: '*', opacity: 1 })),
1351
+ ]),
1352
+ ]),
1353
+ ], template: "<div class=\"content\">\n <div class=\"toast\">\n <mat-icon [style.color]=\"textColor\" class=\"icon\">{{ icon }}</mat-icon>\n <ul>\n @for (message of messages; track $index) {\n <li [innerHTML]=\"message | ngxHelperMultiLine\"></li>\n }\n </ul>\n </div>\n <!-- CLOSE ICON -->\n @if (showClose) {\n <mat-icon [style.color]=\"textColor\" class=\"close\">close</mat-icon>\n }\n</div>\n\n<div class=\"progress-container\" [style.background-color]=\"backgroundColor\">\n @if (timeout !== 0) {\n <div\n class=\"progress-value\"\n [style.background-color]=\"'color-mix(in srgb, ' + backgroundColor + ', black 25%)'\"\n [style.width]=\"(animation === 'DECREASE' ? 100 - progress : progress) + '%'\"\n ></div>\n }\n</div>\n" }]
1354
+ }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { onClick: [{
1355
+ type: HostListener,
1356
+ args: ['click']
1357
+ }], host: [{
1358
+ type: HostBinding,
1359
+ args: ['@host']
1360
+ }], className: [{
1361
+ type: HostBinding,
1362
+ args: ['className']
1363
+ }], top: [{
1364
+ type: HostBinding,
1365
+ args: ['style.top']
1366
+ }], textColor: [{
1367
+ type: HostBinding,
1368
+ args: ['style.color']
1369
+ }], borderColor: [{
1370
+ type: HostBinding,
1371
+ args: ['style.border-color']
1372
+ }], backgroundColor: [{
1373
+ type: HostBinding,
1374
+ args: ['style.background-color']
1375
+ }] } });
1376
+
1377
+ class NgxHelperToastService {
1378
+ applicationRef;
1379
+ injector;
1380
+ config;
1381
+ components = [];
1382
+ constructor(applicationRef, injector, config) {
1383
+ this.applicationRef = applicationRef;
1384
+ this.injector = injector;
1385
+ this.config = config;
1386
+ }
1387
+ getId() {
1388
+ let id = undefined;
1389
+ while (!id || this.components.some((c) => c.id === id))
1390
+ id = Helper.STRING.getRandom(10);
1391
+ return id;
1392
+ }
1393
+ updatePositions() {
1394
+ let top = 0;
1395
+ this.components.forEach((c, index) => {
1396
+ c.componentRef.instance.top = `calc(${(index / 1.5).toFixed(1)}rem + calc(${top}px + 1rem))`;
1397
+ top += +c.componentRef.instance.elementRef.nativeElement.offsetHeight;
1398
+ });
1399
+ }
1400
+ toast(toast, message, arg1, arg2) {
1401
+ const config = arg2 ? arg1 : typeof arg1 === 'object' ? arg1 : {};
1402
+ const onClose = arg2 || (typeof arg1 === 'function' ? arg1 : () => { });
1403
+ const messages = typeof message === 'string' ? [message] : message;
1404
+ const content = [toast.icon, toast.textColor, toast.backgroundColor, ...messages].join('\n');
1405
+ const duplicate = this.components.find((component) => component.content === content);
1406
+ if (!this.config?.toastAllowDuplicates && duplicate) {
1407
+ if (this.config?.toastResetDuplicates) {
1408
+ duplicate.componentRef.instance.start = new Date().getTime();
1409
+ duplicate.componentRef.instance.progress = 0;
1410
+ }
1411
+ return;
1412
+ }
1413
+ const componentRef = createComponent(ToastComponent, {
1414
+ environmentInjector: this.applicationRef.injector,
1415
+ elementInjector: this.injector,
1416
+ });
1417
+ const id = this.getId();
1418
+ componentRef.instance.id = id;
1419
+ componentRef.instance.icon = toast.icon;
1420
+ componentRef.instance.textColor = toast.textColor;
1421
+ componentRef.instance.backgroundColor = toast.backgroundColor;
1422
+ componentRef.instance.messages = messages;
1423
+ componentRef.instance.config = { helper: this.config, toast: config };
1424
+ componentRef.instance.init = () => this.updatePositions();
1425
+ componentRef.instance.close = () => {
1426
+ this.applicationRef.detachView(componentRef.hostView);
1427
+ document.body.removeChild(htmlElement);
1428
+ componentRef.destroy();
1429
+ this.components = this.components.filter((c) => c.id !== componentRef.instance.id);
1430
+ this.updatePositions();
1431
+ if (onClose)
1432
+ onClose();
1433
+ };
1434
+ const htmlElement = componentRef.hostView.rootNodes[0];
1435
+ this.applicationRef.attachView(componentRef.hostView);
1436
+ document.body.appendChild(htmlElement);
1437
+ this.components.push({ id, componentRef, content });
1438
+ this.updatePositions();
1439
+ }
1440
+ info(message, arg1, arg2) {
1441
+ const toast = { icon: 'warning_amber', textColor: '#fff', backgroundColor: '#2f96b4' };
1442
+ this.toast(toast, message, arg1, arg2);
1443
+ }
1444
+ success(message, arg1, arg2) {
1445
+ const toast = { icon: 'done_all', textColor: '#fff', backgroundColor: '#51a351' };
1446
+ this.toast(toast, message, arg1, arg2);
1447
+ }
1448
+ warning(message, arg1, arg2) {
1449
+ const toast = { icon: 'info', textColor: '#fff', backgroundColor: '#f89406' };
1450
+ this.toast(toast, message, arg1, arg2);
1451
+ }
1452
+ error(message, arg1, arg2) {
1453
+ const toast = { icon: 'cancel', textColor: '#fff', backgroundColor: '#bd362f' };
1454
+ this.toast(toast, message, arg1, arg2);
1455
+ }
1456
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperToastService, deps: [{ token: i0.ApplicationRef }, { token: i0.Injector }, { token: NGX_HELPER_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
1457
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperToastService, providedIn: 'root' });
1458
+ }
1459
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperToastService, decorators: [{
1460
+ type: Injectable,
1461
+ args: [{ providedIn: 'root' }]
1462
+ }], ctorParameters: () => [{ type: i0.ApplicationRef }, { type: i0.Injector }, { type: undefined, decorators: [{
1463
+ type: Optional
1464
+ }, {
1465
+ type: Inject,
1466
+ args: [NGX_HELPER_CONFIG]
1467
+ }] }] });
1468
+
1469
+ class DownloadComponent {
1470
+ httpClient;
1471
+ ngxHelperToastService;
1472
+ host = true;
1473
+ className = 'ngx-helper-m3-http';
1474
+ bottom = '1rem';
1475
+ id;
1476
+ path;
1477
+ title;
1478
+ config;
1479
+ onSuccess;
1480
+ onError;
1481
+ close;
1482
+ progress = 0;
1483
+ constructor(httpClient, ngxHelperToastService) {
1484
+ this.httpClient = httpClient;
1485
+ this.ngxHelperToastService = ngxHelperToastService;
1486
+ }
1487
+ ngAfterViewInit() {
1488
+ setTimeout(this.download.bind(this), 0);
1489
+ }
1490
+ download() {
1491
+ let headers = new HttpHeaders();
1492
+ const header = this.config.header || {};
1493
+ Object.keys(header).forEach((key) => (headers = headers.set(key, header[key])));
1494
+ let request;
1495
+ switch (this.config.method || 'GET') {
1496
+ case 'GET':
1497
+ request = this.httpClient.get(this.path, {
1498
+ headers,
1499
+ reportProgress: true,
1500
+ observe: 'events',
1501
+ responseType: 'arraybuffer',
1502
+ });
1503
+ break;
1504
+ case 'POST':
1505
+ request = this.httpClient.post(this.path, {
1506
+ headers,
1507
+ reportProgress: true,
1508
+ observe: 'events',
1509
+ responseType: 'arraybuffer',
1510
+ });
1511
+ break;
1512
+ case 'PUT':
1513
+ request = this.httpClient.put(this.path, {
1514
+ headers,
1515
+ reportProgress: true,
1516
+ observe: 'events',
1517
+ responseType: 'arraybuffer',
1518
+ });
1519
+ break;
1520
+ case 'PATCH':
1521
+ request = this.httpClient.patch(this.path, {
1522
+ headers,
1523
+ reportProgress: true,
1524
+ observe: 'events',
1525
+ responseType: 'arraybuffer',
1526
+ });
1527
+ break;
1528
+ }
1529
+ request.subscribe({
1530
+ next: (event) => {
1531
+ switch (event.type) {
1532
+ case HttpEventType.DownloadProgress:
1533
+ const progress = event.loaded && event.total ? Math.ceil((event.loaded / event.total) * 1000) / 10 : 0;
1534
+ this.progress = progress <= 100 ? progress : 100;
1535
+ break;
1536
+ case HttpEventType.Response:
1537
+ console.log(event);
1538
+ this.progress = 100;
1539
+ this.onSuccess(event.body);
1540
+ this.close();
1541
+ break;
1542
+ }
1543
+ },
1544
+ error: () => {
1545
+ this.onError();
1546
+ this.close();
1547
+ },
1548
+ });
1549
+ }
1550
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: DownloadComponent, deps: [{ token: i1$4.HttpClient }, { token: NgxHelperToastService }], target: i0.ɵɵFactoryTarget.Component });
1551
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.4", type: DownloadComponent, isStandalone: true, selector: "ng-component", host: { attributes: { "selector": "download" }, properties: { "@host": "this.host", "className": "this.className", "style.bottom": "this.bottom" } }, ngImport: i0, template: "<div class=\"content\">\n <mat-icon>file_download</mat-icon>\n <div class=\"title\">{{ title }}</div>\n</div>\n\n<div class=\"progress-container\">\n <div class=\"progress-value\" [style.width]=\"progress + '%'\"></div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], animations: [
1552
+ trigger('host', [
1553
+ transition(':enter', [
1554
+ style({ left: 'calc(-250px - 1rem)' }),
1555
+ animate('100ms ease-in-out', style({ left: '1rem' })),
1556
+ ]),
1557
+ ]),
1558
+ ] });
1559
+ }
1560
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: DownloadComponent, decorators: [{
1561
+ type: Component,
1562
+ args: [{ host: { selector: 'download' }, imports: [MatIcon], animations: [
1563
+ trigger('host', [
1564
+ transition(':enter', [
1565
+ style({ left: 'calc(-250px - 1rem)' }),
1566
+ animate('100ms ease-in-out', style({ left: '1rem' })),
1567
+ ]),
1568
+ ]),
1569
+ ], template: "<div class=\"content\">\n <mat-icon>file_download</mat-icon>\n <div class=\"title\">{{ title }}</div>\n</div>\n\n<div class=\"progress-container\">\n <div class=\"progress-value\" [style.width]=\"progress + '%'\"></div>\n</div>\n" }]
1570
+ }], ctorParameters: () => [{ type: i1$4.HttpClient }, { type: NgxHelperToastService }], propDecorators: { host: [{
1571
+ type: HostBinding,
1572
+ args: ['@host']
1573
+ }], className: [{
1574
+ type: HostBinding,
1575
+ args: ['className']
1576
+ }], bottom: [{
1577
+ type: HostBinding,
1578
+ args: ['style.bottom']
1579
+ }] } });
1580
+
1581
+ class UploadComponent {
1582
+ httpClient;
1583
+ host = true;
1584
+ className = 'ngx-helper-m3-http';
1585
+ bottom = '1rem';
1586
+ id;
1587
+ file;
1588
+ url;
1589
+ config;
1590
+ close;
1591
+ progress = 0;
1592
+ constructor(httpClient) {
1593
+ this.httpClient = httpClient;
1594
+ }
1595
+ ngAfterViewInit() {
1596
+ setTimeout(this.upload.bind(this), 0);
1597
+ }
1598
+ upload() {
1599
+ const formData = new FormData();
1600
+ formData.append('file', this.file);
1601
+ const body = this.config.body || {};
1602
+ Object.keys(body).forEach((k) => formData.append(k, body[k]));
1603
+ let headers = new HttpHeaders();
1604
+ const header = this.config.header || {};
1605
+ Object.keys(header).forEach((key) => (headers = headers.set(key, header[key])));
1606
+ let request;
1607
+ switch (this.config.method || 'POST') {
1608
+ case 'POST':
1609
+ request = this.httpClient.post(this.url, formData, { headers, reportProgress: true, observe: 'events' });
1610
+ break;
1611
+ case 'PUT':
1612
+ request = this.httpClient.put(this.url, formData, { headers, reportProgress: true, observe: 'events' });
1613
+ break;
1614
+ case 'PATCH':
1615
+ request = this.httpClient.patch(this.url, formData, { headers, reportProgress: true, observe: 'events' });
1616
+ break;
1617
+ }
1618
+ request.subscribe({
1619
+ next: (event) => {
1620
+ switch (event.type) {
1621
+ case HttpEventType.UploadProgress:
1622
+ if (!event.loaded || !event.total)
1623
+ return;
1624
+ const progress = (event.loaded / event.total) * 100;
1625
+ this.progress = progress > 100 ? 100 : +progress.toFixed(2);
1626
+ break;
1627
+ case HttpEventType.Response:
1628
+ this.progress = 100;
1629
+ this.close('RESPONSE', event.body, event.status);
1630
+ break;
1631
+ }
1632
+ },
1633
+ error: (error) => this.close('ERROR', error.error, error.status),
1634
+ });
1635
+ }
1636
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: UploadComponent, deps: [{ token: i1$4.HttpClient }], target: i0.ɵɵFactoryTarget.Component });
1637
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.4", type: UploadComponent, isStandalone: true, selector: "ng-component", host: { attributes: { "selector": "upload" }, properties: { "@host": "this.host", "className": "this.className", "style.bottom": "this.bottom" } }, ngImport: i0, template: "<div class=\"content\">\n <mat-icon>file_upload</mat-icon>\n <div class=\"file\">{{ file.name }}</div>\n</div>\n\n<div class=\"progress-container\">\n <div class=\"progress-value\" [style.width]=\"progress + '%'\"></div>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], animations: [
1638
+ trigger('host', [
1639
+ transition(':enter', [
1640
+ style({ left: 'calc(-250px - 1rem)' }),
1641
+ animate('100ms ease-in-out', style({ left: '1rem' })),
1642
+ ]),
1643
+ ]),
1644
+ ] });
1645
+ }
1646
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: UploadComponent, decorators: [{
1647
+ type: Component,
1648
+ args: [{ host: { selector: 'upload' }, imports: [MatIcon], animations: [
1649
+ trigger('host', [
1650
+ transition(':enter', [
1651
+ style({ left: 'calc(-250px - 1rem)' }),
1652
+ animate('100ms ease-in-out', style({ left: '1rem' })),
1653
+ ]),
1654
+ ]),
1655
+ ], template: "<div class=\"content\">\n <mat-icon>file_upload</mat-icon>\n <div class=\"file\">{{ file.name }}</div>\n</div>\n\n<div class=\"progress-container\">\n <div class=\"progress-value\" [style.width]=\"progress + '%'\"></div>\n</div>\n" }]
1656
+ }], ctorParameters: () => [{ type: i1$4.HttpClient }], propDecorators: { host: [{
1657
+ type: HostBinding,
1658
+ args: ['@host']
1659
+ }], className: [{
1660
+ type: HostBinding,
1661
+ args: ['className']
1662
+ }], bottom: [{
1663
+ type: HostBinding,
1664
+ args: ['style.bottom']
1665
+ }] } });
1666
+
1667
+ class NgxHelperHttpService {
1668
+ applicationRef;
1669
+ injector;
1670
+ ngxHelperToastService;
1671
+ components = [];
1672
+ constructor(applicationRef, injector, ngxHelperToastService) {
1673
+ this.applicationRef = applicationRef;
1674
+ this.injector = injector;
1675
+ this.ngxHelperToastService = ngxHelperToastService;
1676
+ }
1677
+ getId() {
1678
+ let id = undefined;
1679
+ while (!id || this.components.some((c) => c.id === id))
1680
+ id = Helper.STRING.getRandom(10);
1681
+ return id;
1682
+ }
1683
+ updatePositions() {
1684
+ this.components.forEach((c, index) => {
1685
+ c.componentRef.instance.bottom = `calc(${(index / 1.5).toFixed(1)}rem + calc(${index * 40}px + 1rem))`;
1686
+ });
1687
+ }
1688
+ getBuffer(path, title, config) {
1689
+ return new Promise((resolve, reject) => {
1690
+ const componentRef = createComponent(DownloadComponent, {
1691
+ environmentInjector: this.applicationRef.injector,
1692
+ elementInjector: this.injector,
1693
+ });
1694
+ const id = this.getId();
1695
+ componentRef.instance.id = id;
1696
+ componentRef.instance.path = path;
1697
+ componentRef.instance.title = title;
1698
+ componentRef.instance.config = config || {};
1699
+ componentRef.instance.onSuccess = (arrayBuffer) => resolve(arrayBuffer);
1700
+ componentRef.instance.onError = () => reject();
1701
+ componentRef.instance.close = () => {
1702
+ this.applicationRef.detachView(componentRef.hostView);
1703
+ document.body.removeChild(htmlElement);
1704
+ componentRef.destroy();
1705
+ this.components = this.components.filter((c) => c.id !== componentRef.instance.id);
1706
+ this.updatePositions();
1707
+ };
1708
+ const htmlElement = componentRef.hostView.rootNodes[0];
1709
+ this.applicationRef.attachView(componentRef.hostView);
1710
+ document.body.appendChild(htmlElement);
1711
+ this.components.push({ id, componentRef });
1712
+ this.updatePositions();
1713
+ });
1714
+ }
1715
+ download(path, title, config) {
1716
+ const onError = () => this.ngxHelperToastService.error('امکان دانلود فایل وجود ندارد.');
1717
+ const onSuccess = (arrayBuffer) => {
1718
+ try {
1719
+ const split = path
1720
+ .split('.')
1721
+ .map((text) => text.trim().replace(/\//gi, ''))
1722
+ .filter((text) => !!text);
1723
+ const name = Helper.STRING.getFileName(title, split[split.length - 1] || '');
1724
+ const href = URL.createObjectURL(new Blob([arrayBuffer]));
1725
+ const a = document.createElement('a');
1726
+ a.href = href;
1727
+ a.download = name;
1728
+ a.click();
1729
+ }
1730
+ catch (e) {
1731
+ onError();
1732
+ }
1733
+ };
1734
+ this.getBuffer(path, title, config || {}).then(onSuccess, onError);
1735
+ }
1736
+ upload(file, url, arg1, arg2, arg3) {
1737
+ const config = typeof arg3 === 'function' ? arg1 : {};
1738
+ const onSuccess = typeof arg3 === 'function' ? arg2 : arg1;
1739
+ const onError = typeof arg3 === 'function' ? arg3 : arg2;
1740
+ const componentRef = createComponent(UploadComponent, {
1741
+ environmentInjector: this.applicationRef.injector,
1742
+ elementInjector: this.injector,
1743
+ });
1744
+ const id = this.getId();
1745
+ componentRef.instance.id = id;
1746
+ componentRef.instance.file = file;
1747
+ componentRef.instance.url = url;
1748
+ componentRef.instance.config = config;
1749
+ componentRef.instance.close = (type, result, status) => {
1750
+ this.applicationRef.detachView(componentRef.hostView);
1751
+ document.body.removeChild(htmlElement);
1752
+ componentRef.destroy();
1753
+ this.components = this.components.filter((c) => c.id !== componentRef.instance.id);
1754
+ this.updatePositions();
1755
+ switch (type) {
1756
+ case 'RESPONSE':
1757
+ onSuccess(result || undefined, status);
1758
+ break;
1759
+ case 'ERROR':
1760
+ onError(result || undefined, status);
1761
+ break;
1762
+ }
1763
+ };
1764
+ const htmlElement = componentRef.hostView.rootNodes[0];
1765
+ this.applicationRef.attachView(componentRef.hostView);
1766
+ document.body.appendChild(htmlElement);
1767
+ this.components.push({ id, componentRef });
1768
+ this.updatePositions();
1769
+ }
1770
+ printPDF(data, config) {
1771
+ const getPDF = () => {
1772
+ return new Promise((resolve, reject) => {
1773
+ if (typeof data !== 'string') {
1774
+ resolve(new Blob([data], { type: 'application/pdf' }));
1775
+ return;
1776
+ }
1777
+ this.getBuffer(data, 'دریافت فایل', config || {}).then((arrayBuffer) => resolve(new Blob([arrayBuffer], { type: 'application/pdf' })), () => reject());
1778
+ });
1779
+ };
1780
+ getPDF().then((blob) => {
1781
+ try {
1782
+ const prevIframe = document.getElementById('ngx-helper-http-pdf-download-iframe');
1783
+ if (prevIframe)
1784
+ document.body.removeChild(prevIframe);
1785
+ const src = URL.createObjectURL(blob);
1786
+ const iframe = document.createElement('iframe');
1787
+ iframe.id = 'ngx-helper-http-pdf-download-iframe';
1788
+ iframe.style.display = 'none';
1789
+ document.body.appendChild(iframe);
1790
+ iframe.src = src;
1791
+ iframe.onload = () => iframe.contentWindow?.print();
1792
+ }
1793
+ catch (e) {
1794
+ this.ngxHelperToastService.error('امکان پرینت فایل وجود ندارد.');
1795
+ }
1796
+ }, () => this.ngxHelperToastService.error('امکان دانلود فایل وجود ندارد.'));
1797
+ }
1798
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperHttpService, deps: [{ token: i0.ApplicationRef }, { token: i0.Injector }, { token: NgxHelperToastService }], target: i0.ɵɵFactoryTarget.Injectable });
1799
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperHttpService, providedIn: 'root' });
1800
+ }
1801
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: NgxHelperHttpService, decorators: [{
1802
+ type: Injectable,
1803
+ args: [{ providedIn: 'root' }]
1804
+ }], ctorParameters: () => [{ type: i0.ApplicationRef }, { type: i0.Injector }, { type: NgxHelperToastService }] });
1805
+
1286
1806
  /*
1287
1807
  * Public API Surface of ngx-helper-m3
1288
1808
  */
@@ -1291,5 +1811,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImpor
1291
1811
  * Generated bundle index. Do not edit.
1292
1812
  */
1293
1813
 
1294
- export { NGX_HELPER_BOX_DATA, NGX_HELPER_CONFIG, NGX_HELPER_CONTAINER_CLOSE, NGX_HELPER_CONTAINER_DATA, NGX_HELPER_CONTAINER_TYPE, NGX_HELPER_PAGE_GROUP_DATA, NGX_HELPER_PAGE_GROUP_DATA_CHANGE, NGX_HELPER_PAGE_GROUP_ITEM, NgxHelperBankCardPipe, NgxHelperBoxComponent, NgxHelperCardComponent, NgxHelperConfirmService, NgxHelperContainerService, NgxHelperDatePipe, NgxHelperDurationPipe, NgxHelperFileSizePipe, NgxHelperLoaderComponent, NgxHelperMobilePipe, NgxHelperMultiLinePipe, NgxHelperNumberPipe, NgxHelperPageGroupComponent, NgxHelperPeriodPipe, NgxHelperPricePipe, NgxHelperSafePipe, NgxHelperSectionColumnComponent, NgxHelperSectionComponent, NgxHelperSectionStickyDirective, NgxHelperValueBoxComponent, NgxHelperValueListComponent, NgxHelperValuePipe, NgxHelperVolumePipe, NgxHelperWeightPipe, provideNgxHelperConfig };
1814
+ export { NGX_HELPER_BOX_DATA, NGX_HELPER_CONFIG, NGX_HELPER_CONTAINER_CLOSE, NGX_HELPER_CONTAINER_DATA, NGX_HELPER_CONTAINER_TYPE, NGX_HELPER_PAGE_GROUP_DATA, NGX_HELPER_PAGE_GROUP_DATA_CHANGE, NGX_HELPER_PAGE_GROUP_ITEM, NgxHelperBankCardPipe, NgxHelperBoxComponent, NgxHelperCardComponent, NgxHelperConfirmService, NgxHelperContainerService, NgxHelperDatePipe, NgxHelperDurationPipe, NgxHelperFileSizePipe, NgxHelperHttpService, NgxHelperLoaderComponent, NgxHelperMobilePipe, NgxHelperMultiLinePipe, NgxHelperNumberPipe, NgxHelperPageGroupComponent, NgxHelperPeriodPipe, NgxHelperPricePipe, NgxHelperSafePipe, NgxHelperSectionColumnComponent, NgxHelperSectionComponent, NgxHelperSectionStickyDirective, NgxHelperToastService, NgxHelperValueBoxComponent, NgxHelperValueListComponent, NgxHelperValuePipe, NgxHelperVolumePipe, NgxHelperWeightPipe, provideNgxHelperConfig };
1295
1815
  //# sourceMappingURL=webilix-ngx-helper-m3.mjs.map