@ng-solid/design-system 22.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3142 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, ElementRef, ChangeDetectorRef, PLATFORM_ID, Renderer2, NgZone, numberAttribute, ViewChild, Input, ViewEncapsulation, ChangeDetectionStrategy, Component, booleanAttribute, Directive, forwardRef, Injectable, LOCALE_ID, HostListener, ContentChildren, ApplicationRef, DestroyRef, EnvironmentInjector, DOCUMENT, createComponent, Injector, ContentChild, DEFAULT_CURRENCY_CODE, HostBinding, Output, InjectionToken, Pipe, ViewContainerRef, RendererFactory2, TemplateRef } from '@angular/core';
3
+ import * as i1$1 from '@angular/common';
4
+ import { isPlatformBrowser, NgClass, DATE_PIPE_DEFAULT_OPTIONS, CommonModule, TitleCasePipe, NgStyle } from '@angular/common';
5
+ import { isValidURL, Guid, nsAutoClose, NS_FORMAT_OPTIONS, YesNo, NsSafeHtmlPipe, NsHumanizePipe, NS_UPLOAD_CLIENT, NsFile, notEmpty } from '@ng-solid/core';
6
+ import { NsIconsComponent } from '@ng-solid/icons';
7
+ import * as i1 from '@angular/forms';
8
+ import { FormsModule, NG_VALUE_ACCESSOR, FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
9
+ import { Subject, filter, timer, take as take$1, tap } from 'rxjs';
10
+ import { isSameMonth, getLocalTimeZone, today, DateFormatter, startOfWeek, getWeeksInMonth, getDayOfWeek, isToday, parseDate, isEqualDay, startOfMonth, endOfMonth } from '@internationalized/date';
11
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
12
+ import { NumberFormatter, NumberParser } from '@internationalized/number';
13
+ import { RouterLink } from '@angular/router';
14
+ import { take } from 'rxjs/operators';
15
+ import { DomSanitizer } from '@angular/platform-browser';
16
+
17
+ class NsAvatarComponent {
18
+ src;
19
+ atl;
20
+ icon;
21
+ shape = 'circle';
22
+ size = 'small';
23
+ gap = 4;
24
+ textRef;
25
+ hasCover;
26
+ hasIcon;
27
+ elementRef = inject(ElementRef);
28
+ cdr = inject(ChangeDetectorRef);
29
+ platformId = inject(PLATFORM_ID);
30
+ renderer = inject(Renderer2);
31
+ ngZone = inject(NgZone);
32
+ ngOnChanges() {
33
+ this.hasCover = isValidURL(this.src);
34
+ this.hasIcon = !this.src && !!this.icon;
35
+ this.notifyCalc();
36
+ }
37
+ imgError($event) {
38
+ if (!$event.defaultPrevented) {
39
+ this.hasIcon = false;
40
+ this.hasCover = false;
41
+ if (this.icon) {
42
+ this.hasIcon = true;
43
+ }
44
+ else if (isValidURL(this.src)) {
45
+ this.hasCover = true;
46
+ }
47
+ this.cdr.detectChanges();
48
+ this.notifyCalc();
49
+ }
50
+ }
51
+ calcStringSize() {
52
+ const textEl = this.textRef?.nativeElement;
53
+ if (this.hasCover || !textEl) {
54
+ return;
55
+ }
56
+ const childrenWidth = textEl.offsetWidth;
57
+ const avatarWidth = this.elementRef.nativeElement.getBoundingClientRect().width;
58
+ const offset = this.gap * 2 < avatarWidth ? this.gap * 2 : 8;
59
+ const scale = avatarWidth - offset < childrenWidth
60
+ ? (avatarWidth - offset) / childrenWidth
61
+ : 1;
62
+ this.renderer.setStyle(textEl, 'transform', `scale(${scale}) translateX(-50%)`);
63
+ }
64
+ notifyCalc() {
65
+ if (isPlatformBrowser(this.platformId)) {
66
+ this.ngZone.runOutsideAngular(() => setTimeout(() => this.calcStringSize()));
67
+ }
68
+ }
69
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsAvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
70
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsAvatarComponent, isStandalone: true, selector: "ns-avatar", inputs: { src: "src", atl: "atl", icon: "icon", shape: "shape", size: "size", gap: ["gap", "gap", numberAttribute] }, host: { properties: { "class.ns-avatar--circle": "shape === 'circle'", "class.ns-avatar--square": "shape === 'square'", "class.ns-avatar--large": "size === 'large'", "class.ns-avatar--medium": "size === 'medium'", "class.ns-avatar--small": "size === 'small'" }, classAttribute: "ns-avatar" }, viewQueries: [{ propertyName: "textRef", first: true, predicate: ["textRef"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
71
+ @if (hasCover) {
72
+ <img
73
+ class="ns-avatar__cover"
74
+ [attr.src]="src"
75
+ [attr.alt]="atl"
76
+ (error)="imgError($event)"
77
+ />
78
+ } @else {
79
+ <span class="ns-avatar__text" #textRef>{{ src }}</span>
80
+ }
81
+ `, isInline: true, styles: [".ns-avatar{box-sizing:border-box;margin:0;padding:0;color:#fff;font-size:1rem;font-variant:tabular-nums;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;overflow:hidden;white-space:nowrap;text-align:center;vertical-align:middle;background:#ccc}.ns-avatar--small{line-height:2rem;width:2rem;height:2rem}.ns-avatar--medium{line-height:3rem;width:3rem;height:3rem}.ns-avatar--large{font-size:1.5rem;line-height:4rem;width:4rem;height:4rem}.ns-avatar--circle{border-radius:50%}.ns-avatar--square{border-radius:2px}.ns-avatar__cover{border:2px solid transparent;border-radius:100px;background:radial-gradient(circle,#5dea63,#11b719);box-sizing:border-box}.ns-avatar__text{transform-origin:0 center}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
82
+ }
83
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsAvatarComponent, decorators: [{
84
+ type: Component,
85
+ args: [{ selector: 'ns-avatar', template: `
86
+ @if (hasCover) {
87
+ <img
88
+ class="ns-avatar__cover"
89
+ [attr.src]="src"
90
+ [attr.alt]="atl"
91
+ (error)="imgError($event)"
92
+ />
93
+ } @else {
94
+ <span class="ns-avatar__text" #textRef>{{ src }}</span>
95
+ }
96
+ `, host: {
97
+ class: 'ns-avatar',
98
+ '[class.ns-avatar--circle]': `shape === 'circle'`,
99
+ '[class.ns-avatar--square]': `shape === 'square'`,
100
+ '[class.ns-avatar--large]': `size === 'large'`,
101
+ '[class.ns-avatar--medium]': `size === 'medium'`,
102
+ '[class.ns-avatar--small]': `size === 'small'`
103
+ }, changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, encapsulation: ViewEncapsulation.None, styles: [".ns-avatar{box-sizing:border-box;margin:0;padding:0;color:#fff;font-size:1rem;font-variant:tabular-nums;list-style:none;font-feature-settings:\"tnum\";position:relative;display:inline-block;overflow:hidden;white-space:nowrap;text-align:center;vertical-align:middle;background:#ccc}.ns-avatar--small{line-height:2rem;width:2rem;height:2rem}.ns-avatar--medium{line-height:3rem;width:3rem;height:3rem}.ns-avatar--large{font-size:1.5rem;line-height:4rem;width:4rem;height:4rem}.ns-avatar--circle{border-radius:50%}.ns-avatar--square{border-radius:2px}.ns-avatar__cover{border:2px solid transparent;border-radius:100px;background:radial-gradient(circle,#5dea63,#11b719);box-sizing:border-box}.ns-avatar__text{transform-origin:0 center}\n"] }]
104
+ }], propDecorators: { src: [{
105
+ type: Input,
106
+ args: [{ required: true }]
107
+ }], atl: [{
108
+ type: Input
109
+ }], icon: [{
110
+ type: Input
111
+ }], shape: [{
112
+ type: Input
113
+ }], size: [{
114
+ type: Input
115
+ }], gap: [{
116
+ type: Input,
117
+ args: [{ transform: numberAttribute }]
118
+ }], textRef: [{
119
+ type: ViewChild,
120
+ args: ['textRef', { static: false }]
121
+ }] } });
122
+
123
+ class NsButtonComponent {
124
+ label;
125
+ type = 'button';
126
+ theme = 'secondary';
127
+ block;
128
+ disabled;
129
+ loading;
130
+ icon;
131
+ value;
132
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
133
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsButtonComponent, isStandalone: true, selector: "ns-button", inputs: { label: "label", type: "type", theme: "theme", block: ["block", "block", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], loading: ["loading", "loading", booleanAttribute], icon: "icon", value: "value" }, host: { properties: { "class.ns-button": "true", "class.ns-button__grid": "block", "class.ns-button--loading": "loading", "class.ns-button--disabled": "disabled" } }, ngImport: i0, template: `
134
+ <button
135
+ [attr.type]="type"
136
+ class="btn"
137
+ [ngClass]="{
138
+ btn__primary: theme == 'primary',
139
+ btn__secondary: theme == 'secondary',
140
+ btn__success: theme == 'success',
141
+ btn__block: block,
142
+ 'btn--icon': icon
143
+ }"
144
+ [disabled]="disabled || loading"
145
+ >
146
+ @if (!loading) {
147
+ @if (icon) {
148
+ <ns-icon [name]="icon" size="16" />
149
+ }
150
+ {{ label }}
151
+ } @else {
152
+ <ns-icon name="preload" size="16" />
153
+ }
154
+ </button>
155
+ `, isInline: true, styles: [":host{display:block;width:fit-content}:host.ns-button__grid{display:grid;width:100%}:host.ns-button--disabled,:host.ns-button--loading{pointer-events:none}.btn{display:block;position:relative;border-radius:var(--ns-border-radius, .375rem);vertical-align:center;text-align:center;text-transform:none;font-size:.875rem;line-height:1rem;outline:none;white-space:nowrap;padding:var(--ns-btn-padding-y, .5rem) var(--ns-btn-padding-x, 1rem);cursor:pointer}.btn:disabled{pointer-events:none}.btn__primary{background-color:var(--ns-color-primary, #3665f3);border:1px solid var(--ns-color-primary, #3665f3);color:var(--ns-color-primary-foreground, #fff);min-width:var(--ns-btn-min-width, 5rem)}.btn__primary:focus,.btn__primary:active{color:var(--ns-color-primary-foreground, #fff);border-color:var(--ns-color-primary-hover, #2f57d9);box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__primary:hover{background-color:var(--ns-color-primary-hover, #2f57d9)}.btn__secondary{color:var(--ns-color-foreground, #1f2937);background-color:var(--ns-color-surface, #fff);min-width:var(--ns-btn-min-width, 5rem);border:1px solid var(--ns-color-border, rgb(219, 214, 225))}.btn__secondary:focus,.btn__secondary:active{color:var(--ns-color-foreground, #1f2937);border:1px solid var(--ns-color-border, rgb(219, 214, 225));box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__secondary:hover{background-color:var(--ns-color-surface-muted, rgba(9, 30, 66, .08))}.btn__success{border-color:transparent;background-color:var(--ns-color-success, #0cac42);color:var(--ns-color-primary-foreground, #fff);min-width:var(--ns-btn-min-width, 5rem)}.btn__success:focus,.btn__success:active{color:var(--ns-color-success, #0cac42);border:1px solid var(--ns-color-border, rgb(219, 214, 225));box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__success:hover{background-color:var(--ns-color-success, #0cac42)}.btn__block{width:100%;min-height:2.5rem}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: NsIconsComponent, selector: "ns-icon", inputs: ["name", "color", "size", "strokeWidth", "viewBox"] }] });
156
+ }
157
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsButtonComponent, decorators: [{
158
+ type: Component,
159
+ args: [{ selector: 'ns-button', imports: [NgClass, NsIconsComponent], template: `
160
+ <button
161
+ [attr.type]="type"
162
+ class="btn"
163
+ [ngClass]="{
164
+ btn__primary: theme == 'primary',
165
+ btn__secondary: theme == 'secondary',
166
+ btn__success: theme == 'success',
167
+ btn__block: block,
168
+ 'btn--icon': icon
169
+ }"
170
+ [disabled]="disabled || loading"
171
+ >
172
+ @if (!loading) {
173
+ @if (icon) {
174
+ <ns-icon [name]="icon" size="16" />
175
+ }
176
+ {{ label }}
177
+ } @else {
178
+ <ns-icon name="preload" size="16" />
179
+ }
180
+ </button>
181
+ `, host: {
182
+ '[class.ns-button]': 'true',
183
+ '[class.ns-button__grid]': 'block',
184
+ '[class.ns-button--loading]': 'loading',
185
+ '[class.ns-button--disabled]': 'disabled'
186
+ }, styles: [":host{display:block;width:fit-content}:host.ns-button__grid{display:grid;width:100%}:host.ns-button--disabled,:host.ns-button--loading{pointer-events:none}.btn{display:block;position:relative;border-radius:var(--ns-border-radius, .375rem);vertical-align:center;text-align:center;text-transform:none;font-size:.875rem;line-height:1rem;outline:none;white-space:nowrap;padding:var(--ns-btn-padding-y, .5rem) var(--ns-btn-padding-x, 1rem);cursor:pointer}.btn:disabled{pointer-events:none}.btn__primary{background-color:var(--ns-color-primary, #3665f3);border:1px solid var(--ns-color-primary, #3665f3);color:var(--ns-color-primary-foreground, #fff);min-width:var(--ns-btn-min-width, 5rem)}.btn__primary:focus,.btn__primary:active{color:var(--ns-color-primary-foreground, #fff);border-color:var(--ns-color-primary-hover, #2f57d9);box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__primary:hover{background-color:var(--ns-color-primary-hover, #2f57d9)}.btn__secondary{color:var(--ns-color-foreground, #1f2937);background-color:var(--ns-color-surface, #fff);min-width:var(--ns-btn-min-width, 5rem);border:1px solid var(--ns-color-border, rgb(219, 214, 225))}.btn__secondary:focus,.btn__secondary:active{color:var(--ns-color-foreground, #1f2937);border:1px solid var(--ns-color-border, rgb(219, 214, 225));box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__secondary:hover{background-color:var(--ns-color-surface-muted, rgba(9, 30, 66, .08))}.btn__success{border-color:transparent;background-color:var(--ns-color-success, #0cac42);color:var(--ns-color-primary-foreground, #fff);min-width:var(--ns-btn-min-width, 5rem)}.btn__success:focus,.btn__success:active{color:var(--ns-color-success, #0cac42);border:1px solid var(--ns-color-border, rgb(219, 214, 225));box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__success:hover{background-color:var(--ns-color-success, #0cac42)}.btn__block{width:100%;min-height:2.5rem}\n"] }]
187
+ }], propDecorators: { label: [{
188
+ type: Input
189
+ }], type: [{
190
+ type: Input
191
+ }], theme: [{
192
+ type: Input
193
+ }], block: [{
194
+ type: Input,
195
+ args: [{ transform: booleanAttribute }]
196
+ }], disabled: [{
197
+ type: Input,
198
+ args: [{ transform: booleanAttribute }]
199
+ }], loading: [{
200
+ type: Input,
201
+ args: [{ transform: booleanAttribute }]
202
+ }], icon: [{
203
+ type: Input
204
+ }], value: [{
205
+ type: Input
206
+ }] } });
207
+
208
+ class NsValueAccessor {
209
+ type = 'text';
210
+ placeholder = '';
211
+ label;
212
+ disabled;
213
+ readonly;
214
+ id = Guid.create();
215
+ _value;
216
+ get value() {
217
+ return this._value;
218
+ }
219
+ set value(value) {
220
+ if (`${this._value}` !== `${value}`) {
221
+ this.onChange(value);
222
+ }
223
+ this._value = value;
224
+ }
225
+ onTouched = () => { };
226
+ onChange = () => { };
227
+ writeValue(value) {
228
+ if (typeof value !== 'undefined') {
229
+ this._value = value;
230
+ }
231
+ }
232
+ registerOnChange(fn) {
233
+ this.onChange = fn;
234
+ }
235
+ registerOnTouched(fn) {
236
+ this.onTouched = fn;
237
+ }
238
+ setDisabledState(isDisabled) {
239
+ this.disabled = isDisabled;
240
+ }
241
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsValueAccessor, deps: [], target: i0.ɵɵFactoryTarget.Directive });
242
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.21", type: NsValueAccessor, isStandalone: true, inputs: { type: "type", placeholder: "placeholder", label: "label", disabled: "disabled", readonly: "readonly", value: "value" }, ngImport: i0 });
243
+ }
244
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsValueAccessor, decorators: [{
245
+ type: Directive
246
+ }], propDecorators: { type: [{
247
+ type: Input
248
+ }], placeholder: [{
249
+ type: Input
250
+ }], label: [{
251
+ type: Input
252
+ }], disabled: [{
253
+ type: Input
254
+ }], readonly: [{
255
+ type: Input
256
+ }], value: [{
257
+ type: Input
258
+ }] } });
259
+
260
+ class NsCheckboxComponent extends NsValueAccessor {
261
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsCheckboxComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
262
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.21", type: NsCheckboxComponent, isStandalone: true, selector: "ns-checkbox", providers: [
263
+ {
264
+ provide: NG_VALUE_ACCESSOR,
265
+ useExisting: forwardRef(() => NsCheckboxComponent),
266
+ multi: true
267
+ }
268
+ ], usesInheritance: true, ngImport: i0, template: `
269
+ <label class="form-check-label">
270
+ <input
271
+ class="form-check-input"
272
+ [(ngModel)]="value"
273
+ type="checkbox"
274
+ (blur)="onTouched()"
275
+ [disabled]="disabled"
276
+ />
277
+ {{ label }}
278
+ </label>
279
+ `, isInline: true, styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}.form-check-label{margin-bottom:var(--ns-space-2, .5rem)}.form-check-input{position:relative;margin-left:unset;margin-right:var(--ns-space-1, .25rem)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
280
+ }
281
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsCheckboxComponent, decorators: [{
282
+ type: Component,
283
+ args: [{ selector: 'ns-checkbox', imports: [FormsModule], template: `
284
+ <label class="form-check-label">
285
+ <input
286
+ class="form-check-input"
287
+ [(ngModel)]="value"
288
+ type="checkbox"
289
+ (blur)="onTouched()"
290
+ [disabled]="disabled"
291
+ />
292
+ {{ label }}
293
+ </label>
294
+ `, providers: [
295
+ {
296
+ provide: NG_VALUE_ACCESSOR,
297
+ useExisting: forwardRef(() => NsCheckboxComponent),
298
+ multi: true
299
+ }
300
+ ], styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}.form-check-label{margin-bottom:var(--ns-space-2, .5rem)}.form-check-input{position:relative;margin-left:unset;margin-right:var(--ns-space-1, .25rem)}\n"] }]
301
+ }] });
302
+
303
+ function isDateSelectable(date, state) {
304
+ const { minDate, maxDate, disabled } = state;
305
+ return !(date === null ||
306
+ date === undefined ||
307
+ disabled ||
308
+ (minDate && isSameMonth(date, minDate)) ||
309
+ (maxDate && isSameMonth(date, maxDate)));
310
+ }
311
+
312
+ class NsCalendar {
313
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsCalendar, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
314
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsCalendar, providedIn: 'root', useFactory: () => new NsCalendarGregorian() });
315
+ }
316
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsCalendar, decorators: [{
317
+ type: Injectable,
318
+ args: [{ providedIn: 'root', useFactory: () => new NsCalendarGregorian() }]
319
+ }] });
320
+ class NsCalendarGregorian extends NsCalendar {
321
+ timeZone = getLocalTimeZone();
322
+ _today = today(this.timeZone);
323
+ today() {
324
+ return this._today.toString();
325
+ }
326
+ add(duration) {
327
+ return this._today.add(duration).toString();
328
+ }
329
+ subtract(duration) {
330
+ return this._today.subtract(duration).toString();
331
+ }
332
+ getFormattedMonth(date, locale) {
333
+ const formatter = new DateFormatter(locale, {
334
+ month: 'long',
335
+ year: 'numeric'
336
+ });
337
+ const segments = formatter.formatToParts(date.toDate(this.timeZone));
338
+ return `${segments[0].value} ${segments[2].value}`;
339
+ }
340
+ getWeekDays(date, weekdayStyle, locale, firstDayOfWeek) {
341
+ const weekStart = startOfWeek(date, locale, firstDayOfWeek);
342
+ const formatter = new DateFormatter(locale, {
343
+ calendar: weekStart.calendar.identifier,
344
+ weekday: weekdayStyle,
345
+ timeZone: this.timeZone
346
+ });
347
+ return [...new Array(7).keys()].map((index) => {
348
+ const date = weekStart.add({ days: index });
349
+ return formatter.format(date.toDate(this.timeZone));
350
+ });
351
+ }
352
+ getWeeksInMonth(date, locale, firstDayOfWeek) {
353
+ const weeks = [];
354
+ const weeksInMonth = getWeeksInMonth(date, locale, firstDayOfWeek);
355
+ for (let weekIndex = 0; weekIndex < weeksInMonth; weekIndex++) {
356
+ weeks.push({
357
+ number: weekIndex,
358
+ days: this.getDatesInWeek(weekIndex, date, locale, firstDayOfWeek)
359
+ });
360
+ }
361
+ return weeks;
362
+ }
363
+ getDatesInWeek(weekIndex, from, locale, firstDayOfWeek) {
364
+ let date = startOfWeek(from.add({ weeks: weekIndex }), locale, firstDayOfWeek);
365
+ const daysPerWeek = getDayOfWeek(date, locale, firstDayOfWeek);
366
+ const formatter = new DateFormatter(locale, {
367
+ month: 'numeric',
368
+ day: 'numeric',
369
+ year: 'numeric',
370
+ timeZone: this.timeZone
371
+ });
372
+ const dates = Array(daysPerWeek).fill(null);
373
+ // week has days
374
+ while (dates.length < 7) {
375
+ dates.push({
376
+ number: date.day,
377
+ date: date,
378
+ context: {
379
+ $implicit: date,
380
+ date: date,
381
+ month: date.month,
382
+ year: date.year,
383
+ disabled: false,
384
+ selected: false,
385
+ isToday: isToday(date, this.timeZone)
386
+ },
387
+ tabindex: -1,
388
+ ariaLabel: formatter.format(date.toDate(this.timeZone))
389
+ });
390
+ date = date.add({ days: 1 });
391
+ }
392
+ return dates;
393
+ }
394
+ getHoursInDay() {
395
+ return Array.from({ length: 24 }, (_, i) => i);
396
+ }
397
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsCalendarGregorian, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
398
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsCalendarGregorian });
399
+ }
400
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsCalendarGregorian, decorators: [{
401
+ type: Injectable
402
+ }] });
403
+
404
+ class NsDatepickerService {
405
+ calendar = inject(NsCalendar);
406
+ locale = inject(LOCALE_ID);
407
+ _state = {
408
+ maxDate: null,
409
+ minDate: null,
410
+ visibleMonths: 1,
411
+ startDate: null,
412
+ firstDayOfWeek: 'sun',
413
+ endDate: null,
414
+ months: [],
415
+ navigation: 'select',
416
+ weekdayStyle: 'narrow',
417
+ locale: this.locale,
418
+ weekdaysVisible: true,
419
+ disabled: false
420
+ };
421
+ _selected$ = new Subject();
422
+ get selected$() {
423
+ return this._selected$.pipe(filter((date) => date !== null));
424
+ }
425
+ _model$ = new Subject();
426
+ get model$() {
427
+ return this._model$.pipe(filter((model) => !!model.months.length));
428
+ }
429
+ today() {
430
+ return parseDate(this.calendar.today());
431
+ }
432
+ set(patch) {
433
+ if (Object.keys(patch).length > 0) {
434
+ this._nextState(patch);
435
+ }
436
+ }
437
+ getMonth(startDate) {
438
+ for (let month of this._state.months) {
439
+ if (isSameMonth(startDate, month.startDate)) {
440
+ return month;
441
+ }
442
+ }
443
+ throw new Error(`month ${startDate.month} of year ${startDate.year} not found`);
444
+ }
445
+ navigate(startDate) {
446
+ if (startDate != null && !this._state.disabled) {
447
+ this._nextState({ startDate });
448
+ }
449
+ }
450
+ select(selectedDate, options = {}) {
451
+ if (selectedDate != null && !this._state.disabled) {
452
+ if (!this._state.selectedDate ||
453
+ !isEqualDay(this._state.selectedDate, selectedDate)) {
454
+ this._nextState({ selectedDate });
455
+ }
456
+ if (options.emitEvent && isDateSelectable(selectedDate, this._state)) {
457
+ this._selected$.next(selectedDate);
458
+ }
459
+ }
460
+ }
461
+ buildMonths(date, state) {
462
+ const { visibleMonths, months: existingMonths } = state;
463
+ // ensure start date for the first month
464
+ const currentMonth = startOfMonth(date);
465
+ // move old months to a temporary array
466
+ const monthsToReuse = existingMonths.slice();
467
+ // generate new first dates, nullify or reuse months
468
+ return Array.from({ length: visibleMonths }, (_, i) => {
469
+ const startDate = currentMonth.add({ months: i });
470
+ const reusedIndex = monthsToReuse.findIndex((month) => isEqualDay(month.startDate, startDate));
471
+ if (reusedIndex !== -1) {
472
+ return monthsToReuse.splice(reusedIndex, 1)[0];
473
+ }
474
+ return this.buildMonth(startDate, state, monthsToReuse.shift() || {});
475
+ });
476
+ }
477
+ buildMonth(startDate, state, month = {}) {
478
+ const { firstDayOfWeek, weekdayStyle, locale, weekdaysVisible } = state;
479
+ month.label = this.calendar.getFormattedMonth(startDate, locale);
480
+ month.startDate = startDate;
481
+ month.endDate = endOfMonth(startDate);
482
+ month.number = startDate.month;
483
+ month.year = startDate.year;
484
+ month.weeks = month.weeks || [];
485
+ month.weekdays = [];
486
+ // month has weekdays
487
+ if (weekdaysVisible) {
488
+ month.weekdays = this.calendar.getWeekDays(month.startDate, weekdayStyle, locale, firstDayOfWeek);
489
+ }
490
+ // month has weeks
491
+ month.weeks = this.calendar.getWeeksInMonth(month.startDate, locale, firstDayOfWeek);
492
+ return month;
493
+ }
494
+ _nextState(patch) {
495
+ const newState = this._updateState(patch);
496
+ this._patchContexts(newState);
497
+ this._state = newState;
498
+ this._model$.next(this._state);
499
+ }
500
+ _updateState(patch) {
501
+ const state = Object.assign({}, this._state, patch);
502
+ let startDate = state.startDate || this.today();
503
+ // initial rebuild via 'select()'
504
+ if ('selectedDate' in patch && this._state.months.length === 0) {
505
+ startDate = startOfMonth(state.selectedDate);
506
+ }
507
+ // initial rebuild via 'navigate()'
508
+ if (startDate) {
509
+ state.months = this.buildMonths(startDate, state);
510
+ state.startDate = state.months[0].startDate;
511
+ state.endDate = state.months[state.months.length - 1].endDate;
512
+ }
513
+ return state;
514
+ }
515
+ _patchContexts(state) {
516
+ const { selectedDate, minDate, maxDate, disabled } = state;
517
+ state.months.forEach((month) => {
518
+ month.weeks.forEach((week) => {
519
+ week.days.forEach((day) => {
520
+ // patch selection flag
521
+ if (selectedDate !== undefined) {
522
+ day.context.selected =
523
+ selectedDate !== null && isEqualDay(selectedDate, day.date);
524
+ }
525
+ // disability
526
+ const isUnavailable = !isSameMonth(month.startDate, day.date);
527
+ const isNotValid = (typeof minDate !== 'undefined' && day.date.compare(minDate) < 0) ||
528
+ (typeof maxDate !== 'undefined' && day.date.compare(maxDate) > 0);
529
+ day.context.disabled = disabled || isUnavailable || isNotValid;
530
+ });
531
+ });
532
+ });
533
+ }
534
+ ensureDateValue(date) {
535
+ if (!date) {
536
+ return null;
537
+ }
538
+ if (typeof date === 'string') {
539
+ return parseDate(date);
540
+ }
541
+ if (date instanceof Date) {
542
+ return parseDate(date.toISOString());
543
+ }
544
+ return date;
545
+ }
546
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDatepickerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
547
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDatepickerService, providedIn: 'root' });
548
+ }
549
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDatepickerService, decorators: [{
550
+ type: Injectable,
551
+ args: [{ providedIn: 'root' }]
552
+ }] });
553
+
554
+ class NsDateParserFormatter {
555
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateParserFormatter, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
556
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateParserFormatter, providedIn: 'root', useFactory: () => new NsDateISOParserFormatter() });
557
+ }
558
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateParserFormatter, decorators: [{
559
+ type: Injectable,
560
+ args: [{
561
+ providedIn: 'root',
562
+ useFactory: () => new NsDateISOParserFormatter()
563
+ }]
564
+ }] });
565
+ class NsDateISOParserFormatter extends NsDateParserFormatter {
566
+ locale = inject(LOCALE_ID);
567
+ config = inject(DATE_PIPE_DEFAULT_OPTIONS, {
568
+ optional: true
569
+ });
570
+ formatter = new DateFormatter(this.locale, {
571
+ day: '2-digit',
572
+ month: 'short',
573
+ year: 'numeric'
574
+ });
575
+ timeZone = getLocalTimeZone();
576
+ defaultFormat = 'dd MMM, yyyy';
577
+ parse(value) {
578
+ return value ? parseDate(value) : null;
579
+ }
580
+ format(date) {
581
+ const dateTimeFormat = this.config?.dateFormat || this.defaultFormat;
582
+ if (!date) {
583
+ return dateTimeFormat;
584
+ }
585
+ const parts = this.formatter.formatToParts(date.toDate(this.timeZone));
586
+ const day = parts.find((p) => p.type === 'day')?.value || '';
587
+ const month = parts.find((p) => p.type === 'month')?.value || '';
588
+ const year = parts.find((p) => p.type === 'year')?.value || '';
589
+ return dateTimeFormat
590
+ .replace('dd', day)
591
+ .replace('MMM', month)
592
+ .replace('yyyy', year);
593
+ }
594
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateISOParserFormatter, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
595
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateISOParserFormatter });
596
+ }
597
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateISOParserFormatter, decorators: [{
598
+ type: Injectable
599
+ }] });
600
+
601
+ class NsDatePickerMonthComponent {
602
+ month;
603
+ service = inject(NsDatepickerService);
604
+ doSelect(day) {
605
+ if (!day.context.disabled) {
606
+ this.service.select(day.date, { emitEvent: true });
607
+ }
608
+ }
609
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDatePickerMonthComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
610
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsDatePickerMonthComponent, isStandalone: true, selector: "ns-date-picker-month", inputs: { month: "month" }, ngImport: i0, template: `
611
+ <table class="ns-date-picker__month">
612
+ <thead>
613
+ <tr>
614
+ @for (weekday of month.weekdays; track weekday) {
615
+ <th class="ns-date-picker__weekday">{{ weekday | titlecase }}</th>
616
+ }
617
+ </tr>
618
+ </thead>
619
+
620
+ <tbody>
621
+ @for (week of month.weeks; track week.number) {
622
+ <tr>
623
+ @for (day of week.days; track day.number) {
624
+ <td
625
+ [ngClass]="{
626
+ 'ns-date-picker--selected': day.context.selected,
627
+ 'ns-date-picker--disabled': day.context.disabled,
628
+ 'ns-date-picker--current': day.context.isToday
629
+ }"
630
+ >
631
+ <button
632
+ class="ns-date-picker__day"
633
+ (click)="doSelect(day)"
634
+ [disabled]="day.context.disabled"
635
+ >
636
+ {{ day.date.day }}
637
+ </button>
638
+ </td>
639
+ }
640
+ </tr>
641
+ }
642
+ </tbody>
643
+ </table>
644
+ `, isInline: true, styles: [".ns-date-picker__day{border:none;background-color:transparent;text-align:center;border-radius:.5rem;height:2rem;width:100%}.ns-date-picker__weekday{font-weight:600;text-align:center}.ns-date-picker--selected>.ns-date-picker__day{background-color:#5b5fc7;color:#fff}.ns-date-picker--current:not(.ns-date-picker--selected)>.ns-date-picker__day{border:2px solid #dcdffa;font-weight:600;color:#5b5fc7}.ns-date-picker--disabled>.ns-date-picker__day{pointer-events:none;color:#bdbdbd}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: i1$1.TitleCasePipe, name: "titlecase" }] });
645
+ }
646
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDatePickerMonthComponent, decorators: [{
647
+ type: Component,
648
+ args: [{ selector: 'ns-date-picker-month', imports: [CommonModule], template: `
649
+ <table class="ns-date-picker__month">
650
+ <thead>
651
+ <tr>
652
+ @for (weekday of month.weekdays; track weekday) {
653
+ <th class="ns-date-picker__weekday">{{ weekday | titlecase }}</th>
654
+ }
655
+ </tr>
656
+ </thead>
657
+
658
+ <tbody>
659
+ @for (week of month.weeks; track week.number) {
660
+ <tr>
661
+ @for (day of week.days; track day.number) {
662
+ <td
663
+ [ngClass]="{
664
+ 'ns-date-picker--selected': day.context.selected,
665
+ 'ns-date-picker--disabled': day.context.disabled,
666
+ 'ns-date-picker--current': day.context.isToday
667
+ }"
668
+ >
669
+ <button
670
+ class="ns-date-picker__day"
671
+ (click)="doSelect(day)"
672
+ [disabled]="day.context.disabled"
673
+ >
674
+ {{ day.date.day }}
675
+ </button>
676
+ </td>
677
+ }
678
+ </tr>
679
+ }
680
+ </tbody>
681
+ </table>
682
+ `, styles: [".ns-date-picker__day{border:none;background-color:transparent;text-align:center;border-radius:.5rem;height:2rem;width:100%}.ns-date-picker__weekday{font-weight:600;text-align:center}.ns-date-picker--selected>.ns-date-picker__day{background-color:#5b5fc7;color:#fff}.ns-date-picker--current:not(.ns-date-picker--selected)>.ns-date-picker__day{border:2px solid #dcdffa;font-weight:600;color:#5b5fc7}.ns-date-picker--disabled>.ns-date-picker__day{pointer-events:none;color:#bdbdbd}\n"] }]
683
+ }], propDecorators: { month: [{
684
+ type: Input
685
+ }] } });
686
+
687
+ class NsDatePickerNavigationComponent {
688
+ month;
689
+ service = inject(NsDatepickerService);
690
+ prev() {
691
+ this.service.navigate(this.month.startDate.subtract({ months: 1 }));
692
+ }
693
+ next() {
694
+ this.service.navigate(this.month.startDate.add({ months: 1 }));
695
+ }
696
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDatePickerNavigationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
697
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.21", type: NsDatePickerNavigationComponent, isStandalone: true, selector: "ns-date-picker-navigation", inputs: { month: "month" }, host: { properties: { "class.ns-date-picker__navigation": "true" } }, ngImport: i0, template: `
698
+ <div class="ns-date-picker__wrap">
699
+ <ns-button icon="angle-left" (click)="prev()" />
700
+ <span class="ns-date-picker__month-title">{{
701
+ month.label | titlecase
702
+ }}</span>
703
+ <ns-button icon="angle-right" (click)="next()" />
704
+ </div>
705
+ `, isInline: true, styles: [".ns-date-picker__wrap{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid #eee;padding:.5rem;margin-bottom:.5rem}.ns-date-picker__wrap::ng-deep .btn{min-width:unset;padding:unset}\n"], dependencies: [{ kind: "component", type: NsButtonComponent, selector: "ns-button", inputs: ["label", "type", "theme", "block", "disabled", "loading", "icon", "value"] }, { kind: "pipe", type: TitleCasePipe, name: "titlecase" }] });
706
+ }
707
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDatePickerNavigationComponent, decorators: [{
708
+ type: Component,
709
+ args: [{ selector: 'ns-date-picker-navigation', imports: [NsButtonComponent, TitleCasePipe], standalone: true, template: `
710
+ <div class="ns-date-picker__wrap">
711
+ <ns-button icon="angle-left" (click)="prev()" />
712
+ <span class="ns-date-picker__month-title">{{
713
+ month.label | titlecase
714
+ }}</span>
715
+ <ns-button icon="angle-right" (click)="next()" />
716
+ </div>
717
+ `, host: {
718
+ '[class.ns-date-picker__navigation]': 'true'
719
+ }, styles: [".ns-date-picker__wrap{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid #eee;padding:.5rem;margin-bottom:.5rem}.ns-date-picker__wrap::ng-deep .btn{min-width:unset;padding:unset}\n"] }]
720
+ }], propDecorators: { month: [{
721
+ type: Input
722
+ }] } });
723
+
724
+ class NsDatePickerMenuComponent {
725
+ model;
726
+ placement;
727
+ service = inject(NsDatepickerService);
728
+ set startDate(firstDate) {
729
+ this.model = this.service.getMonth(firstDate);
730
+ }
731
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDatePickerMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
732
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.21", type: NsDatePickerMenuComponent, isStandalone: true, selector: "ns-date-picker-menu", inputs: { placement: "placement", startDate: "startDate" }, host: { properties: { "class.ns-date-picker__menu": "true", "class.ns-date-picker__menu--start": "placement == \"bottom-start\"", "class.ns-date-picker__menu--end": "placement == \"bottom-end\"" } }, ngImport: i0, template: `
733
+ <ns-date-picker-navigation [month]="model" />
734
+ <ns-date-picker-month [month]="model" />
735
+ `, isInline: true, styles: [":host{position:absolute;overflow:hidden;min-width:100%;height:auto;box-sizing:border-box;z-index:1100;display:block;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;margin:.5rem 0 0;padding:.5rem}:host.ns-date-picker__menu--start{position:absolute;inset:auto auto auto 0}:host.ns-date-picker__menu--end{position:absolute;inset:auto 0 auto auto}\n"], dependencies: [{ kind: "component", type: NsDatePickerMonthComponent, selector: "ns-date-picker-month", inputs: ["month"] }, { kind: "component", type: NsDatePickerNavigationComponent, selector: "ns-date-picker-navigation", inputs: ["month"] }] });
736
+ }
737
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDatePickerMenuComponent, decorators: [{
738
+ type: Component,
739
+ args: [{ selector: 'ns-date-picker-menu', standalone: true, imports: [NsDatePickerMonthComponent, NsDatePickerNavigationComponent], template: `
740
+ <ns-date-picker-navigation [month]="model" />
741
+ <ns-date-picker-month [month]="model" />
742
+ `, host: {
743
+ '[class.ns-date-picker__menu]': 'true',
744
+ '[class.ns-date-picker__menu--start]': 'placement == "bottom-start"',
745
+ '[class.ns-date-picker__menu--end]': 'placement == "bottom-end"'
746
+ }, styles: [":host{position:absolute;overflow:hidden;min-width:100%;height:auto;box-sizing:border-box;z-index:1100;display:block;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem;margin:.5rem 0 0;padding:.5rem}:host.ns-date-picker__menu--start{position:absolute;inset:auto auto auto 0}:host.ns-date-picker__menu--end{position:absolute;inset:auto 0 auto auto}\n"] }]
747
+ }], propDecorators: { placement: [{
748
+ type: Input
749
+ }], startDate: [{
750
+ type: Input
751
+ }] } });
752
+
753
+ class NsDropdownItemDirective {
754
+ label;
755
+ value;
756
+ disabled = false;
757
+ constructor() { }
758
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDropdownItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
759
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.21", type: NsDropdownItemDirective, isStandalone: true, selector: "ns-dropdown-item", inputs: { label: "label", value: "value", disabled: "disabled" }, ngImport: i0 });
760
+ }
761
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDropdownItemDirective, decorators: [{
762
+ type: Directive,
763
+ args: [{
764
+ selector: 'ns-dropdown-item'
765
+ }]
766
+ }], ctorParameters: () => [], propDecorators: { label: [{
767
+ type: Input
768
+ }], value: [{
769
+ type: Input
770
+ }], disabled: [{
771
+ type: Input
772
+ }] } });
773
+
774
+ class NsDropdownComponent extends NsValueAccessor {
775
+ labelField = 'label';
776
+ valueField = 'value';
777
+ iconName;
778
+ defaultFirst;
779
+ placement = 'start';
780
+ filterable;
781
+ searchRef;
782
+ items;
783
+ show = false;
784
+ _filtered;
785
+ _collection = [];
786
+ _search;
787
+ constructor() {
788
+ super();
789
+ }
790
+ ngOnInit() { }
791
+ ngAfterContentInit() {
792
+ if (!this.collection.length && !!this.items) {
793
+ this.collection = this.items.toArray().map((item) => ({
794
+ label: item.label,
795
+ value: item.value,
796
+ disabled: item.disabled
797
+ }));
798
+ }
799
+ }
800
+ set collection(source) {
801
+ this._collection = this._filtered = source;
802
+ }
803
+ get collection() {
804
+ return this.filterable ? this._filtered : this._collection;
805
+ }
806
+ get selected() {
807
+ return this.collection.find((item) => item[this.valueField] == this.value);
808
+ }
809
+ set search(value) {
810
+ this._search = value;
811
+ this._filtered = this._collection.filter((item) => String(item[this.labelField]).toLowerCase().includes(value.toLowerCase()));
812
+ this.show = !!value;
813
+ }
814
+ get search() {
815
+ return this._search;
816
+ }
817
+ select(item) {
818
+ const value = item[this.valueField];
819
+ if (typeof value === 'string' || typeof value === 'number') {
820
+ this.value = value;
821
+ }
822
+ }
823
+ toggle(event) {
824
+ event.preventDefault();
825
+ if (!this.disabled) {
826
+ this.show = !this.show;
827
+ if (this.filterable) {
828
+ if (this.show) {
829
+ this.searchRef.nativeElement.focus();
830
+ }
831
+ else {
832
+ this._search = '';
833
+ this._filtered = this._collection;
834
+ }
835
+ }
836
+ }
837
+ }
838
+ keyDown(event) {
839
+ if (this.show) {
840
+ let index = this.selected
841
+ ? this.collection.findIndex((item) => this.selected[this.valueField] === item[this.valueField])
842
+ : -1;
843
+ switch (event.key) {
844
+ case 'ArrowUp':
845
+ if (index >= 1) {
846
+ this.value = String(this.collection[--index][this.valueField]);
847
+ }
848
+ break;
849
+ case 'ArrowDown':
850
+ if (index < this.collection.length - 1) {
851
+ this.value = String(this.collection[++index][this.valueField]);
852
+ }
853
+ break;
854
+ case 'Enter':
855
+ event.preventDefault();
856
+ this._search = '';
857
+ this.show = false;
858
+ }
859
+ }
860
+ else if (event.key == 'Enter') {
861
+ event.preventDefault();
862
+ this._search = '';
863
+ this._filtered = this._collection;
864
+ this.show = true;
865
+ }
866
+ }
867
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
868
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsDropdownComponent, isStandalone: true, selector: "ns-dropdown", inputs: { labelField: "labelField", valueField: "valueField", iconName: "iconName", defaultFirst: "defaultFirst", placement: "placement", filterable: "filterable", collection: "collection" }, host: { listeners: { "click": "toggle($event)", "keydown": "keyDown($event)" }, properties: { "class.dropdown": "true", "class.ns-dropdown__filterable": "filterable", "class.show": "show" } }, providers: [
869
+ {
870
+ provide: NG_VALUE_ACCESSOR,
871
+ useExisting: forwardRef(() => NsDropdownComponent),
872
+ multi: true
873
+ }
874
+ ], queries: [{ propertyName: "items", predicate: NsDropdownItemDirective }], viewQueries: [{ propertyName: "searchRef", first: true, predicate: ["input"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "@if (label) {\n <label class=\"form-label\" [attr.for]=\"id\">{{ label }}</label>\n}\n@if (filterable) {\n <div class=\"ns-dropdown__search\" [class.disabled]=\"disabled\">\n <div\n class=\"ns-dropdown__value\"\n [ngClass]=\"{ 'ns-dropdown__placeholder': !selected || show }\"\n [hidden]=\"!!search\"\n >\n <span class=\"ns-dropdown__value-label\">\n {{ !!selected ? selected[labelField] : placeholder }}\n </span>\n </div>\n\n <div class=\"ns-dropdown__input\">\n <input\n class=\"form-control\"\n [(ngModel)]=\"search\"\n #input\n [disabled]=\"disabled\"\n [id]=\"id\"\n />\n </div>\n\n <svg\n class=\"dropdown-toggle\"\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n height=\"12px\"\n width=\"12px\"\n >\n <path\n d=\"M14,11.75a.74.74,0,0,1-.53-.22L8,6.06,2.53,11.53a.75.75,0,0,1-1.06-1.06l6-6a.75.75,0,0,1,1.06,0l6,6a.75.75,0,0,1,0,1.06A.74.74,0,0,1,14,11.75Z\"\n ></path>\n </svg>\n </div>\n} @else {\n <button\n class=\"btn btn__secondary\"\n [id]=\"id\"\n type=\"button\"\n [disabled]=\"disabled\"\n >\n @if (iconName) {\n <ns-icon [name]=\"iconName\" [size]=\"16\" />\n }\n @if (placeholder && selected) {\n <label class=\"form-label\">\n {{ placeholder }}: <span [innerHtml]=\"selected[labelField]\"></span>\n </label>\n } @else {\n <label\n class=\"form-label\"\n [innerHtml]=\"!!selected ? selected[labelField] : placeholder\"\n ></label>\n }\n\n <svg\n class=\"dropdown-toggle\"\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n height=\"12px\"\n width=\"12px\"\n >\n <path\n d=\"M14,11.75a.74.74,0,0,1-.53-.22L8,6.06,2.53,11.53a.75.75,0,0,1-1.06-1.06l6-6a.75.75,0,0,1,1.06,0l6,6a.75.75,0,0,1,0,1.06A.74.74,0,0,1,14,11.75Z\"\n ></path>\n </svg>\n </button>\n}\n\n<ul\n class=\"dropdown-menu\"\n [attr.aria-labelledby]=\"id\"\n [ngClass]=\"{\n show: show,\n 'dropdown-start': placement !== 'end',\n 'dropdown-end': placement == 'end'\n }\"\n (mouseleave)=\"show = false\"\n>\n @for (item of collection; track item) {\n <li>\n <button\n class=\"dropdown-item\"\n [ngClass]=\"{ active: selected === item }\"\n (click)=\"select(item)\"\n >\n <svg\n class=\"icon-check-mark\"\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n height=\"16px\"\n width=\"16px\"\n >\n <path\n d=\"M6.19,14.51a.77.77,0,0,1-.57-.25l-4.2-4.8a.75.75,0,0,1,1.13-1l3.56,4.06L13.36,1.82a.75.75,0,0,1,1-.21.76.76,0,0,1,.21,1.05L6.81,14.18a.73.73,0,0,1-.58.33Z\"\n ></path>\n </svg>\n <span>{{ item[labelField] }}</span>\n </button>\n </li>\n }\n @if (!collection?.length) {\n <button class=\"dropdown-item\">\n <span>No items found</span>\n </button>\n }\n</ul>\n", styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}:host.show .dropdown-toggle{transform:rotate(0)}.btn{display:block;position:relative;border-radius:var(--ns-border-radius, .375rem);vertical-align:center;text-align:center;text-transform:none;font-size:.875rem;line-height:1rem;outline:none;white-space:nowrap;padding:var(--ns-btn-padding-y, .5rem) var(--ns-btn-padding-x, 1rem);cursor:pointer}.btn:disabled{pointer-events:none}.btn{display:flex;justify-content:flex-start;align-items:center;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);width:100%}.btn__secondary{color:var(--ns-color-foreground, #1f2937);background-color:var(--ns-color-surface, #fff);min-width:var(--ns-btn-min-width, 5rem);border:1px solid var(--ns-color-border, rgb(219, 214, 225))}.btn__secondary:focus,.btn__secondary:active{color:var(--ns-color-foreground, #1f2937);border:1px solid var(--ns-color-border, rgb(219, 214, 225));box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__secondary:hover{background-color:var(--ns-color-surface-muted, rgba(9, 30, 66, .08))}.btn__secondary{background-color:var(--ns-color-surface, #fff);border:1px solid var(--ns-color-border, #cfcfdb)}.btn__secondary:hover{background-color:var(--ns-color-surface, #fff)}.btn .form-label{text-overflow:ellipsis;overflow:hidden;margin-bottom:unset;font-weight:600}.btn .form-label span{font-weight:400}.btn:disabled{background-color:var(--ns-color-surface-muted, #e9ecef)}.ns-dropdown__search{display:flex;position:relative;flex:1;overflow:hidden;text-overflow:ellipsis;padding-left:10px;padding-right:10px;align-items:center;height:36px}.ns-dropdown__search.disabled{pointer-events:none}.ns-dropdown__search.disabled .ns-dropdown__value-label{opacity:.65}.ns-dropdown__placeholder{color:var(--ns-gray-400, #bdbed4)}.ns-dropdown__value{display:flex;align-items:center;font-weight:600;font-size:.875rem;z-index:1001}.ns-dropdown__input{position:absolute;left:0;width:100%}.ns-dropdown__input .form-control{margin-bottom:unset}.dropdown-menu{min-width:100%;overflow:hidden;overflow-y:auto;position:relative;height:auto;box-sizing:border-box;max-height:240px;z-index:1100;margin-top:.5rem}.dropdown-menu li{position:static;margin:0;padding:0 4px}.dropdown-toggle{margin-left:auto;transform:rotate(180deg);transition:transform .2s ease-in-out 0s;flex-shrink:0}.dropdown-item{display:flex;position:relative;border-radius:4px;box-sizing:border-box;align-items:center;z-index:1}.dropdown-item .icon-check-mark{opacity:0;margin:0 .35rem 0 -.35rem}.dropdown-item.active,.dropdown-item:hover{color:initial;background:var(--ns-color-surface-muted, rgba(108, 96, 199, .08))}.dropdown-item.active{color:var(--ns-color-primary, #584ac0)}.dropdown-item.active .icon-check-mark{opacity:1}.dropdown-item span{line-height:1.4;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:100%}.dropdown-start{position:absolute;inset:auto auto auto 0}.dropdown-end{position:absolute;inset:auto 0 auto auto}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NsIconsComponent, selector: "ns-icon", inputs: ["name", "color", "size", "strokeWidth", "viewBox"] }] });
875
+ }
876
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDropdownComponent, decorators: [{
877
+ type: Component,
878
+ args: [{ selector: 'ns-dropdown', host: {
879
+ '[class.dropdown]': 'true',
880
+ '[class.ns-dropdown__filterable]': 'filterable',
881
+ '[class.show]': 'show'
882
+ }, providers: [
883
+ {
884
+ provide: NG_VALUE_ACCESSOR,
885
+ useExisting: forwardRef(() => NsDropdownComponent),
886
+ multi: true
887
+ }
888
+ ], imports: [NgClass, FormsModule, NsIconsComponent], template: "@if (label) {\n <label class=\"form-label\" [attr.for]=\"id\">{{ label }}</label>\n}\n@if (filterable) {\n <div class=\"ns-dropdown__search\" [class.disabled]=\"disabled\">\n <div\n class=\"ns-dropdown__value\"\n [ngClass]=\"{ 'ns-dropdown__placeholder': !selected || show }\"\n [hidden]=\"!!search\"\n >\n <span class=\"ns-dropdown__value-label\">\n {{ !!selected ? selected[labelField] : placeholder }}\n </span>\n </div>\n\n <div class=\"ns-dropdown__input\">\n <input\n class=\"form-control\"\n [(ngModel)]=\"search\"\n #input\n [disabled]=\"disabled\"\n [id]=\"id\"\n />\n </div>\n\n <svg\n class=\"dropdown-toggle\"\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n height=\"12px\"\n width=\"12px\"\n >\n <path\n d=\"M14,11.75a.74.74,0,0,1-.53-.22L8,6.06,2.53,11.53a.75.75,0,0,1-1.06-1.06l6-6a.75.75,0,0,1,1.06,0l6,6a.75.75,0,0,1,0,1.06A.74.74,0,0,1,14,11.75Z\"\n ></path>\n </svg>\n </div>\n} @else {\n <button\n class=\"btn btn__secondary\"\n [id]=\"id\"\n type=\"button\"\n [disabled]=\"disabled\"\n >\n @if (iconName) {\n <ns-icon [name]=\"iconName\" [size]=\"16\" />\n }\n @if (placeholder && selected) {\n <label class=\"form-label\">\n {{ placeholder }}: <span [innerHtml]=\"selected[labelField]\"></span>\n </label>\n } @else {\n <label\n class=\"form-label\"\n [innerHtml]=\"!!selected ? selected[labelField] : placeholder\"\n ></label>\n }\n\n <svg\n class=\"dropdown-toggle\"\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n height=\"12px\"\n width=\"12px\"\n >\n <path\n d=\"M14,11.75a.74.74,0,0,1-.53-.22L8,6.06,2.53,11.53a.75.75,0,0,1-1.06-1.06l6-6a.75.75,0,0,1,1.06,0l6,6a.75.75,0,0,1,0,1.06A.74.74,0,0,1,14,11.75Z\"\n ></path>\n </svg>\n </button>\n}\n\n<ul\n class=\"dropdown-menu\"\n [attr.aria-labelledby]=\"id\"\n [ngClass]=\"{\n show: show,\n 'dropdown-start': placement !== 'end',\n 'dropdown-end': placement == 'end'\n }\"\n (mouseleave)=\"show = false\"\n>\n @for (item of collection; track item) {\n <li>\n <button\n class=\"dropdown-item\"\n [ngClass]=\"{ active: selected === item }\"\n (click)=\"select(item)\"\n >\n <svg\n class=\"icon-check-mark\"\n viewBox=\"0 0 16 16\"\n fill=\"currentColor\"\n height=\"16px\"\n width=\"16px\"\n >\n <path\n d=\"M6.19,14.51a.77.77,0,0,1-.57-.25l-4.2-4.8a.75.75,0,0,1,1.13-1l3.56,4.06L13.36,1.82a.75.75,0,0,1,1-.21.76.76,0,0,1,.21,1.05L6.81,14.18a.73.73,0,0,1-.58.33Z\"\n ></path>\n </svg>\n <span>{{ item[labelField] }}</span>\n </button>\n </li>\n }\n @if (!collection?.length) {\n <button class=\"dropdown-item\">\n <span>No items found</span>\n </button>\n }\n</ul>\n", styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}:host.show .dropdown-toggle{transform:rotate(0)}.btn{display:block;position:relative;border-radius:var(--ns-border-radius, .375rem);vertical-align:center;text-align:center;text-transform:none;font-size:.875rem;line-height:1rem;outline:none;white-space:nowrap;padding:var(--ns-btn-padding-y, .5rem) var(--ns-btn-padding-x, 1rem);cursor:pointer}.btn:disabled{pointer-events:none}.btn{display:flex;justify-content:flex-start;align-items:center;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);width:100%}.btn__secondary{color:var(--ns-color-foreground, #1f2937);background-color:var(--ns-color-surface, #fff);min-width:var(--ns-btn-min-width, 5rem);border:1px solid var(--ns-color-border, rgb(219, 214, 225))}.btn__secondary:focus,.btn__secondary:active{color:var(--ns-color-foreground, #1f2937);border:1px solid var(--ns-color-border, rgb(219, 214, 225));box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__secondary:hover{background-color:var(--ns-color-surface-muted, rgba(9, 30, 66, .08))}.btn__secondary{background-color:var(--ns-color-surface, #fff);border:1px solid var(--ns-color-border, #cfcfdb)}.btn__secondary:hover{background-color:var(--ns-color-surface, #fff)}.btn .form-label{text-overflow:ellipsis;overflow:hidden;margin-bottom:unset;font-weight:600}.btn .form-label span{font-weight:400}.btn:disabled{background-color:var(--ns-color-surface-muted, #e9ecef)}.ns-dropdown__search{display:flex;position:relative;flex:1;overflow:hidden;text-overflow:ellipsis;padding-left:10px;padding-right:10px;align-items:center;height:36px}.ns-dropdown__search.disabled{pointer-events:none}.ns-dropdown__search.disabled .ns-dropdown__value-label{opacity:.65}.ns-dropdown__placeholder{color:var(--ns-gray-400, #bdbed4)}.ns-dropdown__value{display:flex;align-items:center;font-weight:600;font-size:.875rem;z-index:1001}.ns-dropdown__input{position:absolute;left:0;width:100%}.ns-dropdown__input .form-control{margin-bottom:unset}.dropdown-menu{min-width:100%;overflow:hidden;overflow-y:auto;position:relative;height:auto;box-sizing:border-box;max-height:240px;z-index:1100;margin-top:.5rem}.dropdown-menu li{position:static;margin:0;padding:0 4px}.dropdown-toggle{margin-left:auto;transform:rotate(180deg);transition:transform .2s ease-in-out 0s;flex-shrink:0}.dropdown-item{display:flex;position:relative;border-radius:4px;box-sizing:border-box;align-items:center;z-index:1}.dropdown-item .icon-check-mark{opacity:0;margin:0 .35rem 0 -.35rem}.dropdown-item.active,.dropdown-item:hover{color:initial;background:var(--ns-color-surface-muted, rgba(108, 96, 199, .08))}.dropdown-item.active{color:var(--ns-color-primary, #584ac0)}.dropdown-item.active .icon-check-mark{opacity:1}.dropdown-item span{line-height:1.4;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:100%}.dropdown-start{position:absolute;inset:auto auto auto 0}.dropdown-end{position:absolute;inset:auto 0 auto auto}\n"] }]
889
+ }], ctorParameters: () => [], propDecorators: { labelField: [{
890
+ type: Input
891
+ }], valueField: [{
892
+ type: Input
893
+ }], iconName: [{
894
+ type: Input
895
+ }], defaultFirst: [{
896
+ type: Input
897
+ }], placement: [{
898
+ type: Input
899
+ }], filterable: [{
900
+ type: Input
901
+ }], searchRef: [{
902
+ type: ViewChild,
903
+ args: ['input', { read: ElementRef }]
904
+ }], items: [{
905
+ type: ContentChildren,
906
+ args: [NsDropdownItemDirective]
907
+ }], collection: [{
908
+ type: Input
909
+ }], toggle: [{
910
+ type: HostListener,
911
+ args: ['click', ['$event']]
912
+ }], keyDown: [{
913
+ type: HostListener,
914
+ args: ['keydown', ['$event']]
915
+ }] } });
916
+
917
+ class NsDatePickerComponent extends NsValueAccessor {
918
+ model;
919
+ service = inject(NsDatepickerService);
920
+ parserFormatter = inject(NsDateParserFormatter);
921
+ elRef = inject((ElementRef));
922
+ appRef = inject(ApplicationRef);
923
+ cdRef = inject(ChangeDetectorRef);
924
+ destroyRef = inject(DestroyRef);
925
+ injector = inject(EnvironmentInjector);
926
+ ngZone = inject(NgZone);
927
+ document = inject(DOCUMENT);
928
+ autoClose = true;
929
+ placement = 'bottom-start';
930
+ view;
931
+ visibleMonths = 1;
932
+ firstDayOfWeek = 'sun';
933
+ maxDate;
934
+ minDate;
935
+ navigation = 'select';
936
+ weekdayStyle = 'short';
937
+ controlValue;
938
+ popupRef = null;
939
+ destroyCloseHandlers$ = new Subject();
940
+ ngOnInit() {
941
+ if (this.model === undefined) {
942
+ const inputs = {};
943
+ [
944
+ 'visibleMonths',
945
+ 'firstDayOfWeek',
946
+ 'navigation',
947
+ 'minDate',
948
+ 'maxDate',
949
+ 'weekdayStyle'
950
+ ].forEach((name) => (inputs[name] = this[name]));
951
+ this.service.set(inputs);
952
+ }
953
+ this.service.selected$
954
+ .pipe(takeUntilDestroyed(this.destroyRef))
955
+ .subscribe((date) => {
956
+ this._value = this.parserFormatter.format(date);
957
+ this.onChange(date.toString());
958
+ if (this.autoClose === true || this.autoClose === 'inside') {
959
+ this.close();
960
+ }
961
+ this.cdRef.markForCheck();
962
+ });
963
+ this.service.model$
964
+ .pipe(takeUntilDestroyed(this.destroyRef))
965
+ .subscribe((model) => {
966
+ this.model = model;
967
+ this.cdRef.markForCheck();
968
+ });
969
+ }
970
+ writeValue(value) {
971
+ this.controlValue = this.service.ensureDateValue(value);
972
+ this._value = this.parserFormatter.format(this.controlValue);
973
+ }
974
+ isOpen() {
975
+ return !!this.popupRef;
976
+ }
977
+ toggleCalendar() {
978
+ if (this.isOpen()) {
979
+ this.close();
980
+ }
981
+ else {
982
+ this.open();
983
+ }
984
+ }
985
+ open() {
986
+ if (!this.isOpen()) {
987
+ this.popupRef = this._createComponent(NsDatePickerMenuComponent);
988
+ this.appRef.attachView(this.popupRef.hostView);
989
+ this.elRef.nativeElement.appendChild(this.popupRef.location.nativeElement);
990
+ this._applyDatepickerInputs(this.popupRef);
991
+ this._setCloseHandlers();
992
+ this.popupRef.changeDetectorRef.detectChanges();
993
+ }
994
+ }
995
+ _createComponent(component) {
996
+ return createComponent(component, {
997
+ environmentInjector: this.injector,
998
+ elementInjector: Injector.create({
999
+ providers: [
1000
+ {
1001
+ provide: NsDatepickerService,
1002
+ useFactory: () => this.service
1003
+ }
1004
+ ]
1005
+ })
1006
+ });
1007
+ }
1008
+ _applyDatepickerInputs(menuRef) {
1009
+ menuRef.setInput('startDate', this.model?.startDate || this.service.today());
1010
+ menuRef.setInput('placement', this.placement);
1011
+ }
1012
+ close() {
1013
+ if (this.isOpen()) {
1014
+ this.elRef.nativeElement.removeChild(this.popupRef.location.nativeElement);
1015
+ this.popupRef?.destroy();
1016
+ this.popupRef = null;
1017
+ this.destroyCloseHandlers$.next();
1018
+ this.cdRef.markForCheck();
1019
+ }
1020
+ }
1021
+ _setCloseHandlers() {
1022
+ const popupRef = this.popupRef;
1023
+ if (!popupRef) {
1024
+ return;
1025
+ }
1026
+ nsAutoClose(this.ngZone, this.document, this.autoClose, () => this.close(), this.destroyCloseHandlers$, [], [this.elRef.nativeElement, popupRef.location.nativeElement]);
1027
+ }
1028
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDatePickerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1029
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsDatePickerComponent, isStandalone: true, selector: "ns-date-picker", inputs: { autoClose: "autoClose", placement: "placement", view: "view", visibleMonths: "visibleMonths", firstDayOfWeek: "firstDayOfWeek", maxDate: "maxDate", minDate: "minDate", navigation: "navigation", weekdayStyle: "weekdayStyle" }, host: { properties: { "class.ns-date-picker": "true", "class.ns-date-picker--show": "isOpen()" } }, providers: [
1030
+ {
1031
+ provide: NG_VALUE_ACCESSOR,
1032
+ useExisting: forwardRef(() => NsDatePickerComponent),
1033
+ multi: true
1034
+ },
1035
+ NsDatepickerService
1036
+ ], usesInheritance: true, ngImport: i0, template: `
1037
+ @if (label) {
1038
+ <label class="form-label" [attr.for]="id">{{ label }}</label>
1039
+ }
1040
+
1041
+ <div class="row">
1042
+ <div class="col-md-8">
1043
+ <div class="form-control" (click)="toggleCalendar()">
1044
+ <ns-icon name="calendar" size="18" />
1045
+
1046
+ <input
1047
+ type="text"
1048
+ class="ns-date-picker__input"
1049
+ readonly
1050
+ [ngModel]="value"
1051
+ [attr.id]="id"
1052
+ [attr.placeholder]="placeholder"
1053
+ [disabled]="disabled"
1054
+ (blur)="onTouched()"
1055
+ #input
1056
+ />
1057
+ </div>
1058
+ </div>
1059
+
1060
+ <div class="col-md-4">
1061
+ <ns-dropdown iconName="clock">
1062
+ <ns-dropdown-item label="12:00 AM" value="0" />
1063
+ </ns-dropdown>
1064
+ </div>
1065
+ </div>
1066
+ `, isInline: true, styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}:host{max-width:15rem}:host.ns-date-picker--show>.form-control{border-color:#567af0;box-shadow:unset;outline:0}.form-control{display:flex;position:relative;align-items:center;gap:.2rem}.btn{font-weight:500}.btn:focus{box-shadow:none}.btn:focus:not(:focus-visible){outline:none}.btn:disabled{background-color:#e9ecef}.ns-date-picker__input{appearance:none;border:none;width:100%;outline:none}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NsIconsComponent, selector: "ns-icon", inputs: ["name", "color", "size", "strokeWidth", "viewBox"] }, { kind: "component", type: NsDropdownComponent, selector: "ns-dropdown", inputs: ["labelField", "valueField", "iconName", "defaultFirst", "placement", "filterable", "collection"] }, { kind: "directive", type: NsDropdownItemDirective, selector: "ns-dropdown-item", inputs: ["label", "value", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1067
+ }
1068
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDatePickerComponent, decorators: [{
1069
+ type: Component,
1070
+ args: [{ selector: 'ns-date-picker', imports: [
1071
+ FormsModule,
1072
+ NsIconsComponent,
1073
+ NsDropdownComponent,
1074
+ NsDropdownItemDirective
1075
+ ], standalone: true, template: `
1076
+ @if (label) {
1077
+ <label class="form-label" [attr.for]="id">{{ label }}</label>
1078
+ }
1079
+
1080
+ <div class="row">
1081
+ <div class="col-md-8">
1082
+ <div class="form-control" (click)="toggleCalendar()">
1083
+ <ns-icon name="calendar" size="18" />
1084
+
1085
+ <input
1086
+ type="text"
1087
+ class="ns-date-picker__input"
1088
+ readonly
1089
+ [ngModel]="value"
1090
+ [attr.id]="id"
1091
+ [attr.placeholder]="placeholder"
1092
+ [disabled]="disabled"
1093
+ (blur)="onTouched()"
1094
+ #input
1095
+ />
1096
+ </div>
1097
+ </div>
1098
+
1099
+ <div class="col-md-4">
1100
+ <ns-dropdown iconName="clock">
1101
+ <ns-dropdown-item label="12:00 AM" value="0" />
1102
+ </ns-dropdown>
1103
+ </div>
1104
+ </div>
1105
+ `, host: {
1106
+ '[class.ns-date-picker]': 'true',
1107
+ '[class.ns-date-picker--show]': 'isOpen()'
1108
+ }, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
1109
+ {
1110
+ provide: NG_VALUE_ACCESSOR,
1111
+ useExisting: forwardRef(() => NsDatePickerComponent),
1112
+ multi: true
1113
+ },
1114
+ NsDatepickerService
1115
+ ], styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}:host{max-width:15rem}:host.ns-date-picker--show>.form-control{border-color:#567af0;box-shadow:unset;outline:0}.form-control{display:flex;position:relative;align-items:center;gap:.2rem}.btn{font-weight:500}.btn:focus{box-shadow:none}.btn:focus:not(:focus-visible){outline:none}.btn:disabled{background-color:#e9ecef}.ns-date-picker__input{appearance:none;border:none;width:100%;outline:none}\n"] }]
1116
+ }], propDecorators: { autoClose: [{
1117
+ type: Input
1118
+ }], placement: [{
1119
+ type: Input
1120
+ }], view: [{
1121
+ type: Input
1122
+ }], visibleMonths: [{
1123
+ type: Input
1124
+ }], firstDayOfWeek: [{
1125
+ type: Input
1126
+ }], maxDate: [{
1127
+ type: Input
1128
+ }], minDate: [{
1129
+ type: Input
1130
+ }], navigation: [{
1131
+ type: Input
1132
+ }], weekdayStyle: [{
1133
+ type: Input
1134
+ }] } });
1135
+
1136
+ class NsDateRangeStartDirective extends NsValueAccessor {
1137
+ parserFormatter = inject(NsDateParserFormatter);
1138
+ writeValue(value) {
1139
+ const nsDate = this.parserFormatter.parse(value);
1140
+ this._value = this.parserFormatter.format(nsDate);
1141
+ }
1142
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateRangeStartDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1143
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.21", type: NsDateRangeStartDirective, isStandalone: true, selector: "ns-date-range-start", providers: [
1144
+ {
1145
+ provide: NG_VALUE_ACCESSOR,
1146
+ useExisting: forwardRef(() => NsDateRangeStartDirective),
1147
+ multi: true
1148
+ }
1149
+ ], usesInheritance: true, ngImport: i0 });
1150
+ }
1151
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateRangeStartDirective, decorators: [{
1152
+ type: Directive,
1153
+ args: [{
1154
+ selector: 'ns-date-range-start',
1155
+ standalone: true,
1156
+ providers: [
1157
+ {
1158
+ provide: NG_VALUE_ACCESSOR,
1159
+ useExisting: forwardRef(() => NsDateRangeStartDirective),
1160
+ multi: true
1161
+ }
1162
+ ]
1163
+ }]
1164
+ }] });
1165
+ class NsDateRangeEndDirective extends NsValueAccessor {
1166
+ parserFormatter = inject(NsDateParserFormatter);
1167
+ writeValue(value) {
1168
+ const nsDate = this.parserFormatter.parse(value);
1169
+ this._value = this.parserFormatter.format(nsDate);
1170
+ }
1171
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateRangeEndDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive });
1172
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.21", type: NsDateRangeEndDirective, isStandalone: true, selector: "ns-date-range-end", providers: [
1173
+ {
1174
+ provide: NG_VALUE_ACCESSOR,
1175
+ useExisting: forwardRef(() => NsDateRangeEndDirective),
1176
+ multi: true
1177
+ }
1178
+ ], usesInheritance: true, ngImport: i0 });
1179
+ }
1180
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateRangeEndDirective, decorators: [{
1181
+ type: Directive,
1182
+ args: [{
1183
+ selector: 'ns-date-range-end',
1184
+ standalone: true,
1185
+ providers: [
1186
+ {
1187
+ provide: NG_VALUE_ACCESSOR,
1188
+ useExisting: forwardRef(() => NsDateRangeEndDirective),
1189
+ multi: true
1190
+ }
1191
+ ]
1192
+ }]
1193
+ }] });
1194
+
1195
+ class NsDateRangePickerComponent {
1196
+ placeholder;
1197
+ start;
1198
+ end;
1199
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateRangePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1200
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsDateRangePickerComponent, isStandalone: true, selector: "ns-date-range", inputs: { placeholder: "placeholder" }, host: { properties: { "class.ns-date-range": "true" } }, queries: [{ propertyName: "start", first: true, predicate: NsDateRangeStartDirective, descendants: true }, { propertyName: "end", first: true, predicate: NsDateRangeEndDirective, descendants: true }], ngImport: i0, template: `
1201
+ <div class="ns-date-range__wrap">
1202
+ @if (start) {
1203
+ <ns-date-picker
1204
+ [label]="start.label"
1205
+ [placeholder]="placeholder"
1206
+ [(ngModel)]="start.value"
1207
+ />
1208
+ }
1209
+ @if (end) {
1210
+ <ns-date-picker
1211
+ [label]="end.label"
1212
+ [placeholder]="placeholder"
1213
+ [(ngModel)]="end.value"
1214
+ />
1215
+ }
1216
+ </div>
1217
+ `, isInline: true, styles: [":host{display:block;position:relative;max-width:30rem}.ns-date-range__wrap{display:grid;grid-template-columns:1fr 1fr;column-gap:1rem}\n"], dependencies: [{ kind: "component", type: NsDatePickerComponent, selector: "ns-date-picker", inputs: ["autoClose", "placement", "view", "visibleMonths", "firstDayOfWeek", "maxDate", "minDate", "navigation", "weekdayStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
1218
+ }
1219
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsDateRangePickerComponent, decorators: [{
1220
+ type: Component,
1221
+ args: [{ selector: 'ns-date-range', standalone: true, imports: [NsDatePickerComponent, FormsModule], template: `
1222
+ <div class="ns-date-range__wrap">
1223
+ @if (start) {
1224
+ <ns-date-picker
1225
+ [label]="start.label"
1226
+ [placeholder]="placeholder"
1227
+ [(ngModel)]="start.value"
1228
+ />
1229
+ }
1230
+ @if (end) {
1231
+ <ns-date-picker
1232
+ [label]="end.label"
1233
+ [placeholder]="placeholder"
1234
+ [(ngModel)]="end.value"
1235
+ />
1236
+ }
1237
+ </div>
1238
+ `, host: {
1239
+ '[class.ns-date-range]': 'true'
1240
+ }, styles: [":host{display:block;position:relative;max-width:30rem}.ns-date-range__wrap{display:grid;grid-template-columns:1fr 1fr;column-gap:1rem}\n"] }]
1241
+ }], propDecorators: { placeholder: [{
1242
+ type: Input
1243
+ }], start: [{
1244
+ type: ContentChild,
1245
+ args: [NsDateRangeStartDirective]
1246
+ }], end: [{
1247
+ type: ContentChild,
1248
+ args: [NsDateRangeEndDirective]
1249
+ }] } });
1250
+
1251
+ class NsInputComponent extends NsValueAccessor {
1252
+ prepend;
1253
+ append;
1254
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsInputComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1255
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsInputComponent, isStandalone: true, selector: "ns-input", inputs: { prepend: "prepend", append: "append" }, providers: [
1256
+ {
1257
+ provide: NG_VALUE_ACCESSOR,
1258
+ useExisting: forwardRef(() => NsInputComponent),
1259
+ multi: true
1260
+ }
1261
+ ], usesInheritance: true, ngImport: i0, template: "@if (label) {\n <label class=\"form-label\" [attr.for]=\"id\">{{ label }}</label>\n}\n\n<input\n [(ngModel)]=\"value\"\n class=\"form-control\"\n [attr.id]=\"id\"\n [type]=\"type\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [attr.readonly]=\"readonly\"\n (blur)=\"onTouched()\"\n/>\n", styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
1262
+ }
1263
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsInputComponent, decorators: [{
1264
+ type: Component,
1265
+ args: [{ selector: 'ns-input', providers: [
1266
+ {
1267
+ provide: NG_VALUE_ACCESSOR,
1268
+ useExisting: forwardRef(() => NsInputComponent),
1269
+ multi: true
1270
+ }
1271
+ ], imports: [FormsModule], template: "@if (label) {\n <label class=\"form-label\" [attr.for]=\"id\">{{ label }}</label>\n}\n\n<input\n [(ngModel)]=\"value\"\n class=\"form-control\"\n [attr.id]=\"id\"\n [type]=\"type\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [attr.readonly]=\"readonly\"\n (blur)=\"onTouched()\"\n/>\n", styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}\n"] }]
1272
+ }], propDecorators: { prepend: [{
1273
+ type: Input
1274
+ }], append: [{
1275
+ type: Input
1276
+ }] } });
1277
+
1278
+ class NsInputGroupComponent {
1279
+ label;
1280
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsInputGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1281
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsInputGroupComponent, isStandalone: true, selector: "ns-input-group", inputs: { label: "label" }, host: { properties: { "class.ns-input-group": "true" } }, ngImport: i0, template: "@if (label) {\n <label class=\"form-label\">{{ label }}</label>\n}\n\n<div class=\"input-group\">\n <ng-content></ng-content>\n</div>\n", styles: [".form-label{display:block;margin-bottom:var(--ns-space-2, .5rem);font-size:var(--ns-font-size-sm, .875rem)}.form-control{width:100%}.input-group{display:flex;flex-direction:row;align-items:center;width:100%;max-width:100%;position:relative;margin-bottom:var(--ns-space-2, .5rem)}.input-group ns-input{display:flex;margin-bottom:unset}.input-group:has(>ns-input-group-addon:first-child){background-color:var(--ns-color-surface, #fff)}.input-group:has(>ns-input:first-child) .form-control{border-top-right-radius:unset;border-bottom-right-radius:unset;margin:unset}.input-group:has(>ns-input:last-child) .form-control{border-top-left-radius:unset;border-bottom-left-radius:unset;margin:unset}.input-group:has(>ns-button:first-child) .btn{border-top-right-radius:unset;border-bottom-right-radius:unset;border-right-width:0;margin:unset}.input-group:has(>ns-button:last-child) .btn{border-top-left-radius:unset;border-bottom-left-radius:unset;border-left-width:0;margin:unset}\n"], encapsulation: i0.ViewEncapsulation.ShadowDom });
1282
+ }
1283
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsInputGroupComponent, decorators: [{
1284
+ type: Component,
1285
+ args: [{ selector: 'ns-input-group', encapsulation: ViewEncapsulation.ShadowDom, host: {
1286
+ '[class.ns-input-group]': 'true'
1287
+ }, template: "@if (label) {\n <label class=\"form-label\">{{ label }}</label>\n}\n\n<div class=\"input-group\">\n <ng-content></ng-content>\n</div>\n", styles: [".form-label{display:block;margin-bottom:var(--ns-space-2, .5rem);font-size:var(--ns-font-size-sm, .875rem)}.form-control{width:100%}.input-group{display:flex;flex-direction:row;align-items:center;width:100%;max-width:100%;position:relative;margin-bottom:var(--ns-space-2, .5rem)}.input-group ns-input{display:flex;margin-bottom:unset}.input-group:has(>ns-input-group-addon:first-child){background-color:var(--ns-color-surface, #fff)}.input-group:has(>ns-input:first-child) .form-control{border-top-right-radius:unset;border-bottom-right-radius:unset;margin:unset}.input-group:has(>ns-input:last-child) .form-control{border-top-left-radius:unset;border-bottom-left-radius:unset;margin:unset}.input-group:has(>ns-button:first-child) .btn{border-top-right-radius:unset;border-bottom-right-radius:unset;border-right-width:0;margin:unset}.input-group:has(>ns-button:last-child) .btn{border-top-left-radius:unset;border-bottom-left-radius:unset;border-left-width:0;margin:unset}\n"] }]
1288
+ }], propDecorators: { label: [{
1289
+ type: Input
1290
+ }] } });
1291
+
1292
+ function clamp(value, min = -Infinity, max = Infinity) {
1293
+ return Math.min(Math.max(value, min), max);
1294
+ }
1295
+ function roundToStepPrecision(value, step) {
1296
+ let roundedValue = value;
1297
+ let stepString = step.toString();
1298
+ let pointIndex = stepString.indexOf('.');
1299
+ let precision = pointIndex >= 0 ? stepString.length - pointIndex : 0;
1300
+ if (precision > 0) {
1301
+ let pow = Math.pow(10, precision);
1302
+ roundedValue = Math.round(roundedValue * pow) / pow;
1303
+ }
1304
+ return roundedValue;
1305
+ }
1306
+ function snapValueToStep(value, min, max, step) {
1307
+ min = Number(min);
1308
+ max = Number(max);
1309
+ let remainder = (value - (isNaN(min) ? 0 : min)) % step;
1310
+ let snappedValue = roundToStepPrecision(Math.abs(remainder) * 2 >= step
1311
+ ? value + Math.sign(remainder) * (step - Math.abs(remainder))
1312
+ : value - remainder, step);
1313
+ if (!isNaN(min)) {
1314
+ if (snappedValue < min) {
1315
+ snappedValue = min;
1316
+ }
1317
+ else if (!isNaN(max) && snappedValue > max) {
1318
+ snappedValue =
1319
+ min + Math.floor(roundToStepPrecision((max - min) / step, step)) * step;
1320
+ }
1321
+ }
1322
+ else if (!isNaN(max) && snappedValue > max) {
1323
+ snappedValue = Math.floor(roundToStepPrecision(max / step, step)) * step;
1324
+ }
1325
+ // correct floating point behavior by rounding to step precision
1326
+ snappedValue = roundToStepPrecision(snappedValue, step);
1327
+ return snappedValue;
1328
+ }
1329
+ const handleDecimalOperation = (operator, value1, value2) => {
1330
+ let result = operator === '+' ? value1 + value2 : value1 - value2;
1331
+ // Check if we have decimals
1332
+ if (value1 % 1 !== 0 || value2 % 1 !== 0) {
1333
+ const value1Decimal = value1.toString().split('.');
1334
+ const value2Decimal = value2.toString().split('.');
1335
+ const value1DecimalLength = (value1Decimal[1] && value1Decimal[1].length) || 0;
1336
+ const value2DecimalLength = (value2Decimal[1] && value2Decimal[1].length) || 0;
1337
+ const multiplier = Math.pow(10, Math.max(value1DecimalLength, value2DecimalLength));
1338
+ // Transform the decimals to integers based on the precision
1339
+ value1 = Math.round(value1 * multiplier);
1340
+ value2 = Math.round(value2 * multiplier);
1341
+ // Perform the operation on integers values to make sure we don't get a fancy decimal value
1342
+ result = operator === '+' ? value1 + value2 : value1 - value2;
1343
+ // Transform the integer result back to decimal
1344
+ result /= multiplier;
1345
+ }
1346
+ return result;
1347
+ };
1348
+
1349
+ const NS_INPUT_NUMBER_PROVIDER = {
1350
+ provide: NG_VALUE_ACCESSOR,
1351
+ useExisting: forwardRef(() => NsInputNumberComponent),
1352
+ multi: true
1353
+ };
1354
+ class NsInputNumberComponent extends NsValueAccessor {
1355
+ step;
1356
+ precision;
1357
+ minValue;
1358
+ maxValue;
1359
+ formatStyle = 'decimal';
1360
+ input;
1361
+ numberInput = 0;
1362
+ defaultOptions = inject(NS_FORMAT_OPTIONS);
1363
+ currency = inject(DEFAULT_CURRENCY_CODE);
1364
+ renderer = inject(Renderer2);
1365
+ locale = inject(LOCALE_ID);
1366
+ formatter;
1367
+ parser;
1368
+ ngOnInit() {
1369
+ this.formatter = new NumberFormatter(this.locale, this.formatOptions);
1370
+ this.parser = new NumberParser(this.locale, this.formatOptions);
1371
+ }
1372
+ get formatOptions() {
1373
+ return {
1374
+ ...this.defaultOptions.number,
1375
+ style: this.formatStyle,
1376
+ currency: this.currency,
1377
+ minimumFractionDigits: this.precision,
1378
+ maximumFractionDigits: this.precision
1379
+ };
1380
+ }
1381
+ writeValue(value) {
1382
+ if (value === null) {
1383
+ value = NaN;
1384
+ }
1385
+ else if (typeof value === 'string') {
1386
+ value = Number(value);
1387
+ }
1388
+ if (value === undefined && !isNaN(value)) {
1389
+ if (this.step !== undefined && !isNaN(this.step)) {
1390
+ value = snapValueToStep(value, this.minValue, this.maxValue, this.step);
1391
+ }
1392
+ else {
1393
+ value = clamp(value, this.minValue, this.maxValue);
1394
+ }
1395
+ }
1396
+ this._value = this.formatter.format(!isNaN(value) ? value : 0);
1397
+ this.numberInput = this.parser.parse(this._value);
1398
+ }
1399
+ set value(value) {
1400
+ if (this._value !== value) {
1401
+ let parsedValue = this.parser.parse(value);
1402
+ if (this.step !== undefined && !isNaN(this.step)) {
1403
+ parsedValue = snapValueToStep(parsedValue, this.minValue, this.maxValue, this.step);
1404
+ }
1405
+ else {
1406
+ parsedValue = clamp(parsedValue, this.minValue, this.maxValue);
1407
+ }
1408
+ if (isNaN(parsedValue)) {
1409
+ parsedValue = 0; // Reset to 0 if parsing fails
1410
+ }
1411
+ if (this.numberInput !== parsedValue) {
1412
+ this._value = value;
1413
+ this.numberInput = parsedValue;
1414
+ this.onChange(parsedValue);
1415
+ }
1416
+ }
1417
+ }
1418
+ get value() {
1419
+ return String(this._value);
1420
+ }
1421
+ onInput(event) {
1422
+ const { value } = event.target;
1423
+ if (!this.parser.isValidPartialNumber(value)) {
1424
+ if (this.type === 'currency') {
1425
+ this.renderer.setProperty(this.input.nativeElement, 'value', this.formatOptions.currency);
1426
+ }
1427
+ this.value = '';
1428
+ }
1429
+ else {
1430
+ this.value = value;
1431
+ }
1432
+ }
1433
+ onKeyUp(event) {
1434
+ if (!this.disabled) {
1435
+ let newValue = NaN;
1436
+ if (event.key === 'ArrowUp') {
1437
+ newValue = this.safeNextStep('+', this.minValue);
1438
+ }
1439
+ else if (event.key === 'ArrowDown') {
1440
+ newValue = this.safeNextStep('-', this.maxValue);
1441
+ }
1442
+ if (!isNaN(newValue)) {
1443
+ event?.preventDefault();
1444
+ this.value = this.formatter.format(newValue);
1445
+ }
1446
+ }
1447
+ }
1448
+ onFocusOut(event) {
1449
+ if (!this.disabled) {
1450
+ event?.preventDefault();
1451
+ this._value = this.formatter.format(this.numberInput);
1452
+ }
1453
+ }
1454
+ safeNextStep = (operation, minMax = 0) => {
1455
+ let prev = this.numberInput;
1456
+ let clampStep = this.step !== undefined && !isNaN(this.step) ? this.step : 1;
1457
+ if (this.formatOptions.style === 'percent' &&
1458
+ (this.step === undefined || isNaN(this.step))) {
1459
+ clampStep = 0.01;
1460
+ }
1461
+ if (isNaN(prev)) {
1462
+ // if the input is empty, start from the min/max value when incrementing/decrementing,
1463
+ // or zero if there is no min/max value defined.
1464
+ let newValue = isNaN(minMax) ? 0 : minMax;
1465
+ return snapValueToStep(newValue, this.minValue, this.maxValue, clampStep);
1466
+ }
1467
+ else {
1468
+ // otherwise, first snap the current value to the nearest step. if it moves in the direction
1469
+ // we're going, use that value, otherwise add the step and snap that value.
1470
+ let newValue = snapValueToStep(prev, this.minValue, this.maxValue, clampStep);
1471
+ if ((operation === '+' && newValue > prev) ||
1472
+ (operation === '-' && newValue < prev)) {
1473
+ return newValue;
1474
+ }
1475
+ return snapValueToStep(handleDecimalOperation(operation, prev, clampStep), this.minValue, this.maxValue, clampStep);
1476
+ }
1477
+ };
1478
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsInputNumberComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1479
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsInputNumberComponent, isStandalone: true, selector: "ns-input-number", inputs: { step: ["step", "step", numberAttribute], precision: ["precision", "precision", numberAttribute], minValue: ["minValue", "minValue", numberAttribute], maxValue: ["maxValue", "maxValue", numberAttribute], formatStyle: "formatStyle" }, host: { listeners: { "keydown": "onKeyUp($event)", "focusout": "onFocusOut($event)" } }, providers: [NS_INPUT_NUMBER_PROVIDER], viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: ` @if (label) {
1480
+ <label class="form-label" [attr.for]="id">{{ label }}</label>
1481
+ }
1482
+
1483
+ <div class="input-group">
1484
+ <input
1485
+ #input
1486
+ class="form-control"
1487
+ type="text"
1488
+ autocomplete="off"
1489
+ [attr.id]="id"
1490
+ [attr.min]="minValue"
1491
+ [attr.max]="maxValue"
1492
+ [attr.readonly]="readonly"
1493
+ [attr.step]="step"
1494
+ [placeholder]="placeholder"
1495
+ [disabled]="disabled"
1496
+ [ngModel]="value"
1497
+ (input)="onInput($event)"
1498
+ />
1499
+ </div>`, isInline: true, styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
1500
+ }
1501
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsInputNumberComponent, decorators: [{
1502
+ type: Component,
1503
+ args: [{ selector: 'ns-input-number', imports: [FormsModule], template: ` @if (label) {
1504
+ <label class="form-label" [attr.for]="id">{{ label }}</label>
1505
+ }
1506
+
1507
+ <div class="input-group">
1508
+ <input
1509
+ #input
1510
+ class="form-control"
1511
+ type="text"
1512
+ autocomplete="off"
1513
+ [attr.id]="id"
1514
+ [attr.min]="minValue"
1515
+ [attr.max]="maxValue"
1516
+ [attr.readonly]="readonly"
1517
+ [attr.step]="step"
1518
+ [placeholder]="placeholder"
1519
+ [disabled]="disabled"
1520
+ [ngModel]="value"
1521
+ (input)="onInput($event)"
1522
+ />
1523
+ </div>`, providers: [NS_INPUT_NUMBER_PROVIDER], styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}\n"] }]
1524
+ }], propDecorators: { step: [{
1525
+ type: Input,
1526
+ args: [{ transform: numberAttribute }]
1527
+ }], precision: [{
1528
+ type: Input,
1529
+ args: [{ transform: numberAttribute }]
1530
+ }], minValue: [{
1531
+ type: Input,
1532
+ args: [{ transform: numberAttribute }]
1533
+ }], maxValue: [{
1534
+ type: Input,
1535
+ args: [{ transform: numberAttribute }]
1536
+ }], formatStyle: [{
1537
+ type: Input
1538
+ }], input: [{
1539
+ type: ViewChild,
1540
+ args: ['input', { static: true }]
1541
+ }], onKeyUp: [{
1542
+ type: HostListener,
1543
+ args: ['keydown', ['$event']]
1544
+ }], onFocusOut: [{
1545
+ type: HostListener,
1546
+ args: ['focusout', ['$event']]
1547
+ }] } });
1548
+
1549
+ class NsPasswordComponent extends NsValueAccessor {
1550
+ forgotLink;
1551
+ showAndHide;
1552
+ show;
1553
+ constructor() {
1554
+ super();
1555
+ }
1556
+ ngOnInit() { }
1557
+ toggle() {
1558
+ this.show = !this.show;
1559
+ }
1560
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsPasswordComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1561
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsPasswordComponent, isStandalone: true, selector: "ns-password", inputs: { forgotLink: "forgotLink", showAndHide: "showAndHide" }, providers: [
1562
+ {
1563
+ provide: NG_VALUE_ACCESSOR,
1564
+ useExisting: forwardRef(() => NsPasswordComponent),
1565
+ multi: true
1566
+ }
1567
+ ], usesInheritance: true, ngImport: i0, template: "@if (label) {\n <label class=\"form-label\">\n {{ label }}\n @if (forgotLink) {\n <a [routerLink]=\"forgotLink\">Olvido su contrase\u00F1a?</a>\n }\n </label>\n}\n\n<div class=\"input-group\">\n <input\n class=\"form-control\"\n [type]=\"show ? 'input' : 'password'\"\n [(ngModel)]=\"value\"\n [placeholder]=\"placeholder\"\n (blur)=\"onTouched()\"\n [disabled]=\"disabled\"\n />\n\n @if (showAndHide) {\n <div class=\"input-group-append\" (click)=\"toggle()\">\n <span class=\"input-group-text\">\n <ns-icon [name]=\"show ? 'eye-hide' : 'eye-show'\" />\n </span>\n </div>\n }\n</div>\n", styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NsIconsComponent, selector: "ns-icon", inputs: ["name", "color", "size", "strokeWidth", "viewBox"] }] });
1568
+ }
1569
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsPasswordComponent, decorators: [{
1570
+ type: Component,
1571
+ args: [{ selector: 'ns-password', providers: [
1572
+ {
1573
+ provide: NG_VALUE_ACCESSOR,
1574
+ useExisting: forwardRef(() => NsPasswordComponent),
1575
+ multi: true
1576
+ }
1577
+ ], imports: [RouterLink, FormsModule, NsIconsComponent], template: "@if (label) {\n <label class=\"form-label\">\n {{ label }}\n @if (forgotLink) {\n <a [routerLink]=\"forgotLink\">Olvido su contrase\u00F1a?</a>\n }\n </label>\n}\n\n<div class=\"input-group\">\n <input\n class=\"form-control\"\n [type]=\"show ? 'input' : 'password'\"\n [(ngModel)]=\"value\"\n [placeholder]=\"placeholder\"\n (blur)=\"onTouched()\"\n [disabled]=\"disabled\"\n />\n\n @if (showAndHide) {\n <div class=\"input-group-append\" (click)=\"toggle()\">\n <span class=\"input-group-text\">\n <ns-icon [name]=\"show ? 'eye-hide' : 'eye-show'\" />\n </span>\n </div>\n }\n</div>\n", styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}\n"] }]
1578
+ }], ctorParameters: () => [], propDecorators: { forgotLink: [{
1579
+ type: Input
1580
+ }], showAndHide: [{
1581
+ type: Input
1582
+ }] } });
1583
+
1584
+ class NsSwitchComponent extends NsValueAccessor {
1585
+ boolean = true;
1586
+ size = 'small';
1587
+ theme = 'primary';
1588
+ get value() {
1589
+ return typeof this._value === 'boolean'
1590
+ ? this._value
1591
+ : YesNo.isYes(this._value);
1592
+ }
1593
+ set value(checked) {
1594
+ this._value = checked;
1595
+ this.onChange(this.boolean ? checked : YesNo.yesOrNo(checked));
1596
+ }
1597
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsSwitchComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1598
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.2.21", type: NsSwitchComponent, isStandalone: true, selector: "ns-switch", inputs: { boolean: ["boolean", "boolean", booleanAttribute], size: "size", theme: "theme", value: "value" }, host: { properties: { "class.ns-switch": "true", "class.ns-switch--small": "size === \"small\"", "class.ns-switch--large": "size === \"large\"" } }, providers: [
1599
+ {
1600
+ provide: NG_VALUE_ACCESSOR,
1601
+ useExisting: forwardRef(() => NsSwitchComponent),
1602
+ multi: true
1603
+ }
1604
+ ], usesInheritance: true, ngImport: i0, template: `
1605
+ <input
1606
+ type="checkbox"
1607
+ class="ns-switch__input"
1608
+ role="switch"
1609
+ [(ngModel)]="value"
1610
+ [ngClass]="{ 'ns-switch__input--success': theme == 'success' }"
1611
+ [attr.id]="id"
1612
+ [disabled]="disabled"
1613
+ />
1614
+ <label class="ns-switch__label" [attr.for]="id">{{ label }}</label>
1615
+ `, isInline: true, styles: [":host{display:block;min-height:1.5rem;padding-left:2.5rem;margin-bottom:.5rem;padding-top:.25rem}:host .ns-switch__input{margin-left:-2.5em;border-radius:2em;transition:background-position .15s ease-in-out;width:2em;height:1em;float:left;margin-top:.2em;vertical-align:top;background-size:contain;background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e\");background-position:left center;background-repeat:no-repeat;border:1px solid rgba(0,0,0,.25);appearance:none}:host .ns-switch__input:checked{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e\");background-position:right center;background-repeat:no-repeat;background-color:var(--ns-color-primary, #3665f3);border-color:var(--ns-color-primary, #3665f3)}:host .ns-switch__input.ns-switch__input--success:checked{background-color:var(--ns-color-success, #0cac42);border-color:var(--ns-color-success, #0cac42)}:host .ns-switch__input:disabled{pointer-events:none;filter:none;opacity:.5}:host .ns-switch__label{display:inline-block}:host.ns-switch--large .ns-switch__input{width:3em;height:1.5em}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
1616
+ }
1617
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsSwitchComponent, decorators: [{
1618
+ type: Component,
1619
+ args: [{ selector: 'ns-switch', imports: [FormsModule, NgClass], template: `
1620
+ <input
1621
+ type="checkbox"
1622
+ class="ns-switch__input"
1623
+ role="switch"
1624
+ [(ngModel)]="value"
1625
+ [ngClass]="{ 'ns-switch__input--success': theme == 'success' }"
1626
+ [attr.id]="id"
1627
+ [disabled]="disabled"
1628
+ />
1629
+ <label class="ns-switch__label" [attr.for]="id">{{ label }}</label>
1630
+ `, providers: [
1631
+ {
1632
+ provide: NG_VALUE_ACCESSOR,
1633
+ useExisting: forwardRef(() => NsSwitchComponent),
1634
+ multi: true
1635
+ }
1636
+ ], host: {
1637
+ '[class.ns-switch]': 'true',
1638
+ '[class.ns-switch--small]': 'size === "small"',
1639
+ '[class.ns-switch--large]': 'size === "large"'
1640
+ }, styles: [":host{display:block;min-height:1.5rem;padding-left:2.5rem;margin-bottom:.5rem;padding-top:.25rem}:host .ns-switch__input{margin-left:-2.5em;border-radius:2em;transition:background-position .15s ease-in-out;width:2em;height:1em;float:left;margin-top:.2em;vertical-align:top;background-size:contain;background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e\");background-position:left center;background-repeat:no-repeat;border:1px solid rgba(0,0,0,.25);appearance:none}:host .ns-switch__input:checked{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e\");background-position:right center;background-repeat:no-repeat;background-color:var(--ns-color-primary, #3665f3);border-color:var(--ns-color-primary, #3665f3)}:host .ns-switch__input.ns-switch__input--success:checked{background-color:var(--ns-color-success, #0cac42);border-color:var(--ns-color-success, #0cac42)}:host .ns-switch__input:disabled{pointer-events:none;filter:none;opacity:.5}:host .ns-switch__label{display:inline-block}:host.ns-switch--large .ns-switch__input{width:3em;height:1.5em}\n"] }]
1641
+ }], propDecorators: { boolean: [{
1642
+ type: Input,
1643
+ args: [{ transform: booleanAttribute }]
1644
+ }], size: [{
1645
+ type: Input
1646
+ }], theme: [{
1647
+ type: Input
1648
+ }], value: [{
1649
+ type: Input
1650
+ }] } });
1651
+
1652
+ class NsTextAreaComponent extends NsValueAccessor {
1653
+ rows = 3;
1654
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsTextAreaComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1655
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsTextAreaComponent, isStandalone: true, selector: "ns-textarea", inputs: { rows: "rows" }, providers: [
1656
+ {
1657
+ provide: NG_VALUE_ACCESSOR,
1658
+ useExisting: forwardRef(() => NsTextAreaComponent),
1659
+ multi: true
1660
+ }
1661
+ ], usesInheritance: true, ngImport: i0, template: `
1662
+ @if (label) {
1663
+ <label class="form-label" [attr.for]="id">{{ label }}</label>
1664
+ }
1665
+
1666
+ <textarea
1667
+ class="form-control"
1668
+ [(ngModel)]="value"
1669
+ [id]="id"
1670
+ [rows]="rows"
1671
+ [placeholder]="placeholder"
1672
+ (blur)="onTouched()"
1673
+ [disabled]="disabled"
1674
+ ></textarea>
1675
+ `, isInline: true, styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
1676
+ }
1677
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsTextAreaComponent, decorators: [{
1678
+ type: Component,
1679
+ args: [{ selector: 'ns-textarea', template: `
1680
+ @if (label) {
1681
+ <label class="form-label" [attr.for]="id">{{ label }}</label>
1682
+ }
1683
+
1684
+ <textarea
1685
+ class="form-control"
1686
+ [(ngModel)]="value"
1687
+ [id]="id"
1688
+ [rows]="rows"
1689
+ [placeholder]="placeholder"
1690
+ (blur)="onTouched()"
1691
+ [disabled]="disabled"
1692
+ ></textarea>
1693
+ `, providers: [
1694
+ {
1695
+ provide: NG_VALUE_ACCESSOR,
1696
+ useExisting: forwardRef(() => NsTextAreaComponent),
1697
+ multi: true
1698
+ }
1699
+ ], imports: [FormsModule], styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}\n"] }]
1700
+ }], propDecorators: { rows: [{
1701
+ type: Input
1702
+ }] } });
1703
+
1704
+ class NsContentEditableComponent extends NsValueAccessor {
1705
+ elementRef = inject(ElementRef);
1706
+ renderer = inject(Renderer2);
1707
+ maxLength;
1708
+ enabled = true;
1709
+ writeValue(value) {
1710
+ if (typeof value !== 'undefined') {
1711
+ this.renderer.setProperty(this.elementRef.nativeElement, 'innerHTML', value || '');
1712
+ }
1713
+ }
1714
+ onInput() {
1715
+ this.onChange(this.elementRef.nativeElement.innerHTML);
1716
+ }
1717
+ onBlur() {
1718
+ this.onTouched();
1719
+ }
1720
+ onKeyUp(event) {
1721
+ if (this.maxLength &&
1722
+ this.elementRef.nativeElement.innerText.length >= this.maxLength &&
1723
+ event.key !== 'Backspace') {
1724
+ event.preventDefault();
1725
+ }
1726
+ }
1727
+ setDisabledState(isDisabled) {
1728
+ this.disabled = isDisabled;
1729
+ this.enabled = !isDisabled;
1730
+ }
1731
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsContentEditableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1732
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.21", type: NsContentEditableComponent, isStandalone: true, selector: "ns-content-editable", inputs: { maxLength: ["maxlength", "maxLength"] }, host: { listeners: { "input": "onInput()", "blur": "onBlur()", "keydown": "onKeyUp($event)" }, properties: { "class.ns-content--disabled": "disabled", "attr.contenteditable": "this.enabled" } }, providers: [
1733
+ {
1734
+ provide: NG_VALUE_ACCESSOR,
1735
+ useExisting: forwardRef(() => NsContentEditableComponent),
1736
+ multi: true
1737
+ }
1738
+ ], usesInheritance: true, ngImport: i0, template: '', isInline: true, styles: [":host{display:block;position:relative;background-color:var(--ns-content-bg, #fff);width:100%;height:fit-content;min-height:7rem;outline:none}\n", ":host.ns-content--disabled{background-color:var(--ns-content-disabled-bg,#e9ecef);opacity:.65}\n"] });
1739
+ }
1740
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsContentEditableComponent, decorators: [{
1741
+ type: Component,
1742
+ args: [{ selector: 'ns-content-editable', template: '', providers: [
1743
+ {
1744
+ provide: NG_VALUE_ACCESSOR,
1745
+ useExisting: forwardRef(() => NsContentEditableComponent),
1746
+ multi: true
1747
+ }
1748
+ ], host: {
1749
+ '[class.ns-content--disabled]': 'disabled'
1750
+ }, styles: [":host{display:block;position:relative;background-color:var(--ns-content-bg, #fff);width:100%;height:fit-content;min-height:7rem;outline:none}\n", ":host.ns-content--disabled{background-color:var(--ns-content-disabled-bg,#e9ecef);opacity:.65}\n"] }]
1751
+ }], propDecorators: { maxLength: [{
1752
+ type: Input,
1753
+ args: ['maxlength']
1754
+ }], enabled: [{
1755
+ type: HostBinding,
1756
+ args: ['attr.contenteditable']
1757
+ }], onInput: [{
1758
+ type: HostListener,
1759
+ args: ['input']
1760
+ }], onBlur: [{
1761
+ type: HostListener,
1762
+ args: ['blur']
1763
+ }], onKeyUp: [{
1764
+ type: HostListener,
1765
+ args: ['keydown', ['$event']]
1766
+ }] } });
1767
+
1768
+ // COMPONENTS
1769
+
1770
+ class NsButtonGroupComponent extends NsValueAccessor {
1771
+ items;
1772
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsButtonGroupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1773
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsButtonGroupComponent, isStandalone: true, selector: "ns-button-group", host: { properties: { "class.ns-button-group": "true" } }, providers: [
1774
+ {
1775
+ provide: NG_VALUE_ACCESSOR,
1776
+ useExisting: forwardRef(() => NsButtonGroupComponent),
1777
+ multi: true
1778
+ }
1779
+ ], queries: [{ propertyName: "items", predicate: NsButtonComponent }], usesInheritance: true, ngImport: i0, template: `
1780
+ @if (label) {
1781
+ <label class="form-label">{{ label }}</label>
1782
+ }
1783
+
1784
+ <div
1785
+ class="btn__group"
1786
+ role="group"
1787
+ aria-label="Basic radio toggle button group"
1788
+ >
1789
+ @for (item of items; track item; let i = $index; let isFirst = $first) {
1790
+ <input
1791
+ type="radio"
1792
+ class="btn__check"
1793
+ autocomplete="off"
1794
+ [attr.id]="'btn-group__' + i"
1795
+ [checked]="value == item.value"
1796
+ (click)="value = item.value"
1797
+ />
1798
+ <label class="btn btn__outline-primary" [attr.for]="'btn-group__' + i">
1799
+ {{ item.label }}
1800
+ </label>
1801
+ }
1802
+ </div>
1803
+ `, isInline: true, styles: [":host{display:block;width:fit-content;margin-bottom:var(--ns-space-2, .5rem)}.form-label{display:block;font-size:var(--ns-font-size-sm, .875rem);margin-bottom:var(--ns-space-2, .5rem)}.btn{display:block;position:relative;border-radius:var(--ns-border-radius, .375rem);vertical-align:center;text-align:center;text-transform:none;font-size:.875rem;line-height:1rem;outline:none;white-space:nowrap;padding:var(--ns-btn-padding-y, .5rem) var(--ns-btn-padding-x, 1rem);cursor:pointer}.btn:disabled{pointer-events:none}.btn__check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn__group{position:relative;display:inline-flex;vertical-align:middle}.btn__outline-primary{color:var(--ns-color-primary, #3665f3);background-color:var(--ns-color-surface, #fff);min-width:var(--ns-btn-min-width, 5rem);border:1px solid var(--ns-color-primary, #3665f3)}.btn__outline-primary:focus,.btn__outline-primary:active{color:var(--ns-color-primary-hover, #2f57d9);border-color:var(--ns-color-primary, #3665f3);box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__outline-primary:hover{color:var(--ns-color-primary-hover, #2f57d9);border-color:var(--ns-color-primary, #3665f3)}.btn__check:checked+.btn__outline-primary{background-color:var(--ns-color-primary, #3665f3);border:1px solid var(--ns-color-primary, #3665f3);color:var(--ns-color-primary-foreground, #fff);min-width:var(--ns-btn-min-width, 5rem)}.btn__check:checked+.btn__outline-primary:focus,.btn__check:checked+.btn__outline-primary:active{color:var(--ns-color-primary-foreground, #fff);border-color:var(--ns-color-primary-hover, #2f57d9);box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__check:checked+.btn__outline-primary:hover{background-color:var(--ns-color-primary-hover, #2f57d9)}.btn:not(:first-child){margin-left:-1px}.btn:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}\n"] });
1804
+ }
1805
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsButtonGroupComponent, decorators: [{
1806
+ type: Component,
1807
+ args: [{ selector: 'ns-button-group', standalone: true, imports: [], template: `
1808
+ @if (label) {
1809
+ <label class="form-label">{{ label }}</label>
1810
+ }
1811
+
1812
+ <div
1813
+ class="btn__group"
1814
+ role="group"
1815
+ aria-label="Basic radio toggle button group"
1816
+ >
1817
+ @for (item of items; track item; let i = $index; let isFirst = $first) {
1818
+ <input
1819
+ type="radio"
1820
+ class="btn__check"
1821
+ autocomplete="off"
1822
+ [attr.id]="'btn-group__' + i"
1823
+ [checked]="value == item.value"
1824
+ (click)="value = item.value"
1825
+ />
1826
+ <label class="btn btn__outline-primary" [attr.for]="'btn-group__' + i">
1827
+ {{ item.label }}
1828
+ </label>
1829
+ }
1830
+ </div>
1831
+ `, providers: [
1832
+ {
1833
+ provide: NG_VALUE_ACCESSOR,
1834
+ useExisting: forwardRef(() => NsButtonGroupComponent),
1835
+ multi: true
1836
+ }
1837
+ ], host: {
1838
+ '[class.ns-button-group]': 'true'
1839
+ }, styles: [":host{display:block;width:fit-content;margin-bottom:var(--ns-space-2, .5rem)}.form-label{display:block;font-size:var(--ns-font-size-sm, .875rem);margin-bottom:var(--ns-space-2, .5rem)}.btn{display:block;position:relative;border-radius:var(--ns-border-radius, .375rem);vertical-align:center;text-align:center;text-transform:none;font-size:.875rem;line-height:1rem;outline:none;white-space:nowrap;padding:var(--ns-btn-padding-y, .5rem) var(--ns-btn-padding-x, 1rem);cursor:pointer}.btn:disabled{pointer-events:none}.btn__check{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.btn__group{position:relative;display:inline-flex;vertical-align:middle}.btn__outline-primary{color:var(--ns-color-primary, #3665f3);background-color:var(--ns-color-surface, #fff);min-width:var(--ns-btn-min-width, 5rem);border:1px solid var(--ns-color-primary, #3665f3)}.btn__outline-primary:focus,.btn__outline-primary:active{color:var(--ns-color-primary-hover, #2f57d9);border-color:var(--ns-color-primary, #3665f3);box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__outline-primary:hover{color:var(--ns-color-primary-hover, #2f57d9);border-color:var(--ns-color-primary, #3665f3)}.btn__check:checked+.btn__outline-primary{background-color:var(--ns-color-primary, #3665f3);border:1px solid var(--ns-color-primary, #3665f3);color:var(--ns-color-primary-foreground, #fff);min-width:var(--ns-btn-min-width, 5rem)}.btn__check:checked+.btn__outline-primary:focus,.btn__check:checked+.btn__outline-primary:active{color:var(--ns-color-primary-foreground, #fff);border-color:var(--ns-color-primary-hover, #2f57d9);box-shadow:var(--ns-shadow-focus, rgba(43, 34, 51, .04) 0 1px 4px)}.btn__check:checked+.btn__outline-primary:hover{background-color:var(--ns-color-primary-hover, #2f57d9)}.btn:not(:first-child){margin-left:-1px}.btn:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn:not(:last-child){border-top-right-radius:0;border-bottom-right-radius:0}\n"] }]
1840
+ }], propDecorators: { items: [{
1841
+ type: ContentChildren,
1842
+ args: [NsButtonComponent]
1843
+ }] } });
1844
+
1845
+ class NsCommentComponent {
1846
+ title;
1847
+ description;
1848
+ placeholder;
1849
+ messages = [];
1850
+ cover;
1851
+ submitText;
1852
+ logged;
1853
+ maxLength = 128;
1854
+ disabled;
1855
+ commit = new Subject();
1856
+ invalid = false;
1857
+ content = '';
1858
+ clearEmptyValues = new RegExp(/(<div><br><\/div>)*/g);
1859
+ constructor() { }
1860
+ ngOnInit() { }
1861
+ publish() {
1862
+ if (this.content) {
1863
+ this.commit.next(this.content.replace(this.clearEmptyValues, ''));
1864
+ this.content = '';
1865
+ }
1866
+ else {
1867
+ this.invalid = true;
1868
+ }
1869
+ }
1870
+ get counter() {
1871
+ const characters = this.maxLength - this.content.length;
1872
+ return characters > 0 ? characters : 0;
1873
+ }
1874
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsCommentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1875
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsCommentComponent, isStandalone: true, selector: "ns-comment", inputs: { title: "title", description: "description", placeholder: "placeholder", messages: "messages", cover: "cover", submitText: "submitText", logged: "logged", maxLength: "maxLength", disabled: "disabled" }, outputs: { commit: "commit" }, ngImport: i0, template: "@if (logged) {\n <div class=\"ns-comment-box\" [ngClass]=\"{ 'ns-comment-invalid': invalid }\">\n <ns-avatar class=\"ns-comment-avatar\" [src]=\"cover?.url\" />\n\n <div class=\"ns-comment-input-wrap\">\n <div class=\"ns-comment-input\">\n <ns-content-editable\n class=\"ns-comment-input-content\"\n [maxlength]=\"maxLength\"\n [(ngModel)]=\"content\"\n [disabled]=\"disabled\"\n />\n\n @if (!content) {\n <span class=\"ns-comment-input-placeholder\">{{ placeholder }}</span>\n }\n </div>\n\n <div class=\"ns-comment-footer\">\n <span class=\"ns-comment-counter\">Quedan {{ counter }} caracteres</span>\n\n @if (submitText) {\n <button\n class=\"ns-comment-submit\"\n (click)=\"publish()\"\n [disabled]=\"disabled\"\n >\n {{ submitText }}\n </button>\n }\n </div>\n </div>\n </div>\n} @else {\n <h4 class=\"ns-comment-title\">\n {{ title }} <br />\n <small\n class=\"ns-comment-description\"\n [innerHTML]=\"description | nsSafeHtml\"\n ></small>\n </h4>\n\n <div class=\"ns-comment-logout\">\n <ng-content />\n </div>\n}\n@if (messages?.length) {\n <ul class=\"ns-comment-list\">\n @for (comment of messages; track comment) {\n <li class=\"ns-comment\">\n <ns-avatar\n class=\"ns-comment-cover\"\n [src]=\"comment.cover?.url\"\n size=\"medium\"\n />\n\n <div class=\"ns-comment-wrap\">\n <div class=\"ns-comment-user-wrap\">\n @if (comment?.author; as author) {\n <a [attr.href]=\"author.link\" class=\"ns-comment-author\">\n {{ author.name }}\n </a>\n }\n @if (comment?.created; as date) {\n <span class=\"ns-comment-date\">{{ date | nsHumanize }}</span>\n }\n\n <div\n class=\"ns-comment-message\"\n [innerHTML]=\"comment?.message | nsSafeHtml\"\n ></div>\n </div>\n </div>\n </li>\n }\n </ul>\n}\n", styles: ["@charset \"UTF-8\";:host{display:block;background-color:#fff;border-radius:.4rem;padding:1.5rem;margin-bottom:1rem;font-weight:300;color:#555}.ns-comment{display:flex;justify-content:flex-start;align-content:center}.ns-comment-title{margin-top:unset;margin-bottom:1rem}.ns-comment-list{border-top:1px solid #2c3035;margin:1.25rem -1.5rem 0;padding:1rem 2rem}.ns-comment-author{font-weight:500;-webkit-font-smoothing:antialiased}.ns-comment-description{font-weight:300;font-size:70%;color:#333}.ns-comment-cover,.ns-comment-avatar{height:3.5rem;width:4rem}.ns-comment-cover:not(.ns-comment-avatar),.ns-comment-avatar:not(.ns-comment-avatar){margin-top:.7rem}.ns-comment-wrap{padding:1rem;width:100%}.ns-comment-date{font-size:12px;color:#9c9c9c}.ns-comment-date:before{content:\"\\2022\";margin:0 4px}.ns-comment-box{display:flex}.ns-comment-input{position:relative;border-radius:.4rem;padding:1rem;border:1px solid #e8e8e8;margin-bottom:1rem;min-height:58px}.ns-comment-input-wrap{width:100%;margin-left:1rem;flex:1 auto}.ns-comment-input-content{position:relative;min-height:1rem;z-index:2}.ns-comment-input-content:focus-visible{outline:none}.ns-comment-input-placeholder{position:absolute;top:1rem;color:#aaa}.ns-comment-submit{display:flex;justify-content:center;align-items:center;color:#fff;border-radius:var(--ns-radius-lg, .75rem);background-color:var(--ns-color-primary, #3665f3);font-weight:600;border:1px solid transparent;line-height:1.25;transition:background,color,border .3s linear;font-size:.8rem;height:2.3rem;padding:.37rem 1.5rem;-webkit-user-select:none;user-select:none;text-transform:uppercase;-webkit-appearance:button;margin-left:auto}.ns-comment-submit:hover{background-color:var(--ns-color-primary-hover, #2f57d9)}.ns-comment-submit:disabled{cursor:not-allowed;background-color:#3bacf1}.ns-comment-footer{display:flex;align-items:center}.ns-comment-counter{color:#9c9c9c;margin-right:.5rem}.ns-comment-invalid .ns-comment-input{border-color:#ea400e;transition:all .3s ease-in-out}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: NsAvatarComponent, selector: "ns-avatar", inputs: ["src", "atl", "icon", "shape", "size", "gap"] }, { kind: "component", type: NsContentEditableComponent, selector: "ns-content-editable", inputs: ["maxlength"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: NsSafeHtmlPipe, name: "nsSafeHtml" }, { kind: "pipe", type: NsHumanizePipe, name: "nsHumanize" }] });
1876
+ }
1877
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsCommentComponent, decorators: [{
1878
+ type: Component,
1879
+ args: [{ selector: 'ns-comment', imports: [
1880
+ NgClass,
1881
+ NsAvatarComponent,
1882
+ NsContentEditableComponent,
1883
+ FormsModule,
1884
+ NsSafeHtmlPipe,
1885
+ NsHumanizePipe
1886
+ ], template: "@if (logged) {\n <div class=\"ns-comment-box\" [ngClass]=\"{ 'ns-comment-invalid': invalid }\">\n <ns-avatar class=\"ns-comment-avatar\" [src]=\"cover?.url\" />\n\n <div class=\"ns-comment-input-wrap\">\n <div class=\"ns-comment-input\">\n <ns-content-editable\n class=\"ns-comment-input-content\"\n [maxlength]=\"maxLength\"\n [(ngModel)]=\"content\"\n [disabled]=\"disabled\"\n />\n\n @if (!content) {\n <span class=\"ns-comment-input-placeholder\">{{ placeholder }}</span>\n }\n </div>\n\n <div class=\"ns-comment-footer\">\n <span class=\"ns-comment-counter\">Quedan {{ counter }} caracteres</span>\n\n @if (submitText) {\n <button\n class=\"ns-comment-submit\"\n (click)=\"publish()\"\n [disabled]=\"disabled\"\n >\n {{ submitText }}\n </button>\n }\n </div>\n </div>\n </div>\n} @else {\n <h4 class=\"ns-comment-title\">\n {{ title }} <br />\n <small\n class=\"ns-comment-description\"\n [innerHTML]=\"description | nsSafeHtml\"\n ></small>\n </h4>\n\n <div class=\"ns-comment-logout\">\n <ng-content />\n </div>\n}\n@if (messages?.length) {\n <ul class=\"ns-comment-list\">\n @for (comment of messages; track comment) {\n <li class=\"ns-comment\">\n <ns-avatar\n class=\"ns-comment-cover\"\n [src]=\"comment.cover?.url\"\n size=\"medium\"\n />\n\n <div class=\"ns-comment-wrap\">\n <div class=\"ns-comment-user-wrap\">\n @if (comment?.author; as author) {\n <a [attr.href]=\"author.link\" class=\"ns-comment-author\">\n {{ author.name }}\n </a>\n }\n @if (comment?.created; as date) {\n <span class=\"ns-comment-date\">{{ date | nsHumanize }}</span>\n }\n\n <div\n class=\"ns-comment-message\"\n [innerHTML]=\"comment?.message | nsSafeHtml\"\n ></div>\n </div>\n </div>\n </li>\n }\n </ul>\n}\n", styles: ["@charset \"UTF-8\";:host{display:block;background-color:#fff;border-radius:.4rem;padding:1.5rem;margin-bottom:1rem;font-weight:300;color:#555}.ns-comment{display:flex;justify-content:flex-start;align-content:center}.ns-comment-title{margin-top:unset;margin-bottom:1rem}.ns-comment-list{border-top:1px solid #2c3035;margin:1.25rem -1.5rem 0;padding:1rem 2rem}.ns-comment-author{font-weight:500;-webkit-font-smoothing:antialiased}.ns-comment-description{font-weight:300;font-size:70%;color:#333}.ns-comment-cover,.ns-comment-avatar{height:3.5rem;width:4rem}.ns-comment-cover:not(.ns-comment-avatar),.ns-comment-avatar:not(.ns-comment-avatar){margin-top:.7rem}.ns-comment-wrap{padding:1rem;width:100%}.ns-comment-date{font-size:12px;color:#9c9c9c}.ns-comment-date:before{content:\"\\2022\";margin:0 4px}.ns-comment-box{display:flex}.ns-comment-input{position:relative;border-radius:.4rem;padding:1rem;border:1px solid #e8e8e8;margin-bottom:1rem;min-height:58px}.ns-comment-input-wrap{width:100%;margin-left:1rem;flex:1 auto}.ns-comment-input-content{position:relative;min-height:1rem;z-index:2}.ns-comment-input-content:focus-visible{outline:none}.ns-comment-input-placeholder{position:absolute;top:1rem;color:#aaa}.ns-comment-submit{display:flex;justify-content:center;align-items:center;color:#fff;border-radius:var(--ns-radius-lg, .75rem);background-color:var(--ns-color-primary, #3665f3);font-weight:600;border:1px solid transparent;line-height:1.25;transition:background,color,border .3s linear;font-size:.8rem;height:2.3rem;padding:.37rem 1.5rem;-webkit-user-select:none;user-select:none;text-transform:uppercase;-webkit-appearance:button;margin-left:auto}.ns-comment-submit:hover{background-color:var(--ns-color-primary-hover, #2f57d9)}.ns-comment-submit:disabled{cursor:not-allowed;background-color:#3bacf1}.ns-comment-footer{display:flex;align-items:center}.ns-comment-counter{color:#9c9c9c;margin-right:.5rem}.ns-comment-invalid .ns-comment-input{border-color:#ea400e;transition:all .3s ease-in-out}\n"] }]
1887
+ }], ctorParameters: () => [], propDecorators: { title: [{
1888
+ type: Input
1889
+ }], description: [{
1890
+ type: Input
1891
+ }], placeholder: [{
1892
+ type: Input
1893
+ }], messages: [{
1894
+ type: Input
1895
+ }], cover: [{
1896
+ type: Input
1897
+ }], submitText: [{
1898
+ type: Input
1899
+ }], logged: [{
1900
+ type: Input
1901
+ }], maxLength: [{
1902
+ type: Input
1903
+ }], disabled: [{
1904
+ type: Input
1905
+ }], commit: [{
1906
+ type: Output
1907
+ }] } });
1908
+
1909
+ var Commands;
1910
+ (function (Commands) {
1911
+ Commands["BOLD"] = "bold";
1912
+ Commands["CREATE_LINK"] = "createLink";
1913
+ Commands["FONT_NAME"] = "fontName";
1914
+ Commands["FONT_SIZE"] = "fontSize";
1915
+ Commands["FORMAT_BLOCK"] = "formatBlock";
1916
+ Commands["INSERT_HTML"] = "insertHTML";
1917
+ Commands["INSERT_IMAGE"] = "insertImage";
1918
+ Commands["INSERT_ORDERED_LIST"] = "insertOrderedList";
1919
+ Commands["INSERT_UNORDERED_LIST"] = "insertUnorderedList";
1920
+ Commands["INSERT_TEXT"] = "insertText";
1921
+ Commands["ITALIC"] = "italic";
1922
+ Commands["JUSTIFY_CENTER"] = "justifyCenter";
1923
+ Commands["JUSTIFY_FULL"] = "justifyFull";
1924
+ Commands["JUSTIFY_LEFT"] = "justifyLeft";
1925
+ Commands["JUSTIFY_RIGHT"] = "justifyRight";
1926
+ Commands["UNDERLINE"] = "underline";
1927
+ Commands["UNLINK"] = "unlink";
1928
+ Commands["TEXT_COLOR"] = "foreColor";
1929
+ Commands["BACKGROUND_COLOR"] = "backColor";
1930
+ })(Commands || (Commands = {}));
1931
+
1932
+ const LABELS_DEFAULT = {
1933
+ bold: 'Bold',
1934
+ italic: 'Italic',
1935
+ code: 'Code',
1936
+ underline: 'Underline',
1937
+ strike: 'Strike',
1938
+ blockquote: 'Blockquote',
1939
+ bullet_list: 'Bullet List',
1940
+ ordered_list: 'Ordered List',
1941
+ paragraph: 'Paragraph',
1942
+ h1: 'Header 1',
1943
+ h2: 'Header 2',
1944
+ h3: 'Header 3',
1945
+ h4: 'Header 4',
1946
+ h5: 'Header 5',
1947
+ h6: 'Header 6',
1948
+ align_left: 'Left Align',
1949
+ align_center: 'Center Align',
1950
+ align_right: 'Right Align',
1951
+ align_justify: 'Justify',
1952
+ text_color: 'Text Color',
1953
+ background_color: 'Background Color',
1954
+ insert_link: 'Insert Link',
1955
+ link: 'Paste your link',
1956
+ text: 'Text to display',
1957
+ tooltip_link: 'Tooltip',
1958
+ open_new_window: 'Open link in new window',
1959
+ submit_link: 'Insert',
1960
+ remove_color: 'Remove'
1961
+ };
1962
+ class Labels {
1963
+ storage = LABELS_DEFAULT;
1964
+ constructor(newLabels = {}) {
1965
+ this.storage = { ...LABELS_DEFAULT, ...newLabels };
1966
+ }
1967
+ get = (key) => {
1968
+ return this.storage[key] ?? '';
1969
+ };
1970
+ }
1971
+
1972
+ const NS_EDITOR_SETUP = new InjectionToken('NsEditorSetup');
1973
+ class NsEditorService {
1974
+ config = inject(NS_EDITOR_SETUP, { optional: true });
1975
+ doc = inject(DOCUMENT);
1976
+ savedSelection;
1977
+ selectedText;
1978
+ labels;
1979
+ constructor() {
1980
+ const config = this.config;
1981
+ this.labels = new Labels(config ? config.labels : {});
1982
+ }
1983
+ translate(key) {
1984
+ return this.labels.get(key);
1985
+ }
1986
+ saveSelection() {
1987
+ switch (true) {
1988
+ case !!this.doc.getSelection:
1989
+ const sel = this.doc.getSelection();
1990
+ if (sel.getRangeAt && sel.rangeCount) {
1991
+ this.savedSelection = sel.getRangeAt(0);
1992
+ this.selectedText = sel.toString();
1993
+ }
1994
+ break;
1995
+ case !!this.doc.getSelection && !!this.doc.createRange:
1996
+ this.savedSelection = document.createRange();
1997
+ break;
1998
+ default:
1999
+ this.savedSelection = null;
2000
+ }
2001
+ }
2002
+ command(name, value) {
2003
+ this.doc.execCommand(name, false, value);
2004
+ }
2005
+ formatBlock(heading) {
2006
+ const headings = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'pre'];
2007
+ if (headings.includes(heading)) {
2008
+ this.doc.execCommand(Commands.FORMAT_BLOCK, false, heading);
2009
+ }
2010
+ }
2011
+ createLink(link) {
2012
+ const newUrl = `<a href="${link.url}" title="${link.tooltip}" target="${link.openNewWindow ? '_blank' : '_self'}">${link.text}</a>`;
2013
+ this.insertHtml(newUrl);
2014
+ }
2015
+ insertHtml(html) {
2016
+ const isHTMLInserted = this.doc.execCommand(Commands.INSERT_HTML, false, html);
2017
+ if (!isHTMLInserted) {
2018
+ throw new Error('Unable to perform the operation');
2019
+ }
2020
+ }
2021
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2022
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorService, providedIn: 'root' });
2023
+ }
2024
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorService, decorators: [{
2025
+ type: Injectable,
2026
+ args: [{
2027
+ providedIn: 'root'
2028
+ }]
2029
+ }], ctorParameters: () => [] });
2030
+
2031
+ class NsEditorColorPickerComponent {
2032
+ editor = inject(NsEditorService);
2033
+ presets;
2034
+ type = 'text_color';
2035
+ showPopup;
2036
+ activeColor;
2037
+ isActive;
2038
+ trackByIndex = (index) => index;
2039
+ ngOnInit() { }
2040
+ get command() {
2041
+ return this.type === 'text_color'
2042
+ ? Commands.TEXT_COLOR
2043
+ : Commands.BACKGROUND_COLOR;
2044
+ }
2045
+ toggle() {
2046
+ this.showPopup = !this.showPopup;
2047
+ }
2048
+ getContrastYIQ(hexadecimal) {
2049
+ const color = hexadecimal.replace('#', '');
2050
+ const r = parseInt(color.substring(0, 2), 16);
2051
+ const g = parseInt(color.substring(2, 4), 16);
2052
+ const b = parseInt(color.substring(4, 6), 16);
2053
+ const yiq = (r * 299 + g * 587 + b * 114) / 1000;
2054
+ return yiq >= 128 ? 'black' : 'white';
2055
+ }
2056
+ onColorSelect(color) {
2057
+ this.editor.command(this.command, (this.activeColor = color));
2058
+ this.toggle();
2059
+ }
2060
+ remove() { }
2061
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorColorPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2062
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsEditorColorPickerComponent, isStandalone: true, selector: "ns-editor-color-picker", inputs: { presets: "presets", type: "type" }, ngImport: i0, template: "<button type=\"button\" class=\"btn\" (click)=\"toggle()\">\n <span class=\"ns-editor__color-text\">\n <svg role=\"presentation\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14 12.5h-4l-.874 2.186A.5.5 0 0 1 8.66 15H7.273a.5.5 0 0 1-.456-.705l4.05-9A.5.5 0 0 1 11.323 5h1.354a.5.5 0 0 1 .456.295l4.05 9a.5.5 0 0 1-.456.705h-1.388a.5.5 0 0 1-.465-.314L14 12.5zm-.6-1.5L12 7.5 10.6 11h2.8z\"\n fill-rule=\"evenodd\"\n ></path>\n </svg>\n <span></span>\n </span>\n\n <svg\n role=\"presentation\"\n class=\"ns-editor__toggle\"\n fill=\"currentColor\"\n height=\"12px\"\n viewBox=\"0 0 16 16\"\n width=\"12px\"\n >\n <path\n d=\"M14,11.75a.74.74,0,0,1-.53-.22L8,6.06,2.53,11.53a.75.75,0,0,1-1.06-1.06l6-6a.75.75,0,0,1,1.06,0l6,6a.75.75,0,0,1,0,1.06A.74.74,0,0,1,14,11.75Z\"\n ></path>\n </svg>\n</button>\n\n@if (showPopup) {\n <div class=\"ns-editor__popup\">\n @for (colorGroup of presets; track $index) {\n <div class=\"ns-editor__color--container\">\n @for (color of colorGroup; track $index) {\n <button\n class=\"ns-editor__color\"\n type=\"button\"\n [ngStyle]=\"{ backgroundColor: color, color: getContrastYIQ(color) }\"\n [title]=\"color\"\n (click)=\"onColorSelect(color)\"\n ></button>\n }\n </div>\n }\n </div>\n}\n", styles: [".ns-editor__color-text{position:relative}.ns-editor__color-text span{position:absolute;left:0;right:0;top:17px;margin:auto;width:12px;height:3px;border-radius:3px;background:linear-gradient(to right,#6554c0 25%,#00b8d9 25% 50%,#ff991f 50% 75%,#de350b 75%)}.ns-editor__popup{position:absolute;min-width:10rem;padding:.8rem;width:230px;margin:0;z-index:1000;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.ns-editor__color--container{display:flex;justify-content:space-between}.ns-editor__color--container+.ns-editor__color--container{margin-top:5px}.ns-editor__color{border:none;outline:none;border-radius:6px;width:24px;height:24px;flex-shrink:0}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
2063
+ }
2064
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorColorPickerComponent, decorators: [{
2065
+ type: Component,
2066
+ args: [{ selector: 'ns-editor-color-picker', imports: [NgStyle], template: "<button type=\"button\" class=\"btn\" (click)=\"toggle()\">\n <span class=\"ns-editor__color-text\">\n <svg role=\"presentation\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14 12.5h-4l-.874 2.186A.5.5 0 0 1 8.66 15H7.273a.5.5 0 0 1-.456-.705l4.05-9A.5.5 0 0 1 11.323 5h1.354a.5.5 0 0 1 .456.295l4.05 9a.5.5 0 0 1-.456.705h-1.388a.5.5 0 0 1-.465-.314L14 12.5zm-.6-1.5L12 7.5 10.6 11h2.8z\"\n fill-rule=\"evenodd\"\n ></path>\n </svg>\n <span></span>\n </span>\n\n <svg\n role=\"presentation\"\n class=\"ns-editor__toggle\"\n fill=\"currentColor\"\n height=\"12px\"\n viewBox=\"0 0 16 16\"\n width=\"12px\"\n >\n <path\n d=\"M14,11.75a.74.74,0,0,1-.53-.22L8,6.06,2.53,11.53a.75.75,0,0,1-1.06-1.06l6-6a.75.75,0,0,1,1.06,0l6,6a.75.75,0,0,1,0,1.06A.74.74,0,0,1,14,11.75Z\"\n ></path>\n </svg>\n</button>\n\n@if (showPopup) {\n <div class=\"ns-editor__popup\">\n @for (colorGroup of presets; track $index) {\n <div class=\"ns-editor__color--container\">\n @for (color of colorGroup; track $index) {\n <button\n class=\"ns-editor__color\"\n type=\"button\"\n [ngStyle]=\"{ backgroundColor: color, color: getContrastYIQ(color) }\"\n [title]=\"color\"\n (click)=\"onColorSelect(color)\"\n ></button>\n }\n </div>\n }\n </div>\n}\n", styles: [".ns-editor__color-text{position:relative}.ns-editor__color-text span{position:absolute;left:0;right:0;top:17px;margin:auto;width:12px;height:3px;border-radius:3px;background:linear-gradient(to right,#6554c0 25%,#00b8d9 25% 50%,#ff991f 50% 75%,#de350b 75%)}.ns-editor__popup{position:absolute;min-width:10rem;padding:.8rem;width:230px;margin:0;z-index:1000;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.ns-editor__color--container{display:flex;justify-content:space-between}.ns-editor__color--container+.ns-editor__color--container{margin-top:5px}.ns-editor__color{border:none;outline:none;border-radius:6px;width:24px;height:24px;flex-shrink:0}\n"] }]
2067
+ }], propDecorators: { presets: [{
2068
+ type: Input
2069
+ }], type: [{
2070
+ type: Input
2071
+ }] } });
2072
+
2073
+ class NsEditorLabelPipe {
2074
+ editor = inject(NsEditorService);
2075
+ transform(key) {
2076
+ return this.editor.translate(key);
2077
+ }
2078
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorLabelPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2079
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.21", ngImport: i0, type: NsEditorLabelPipe, isStandalone: true, name: "nsEditorLabel" });
2080
+ }
2081
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorLabelPipe, decorators: [{
2082
+ type: Pipe,
2083
+ args: [{
2084
+ name: 'nsEditorLabel'
2085
+ }]
2086
+ }] });
2087
+
2088
+ class NsEditorLinkComponent {
2089
+ formLink;
2090
+ show;
2091
+ fb = inject(FormBuilder);
2092
+ editor = inject(NsEditorService);
2093
+ ngOnInit() {
2094
+ this.formLink = this.fb.group({
2095
+ text: ['', Validators.required],
2096
+ url: ['', Validators.required],
2097
+ tooltip: [''],
2098
+ openNewWindow: [true]
2099
+ });
2100
+ }
2101
+ insert() {
2102
+ if (this.formLink.valid) {
2103
+ this.editor.createLink(this.formLink.getRawValue());
2104
+ this.formLink.reset();
2105
+ this.show = false;
2106
+ }
2107
+ }
2108
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorLinkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2109
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.21", type: NsEditorLinkComponent, isStandalone: true, selector: "ns-editor-link", ngImport: i0, template: "<button type=\"button\" class=\"btn\" id=\"ns-editor-link\" (click)=\"show = true\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" role=\"presentation\">\n <path\n d=\"M12.654 8.764a.858.858 0 01-1.213-1.213l1.214-1.214a3.717 3.717 0 015.257 0 3.714 3.714 0 01.001 5.258l-1.214 1.214-.804.804a3.72 3.72 0 01-5.263.005.858.858 0 011.214-1.214c.781.782 2.05.78 2.836-.005l.804-.803 1.214-1.214a1.998 1.998 0 00-.001-2.831 2 2 0 00-2.83 0l-1.215 1.213zm-.808 6.472a.858.858 0 011.213 1.213l-1.214 1.214a3.717 3.717 0 01-5.257 0 3.714 3.714 0 01-.001-5.258l1.214-1.214.804-.804a3.72 3.72 0 015.263-.005.858.858 0 01-1.214 1.214 2.005 2.005 0 00-2.836.005l-.804.803L7.8 13.618a1.998 1.998 0 00.001 2.831 2 2 0 002.83 0l1.215-1.213z\"\n ></path>\n </svg>\n</button>\n\n<form\n [formGroup]=\"formLink\"\n class=\"ns-editor__form-link\"\n aria-labelledby=\"ns-editor-link\"\n [ngClass]=\"{ show: show }\"\n (ngSubmit)=\"insert()\"\n>\n <header>\n <label>{{ 'insert_link' | nsEditorLabel }}</label>\n <button type=\"button\" class=\"btn-close\" (click)=\"show = false\"></button>\n </header>\n\n <ns-input [formControlName]=\"'url'\" [placeholder]=\"'link' | nsEditorLabel\" />\n <ns-input [formControlName]=\"'text'\" [placeholder]=\"'text' | nsEditorLabel\" />\n <ns-input\n [formControlName]=\"'tooltip'\"\n [placeholder]=\"'tooltip_link' | nsEditorLabel\"\n />\n <ns-checkbox\n [formControlName]=\"'openNewWindow'\"\n [label]=\"'open_new_window' | nsEditorLabel\"\n />\n\n <footer>\n <ns-button type=\"submit\" [label]=\"'submit_link' | nsEditorLabel\" />\n </footer>\n</form>\n", styles: [".ns-editor__form-link{position:absolute;z-index:1000;display:none;min-width:10rem;padding:.8rem;margin:0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.ns-editor__form-link header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.5rem}.ns-editor__form-link footer{margin-top:.5rem}.ns-editor__form-link.show{display:block}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: NsInputComponent, selector: "ns-input", inputs: ["prepend", "append"] }, { kind: "component", type: NsCheckboxComponent, selector: "ns-checkbox" }, { kind: "component", type: NsButtonComponent, selector: "ns-button", inputs: ["label", "type", "theme", "block", "disabled", "loading", "icon", "value"] }, { kind: "pipe", type: NsEditorLabelPipe, name: "nsEditorLabel" }] });
2110
+ }
2111
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorLinkComponent, decorators: [{
2112
+ type: Component,
2113
+ args: [{ selector: 'ns-editor-link', imports: [
2114
+ ReactiveFormsModule,
2115
+ NgClass,
2116
+ NsEditorLabelPipe,
2117
+ NsInputComponent,
2118
+ NsCheckboxComponent,
2119
+ NsButtonComponent
2120
+ ], template: "<button type=\"button\" class=\"btn\" id=\"ns-editor-link\" (click)=\"show = true\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" role=\"presentation\">\n <path\n d=\"M12.654 8.764a.858.858 0 01-1.213-1.213l1.214-1.214a3.717 3.717 0 015.257 0 3.714 3.714 0 01.001 5.258l-1.214 1.214-.804.804a3.72 3.72 0 01-5.263.005.858.858 0 011.214-1.214c.781.782 2.05.78 2.836-.005l.804-.803 1.214-1.214a1.998 1.998 0 00-.001-2.831 2 2 0 00-2.83 0l-1.215 1.213zm-.808 6.472a.858.858 0 011.213 1.213l-1.214 1.214a3.717 3.717 0 01-5.257 0 3.714 3.714 0 01-.001-5.258l1.214-1.214.804-.804a3.72 3.72 0 015.263-.005.858.858 0 01-1.214 1.214 2.005 2.005 0 00-2.836.005l-.804.803L7.8 13.618a1.998 1.998 0 00.001 2.831 2 2 0 002.83 0l1.215-1.213z\"\n ></path>\n </svg>\n</button>\n\n<form\n [formGroup]=\"formLink\"\n class=\"ns-editor__form-link\"\n aria-labelledby=\"ns-editor-link\"\n [ngClass]=\"{ show: show }\"\n (ngSubmit)=\"insert()\"\n>\n <header>\n <label>{{ 'insert_link' | nsEditorLabel }}</label>\n <button type=\"button\" class=\"btn-close\" (click)=\"show = false\"></button>\n </header>\n\n <ns-input [formControlName]=\"'url'\" [placeholder]=\"'link' | nsEditorLabel\" />\n <ns-input [formControlName]=\"'text'\" [placeholder]=\"'text' | nsEditorLabel\" />\n <ns-input\n [formControlName]=\"'tooltip'\"\n [placeholder]=\"'tooltip_link' | nsEditorLabel\"\n />\n <ns-checkbox\n [formControlName]=\"'openNewWindow'\"\n [label]=\"'open_new_window' | nsEditorLabel\"\n />\n\n <footer>\n <ns-button type=\"submit\" [label]=\"'submit_link' | nsEditorLabel\" />\n </footer>\n</form>\n", styles: [".ns-editor__form-link{position:absolute;z-index:1000;display:none;min-width:10rem;padding:.8rem;margin:0;font-size:1rem;color:#212529;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid rgba(0,0,0,.15);border-radius:.25rem}.ns-editor__form-link header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.5rem}.ns-editor__form-link footer{margin-top:.5rem}.ns-editor__form-link.show{display:block}\n"] }]
2121
+ }] });
2122
+
2123
+ class NsEditorListComponent {
2124
+ editor = inject(NsEditorService);
2125
+ commands = Commands;
2126
+ ngOnInit() { }
2127
+ command(name) {
2128
+ this.editor.command(name);
2129
+ }
2130
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2131
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.21", type: NsEditorListComponent, isStandalone: true, selector: "ns-editor-list", ngImport: i0, template: "<button\n type=\"button\"\n class=\"btn\"\n (click)=\"command(commands.INSERT_UNORDERED_LIST)\"\n>\n <svg viewBox=\"0 0 24 24\" role=\"presentation\">\n <path\n d=\"M6 8c0-.552.444-1 1-1 .552 0 1 .444 1 1 0 .552-.444 1-1 1-.552 0-1-.444-1-1zm5-1h6a1 1 0 010 2h-6a1 1 0 010-2zm-5 5c0-.552.444-1 1-1 .552 0 1 .444 1 1 0 .552-.444 1-1 1-.552 0-1-.444-1-1zm5-1h6a1 1 0 010 2h-6a1 1 0 010-2zm-5 5c0-.552.444-1 1-1 .552 0 1 .444 1 1 0 .552-.444 1-1 1-.552 0-1-.444-1-1zm5-1h6a1 1 0 010 2h-6a1 1 0 010-2z\"\n fill-rule=\"evenodd\"\n ></path>\n </svg>\n</button>\n\n<button\n type=\"button\"\n class=\"btn\"\n (click)=\"command(commands.INSERT_ORDERED_LIST)\"\n>\n <svg viewBox=\"0 0 24 24\" role=\"presentation\">\n <path\n d=\"M11 7h6a1 1 0 010 2h-6a1 1 0 010-2zm0 4h6a1 1 0 010 2h-6a1 1 0 010-2zm0 4h6a1 1 0 010 2h-6a1 1 0 010-2zm-5 0h3v1H6v-1zm0 2h3v1H6v-1zm1-9H6V7h2v3H7V8zm-1 3h3v1.333h-.6V13H7.2v-.667H6V11zm0 2h3v1H6v-1zm2 3h2v1H8v-1z\"\n fill-rule=\"evenodd\"\n ></path>\n </svg>\n</button>\n" });
2132
+ }
2133
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorListComponent, decorators: [{
2134
+ type: Component,
2135
+ args: [{ selector: 'ns-editor-list', template: "<button\n type=\"button\"\n class=\"btn\"\n (click)=\"command(commands.INSERT_UNORDERED_LIST)\"\n>\n <svg viewBox=\"0 0 24 24\" role=\"presentation\">\n <path\n d=\"M6 8c0-.552.444-1 1-1 .552 0 1 .444 1 1 0 .552-.444 1-1 1-.552 0-1-.444-1-1zm5-1h6a1 1 0 010 2h-6a1 1 0 010-2zm-5 5c0-.552.444-1 1-1 .552 0 1 .444 1 1 0 .552-.444 1-1 1-.552 0-1-.444-1-1zm5-1h6a1 1 0 010 2h-6a1 1 0 010-2zm-5 5c0-.552.444-1 1-1 .552 0 1 .444 1 1 0 .552-.444 1-1 1-.552 0-1-.444-1-1zm5-1h6a1 1 0 010 2h-6a1 1 0 010-2z\"\n fill-rule=\"evenodd\"\n ></path>\n </svg>\n</button>\n\n<button\n type=\"button\"\n class=\"btn\"\n (click)=\"command(commands.INSERT_ORDERED_LIST)\"\n>\n <svg viewBox=\"0 0 24 24\" role=\"presentation\">\n <path\n d=\"M11 7h6a1 1 0 010 2h-6a1 1 0 010-2zm0 4h6a1 1 0 010 2h-6a1 1 0 010-2zm0 4h6a1 1 0 010 2h-6a1 1 0 010-2zm-5 0h3v1H6v-1zm0 2h3v1H6v-1zm1-9H6V7h2v3H7V8zm-1 3h3v1.333h-.6V13H7.2v-.667H6V11zm0 2h3v1H6v-1zm2 3h2v1H8v-1z\"\n fill-rule=\"evenodd\"\n ></path>\n </svg>\n</button>\n" }]
2136
+ }] });
2137
+
2138
+ class NsEditorParagraphComponent {
2139
+ editor = inject(NsEditorService);
2140
+ id = Guid.create();
2141
+ _value = 'p';
2142
+ get value() {
2143
+ return this._value;
2144
+ }
2145
+ set value(heading) {
2146
+ this.editor.formatBlock(heading);
2147
+ }
2148
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorParagraphComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2149
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.21", type: NsEditorParagraphComponent, isStandalone: true, selector: "ns-editor-paragraph", ngImport: i0, template: "<ns-dropdown [(ngModel)]=\"value\">\n <ns-dropdown-item [label]=\"'paragraph' | nsEditorLabel\" [value]=\"'p'\" />\n <ns-dropdown-item [label]=\"'h1' | nsEditorLabel\" [value]=\"'h1'\" />\n <ns-dropdown-item [label]=\"'h2' | nsEditorLabel\" [value]=\"'h2'\" />\n <ns-dropdown-item [label]=\"'h3' | nsEditorLabel\" [value]=\"'h3'\" />\n <ns-dropdown-item [label]=\"'h4' | nsEditorLabel\" [value]=\"'h4'\" />\n <ns-dropdown-item [label]=\"'h5' | nsEditorLabel\" [value]=\"'h5'\" />\n <ns-dropdown-item [label]=\"'h6' | nsEditorLabel\" [value]=\"'h6'\" />\n</ns-dropdown>\n", styles: [""], dependencies: [{ kind: "component", type: NsDropdownComponent, selector: "ns-dropdown", inputs: ["labelField", "valueField", "iconName", "defaultFirst", "placement", "filterable", "collection"] }, { kind: "directive", type: NsDropdownItemDirective, selector: "ns-dropdown-item", inputs: ["label", "value", "disabled"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: NsEditorLabelPipe, name: "nsEditorLabel" }] });
2150
+ }
2151
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorParagraphComponent, decorators: [{
2152
+ type: Component,
2153
+ args: [{ selector: 'ns-editor-paragraph', imports: [
2154
+ NsDropdownComponent,
2155
+ NsDropdownItemDirective,
2156
+ FormsModule,
2157
+ NsEditorLabelPipe
2158
+ ], template: "<ns-dropdown [(ngModel)]=\"value\">\n <ns-dropdown-item [label]=\"'paragraph' | nsEditorLabel\" [value]=\"'p'\" />\n <ns-dropdown-item [label]=\"'h1' | nsEditorLabel\" [value]=\"'h1'\" />\n <ns-dropdown-item [label]=\"'h2' | nsEditorLabel\" [value]=\"'h2'\" />\n <ns-dropdown-item [label]=\"'h3' | nsEditorLabel\" [value]=\"'h3'\" />\n <ns-dropdown-item [label]=\"'h4' | nsEditorLabel\" [value]=\"'h4'\" />\n <ns-dropdown-item [label]=\"'h5' | nsEditorLabel\" [value]=\"'h5'\" />\n <ns-dropdown-item [label]=\"'h6' | nsEditorLabel\" [value]=\"'h6'\" />\n</ns-dropdown>\n" }]
2159
+ }] });
2160
+
2161
+ class NsEditorToggleCommandComponent {
2162
+ editor = inject(NsEditorService);
2163
+ commands = Commands;
2164
+ command(name) {
2165
+ this.editor.command(name);
2166
+ }
2167
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorToggleCommandComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2168
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.21", type: NsEditorToggleCommandComponent, isStandalone: true, selector: "ns-editor-toggle", ngImport: i0, template: "<button type=\"button\" class=\"btn\" (click)=\"command(commands.BOLD)\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n focusable=\"false\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M8 5a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h4.5c2.481 0 4.5-1.165 4.5-4 0-1.698-.724-2.796-1.837-3.405C15.69 10.967 16 10.112 16 9c0-2.835-2.019-4-4.5-4H8Zm1 2v4h3c1.379 0 2-.857 2-2s-.621-2-2-2H9Zm0 6v4h4c1.379 0 2-.857 2-2s-.621-2-2-2H9Z\"\n clip-rule=\"evenodd\"\n ></path>\n </svg>\n</button>\n\n<button type=\"button\" class=\"btn\" (click)=\"command(commands.ITALIC)\">\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n focusable=\"false\"\n aria-hidden=\"true\"\n >\n <path\n clip-rule=\"evenodd\"\n d=\"M9 6a1 1 0 0 1 1-1h6a1 1 0 1 1 0 2h-2.167l-1.666 10H14a1 1 0 1 1 0 2H8a1 1 0 1 1 0-2h2.167l1.666-10H10a1 1 0 0 1-1-1Z\"\n ></path>\n </svg>\n</button>\n\n<button type=\"button\" class=\"btn\" (click)=\"command(commands.UNDERLINE)\">\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n focusable=\"false\"\n aria-hidden=\"true\"\n >\n <path\n clip-rule=\"evenodd\"\n d=\"M9 5a1 1 0 0 1 1 1v5.5c0 1.343.556 2.5 2 2.5s2-1.157 2-2.5V6a1 1 0 1 1 2 0v5.657C16 13.804 14.469 16 12 16c-2.462 0-4-2.196-4-4.343V6a1 1 0 0 1 1-1ZM6 17a1 1 0 1 0 0 2h12a1 1 0 1 0 0-2H6Z\"\n ></path>\n </svg>\n</button>\n", styles: [""] });
2169
+ }
2170
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorToggleCommandComponent, decorators: [{
2171
+ type: Component,
2172
+ args: [{ selector: 'ns-editor-toggle', template: "<button type=\"button\" class=\"btn\" (click)=\"command(commands.BOLD)\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n focusable=\"false\"\n aria-hidden=\"true\"\n >\n <path\n fill-rule=\"evenodd\"\n d=\"M8 5a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h4.5c2.481 0 4.5-1.165 4.5-4 0-1.698-.724-2.796-1.837-3.405C15.69 10.967 16 10.112 16 9c0-2.835-2.019-4-4.5-4H8Zm1 2v4h3c1.379 0 2-.857 2-2s-.621-2-2-2H9Zm0 6v4h4c1.379 0 2-.857 2-2s-.621-2-2-2H9Z\"\n clip-rule=\"evenodd\"\n ></path>\n </svg>\n</button>\n\n<button type=\"button\" class=\"btn\" (click)=\"command(commands.ITALIC)\">\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n focusable=\"false\"\n aria-hidden=\"true\"\n >\n <path\n clip-rule=\"evenodd\"\n d=\"M9 6a1 1 0 0 1 1-1h6a1 1 0 1 1 0 2h-2.167l-1.666 10H14a1 1 0 1 1 0 2H8a1 1 0 1 1 0-2h2.167l1.666-10H10a1 1 0 0 1-1-1Z\"\n ></path>\n </svg>\n</button>\n\n<button type=\"button\" class=\"btn\" (click)=\"command(commands.UNDERLINE)\">\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n xmlns=\"http://www.w3.org/2000/svg\"\n focusable=\"false\"\n aria-hidden=\"true\"\n >\n <path\n clip-rule=\"evenodd\"\n d=\"M9 5a1 1 0 0 1 1 1v5.5c0 1.343.556 2.5 2 2.5s2-1.157 2-2.5V6a1 1 0 1 1 2 0v5.657C16 13.804 14.469 16 12 16c-2.462 0-4-2.196-4-4.343V6a1 1 0 0 1 1-1ZM6 17a1 1 0 1 0 0 2h12a1 1 0 1 0 0-2H6Z\"\n ></path>\n </svg>\n</button>\n" }]
2173
+ }] });
2174
+
2175
+ const DEFAULT_COLOR_PRESETS = [
2176
+ '#b60205',
2177
+ '#d93f0b',
2178
+ '#fbca04',
2179
+ '#0e8a16',
2180
+ '#006b75',
2181
+ '#1d76db',
2182
+ '#0052cc',
2183
+ '#5319e7',
2184
+ '#e99695',
2185
+ '#f9d0c4',
2186
+ '#fef2c0',
2187
+ '#c2e0c6',
2188
+ '#bfdadc',
2189
+ '#c5def5',
2190
+ '#bfd4f2',
2191
+ '#d4c5f9'
2192
+ ];
2193
+ class NsEditorComponent extends NsValueAccessor {
2194
+ editor = inject(NsEditorService);
2195
+ rows = 3;
2196
+ maxLength;
2197
+ colorPresets = DEFAULT_COLOR_PRESETS;
2198
+ textArea;
2199
+ focused = () => this.textArea.nativeElement.focus();
2200
+ ngOnInit() { }
2201
+ get presets() {
2202
+ const col = 8;
2203
+ const colors = [];
2204
+ this.colorPresets.forEach((color, index) => {
2205
+ const row = Math.floor(index / col);
2206
+ if (!colors[row]) {
2207
+ colors.push([]);
2208
+ }
2209
+ colors[row].push(color);
2210
+ });
2211
+ return colors;
2212
+ }
2213
+ blur() {
2214
+ this.editor.saveSelection();
2215
+ this.onTouched();
2216
+ }
2217
+ ngOnDestroy() { }
2218
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2219
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsEditorComponent, isStandalone: true, selector: "ns-editor", inputs: { rows: "rows", maxLength: "maxLength", colorPresets: "colorPresets" }, host: { listeners: { "click": "focused()" }, properties: { "class.ns-editor": "true", "class.ns-editor--disabled": "disabled" } }, providers: [
2220
+ {
2221
+ provide: NG_VALUE_ACCESSOR,
2222
+ useExisting: forwardRef(() => NsEditorComponent),
2223
+ multi: true
2224
+ }
2225
+ ], viewQueries: [{ propertyName: "textArea", first: true, predicate: NsContentEditableComponent, descendants: true, read: ElementRef, static: true }], usesInheritance: true, ngImport: i0, template: "@if (label) {\n <label class=\"form-label\" [attr.for]=\"id\">{{ label }}</label>\n}\n\n<ul class=\"ns-editor__toolbar\">\n <li class=\"ns-editor__item\">\n <ns-editor-paragraph />\n </li>\n\n <li class=\"ns-editor__item\">\n <ns-editor-toggle />\n </li>\n\n <li class=\"ns-editor__item\">\n <ns-editor-color-picker [presets]=\"presets\" />\n </li>\n\n <li class=\"ns-editor__item\">\n <ns-editor-list />\n </li>\n\n <li class=\"ns-editor__item\">\n <ns-editor-link />\n </li>\n</ul>\n\n<ns-content-editable\n class=\"ns-editor__content\"\n [id]=\"id\"\n (blur)=\"blur()\"\n [maxlength]=\"maxLength\"\n [disabled]=\"disabled\"\n [(ngModel)]=\"value\"\n/>\n", styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}.ns-editor{display:block;margin-bottom:.5rem}.ns-editor__toolbar{display:flex;justify-content:flex-start;align-items:center;background:#fafbfb;border:1px solid #cfcfdb;border-bottom:none;border-radius:.375rem .375rem 0 0;padding:.375rem .5rem;list-style:none;margin-bottom:unset}.ns-editor__item{display:flex;align-items:center}.ns-editor__item .dropdown{display:inline-block;margin-bottom:unset}.ns-editor__item .dropdown>.btn{margin-bottom:unset;background-color:transparent;border:unset;box-shadow:none}.ns-editor__item .btn{position:relative;padding:unset}.ns-editor__item:not(:last-child):after{font-size:2rem;font-weight:100;color:#dfdfdf;content:\"|\";margin:0 8px}.ns-editor__item svg{fill:#5c5f62;width:1.5rem;height:1.5rem}.ns-editor__item svg.ns-editor__toggle,.ns-editor__item svg.dropdown-toggle{width:.8rem;height:.8rem;transform:rotate(180deg)}.ns-editor__content{padding:.5rem;border:1px solid #cfcfdb;border-radius:0 0 .375rem .375rem}.ns-editor__content textarea{outline:none;margin-bottom:-3px;border:unset;width:100%}.ns-editor--disabled{pointer-events:none}.ns-editor--disabled .ns-editor__toolbar{opacity:.65}\n"], dependencies: [{ kind: "component", type: NsEditorParagraphComponent, selector: "ns-editor-paragraph" }, { kind: "component", type: NsEditorToggleCommandComponent, selector: "ns-editor-toggle" }, { kind: "component", type: NsEditorColorPickerComponent, selector: "ns-editor-color-picker", inputs: ["presets", "type"] }, { kind: "component", type: NsEditorListComponent, selector: "ns-editor-list" }, { kind: "component", type: NsEditorLinkComponent, selector: "ns-editor-link" }, { kind: "component", type: NsContentEditableComponent, selector: "ns-content-editable", inputs: ["maxlength"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], encapsulation: i0.ViewEncapsulation.None });
2226
+ }
2227
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsEditorComponent, decorators: [{
2228
+ type: Component,
2229
+ args: [{ selector: 'ns-editor', providers: [
2230
+ {
2231
+ provide: NG_VALUE_ACCESSOR,
2232
+ useExisting: forwardRef(() => NsEditorComponent),
2233
+ multi: true
2234
+ }
2235
+ ], encapsulation: ViewEncapsulation.None, host: {
2236
+ '[class.ns-editor]': 'true',
2237
+ '[class.ns-editor--disabled]': 'disabled'
2238
+ }, imports: [
2239
+ NsEditorParagraphComponent,
2240
+ NsEditorToggleCommandComponent,
2241
+ NsEditorColorPickerComponent,
2242
+ NsEditorListComponent,
2243
+ NsEditorLinkComponent,
2244
+ NsContentEditableComponent,
2245
+ FormsModule
2246
+ ], template: "@if (label) {\n <label class=\"form-label\" [attr.for]=\"id\">{{ label }}</label>\n}\n\n<ul class=\"ns-editor__toolbar\">\n <li class=\"ns-editor__item\">\n <ns-editor-paragraph />\n </li>\n\n <li class=\"ns-editor__item\">\n <ns-editor-toggle />\n </li>\n\n <li class=\"ns-editor__item\">\n <ns-editor-color-picker [presets]=\"presets\" />\n </li>\n\n <li class=\"ns-editor__item\">\n <ns-editor-list />\n </li>\n\n <li class=\"ns-editor__item\">\n <ns-editor-link />\n </li>\n</ul>\n\n<ns-content-editable\n class=\"ns-editor__content\"\n [id]=\"id\"\n (blur)=\"blur()\"\n [maxlength]=\"maxLength\"\n [disabled]=\"disabled\"\n [(ngModel)]=\"value\"\n/>\n", styles: [":host{display:block;position:relative;font-size:var(--ns-font-size-sm, .875rem);width:100%;max-width:100%;margin-bottom:var(--ns-space-2, .5rem)}:host .form-control,:host .form-select{border:1px solid var(--ns-color-border, #cfcfdb);border-radius:var(--ns-radius-sm, .375rem);font-size:var(--ns-font-size-base, 1rem);line-height:1.5;padding:var(--ns-control-padding-y, .5rem) var(--ns-control-padding-x, .75rem);resize:vertical}:host .form-control:focus,:host .form-select:focus{border-color:var(--ns-color-focus, #567af0);box-shadow:unset;outline:0}:host .form-control::placeholder,:host .form-select::placeholder{color:var(--ns-gray-400, #bdbed4);font-weight:600;font-size:.875rem}:host .form-control:disabled,:host .form-control[readonly],:host .form-select:disabled,:host .form-select[readonly]{background-color:var(--ns-color-surface, #fff);opacity:.65}:host .input-group-text{background-color:var(--ns-color-surface, #fff)}.ns-editor{display:block;margin-bottom:.5rem}.ns-editor__toolbar{display:flex;justify-content:flex-start;align-items:center;background:#fafbfb;border:1px solid #cfcfdb;border-bottom:none;border-radius:.375rem .375rem 0 0;padding:.375rem .5rem;list-style:none;margin-bottom:unset}.ns-editor__item{display:flex;align-items:center}.ns-editor__item .dropdown{display:inline-block;margin-bottom:unset}.ns-editor__item .dropdown>.btn{margin-bottom:unset;background-color:transparent;border:unset;box-shadow:none}.ns-editor__item .btn{position:relative;padding:unset}.ns-editor__item:not(:last-child):after{font-size:2rem;font-weight:100;color:#dfdfdf;content:\"|\";margin:0 8px}.ns-editor__item svg{fill:#5c5f62;width:1.5rem;height:1.5rem}.ns-editor__item svg.ns-editor__toggle,.ns-editor__item svg.dropdown-toggle{width:.8rem;height:.8rem;transform:rotate(180deg)}.ns-editor__content{padding:.5rem;border:1px solid #cfcfdb;border-radius:0 0 .375rem .375rem}.ns-editor__content textarea{outline:none;margin-bottom:-3px;border:unset;width:100%}.ns-editor--disabled{pointer-events:none}.ns-editor--disabled .ns-editor__toolbar{opacity:.65}\n"] }]
2247
+ }], propDecorators: { rows: [{
2248
+ type: Input
2249
+ }], maxLength: [{
2250
+ type: Input
2251
+ }], colorPresets: [{
2252
+ type: Input
2253
+ }], textArea: [{
2254
+ type: ViewChild,
2255
+ args: [NsContentEditableComponent, { read: ElementRef, static: true }]
2256
+ }], focused: [{
2257
+ type: HostListener,
2258
+ args: ['click']
2259
+ }] } });
2260
+
2261
+ class NsImageUrlPipe {
2262
+ transform(image) {
2263
+ let url = '';
2264
+ if (image && image.data && typeof image.data === 'string') {
2265
+ switch (true) {
2266
+ case URL.canParse(image.data) || /data:/.test(image.data):
2267
+ url = image.data;
2268
+ break;
2269
+ default:
2270
+ url = `data:${image.type};base64,${image.data}`;
2271
+ }
2272
+ }
2273
+ return url;
2274
+ }
2275
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsImageUrlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2276
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.21", ngImport: i0, type: NsImageUrlPipe, isStandalone: true, name: "nsImageUrl" });
2277
+ }
2278
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsImageUrlPipe, decorators: [{
2279
+ type: Pipe,
2280
+ args: [{
2281
+ name: 'nsImageUrl',
2282
+ standalone: true
2283
+ }]
2284
+ }] });
2285
+
2286
+ class NsImageUploadComponent extends NsValueAccessor {
2287
+ client = inject(NS_UPLOAD_CLIENT, { optional: true });
2288
+ renderer = inject(Renderer2);
2289
+ accept = '.jpg,.jpeg,.png,.webp,.avif,.gif';
2290
+ multi = false;
2291
+ limit = 5;
2292
+ imgRef;
2293
+ loading = new Set();
2294
+ _fromIndex;
2295
+ _toIndex;
2296
+ get images() {
2297
+ return Array.isArray(this.value) ? this.value : [];
2298
+ }
2299
+ get image() {
2300
+ return Array.isArray(this.value) ? null : this.value;
2301
+ }
2302
+ writeValue(value) {
2303
+ if (Array.isArray(value)) {
2304
+ this._value = value;
2305
+ }
2306
+ else {
2307
+ this._value = this.multi && !value ? [] : value;
2308
+ }
2309
+ }
2310
+ onClick() {
2311
+ this.imgRef.nativeElement.click();
2312
+ }
2313
+ load() {
2314
+ const { files } = this.imgRef.nativeElement;
2315
+ if (files.length) {
2316
+ this.add(NsFile.parse(files.item(0)));
2317
+ this.imgRef.nativeElement.value = null;
2318
+ }
2319
+ }
2320
+ add(image) {
2321
+ this.loading.add(image.name);
2322
+ const reader = new FileReader();
2323
+ reader.readAsDataURL(image.data);
2324
+ reader.onload = () => {
2325
+ if (this.client) {
2326
+ this.client.upload(image).subscribe({
2327
+ next: (data) => {
2328
+ if (this.multi) {
2329
+ this._value = this.images.filter((img) => !this.compareWith(img, image));
2330
+ }
2331
+ this.loading.delete(image.name);
2332
+ this.assignValue(data);
2333
+ },
2334
+ error: () => {
2335
+ this.loading.delete(image.name);
2336
+ }
2337
+ });
2338
+ image.data = reader.result;
2339
+ this.assignValue(image);
2340
+ }
2341
+ else {
2342
+ image.data = reader.result;
2343
+ this.loading.delete(image.name);
2344
+ this.assignValue(image);
2345
+ }
2346
+ };
2347
+ }
2348
+ assignValue(image) {
2349
+ if (this.multi) {
2350
+ this._value = [...this.images, image];
2351
+ }
2352
+ else {
2353
+ this._value = image;
2354
+ }
2355
+ this.onChange(this._value);
2356
+ }
2357
+ compareWith(from, to) {
2358
+ return from.id === to.id || from.name === to.name;
2359
+ }
2360
+ remove(image) {
2361
+ this.loading.add(image.name);
2362
+ if (this.client && !!image.id) {
2363
+ this.client.remove(image.id).subscribe({
2364
+ next: () => {
2365
+ this.value = this.multi
2366
+ ? this.images.filter((img) => img !== image)
2367
+ : null;
2368
+ this.loading.delete(image.name);
2369
+ this.onChange(this.value);
2370
+ },
2371
+ error: () => {
2372
+ this.loading.delete(image.name);
2373
+ }
2374
+ });
2375
+ }
2376
+ else {
2377
+ this.value = this.multi
2378
+ ? this.images.filter((img) => img !== image)
2379
+ : null;
2380
+ this.loading.delete(image.name);
2381
+ }
2382
+ }
2383
+ dragstart(event, index) {
2384
+ this.renderer.setStyle(event.target, 'opacity', 0.4);
2385
+ event.dataTransfer.dropEffect = 'move';
2386
+ this._fromIndex = index;
2387
+ }
2388
+ dragover(event, index) {
2389
+ event.preventDefault();
2390
+ this._toIndex = index;
2391
+ }
2392
+ dragend(event) {
2393
+ this.renderer.setStyle(event.target, 'opacity', 1);
2394
+ }
2395
+ drop(event) {
2396
+ event.stopPropagation();
2397
+ if (this._fromIndex !== this._toIndex) {
2398
+ const images = this.images;
2399
+ const element = images[this._fromIndex];
2400
+ images.splice(this._fromIndex, 1);
2401
+ images.splice(this._toIndex, 0, element);
2402
+ this._value = images;
2403
+ this.onChange(this.value);
2404
+ }
2405
+ }
2406
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsImageUploadComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
2407
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsImageUploadComponent, isStandalone: true, selector: "ns-image-upload", inputs: { accept: "accept", multi: ["multi", "multi", booleanAttribute], limit: ["limit", "limit", numberAttribute] }, host: { properties: { "class.ns-image--loaded": "!multi && !!value", "class.ns-image--disabled": "disabled" } }, providers: [
2408
+ {
2409
+ provide: NG_VALUE_ACCESSOR,
2410
+ useExisting: forwardRef(() => NsImageUploadComponent),
2411
+ multi: true
2412
+ }
2413
+ ], viewQueries: [{ propertyName: "imgRef", first: true, predicate: ["input"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "<div\n class=\"ns-image__wrap\"\n [ngClass]=\"{ 'ns-image__multi': multi && images.length }\"\n>\n @if (multi) {\n @for (image of images; let i = $index; track i) {\n <div\n class=\"ns-image__thumbnail\"\n [draggable]=\"!disabled && images.length > 1\"\n (dragstart)=\"dragstart($event, i)\"\n (dragend)=\"dragend($event)\"\n (dragover)=\"dragover($event, i)\"\n (drop)=\"drop($event)\"\n >\n <button\n type=\"button\"\n class=\"ns-image__button\"\n [ngClass]=\"{ 'ns-image__loading': loading.has(image.name) }\"\n [disabled]=\"disabled\"\n >\n <img\n class=\"ns-image\"\n [attr.src]=\"image | nsImageUrl\"\n [attr.alt]=\"image.name\"\n />\n <ns-icon class=\"ns-image__preload\" name=\"preload\" />\n\n <div class=\"ns-image__overlay\">\n <ns-icon class=\"ns-image__drag\" name=\"drag-handle\" />\n <button\n type=\"button\"\n class=\"ns-image__remove\"\n (click)=\"remove(image)\"\n >\n <ns-icon name=\"trash\" />\n </button>\n </div>\n </button>\n </div>\n }\n }\n\n <button\n type=\"button\"\n class=\"ns-image__drag-container\"\n (click)=\"onClick()\"\n [ngClass]=\"{\n 'ns-image--loading': image && !multi && loading.has(image.name)\n }\"\n [hidden]=\"multi && images.length >= limit\"\n [disabled]=\"disabled\"\n >\n @if (image && !multi) {\n <img\n class=\"ns-image__fluid\"\n [attr.src]=\"image | nsImageUrl\"\n [ngClass]=\"{ disabled: disabled }\"\n alt\n />\n }\n\n <div class=\"ns-image__overlay\">\n <div class=\"ns-image__empty\">\n <ns-icon name=\"picture\" />\n <span>{{ label }}</span>\n </div>\n </div>\n\n <input\n [hidden]=\"true\"\n type=\"file\"\n (change)=\"load()\"\n [multiple]=\"false\"\n [accept]=\"accept\"\n #input\n [disabled]=\"disabled\"\n />\n </button>\n</div>\n", styles: [":host{display:block;position:relative;margin-bottom:.5rem}:host.ns-image--loaded .ns-image__overlay{opacity:0;background-color:#0000001a}:host.ns-image--loaded .ns-image__overlay .ns-icon{color:#fff}.ns-image{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%}.ns-image__wrap{width:100%;min-height:10rem;-webkit-user-select:none;user-select:none}.ns-image__wrap.ns-image__multi{display:grid;grid-template-columns:repeat(4,1fr);grid-column-gap:.5rem;grid-row-gap:.5rem}.ns-image__wrap.ns-image__multi .ns-image__drag-container{position:relative}.ns-image__drag-container{position:absolute;overflow:hidden;display:flex;justify-content:center;align-items:center;width:100%;height:100%;background-color:#e9ecef;border:1.5px dashed #cfcfdb;border-radius:5px;margin-bottom:1rem;flex-direction:column;gap:.25rem}.ns-image__drag-container:not(:disabled){background-color:#fff}.ns-image__drag-container:not(:disabled):hover{border:1.5px dashed #b3b3c0}.ns-image__drag-container:not(:disabled):hover .ns-image__overlay{opacity:.8}.ns-image__overlay{position:absolute;display:flex;justify-content:center;align-items:center;width:100%;height:100%;transition:opacity .3s ease-out;-webkit-user-select:none;user-select:none;opacity:.6}.ns-image__empty{display:flex;flex-direction:column;align-items:center;padding:1rem}.ns-image__fluid{width:100%;object-fit:cover}.ns-image__thumbnail{transition:all .3s ease-in-out;cursor:move}.ns-image__thumbnail:first-child{grid-column:1/span 2;grid-row:1/span 2}.ns-image__thumbnail img{display:block;height:100%;width:100%;position:absolute;object-fit:cover}.ns-image__button{border:unset;align-items:center;display:flex;justify-content:center;margin:0;position:relative;text-align:center;width:100%;height:100%;padding:.5rem;border-radius:5px;overflow:hidden}.ns-image__button .ns-image__overlay{opacity:0}.ns-image__button:not(:disabled,.ns-image__loading) .ns-image__overlay{background-color:#0000001a}.ns-image__button:not(:disabled,.ns-image__loading):hover .ns-image__overlay{opacity:1}.ns-image__text{margin-left:1rem}.ns-image__remove{color:#d82c0d;background:transparent;border:unset;position:absolute;top:.5rem;right:.3rem;z-index:5;padding:0}.ns-image__drag{color:#fff;position:absolute;top:.3rem;left:0;z-index:5}.ns-image__preload{display:none;color:#fff;z-index:5}.ns-image__loading{background-color:#0000001a}.ns-image__loading .ns-image__preload{display:block}.ns-image__loading .ns-image{opacity:.8}.ns-image--disabled{pointer-events:none;opacity:.65}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: NsIconsComponent, selector: "ns-icon", inputs: ["name", "color", "size", "strokeWidth", "viewBox"] }, { kind: "pipe", type: NsImageUrlPipe, name: "nsImageUrl" }] });
2414
+ }
2415
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsImageUploadComponent, decorators: [{
2416
+ type: Component,
2417
+ args: [{ selector: 'ns-image-upload', imports: [CommonModule, NsImageUrlPipe, NsIconsComponent], standalone: true, host: {
2418
+ '[class.ns-image--loaded]': '!multi && !!value',
2419
+ '[class.ns-image--disabled]': 'disabled'
2420
+ }, providers: [
2421
+ {
2422
+ provide: NG_VALUE_ACCESSOR,
2423
+ useExisting: forwardRef(() => NsImageUploadComponent),
2424
+ multi: true
2425
+ }
2426
+ ], template: "<div\n class=\"ns-image__wrap\"\n [ngClass]=\"{ 'ns-image__multi': multi && images.length }\"\n>\n @if (multi) {\n @for (image of images; let i = $index; track i) {\n <div\n class=\"ns-image__thumbnail\"\n [draggable]=\"!disabled && images.length > 1\"\n (dragstart)=\"dragstart($event, i)\"\n (dragend)=\"dragend($event)\"\n (dragover)=\"dragover($event, i)\"\n (drop)=\"drop($event)\"\n >\n <button\n type=\"button\"\n class=\"ns-image__button\"\n [ngClass]=\"{ 'ns-image__loading': loading.has(image.name) }\"\n [disabled]=\"disabled\"\n >\n <img\n class=\"ns-image\"\n [attr.src]=\"image | nsImageUrl\"\n [attr.alt]=\"image.name\"\n />\n <ns-icon class=\"ns-image__preload\" name=\"preload\" />\n\n <div class=\"ns-image__overlay\">\n <ns-icon class=\"ns-image__drag\" name=\"drag-handle\" />\n <button\n type=\"button\"\n class=\"ns-image__remove\"\n (click)=\"remove(image)\"\n >\n <ns-icon name=\"trash\" />\n </button>\n </div>\n </button>\n </div>\n }\n }\n\n <button\n type=\"button\"\n class=\"ns-image__drag-container\"\n (click)=\"onClick()\"\n [ngClass]=\"{\n 'ns-image--loading': image && !multi && loading.has(image.name)\n }\"\n [hidden]=\"multi && images.length >= limit\"\n [disabled]=\"disabled\"\n >\n @if (image && !multi) {\n <img\n class=\"ns-image__fluid\"\n [attr.src]=\"image | nsImageUrl\"\n [ngClass]=\"{ disabled: disabled }\"\n alt\n />\n }\n\n <div class=\"ns-image__overlay\">\n <div class=\"ns-image__empty\">\n <ns-icon name=\"picture\" />\n <span>{{ label }}</span>\n </div>\n </div>\n\n <input\n [hidden]=\"true\"\n type=\"file\"\n (change)=\"load()\"\n [multiple]=\"false\"\n [accept]=\"accept\"\n #input\n [disabled]=\"disabled\"\n />\n </button>\n</div>\n", styles: [":host{display:block;position:relative;margin-bottom:.5rem}:host.ns-image--loaded .ns-image__overlay{opacity:0;background-color:#0000001a}:host.ns-image--loaded .ns-image__overlay .ns-icon{color:#fff}.ns-image{display:flex;flex-direction:column;justify-content:center;align-items:center;width:100%}.ns-image__wrap{width:100%;min-height:10rem;-webkit-user-select:none;user-select:none}.ns-image__wrap.ns-image__multi{display:grid;grid-template-columns:repeat(4,1fr);grid-column-gap:.5rem;grid-row-gap:.5rem}.ns-image__wrap.ns-image__multi .ns-image__drag-container{position:relative}.ns-image__drag-container{position:absolute;overflow:hidden;display:flex;justify-content:center;align-items:center;width:100%;height:100%;background-color:#e9ecef;border:1.5px dashed #cfcfdb;border-radius:5px;margin-bottom:1rem;flex-direction:column;gap:.25rem}.ns-image__drag-container:not(:disabled){background-color:#fff}.ns-image__drag-container:not(:disabled):hover{border:1.5px dashed #b3b3c0}.ns-image__drag-container:not(:disabled):hover .ns-image__overlay{opacity:.8}.ns-image__overlay{position:absolute;display:flex;justify-content:center;align-items:center;width:100%;height:100%;transition:opacity .3s ease-out;-webkit-user-select:none;user-select:none;opacity:.6}.ns-image__empty{display:flex;flex-direction:column;align-items:center;padding:1rem}.ns-image__fluid{width:100%;object-fit:cover}.ns-image__thumbnail{transition:all .3s ease-in-out;cursor:move}.ns-image__thumbnail:first-child{grid-column:1/span 2;grid-row:1/span 2}.ns-image__thumbnail img{display:block;height:100%;width:100%;position:absolute;object-fit:cover}.ns-image__button{border:unset;align-items:center;display:flex;justify-content:center;margin:0;position:relative;text-align:center;width:100%;height:100%;padding:.5rem;border-radius:5px;overflow:hidden}.ns-image__button .ns-image__overlay{opacity:0}.ns-image__button:not(:disabled,.ns-image__loading) .ns-image__overlay{background-color:#0000001a}.ns-image__button:not(:disabled,.ns-image__loading):hover .ns-image__overlay{opacity:1}.ns-image__text{margin-left:1rem}.ns-image__remove{color:#d82c0d;background:transparent;border:unset;position:absolute;top:.5rem;right:.3rem;z-index:5;padding:0}.ns-image__drag{color:#fff;position:absolute;top:.3rem;left:0;z-index:5}.ns-image__preload{display:none;color:#fff;z-index:5}.ns-image__loading{background-color:#0000001a}.ns-image__loading .ns-image__preload{display:block}.ns-image__loading .ns-image{opacity:.8}.ns-image--disabled{pointer-events:none;opacity:.65}\n"] }]
2427
+ }], propDecorators: { accept: [{
2428
+ type: Input
2429
+ }], multi: [{
2430
+ type: Input,
2431
+ args: [{ transform: booleanAttribute }]
2432
+ }], limit: [{
2433
+ type: Input,
2434
+ args: [{ transform: numberAttribute }]
2435
+ }], imgRef: [{
2436
+ type: ViewChild,
2437
+ args: ['input', { static: false, read: ElementRef }]
2438
+ }] } });
2439
+
2440
+ class NsModalRef {
2441
+ ref = null;
2442
+ get instance() {
2443
+ if (!this.ref) {
2444
+ throw new Error('Modal reference has already been destroyed');
2445
+ }
2446
+ return this.ref.instance;
2447
+ }
2448
+ addTemplate(template) {
2449
+ switch (template.name) {
2450
+ case 'header':
2451
+ this.instance.headerRef = template.ref;
2452
+ break;
2453
+ case 'footer':
2454
+ this.instance.footerRef = template.ref;
2455
+ break;
2456
+ default:
2457
+ throw new Error('Cannot add template in modal');
2458
+ }
2459
+ }
2460
+ close(timeout = 300) {
2461
+ if (!this.ref) {
2462
+ return;
2463
+ }
2464
+ const ref = this.ref;
2465
+ ref.instance.show = false;
2466
+ ref.changeDetectorRef.detectChanges();
2467
+ timer(timeout)
2468
+ .pipe(take(1))
2469
+ .subscribe(() => {
2470
+ const { nativeElement } = ref.location;
2471
+ nativeElement.parentNode.removeChild(nativeElement);
2472
+ ref.destroy();
2473
+ ref.changeDetectorRef.detectChanges();
2474
+ this.ref = null;
2475
+ });
2476
+ }
2477
+ onDestroy(callback) {
2478
+ this.ref?.onDestroy(callback);
2479
+ }
2480
+ }
2481
+
2482
+ class NsModalComponent {
2483
+ title;
2484
+ size;
2485
+ component;
2486
+ context;
2487
+ close;
2488
+ show;
2489
+ headerRef;
2490
+ footerRef;
2491
+ containerRef;
2492
+ cd = inject(ChangeDetectorRef);
2493
+ keydown(event) {
2494
+ if (event.key == 'Escape') {
2495
+ this.close();
2496
+ }
2497
+ }
2498
+ ngAfterViewInit() {
2499
+ if (this.containerRef) {
2500
+ const componentRef = this.containerRef.createComponent(this.component);
2501
+ Object.assign(componentRef.instance, this.context);
2502
+ this.cd.detectChanges();
2503
+ }
2504
+ }
2505
+ ngAfterViewChecked() {
2506
+ this.cd.detectChanges();
2507
+ }
2508
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2509
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsModalComponent, isStandalone: true, selector: "ns-modal", host: { listeners: { "window:keydown": "keydown($event)" }, properties: { "class.ns-modal": "true" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<div\n role=\"document\"\n class=\"ns-modal__dialog\"\n [ngClass]=\"{ 'ns-modal__lg': size == 'lg', 'ns-modal__xl': size == 'xl' }\"\n>\n <div class=\"ns-modal__content\">\n <div class=\"ns-modal__header\">\n @if (headerRef) {\n <ng-template [ngTemplateOutlet]=\"headerRef\"></ng-template>\n } @else {\n <h4 class=\"ns-modal__title\">{{ title }}</h4>\n <button\n type=\"button\"\n aria-label=\"Close\"\n class=\"btn-close\"\n (click)=\"close()\"\n ></button>\n }\n\n <ng-template #defaultHeaderRef>\n <h4 class=\"ns-modal__title\">{{ title }}</h4>\n <button\n type=\"button\"\n aria-label=\"Close\"\n class=\"btn-close\"\n (click)=\"close()\"\n ></button>\n </ng-template>\n </div>\n\n <div class=\"ns-modal__body\">\n <ng-template #container />\n </div>\n\n @if (footerRef) {\n <div class=\"ns-modal__footer\">\n <ng-template [ngTemplateOutlet]=\"footerRef\"></ng-template>\n </div>\n }\n </div>\n</div>\n\n<div class=\"ns-modal__backdrop\" (click)=\"close()\"></div>\n", styles: [":host{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:var(--ns-backdrop-zindex, 1050)}@media(min-width:992px){:host.ns-modal__lg{--ns-modal-width: 800px}}.ns-modal__content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--ns-modal-color);pointer-events:auto;background-color:var(--ns-modal-bg, var(--ns-color-surface, #fff));background-clip:padding-box;border:var(--ns-modal-border-width, 1px) solid var(--ns-modal-border-color, var(--ns-color-border, rgba(0, 0, 0, .1764705882)));border-radius:var(--ns-modal-border-radius, var(--ns-radius-md, .5rem));outline:0}.ns-modal__dialog{position:relative;width:auto;margin:var(--ns-modal-margin, 1.75rem);margin-right:auto;margin-left:auto;pointer-events:none;max-width:var(--ns-modal-width, 500px);z-index:1}.ns-modal__backdrop{background-color:var(--ns-backdrop-bg, rgba(0, 0, 0, .47));position:fixed;top:0;left:0;width:100vw;height:100vh}.ns-modal__title{margin-bottom:unset}.ns-modal__open{overflow:hidden}.ns-modal__header{display:flex;justify-content:space-between;align-items:center;padding:var(--ns-modal-header-padding, var(--ns-space-4, 1rem))}.ns-modal__body{position:relative;flex:1 1 auto;padding:var(--ns-modal-padding, var(--ns-space-4, 1rem))}.ns-modal__footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:var(--ns-modal-footer-padding, var(--ns-space-4, 1rem))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2510
+ }
2511
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsModalComponent, decorators: [{
2512
+ type: Component,
2513
+ args: [{ selector: 'ns-modal', imports: [CommonModule], standalone: true, host: {
2514
+ '[class.ns-modal]': 'true'
2515
+ }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n role=\"document\"\n class=\"ns-modal__dialog\"\n [ngClass]=\"{ 'ns-modal__lg': size == 'lg', 'ns-modal__xl': size == 'xl' }\"\n>\n <div class=\"ns-modal__content\">\n <div class=\"ns-modal__header\">\n @if (headerRef) {\n <ng-template [ngTemplateOutlet]=\"headerRef\"></ng-template>\n } @else {\n <h4 class=\"ns-modal__title\">{{ title }}</h4>\n <button\n type=\"button\"\n aria-label=\"Close\"\n class=\"btn-close\"\n (click)=\"close()\"\n ></button>\n }\n\n <ng-template #defaultHeaderRef>\n <h4 class=\"ns-modal__title\">{{ title }}</h4>\n <button\n type=\"button\"\n aria-label=\"Close\"\n class=\"btn-close\"\n (click)=\"close()\"\n ></button>\n </ng-template>\n </div>\n\n <div class=\"ns-modal__body\">\n <ng-template #container />\n </div>\n\n @if (footerRef) {\n <div class=\"ns-modal__footer\">\n <ng-template [ngTemplateOutlet]=\"footerRef\"></ng-template>\n </div>\n }\n </div>\n</div>\n\n<div class=\"ns-modal__backdrop\" (click)=\"close()\"></div>\n", styles: [":host{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:var(--ns-backdrop-zindex, 1050)}@media(min-width:992px){:host.ns-modal__lg{--ns-modal-width: 800px}}.ns-modal__content{position:relative;display:flex;flex-direction:column;width:100%;color:var(--ns-modal-color);pointer-events:auto;background-color:var(--ns-modal-bg, var(--ns-color-surface, #fff));background-clip:padding-box;border:var(--ns-modal-border-width, 1px) solid var(--ns-modal-border-color, var(--ns-color-border, rgba(0, 0, 0, .1764705882)));border-radius:var(--ns-modal-border-radius, var(--ns-radius-md, .5rem));outline:0}.ns-modal__dialog{position:relative;width:auto;margin:var(--ns-modal-margin, 1.75rem);margin-right:auto;margin-left:auto;pointer-events:none;max-width:var(--ns-modal-width, 500px);z-index:1}.ns-modal__backdrop{background-color:var(--ns-backdrop-bg, rgba(0, 0, 0, .47));position:fixed;top:0;left:0;width:100vw;height:100vh}.ns-modal__title{margin-bottom:unset}.ns-modal__open{overflow:hidden}.ns-modal__header{display:flex;justify-content:space-between;align-items:center;padding:var(--ns-modal-header-padding, var(--ns-space-4, 1rem))}.ns-modal__body{position:relative;flex:1 1 auto;padding:var(--ns-modal-padding, var(--ns-space-4, 1rem))}.ns-modal__footer{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;padding:var(--ns-modal-footer-padding, var(--ns-space-4, 1rem))}\n"] }]
2516
+ }], propDecorators: { containerRef: [{
2517
+ type: ViewChild,
2518
+ args: ['container', { read: ViewContainerRef }]
2519
+ }], keydown: [{
2520
+ type: HostListener,
2521
+ args: ['window:keydown', ['$event']]
2522
+ }] } });
2523
+
2524
+ class NsModalService {
2525
+ appRef = inject(ApplicationRef);
2526
+ injector = inject(EnvironmentInjector);
2527
+ document = inject(DOCUMENT);
2528
+ factory = inject(RendererFactory2);
2529
+ renderer = this.factory.createRenderer(null, null);
2530
+ stack = new Set();
2531
+ open(component, setup) {
2532
+ const nsModalRef = this.attachComponent(this.document.body);
2533
+ this.renderer.addClass(this.document.body, 'ns-modal__open');
2534
+ this.registerModalRef(nsModalRef);
2535
+ Object.assign(nsModalRef.instance, {
2536
+ component: component,
2537
+ title: setup.title,
2538
+ context: setup.context ?? {},
2539
+ size: setup.size ?? 'lg',
2540
+ close: nsModalRef.close.bind(nsModalRef)
2541
+ });
2542
+ return nsModalRef;
2543
+ }
2544
+ close() {
2545
+ this.stack.forEach((modal) => modal.close());
2546
+ }
2547
+ attachComponent(container) {
2548
+ const nsModalRef = new NsModalRef();
2549
+ const providers = [
2550
+ {
2551
+ provide: NsModalRef,
2552
+ useFactory: () => nsModalRef
2553
+ }
2554
+ ];
2555
+ nsModalRef.ref = createComponent(NsModalComponent, {
2556
+ environmentInjector: this.injector,
2557
+ elementInjector: Injector.create({
2558
+ providers
2559
+ })
2560
+ });
2561
+ const componentRef = nsModalRef.ref;
2562
+ if (!componentRef) {
2563
+ throw new Error('Failed to create modal component');
2564
+ }
2565
+ this.appRef.attachView(componentRef.hostView);
2566
+ container.appendChild(componentRef.location.nativeElement);
2567
+ return nsModalRef;
2568
+ }
2569
+ registerModalRef(ref) {
2570
+ this.stack.add(ref);
2571
+ ref.onDestroy(() => {
2572
+ if (this.stack.has(ref)) {
2573
+ this.stack.delete(ref);
2574
+ }
2575
+ });
2576
+ }
2577
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsModalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2578
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsModalService, providedIn: 'root' });
2579
+ }
2580
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsModalService, decorators: [{
2581
+ type: Injectable,
2582
+ args: [{
2583
+ providedIn: 'root'
2584
+ }]
2585
+ }] });
2586
+
2587
+ class NsSchedule {
2588
+ id;
2589
+ subject;
2590
+ body;
2591
+ startTime;
2592
+ endTime;
2593
+ created;
2594
+ updated;
2595
+ constructor(props = {}) {
2596
+ Object.assign(this, props);
2597
+ }
2598
+ }
2599
+
2600
+ class NsScheduleService {
2601
+ onClick$ = new Subject();
2602
+ _date;
2603
+ constructor() { }
2604
+ setCurrentDate(date) {
2605
+ this._date = date;
2606
+ }
2607
+ get currentDate() {
2608
+ return this._date;
2609
+ }
2610
+ send(schedule) {
2611
+ this.onClick$.next(new NsSchedule(schedule));
2612
+ }
2613
+ formatDate(date) {
2614
+ const pad = (num) => ('00' + num).slice(-2);
2615
+ return (date.getFullYear() +
2616
+ '-' +
2617
+ pad(date.getMonth() + 1) +
2618
+ '-' +
2619
+ pad(date.getDate()) +
2620
+ ' ' +
2621
+ pad(date.getHours()) +
2622
+ ':' +
2623
+ pad(date.getMinutes()) +
2624
+ ':' +
2625
+ pad(date.getSeconds()));
2626
+ }
2627
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsScheduleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2628
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsScheduleService, providedIn: 'root' });
2629
+ }
2630
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsScheduleService, decorators: [{
2631
+ type: Injectable,
2632
+ args: [{
2633
+ providedIn: 'root'
2634
+ }]
2635
+ }], ctorParameters: () => [] });
2636
+
2637
+ class NsScheduleCellComponent {
2638
+ service = inject(NsScheduleService);
2639
+ day;
2640
+ timeline;
2641
+ startIn;
2642
+ endIn;
2643
+ ngOnInit() { }
2644
+ onClick(event) {
2645
+ event.preventDefault();
2646
+ const startTime = new Date(this.service.currentDate.getFullYear(), this.service.currentDate.getMonth(), this.day, this.timeline, this.startIn);
2647
+ const endTime = new Date(this.service.currentDate.getFullYear(), this.service.currentDate.getMonth(), this.day, this.timeline, this.endIn);
2648
+ this.service.send({
2649
+ startTime: this.service.formatDate(startTime),
2650
+ endTime: this.service.formatDate(endTime)
2651
+ });
2652
+ }
2653
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsScheduleCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2654
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.21", type: NsScheduleCellComponent, isStandalone: true, selector: "ns-schedule-cell", inputs: { day: "day", timeline: "timeline", startIn: "startIn", endIn: "endIn" }, host: { listeners: { "click": "onClick($event)" }, properties: { "class.ns-schedule__timeline-cell": "true" } }, ngImport: i0, template: '', isInline: true });
2655
+ }
2656
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsScheduleCellComponent, decorators: [{
2657
+ type: Component,
2658
+ args: [{
2659
+ selector: 'ns-schedule-cell',
2660
+ template: '',
2661
+ standalone: true,
2662
+ host: {
2663
+ '[class.ns-schedule__timeline-cell]': 'true'
2664
+ }
2665
+ }]
2666
+ }], propDecorators: { day: [{
2667
+ type: Input
2668
+ }], timeline: [{
2669
+ type: Input
2670
+ }], startIn: [{
2671
+ type: Input
2672
+ }], endIn: [{
2673
+ type: Input
2674
+ }], onClick: [{
2675
+ type: HostListener,
2676
+ args: ['click', ['$event']]
2677
+ }] } });
2678
+
2679
+ class WeekDayPipe {
2680
+ weekdays = [
2681
+ 'Sunday',
2682
+ 'Monday',
2683
+ 'Tuesday',
2684
+ 'Wednesday',
2685
+ 'Thursday',
2686
+ 'Friday',
2687
+ 'Saturday'
2688
+ ];
2689
+ transform(day) {
2690
+ return this.weekdays[day];
2691
+ }
2692
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: WeekDayPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2693
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.21", ngImport: i0, type: WeekDayPipe, isStandalone: true, name: "nsWeekday" });
2694
+ }
2695
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: WeekDayPipe, decorators: [{
2696
+ type: Pipe,
2697
+ args: [{
2698
+ name: 'nsWeekday',
2699
+ standalone: true
2700
+ }]
2701
+ }] });
2702
+
2703
+ class FilterByDayPipe {
2704
+ service = inject(NsScheduleService);
2705
+ transform(schedules, day) {
2706
+ const current = this.service.currentDate;
2707
+ const selector = ({ startTime }) => {
2708
+ const date = new Date(startTime);
2709
+ return (day === date.getDate() &&
2710
+ current.getMonth() === date.getMonth() &&
2711
+ current.getFullYear() === date.getFullYear());
2712
+ };
2713
+ return notEmpty(schedules) ? schedules.filter(selector) : [];
2714
+ }
2715
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: FilterByDayPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2716
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.21", ngImport: i0, type: FilterByDayPipe, isStandalone: true, name: "filterByDay" });
2717
+ }
2718
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: FilterByDayPipe, decorators: [{
2719
+ type: Pipe,
2720
+ args: [{
2721
+ name: 'filterByDay',
2722
+ standalone: true
2723
+ }]
2724
+ }] });
2725
+
2726
+ class NsScheduleEventComponent {
2727
+ schedule;
2728
+ timeline;
2729
+ height;
2730
+ service = inject(NsScheduleService);
2731
+ get matchHour() {
2732
+ return new Date(this.schedule.startTime).getHours() === this.timeline;
2733
+ }
2734
+ ngAfterContentInit() {
2735
+ if (this.schedule) {
2736
+ const startTime = new Date(this.schedule.startTime);
2737
+ const endTime = new Date(this.schedule.endTime);
2738
+ const hours = Math.abs(startTime.getTime() - endTime.getTime()) / 36e5;
2739
+ this.height = hours > 0.5 ? 49.5 * (hours / 0.5) : 45;
2740
+ }
2741
+ }
2742
+ onClick(event) {
2743
+ event.preventDefault();
2744
+ this.service.send(this.schedule);
2745
+ }
2746
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsScheduleEventComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2747
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsScheduleEventComponent, isStandalone: true, selector: "ns-schedule-event", inputs: { schedule: "schedule", timeline: "timeline" }, host: { listeners: { "click": "onClick($event)" }, properties: { "class.ns-schedule__event": "true", "class.ns-schedule__event--show": "schedule && matchHour", "style.height.px": "height" } }, ngImport: i0, template: "@if (schedule) {\n <span class=\"ns-schedule__event--subject\">{{ schedule?.subject }}</span>\n <div class=\"ns-schedule__event--body\" [innerHtml]=\"schedule?.body\"></div>\n}\n", styles: [".ns-schedule__event{display:none;position:absolute;left:0;right:0;background-color:#dcdffa;color:#5b5fc7;border:none;border-left:4px solid #5b5fc7;border-radius:.25rem;font-size:.9em;margin:.2rem;padding:.2rem;overflow:hidden;white-space:nowrap;flex-shrink:1;text-align:left;-webkit-user-select:none;user-select:none;line-height:1.3;cursor:pointer;z-index:1001}.ns-schedule__event--subject{font-weight:600}.ns-schedule__event--body{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.ns-schedule__event--show{display:block}\n"], encapsulation: i0.ViewEncapsulation.None });
2748
+ }
2749
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsScheduleEventComponent, decorators: [{
2750
+ type: Component,
2751
+ args: [{ selector: 'ns-schedule-event', host: {
2752
+ '[class.ns-schedule__event]': 'true',
2753
+ '[class.ns-schedule__event--show]': 'schedule && matchHour',
2754
+ '[style.height.px]': 'height'
2755
+ }, encapsulation: ViewEncapsulation.None, template: "@if (schedule) {\n <span class=\"ns-schedule__event--subject\">{{ schedule?.subject }}</span>\n <div class=\"ns-schedule__event--body\" [innerHtml]=\"schedule?.body\"></div>\n}\n", styles: [".ns-schedule__event{display:none;position:absolute;left:0;right:0;background-color:#dcdffa;color:#5b5fc7;border:none;border-left:4px solid #5b5fc7;border-radius:.25rem;font-size:.9em;margin:.2rem;padding:.2rem;overflow:hidden;white-space:nowrap;flex-shrink:1;text-align:left;-webkit-user-select:none;user-select:none;line-height:1.3;cursor:pointer;z-index:1001}.ns-schedule__event--subject{font-weight:600}.ns-schedule__event--body{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.ns-schedule__event--show{display:block}\n"] }]
2756
+ }], propDecorators: { schedule: [{
2757
+ type: Input
2758
+ }], timeline: [{
2759
+ type: Input
2760
+ }], onClick: [{
2761
+ type: HostListener,
2762
+ args: ['click', ['$event']]
2763
+ }] } });
2764
+
2765
+ class DayComponent {
2766
+ schedules;
2767
+ current;
2768
+ first;
2769
+ days;
2770
+ hours;
2771
+ service = inject(NsScheduleService);
2772
+ DAYS_OF_WEEK = 7;
2773
+ set currentDate(date) {
2774
+ if (date instanceof Date) {
2775
+ this.current = date.getDate();
2776
+ this.first = date.getDate() - date.getDay();
2777
+ this.days = Array(this.DAYS_OF_WEEK)
2778
+ .fill(this.first)
2779
+ .map((x, y) => x + y);
2780
+ this.service.setCurrentDate(date);
2781
+ }
2782
+ }
2783
+ ngOnInit() {
2784
+ this.hours = Array(24)
2785
+ .fill(0)
2786
+ .map((x, y) => x + y);
2787
+ }
2788
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: DayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2789
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: DayComponent, isStandalone: true, selector: "ns-schedule-day", inputs: { schedules: "schedules", currentDate: "currentDate" }, ngImport: i0, template: "<div class=\"ns-schedule__header-wrap\">\n <div class=\"ns-schedule__header\"></div>\n <div class=\"ns-schedule__header ns-schedule__selected\">\n <div class=\"ns-schedule__header-date\">{{ current }}</div>\n <div class=\"ns-schedule__header-day\">\n {{ days.indexOf(current) | nsWeekday }}\n </div>\n </div>\n</div>\n\n<div class=\"ns-schedule__timeline-wrap\">\n @for (timeline of hours; track timeline) {\n <div class=\"ns-schedule__timeline\">\n <div class=\"ns-schedule__timeline-day\">{{ timeline }}</div>\n <div class=\"ns-schedule__timeline-day ns-schedule__selected\">\n <ns-schedule-cell\n [day]=\"current\"\n [timeline]=\"timeline\"\n [startIn]=\"0\"\n [endIn]=\"30\"\n />\n <ns-schedule-cell\n [day]=\"current\"\n [timeline]=\"timeline + 1\"\n [startIn]=\"30\"\n [endIn]=\"0\"\n />\n\n @for (schedule of schedules | filterByDay: current; track schedule) {\n <ns-schedule-event [schedule]=\"schedule\" [timeline]=\"timeline\" />\n }\n </div>\n </div>\n }\n</div>\n", styles: [".ns-schedule__header-wrap,.ns-schedule__timeline{grid-template-columns:[index] 3rem [timeline] 1fr}\n"], dependencies: [{ kind: "component", type: NsScheduleCellComponent, selector: "ns-schedule-cell", inputs: ["day", "timeline", "startIn", "endIn"] }, { kind: "component", type: NsScheduleEventComponent, selector: "ns-schedule-event", inputs: ["schedule", "timeline"] }, { kind: "pipe", type: WeekDayPipe, name: "nsWeekday" }, { kind: "pipe", type: FilterByDayPipe, name: "filterByDay" }] });
2790
+ }
2791
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: DayComponent, decorators: [{
2792
+ type: Component,
2793
+ args: [{ selector: 'ns-schedule-day', imports: [
2794
+ NsScheduleCellComponent,
2795
+ WeekDayPipe,
2796
+ FilterByDayPipe,
2797
+ NsScheduleEventComponent
2798
+ ], template: "<div class=\"ns-schedule__header-wrap\">\n <div class=\"ns-schedule__header\"></div>\n <div class=\"ns-schedule__header ns-schedule__selected\">\n <div class=\"ns-schedule__header-date\">{{ current }}</div>\n <div class=\"ns-schedule__header-day\">\n {{ days.indexOf(current) | nsWeekday }}\n </div>\n </div>\n</div>\n\n<div class=\"ns-schedule__timeline-wrap\">\n @for (timeline of hours; track timeline) {\n <div class=\"ns-schedule__timeline\">\n <div class=\"ns-schedule__timeline-day\">{{ timeline }}</div>\n <div class=\"ns-schedule__timeline-day ns-schedule__selected\">\n <ns-schedule-cell\n [day]=\"current\"\n [timeline]=\"timeline\"\n [startIn]=\"0\"\n [endIn]=\"30\"\n />\n <ns-schedule-cell\n [day]=\"current\"\n [timeline]=\"timeline + 1\"\n [startIn]=\"30\"\n [endIn]=\"0\"\n />\n\n @for (schedule of schedules | filterByDay: current; track schedule) {\n <ns-schedule-event [schedule]=\"schedule\" [timeline]=\"timeline\" />\n }\n </div>\n </div>\n }\n</div>\n", styles: [".ns-schedule__header-wrap,.ns-schedule__timeline{grid-template-columns:[index] 3rem [timeline] 1fr}\n"] }]
2799
+ }], propDecorators: { schedules: [{
2800
+ type: Input
2801
+ }], currentDate: [{
2802
+ type: Input
2803
+ }] } });
2804
+
2805
+ class WeekComponent {
2806
+ service = inject(NsScheduleService);
2807
+ schedules;
2808
+ currentDay;
2809
+ first;
2810
+ last;
2811
+ days;
2812
+ hours;
2813
+ DAYS_OF_WEEK = 7;
2814
+ set currentDate(date) {
2815
+ if (date instanceof Date) {
2816
+ this.first = date.getDate() - date.getDay();
2817
+ this.last = this.first + 6;
2818
+ this.service.setCurrentDate(date);
2819
+ let lastDayOfPrevMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
2820
+ this.days = Array(this.DAYS_OF_WEEK)
2821
+ .fill(this.first)
2822
+ .map((day, index) => (day > 0 ? day + index : lastDayOfPrevMonth--));
2823
+ }
2824
+ }
2825
+ get current() {
2826
+ return this.service.currentDate;
2827
+ }
2828
+ ngOnInit() {
2829
+ this.currentDay = new Date().getDate();
2830
+ this.hours = Array(24)
2831
+ .fill(0)
2832
+ .map((x, y) => x + y);
2833
+ }
2834
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: WeekComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2835
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: WeekComponent, isStandalone: true, selector: "ns-schedule-week", inputs: { schedules: "schedules", currentDate: "currentDate" }, ngImport: i0, template: "<div class=\"ns-schedule__header-wrap\">\n <div class=\"ns-schedule__header\"></div>\n @for (day of days; track day; let i = $index) {\n <div\n class=\"ns-schedule__header\"\n [ngClass]=\"{ 'ns-schedule__selected': currentDay === day }\"\n >\n <div class=\"ns-schedule__header-date\">{{ day }}</div>\n <div class=\"ns-schedule__header-day\">{{ i | nsWeekday }}</div>\n </div>\n }\n</div>\n\n<div class=\"ns-schedule__timeline-wrap\">\n @for (timeline of hours; track timeline) {\n <div class=\"ns-schedule__timeline\">\n <div class=\"ns-schedule__timeline-day\">{{ timeline }}</div>\n @for (day of days; track day) {\n <div\n class=\"ns-schedule__timeline-day\"\n [ngClass]=\"{ 'ns-schedule__selected': currentDay === day }\"\n >\n <ns-schedule-cell\n [day]=\"day\"\n [timeline]=\"timeline\"\n [startIn]=\"0\"\n [endIn]=\"30\"\n />\n <ns-schedule-cell\n [day]=\"day\"\n [timeline]=\"timeline + 1\"\n [startIn]=\"30\"\n [endIn]=\"0\"\n />\n\n @for (schedule of schedules | filterByDay: day; track schedule) {\n <ns-schedule-event [schedule]=\"schedule\" [timeline]=\"timeline\" />\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".ns-schedule__header-wrap,.ns-schedule__timeline{grid-template-columns:[index] 3rem repeat(7,1fr)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: NsScheduleCellComponent, selector: "ns-schedule-cell", inputs: ["day", "timeline", "startIn", "endIn"] }, { kind: "component", type: NsScheduleEventComponent, selector: "ns-schedule-event", inputs: ["schedule", "timeline"] }, { kind: "pipe", type: WeekDayPipe, name: "nsWeekday" }, { kind: "pipe", type: FilterByDayPipe, name: "filterByDay" }] });
2836
+ }
2837
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: WeekComponent, decorators: [{
2838
+ type: Component,
2839
+ args: [{ selector: 'ns-schedule-week', imports: [
2840
+ CommonModule,
2841
+ WeekDayPipe,
2842
+ NsScheduleCellComponent,
2843
+ FilterByDayPipe,
2844
+ NsScheduleEventComponent
2845
+ ], standalone: true, template: "<div class=\"ns-schedule__header-wrap\">\n <div class=\"ns-schedule__header\"></div>\n @for (day of days; track day; let i = $index) {\n <div\n class=\"ns-schedule__header\"\n [ngClass]=\"{ 'ns-schedule__selected': currentDay === day }\"\n >\n <div class=\"ns-schedule__header-date\">{{ day }}</div>\n <div class=\"ns-schedule__header-day\">{{ i | nsWeekday }}</div>\n </div>\n }\n</div>\n\n<div class=\"ns-schedule__timeline-wrap\">\n @for (timeline of hours; track timeline) {\n <div class=\"ns-schedule__timeline\">\n <div class=\"ns-schedule__timeline-day\">{{ timeline }}</div>\n @for (day of days; track day) {\n <div\n class=\"ns-schedule__timeline-day\"\n [ngClass]=\"{ 'ns-schedule__selected': currentDay === day }\"\n >\n <ns-schedule-cell\n [day]=\"day\"\n [timeline]=\"timeline\"\n [startIn]=\"0\"\n [endIn]=\"30\"\n />\n <ns-schedule-cell\n [day]=\"day\"\n [timeline]=\"timeline + 1\"\n [startIn]=\"30\"\n [endIn]=\"0\"\n />\n\n @for (schedule of schedules | filterByDay: day; track schedule) {\n <ns-schedule-event [schedule]=\"schedule\" [timeline]=\"timeline\" />\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".ns-schedule__header-wrap,.ns-schedule__timeline{grid-template-columns:[index] 3rem repeat(7,1fr)}\n"] }]
2846
+ }], propDecorators: { schedules: [{
2847
+ type: Input
2848
+ }], currentDate: [{
2849
+ type: Input
2850
+ }] } });
2851
+
2852
+ class NsWorkweekComponent {
2853
+ service = inject(NsScheduleService);
2854
+ schedules;
2855
+ current;
2856
+ first;
2857
+ last;
2858
+ days = [];
2859
+ hours;
2860
+ DAYS_OF_WORKWEEK = 5;
2861
+ set currentDate(date) {
2862
+ if (date instanceof Date) {
2863
+ this.first = date.getDate() - date.getDay() + 1;
2864
+ this.last = this.first + 4;
2865
+ this.days = [];
2866
+ this.service.setCurrentDate(date);
2867
+ let lastDayOfPrevMonth = new Date(date.getFullYear(), date.getMonth() - 1, -1).getDate();
2868
+ let current = 0;
2869
+ while (current < this.DAYS_OF_WORKWEEK) {
2870
+ this.days.push(this.first < 1 ? lastDayOfPrevMonth : this.first);
2871
+ this.first++;
2872
+ lastDayOfPrevMonth--;
2873
+ current++;
2874
+ }
2875
+ }
2876
+ }
2877
+ identityDay = (index, item) => item.id;
2878
+ ngOnInit() {
2879
+ this.current = new Date().getDate();
2880
+ this.hours = Array(24)
2881
+ .fill(0)
2882
+ .map((x, y) => x + y);
2883
+ }
2884
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsWorkweekComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2885
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsWorkweekComponent, isStandalone: true, selector: "ns-schedule-workweek", inputs: { schedules: "schedules", currentDate: "currentDate" }, ngImport: i0, template: "<div class=\"ns-schedule__header-wrap\">\n <div class=\"ns-schedule__header\"></div>\n @for (day of days; track day; let i = $index) {\n <div\n class=\"ns-schedule__header\"\n [ngClass]=\"{ 'ns-schedule__selected': current === day }\"\n >\n <div class=\"ns-schedule__header-date\">{{ day }}</div>\n <div class=\"ns-schedule__header-day\">{{ i + 1 | nsWeekday }}</div>\n </div>\n }\n</div>\n\n<div class=\"ns-schedule__timeline-wrap\">\n @for (timeline of hours; track timeline) {\n <div class=\"ns-schedule__timeline\">\n <div class=\"ns-schedule__timeline-day\">{{ timeline }}</div>\n @for (day of days; track day) {\n <div\n class=\"ns-schedule__timeline-day\"\n [ngClass]=\"{ 'ns-schedule__selected': current === day }\"\n >\n <ns-schedule-cell\n [day]=\"current\"\n [timeline]=\"timeline\"\n [startIn]=\"0\"\n [endIn]=\"30\"\n />\n <ns-schedule-cell\n [day]=\"current\"\n [timeline]=\"timeline + 1\"\n [startIn]=\"30\"\n [endIn]=\"0\"\n />\n\n @for (\n schedule of schedules | filterByDay: day;\n track identityDay($index, schedule)\n ) {\n <ns-schedule-event [schedule]=\"schedule\" [timeline]=\"timeline\" />\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".ns-schedule__header-wrap,.ns-schedule__timeline{grid-template-columns:[index] 3rem repeat(5,1fr)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: NsScheduleCellComponent, selector: "ns-schedule-cell", inputs: ["day", "timeline", "startIn", "endIn"] }, { kind: "component", type: NsScheduleEventComponent, selector: "ns-schedule-event", inputs: ["schedule", "timeline"] }, { kind: "pipe", type: WeekDayPipe, name: "nsWeekday" }, { kind: "pipe", type: FilterByDayPipe, name: "filterByDay" }] });
2886
+ }
2887
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsWorkweekComponent, decorators: [{
2888
+ type: Component,
2889
+ args: [{ selector: 'ns-schedule-workweek', imports: [
2890
+ CommonModule,
2891
+ WeekDayPipe,
2892
+ NsScheduleCellComponent,
2893
+ NsScheduleEventComponent,
2894
+ FilterByDayPipe
2895
+ ], standalone: true, template: "<div class=\"ns-schedule__header-wrap\">\n <div class=\"ns-schedule__header\"></div>\n @for (day of days; track day; let i = $index) {\n <div\n class=\"ns-schedule__header\"\n [ngClass]=\"{ 'ns-schedule__selected': current === day }\"\n >\n <div class=\"ns-schedule__header-date\">{{ day }}</div>\n <div class=\"ns-schedule__header-day\">{{ i + 1 | nsWeekday }}</div>\n </div>\n }\n</div>\n\n<div class=\"ns-schedule__timeline-wrap\">\n @for (timeline of hours; track timeline) {\n <div class=\"ns-schedule__timeline\">\n <div class=\"ns-schedule__timeline-day\">{{ timeline }}</div>\n @for (day of days; track day) {\n <div\n class=\"ns-schedule__timeline-day\"\n [ngClass]=\"{ 'ns-schedule__selected': current === day }\"\n >\n <ns-schedule-cell\n [day]=\"current\"\n [timeline]=\"timeline\"\n [startIn]=\"0\"\n [endIn]=\"30\"\n />\n <ns-schedule-cell\n [day]=\"current\"\n [timeline]=\"timeline + 1\"\n [startIn]=\"30\"\n [endIn]=\"0\"\n />\n\n @for (\n schedule of schedules | filterByDay: day;\n track identityDay($index, schedule)\n ) {\n <ns-schedule-event [schedule]=\"schedule\" [timeline]=\"timeline\" />\n }\n </div>\n }\n </div>\n }\n</div>\n", styles: [".ns-schedule__header-wrap,.ns-schedule__timeline{grid-template-columns:[index] 3rem repeat(5,1fr)}\n"] }]
2896
+ }], propDecorators: { schedules: [{
2897
+ type: Input
2898
+ }], currentDate: [{
2899
+ type: Input
2900
+ }] } });
2901
+
2902
+ class NsScheduleComponent {
2903
+ view = 'workweek';
2904
+ selected = new Date();
2905
+ height = 520;
2906
+ data;
2907
+ onClick;
2908
+ service = inject(NsScheduleService);
2909
+ constructor() {
2910
+ this.onClick = this.service.onClick$;
2911
+ }
2912
+ goToday() {
2913
+ this.selected = new Date();
2914
+ }
2915
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsScheduleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2916
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.21", type: NsScheduleComponent, isStandalone: true, selector: "ns-schedule", inputs: { view: "view", selected: "selected", height: "height", data: "data" }, outputs: { onClick: "onClick" }, host: { properties: { "class.ns-schedule": "true" } }, ngImport: i0, template: "<div class=\"ns-schedule__tools\">\n <ns-button class=\"ns-scheduler__today\" label=\"Today\" (click)=\"goToday()\" />\n\n <ns-date-picker [(ngModel)]=\"selected\" [view]=\"view\" />\n\n <ns-dropdown class=\"ns-schedule__view\" [(ngModel)]=\"view\">\n <ns-dropdown-item label=\"Day\" value=\"day\" />\n <ns-dropdown-item label=\"Work week\" value=\"workweek\" />\n <ns-dropdown-item label=\"Week\" value=\"week\" />\n </ns-dropdown>\n</div>\n\n@switch (view) {\n @case ('day') {\n <ns-schedule-day\n [currentDate]=\"selected\"\n [schedules]=\"data\"\n [style.height.px]=\"height\"\n />\n }\n @case ('week') {\n <ns-schedule-week\n [currentDate]=\"selected\"\n [schedules]=\"data\"\n [style.height.px]=\"height\"\n />\n }\n @default {\n <ns-schedule-workweek\n [currentDate]=\"selected\"\n [schedules]=\"data\"\n [style.height.px]=\"height\"\n />\n }\n}\n", styles: [".ns-schedule{display:block;width:100%;color:#616161;font-size:14px;background-color:#f5f5f5}.ns-schedule>:nth-child(2){display:block;overflow-y:auto;overflow-x:hidden}.ns-schedule__tools{display:grid;grid-template-columns:[today] 5rem [calendar] 1fr [view] 4fr;margin-bottom:.5rem;grid-gap:.5rem}.ns-schedule__view{margin-left:auto;margin-bottom:unset}.ns-schedule__header{display:flex;flex-direction:column;padding:.5em 1rem;border:1px solid #d1d1d1;-webkit-user-select:none;user-select:none;line-height:1}.ns-schedule__header-date{font-size:1.5em;font-weight:600}.ns-schedule__header-day{font-size:1em}.ns-schedule__header-wrap{position:sticky;top:0;background-color:#f9f9f9;z-index:1050}.ns-schedule__header:not(:first-child){border-left-width:0}.ns-schedule__timeline-day{position:relative;display:flex;flex-direction:column;min-height:6.5em;border:1px solid #d1d1d1;border-top-width:0}.ns-schedule__timeline-day:not(:first-child){border-left-width:0}.ns-schedule__timeline-day:first-child{text-align:center}.ns-schedule__timeline-day.ns-workweek__selected{background-color:#fafafa}.ns-schedule__timeline-cell{border-color:transparent;background-color:transparent;height:100%;flex:1 1}.ns-schedule__timeline-cell:first-child{border-bottom:1px dashed #d1d1d1}.ns-schedule__timeline-cell:hover{background-color:#ededed}.ns-schedule__selected{color:#5b5fc7;background-color:#fff}.ns-schedule__header-wrap,.ns-schedule__timeline{display:grid}\n"], dependencies: [{ kind: "component", type: NsButtonComponent, selector: "ns-button", inputs: ["label", "type", "theme", "block", "disabled", "loading", "icon", "value"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: DayComponent, selector: "ns-schedule-day", inputs: ["schedules", "currentDate"] }, { kind: "component", type: WeekComponent, selector: "ns-schedule-week", inputs: ["schedules", "currentDate"] }, { kind: "component", type: NsWorkweekComponent, selector: "ns-schedule-workweek", inputs: ["schedules", "currentDate"] }, { kind: "component", type: NsDatePickerComponent, selector: "ns-date-picker", inputs: ["autoClose", "placement", "view", "visibleMonths", "firstDayOfWeek", "maxDate", "minDate", "navigation", "weekdayStyle"] }, { kind: "component", type: NsDropdownComponent, selector: "ns-dropdown", inputs: ["labelField", "valueField", "iconName", "defaultFirst", "placement", "filterable", "collection"] }, { kind: "directive", type: NsDropdownItemDirective, selector: "ns-dropdown-item", inputs: ["label", "value", "disabled"] }], encapsulation: i0.ViewEncapsulation.None });
2917
+ }
2918
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsScheduleComponent, decorators: [{
2919
+ type: Component,
2920
+ args: [{ selector: 'ns-schedule', imports: [
2921
+ NsButtonComponent,
2922
+ FormsModule,
2923
+ DayComponent,
2924
+ WeekComponent,
2925
+ NsWorkweekComponent,
2926
+ NsDatePickerComponent,
2927
+ NsDropdownComponent,
2928
+ NsDropdownItemDirective
2929
+ ], encapsulation: ViewEncapsulation.None, host: {
2930
+ '[class.ns-schedule]': 'true'
2931
+ }, template: "<div class=\"ns-schedule__tools\">\n <ns-button class=\"ns-scheduler__today\" label=\"Today\" (click)=\"goToday()\" />\n\n <ns-date-picker [(ngModel)]=\"selected\" [view]=\"view\" />\n\n <ns-dropdown class=\"ns-schedule__view\" [(ngModel)]=\"view\">\n <ns-dropdown-item label=\"Day\" value=\"day\" />\n <ns-dropdown-item label=\"Work week\" value=\"workweek\" />\n <ns-dropdown-item label=\"Week\" value=\"week\" />\n </ns-dropdown>\n</div>\n\n@switch (view) {\n @case ('day') {\n <ns-schedule-day\n [currentDate]=\"selected\"\n [schedules]=\"data\"\n [style.height.px]=\"height\"\n />\n }\n @case ('week') {\n <ns-schedule-week\n [currentDate]=\"selected\"\n [schedules]=\"data\"\n [style.height.px]=\"height\"\n />\n }\n @default {\n <ns-schedule-workweek\n [currentDate]=\"selected\"\n [schedules]=\"data\"\n [style.height.px]=\"height\"\n />\n }\n}\n", styles: [".ns-schedule{display:block;width:100%;color:#616161;font-size:14px;background-color:#f5f5f5}.ns-schedule>:nth-child(2){display:block;overflow-y:auto;overflow-x:hidden}.ns-schedule__tools{display:grid;grid-template-columns:[today] 5rem [calendar] 1fr [view] 4fr;margin-bottom:.5rem;grid-gap:.5rem}.ns-schedule__view{margin-left:auto;margin-bottom:unset}.ns-schedule__header{display:flex;flex-direction:column;padding:.5em 1rem;border:1px solid #d1d1d1;-webkit-user-select:none;user-select:none;line-height:1}.ns-schedule__header-date{font-size:1.5em;font-weight:600}.ns-schedule__header-day{font-size:1em}.ns-schedule__header-wrap{position:sticky;top:0;background-color:#f9f9f9;z-index:1050}.ns-schedule__header:not(:first-child){border-left-width:0}.ns-schedule__timeline-day{position:relative;display:flex;flex-direction:column;min-height:6.5em;border:1px solid #d1d1d1;border-top-width:0}.ns-schedule__timeline-day:not(:first-child){border-left-width:0}.ns-schedule__timeline-day:first-child{text-align:center}.ns-schedule__timeline-day.ns-workweek__selected{background-color:#fafafa}.ns-schedule__timeline-cell{border-color:transparent;background-color:transparent;height:100%;flex:1 1}.ns-schedule__timeline-cell:first-child{border-bottom:1px dashed #d1d1d1}.ns-schedule__timeline-cell:hover{background-color:#ededed}.ns-schedule__selected{color:#5b5fc7;background-color:#fff}.ns-schedule__header-wrap,.ns-schedule__timeline{display:grid}\n"] }]
2932
+ }], ctorParameters: () => [], propDecorators: { view: [{
2933
+ type: Input
2934
+ }], selected: [{
2935
+ type: Input
2936
+ }], height: [{
2937
+ type: Input
2938
+ }], data: [{
2939
+ type: Input
2940
+ }], onClick: [{
2941
+ type: Output
2942
+ }] } });
2943
+
2944
+ class NsSchemaMarkupComponent {
2945
+ sanitizer = inject(DomSanitizer);
2946
+ data;
2947
+ innerHTML;
2948
+ ngOnInit() { }
2949
+ ngOnChanges({ data }) {
2950
+ const json = { '@context': 'https://schema.org', ...data.currentValue };
2951
+ const template = `<script type="application/ld+json">${JSON.stringify(json, null, 2)}</script>`;
2952
+ this.innerHTML = this.sanitizer.bypassSecurityTrustHtml(template);
2953
+ }
2954
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsSchemaMarkupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2955
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.21", type: NsSchemaMarkupComponent, isStandalone: true, selector: "ns-schema", inputs: { data: "data" }, host: { properties: { "innerHTML": "this.innerHTML" } }, usesOnChanges: true, ngImport: i0, template: '', isInline: true });
2956
+ }
2957
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsSchemaMarkupComponent, decorators: [{
2958
+ type: Component,
2959
+ args: [{
2960
+ selector: 'ns-schema',
2961
+ template: ''
2962
+ }]
2963
+ }], propDecorators: { data: [{
2964
+ type: Input
2965
+ }], innerHTML: [{
2966
+ type: HostBinding,
2967
+ args: ['innerHTML']
2968
+ }] } });
2969
+
2970
+ class TemplateDirective {
2971
+ name;
2972
+ styleClass;
2973
+ ref = inject(TemplateRef);
2974
+ modalRef = inject(NsModalRef, { optional: true });
2975
+ ngOnInit() {
2976
+ if (this.modalRef) {
2977
+ this.modalRef.addTemplate(this);
2978
+ }
2979
+ }
2980
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: TemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
2981
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.21", type: TemplateDirective, isStandalone: true, selector: "[nsTemplate]", inputs: { name: ["nsTemplate", "name"], styleClass: "styleClass" }, ngImport: i0 });
2982
+ }
2983
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: TemplateDirective, decorators: [{
2984
+ type: Directive,
2985
+ args: [{
2986
+ selector: '[nsTemplate]',
2987
+ standalone: true
2988
+ }]
2989
+ }], propDecorators: { name: [{
2990
+ type: Input,
2991
+ args: ['nsTemplate']
2992
+ }], styleClass: [{
2993
+ type: Input
2994
+ }] } });
2995
+
2996
+ var ToastType;
2997
+ (function (ToastType) {
2998
+ ToastType["SUCCESS"] = "success";
2999
+ ToastType["WARNING"] = "warning";
3000
+ ToastType["INFO"] = "info";
3001
+ ToastType["ERROR"] = "error";
3002
+ })(ToastType || (ToastType = {}));
3003
+
3004
+ class ToastRef {
3005
+ ref = null;
3006
+ timeout;
3007
+ constructor(props = {}) {
3008
+ Object.assign(this, props);
3009
+ this.timeout = timer(5000).pipe(take$1(1));
3010
+ }
3011
+ get instance() {
3012
+ return this.ref?.instance;
3013
+ }
3014
+ destroy(timeout) {
3015
+ if (!this.ref) {
3016
+ return timer(timeout).pipe(take$1(1));
3017
+ }
3018
+ const ref = this.ref;
3019
+ ref.instance.state = 'destroy';
3020
+ ref.changeDetectorRef.detectChanges();
3021
+ return timer(timeout).pipe(take$1(1), tap(() => {
3022
+ const { nativeElement } = ref.location;
3023
+ nativeElement.parentNode.removeChild(nativeElement);
3024
+ ref.destroy();
3025
+ this.ref = null;
3026
+ }));
3027
+ }
3028
+ }
3029
+
3030
+ class ToastSetup {
3031
+ parent;
3032
+ type;
3033
+ message;
3034
+ callback;
3035
+ }
3036
+
3037
+ class NsToastComponent {
3038
+ type = ToastType.SUCCESS;
3039
+ message;
3040
+ state = 'display';
3041
+ element = inject(ElementRef);
3042
+ get marginLeft() {
3043
+ return -(this.element.nativeElement.offsetWidth / 2);
3044
+ }
3045
+ get iconName() {
3046
+ switch (this.type) {
3047
+ case ToastType.WARNING:
3048
+ return 'exclamation-triangle';
3049
+ case ToastType.ERROR:
3050
+ return 'exclamation-circle';
3051
+ case ToastType.INFO:
3052
+ return 'info-circle';
3053
+ default:
3054
+ return 'check-circle';
3055
+ }
3056
+ }
3057
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsToastComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3058
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.21", type: NsToastComponent, isStandalone: true, selector: "ns-toast", inputs: { type: "type", message: "message" }, host: { properties: { "class.ns-toast": "true", "class.ns-toast--success": "type ==='success'", "class.ns-toast--warning": "type ==='warning'", "class.ns-toast--info": "type ==='info'", "class.ns-toast--error": "type ==='error'", "class.ns-toast--leaving": "state === 'destroy'", "style.margin-left.px": "marginLeft" } }, ngImport: i0, template: `
3059
+ <span class="ns-toast__message" [innerHTML]="message"></span>
3060
+ <ns-icon [name]="iconName" [size]="24" />
3061
+ `, isInline: true, styles: [":host{position:fixed;display:flex;justify-content:space-between;align-items:center;z-index:10000;left:50%;bottom:1rem;margin-left:50%;color:#fff;width:360px;height:64px;box-sizing:border-box;border-radius:var(--ns-border-radius, 8px);transform:translateY(100%);padding:1rem;animation:ns-toast-enter .3s ease-out forwards}:host.ns-toast--leaving{animation:ns-toast-leave .3s ease-in forwards}:host.ns-toast--success{background-color:var(--ns-success-color, #54b948)}:host.ns-toast--warning{background-color:var(--ns-info-color, #ffc500)}:host.ns-toast--info{background-color:var(--ns-info-color, #2980b9)}:host.ns-toast--error{background-color:var(--ns-danger-color, #c9243f)}:host .ns-toast__message{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;text-overflow:ellipsis;overflow:hidden}@keyframes ns-toast-enter{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes ns-toast-leave{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}\n"], dependencies: [{ kind: "component", type: NsIconsComponent, selector: "ns-icon", inputs: ["name", "color", "size", "strokeWidth", "viewBox"] }] });
3062
+ }
3063
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsToastComponent, decorators: [{
3064
+ type: Component,
3065
+ args: [{ selector: 'ns-toast', imports: [NsIconsComponent], template: `
3066
+ <span class="ns-toast__message" [innerHTML]="message"></span>
3067
+ <ns-icon [name]="iconName" [size]="24" />
3068
+ `, host: {
3069
+ '[class.ns-toast]': 'true',
3070
+ '[class.ns-toast--success]': "type ==='success'",
3071
+ '[class.ns-toast--warning]': "type ==='warning'",
3072
+ '[class.ns-toast--info]': "type ==='info'",
3073
+ '[class.ns-toast--error]': "type ==='error'",
3074
+ '[class.ns-toast--leaving]': "state === 'destroy'",
3075
+ '[style.margin-left.px]': 'marginLeft'
3076
+ }, styles: [":host{position:fixed;display:flex;justify-content:space-between;align-items:center;z-index:10000;left:50%;bottom:1rem;margin-left:50%;color:#fff;width:360px;height:64px;box-sizing:border-box;border-radius:var(--ns-border-radius, 8px);transform:translateY(100%);padding:1rem;animation:ns-toast-enter .3s ease-out forwards}:host.ns-toast--leaving{animation:ns-toast-leave .3s ease-in forwards}:host.ns-toast--success{background-color:var(--ns-success-color, #54b948)}:host.ns-toast--warning{background-color:var(--ns-info-color, #ffc500)}:host.ns-toast--info{background-color:var(--ns-info-color, #2980b9)}:host.ns-toast--error{background-color:var(--ns-danger-color, #c9243f)}:host .ns-toast__message{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;text-overflow:ellipsis;overflow:hidden}@keyframes ns-toast-enter{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes ns-toast-leave{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(100%)}}\n"] }]
3077
+ }], propDecorators: { type: [{
3078
+ type: Input
3079
+ }], message: [{
3080
+ type: Input
3081
+ }] } });
3082
+
3083
+ class NsToastService {
3084
+ appRef = inject(ApplicationRef);
3085
+ document = inject(DOCUMENT);
3086
+ stack = new Set();
3087
+ add(setup) {
3088
+ const parent = setup.parent
3089
+ ? this.document.querySelector(setup.parent)
3090
+ : this.document.body;
3091
+ if (!parent) {
3092
+ throw new Error(`Toast parent "${setup.parent}" was not found`);
3093
+ }
3094
+ const componentRef = this.attachComponent(parent, NsToastComponent);
3095
+ this.registerToast(componentRef);
3096
+ const toastRef = new ToastRef({
3097
+ ref: componentRef
3098
+ });
3099
+ toastRef.timeout.subscribe(() => {
3100
+ toastRef.destroy(500).subscribe(() => {
3101
+ if (typeof setup.callback === 'function') {
3102
+ setup.callback();
3103
+ }
3104
+ });
3105
+ });
3106
+ Object.assign(componentRef.instance, setup);
3107
+ return toastRef;
3108
+ }
3109
+ attachComponent(container, type) {
3110
+ const componentRef = createComponent(type, {
3111
+ environmentInjector: this.appRef.injector
3112
+ });
3113
+ this.appRef.attachView(componentRef.hostView);
3114
+ container.appendChild(componentRef.location.nativeElement);
3115
+ return componentRef;
3116
+ }
3117
+ registerToast(toast) {
3118
+ this.stack.add(toast);
3119
+ toast.onDestroy(() => {
3120
+ if (this.stack.has(toast)) {
3121
+ this.stack.delete(toast);
3122
+ }
3123
+ });
3124
+ }
3125
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3126
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsToastService, providedIn: 'root' });
3127
+ }
3128
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.21", ngImport: i0, type: NsToastService, decorators: [{
3129
+ type: Injectable,
3130
+ args: [{ providedIn: 'root' }]
3131
+ }] });
3132
+
3133
+ /*
3134
+ * Public API Surface of @ng-solid/design-system
3135
+ */
3136
+
3137
+ /**
3138
+ * Generated bundle index. Do not edit.
3139
+ */
3140
+
3141
+ export { NsAvatarComponent, NsButtonComponent, NsButtonGroupComponent, NsCalendar, NsCheckboxComponent, NsCommentComponent, NsContentEditableComponent, NsDateParserFormatter, NsDatePickerComponent, NsDateRangeEndDirective, NsDateRangePickerComponent, NsDateRangeStartDirective, NsDropdownComponent, NsDropdownItemDirective, NsEditorColorPickerComponent, NsEditorComponent, NsEditorLinkComponent, NsEditorListComponent, NsEditorParagraphComponent, NsEditorToggleCommandComponent, NsImageUploadComponent, NsInputComponent, NsInputGroupComponent, NsInputNumberComponent, NsModalComponent, NsModalService, NsPasswordComponent, NsScheduleComponent, NsScheduleService, NsSchemaMarkupComponent, NsSwitchComponent, NsTextAreaComponent, NsToastComponent, NsToastService, NsValueAccessor, TemplateDirective, ToastRef, ToastSetup, ToastType };
3142
+ //# sourceMappingURL=ng-solid-design-system.mjs.map