@dragonworks/ngx-dashboard-widgets 20.1.6 → 20.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, signal, computed, Component, input, numberAttribute, booleanAttribute, ElementRef, NgZone, PLATFORM_ID, DestroyRef, Directive, ChangeDetectionStrategy, Renderer2, viewChild, effect, LOCALE_ID, afterNextRender } from '@angular/core';
2
+ import { inject, signal, computed, Component, input, numberAttribute, booleanAttribute, ElementRef, NgZone, PLATFORM_ID, DestroyRef, effect, Directive, ChangeDetectionStrategy, Renderer2, viewChild, LOCALE_ID, afterNextRender } from '@angular/core';
3
3
  import { DomSanitizer } from '@angular/platform-browser';
4
4
  import * as i2 from '@angular/material/dialog';
5
5
  import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule, MatDialog } from '@angular/material/dialog';
@@ -80,25 +80,50 @@ class ArrowStateDialogComponent {
80
80
  }
81
81
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: ArrowStateDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
82
82
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.1", type: ArrowStateDialogComponent, isStandalone: true, selector: "lib-arrow-state-dialog", ngImport: i0, template: `
83
- <h2 mat-dialog-title>Arrow Settings</h2>
83
+ <h2 mat-dialog-title i18n="@@ngx.dashboard.widgets.arrow.dialog.title">
84
+ Arrow Settings
85
+ </h2>
84
86
  <mat-dialog-content>
85
87
  <!-- Direction Selection -->
86
88
  <mat-form-field appearance="outline" class="direction-field">
87
- <mat-label>Arrow Direction</mat-label>
89
+ <mat-label i18n="@@ngx.dashboard.widgets.arrow.dialog.direction"
90
+ >Arrow Direction</mat-label
91
+ >
88
92
  <mat-select
89
93
  [value]="direction()"
90
94
  (selectionChange)="direction.set($any($event.value))"
91
95
  >
92
- <mat-option value="up">Up</mat-option>
93
- <mat-option value="right">Right</mat-option>
94
- <mat-option value="down">Down</mat-option>
95
- <mat-option value="left">Left</mat-option>
96
+ <mat-option
97
+ value="up"
98
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.direction.up"
99
+ >Up</mat-option
100
+ >
101
+ <mat-option
102
+ value="right"
103
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.direction.right"
104
+ >Right</mat-option
105
+ >
106
+ <mat-option
107
+ value="down"
108
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.direction.down"
109
+ >Down</mat-option
110
+ >
111
+ <mat-option
112
+ value="left"
113
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.direction.left"
114
+ >Left</mat-option
115
+ >
96
116
  </mat-select>
97
117
  </mat-form-field>
98
118
 
99
119
  <!-- Opacity Slider -->
100
120
  <div class="slider-field">
101
- <div class="field-label">Opacity: {{ formatOpacity(opacity()) }}%</div>
121
+ <div
122
+ class="field-label"
123
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.opacity"
124
+ >
125
+ Opacity: {{ formatOpacity(opacity()) }}%
126
+ </div>
102
127
  <mat-slider [min]="0.1" [max]="1" [step]="0.1">
103
128
  <input matSliderThumb [(ngModel)]="opacity" />
104
129
  </mat-slider>
@@ -106,18 +131,35 @@ class ArrowStateDialogComponent {
106
131
 
107
132
  <!-- Background Toggle -->
108
133
  <div class="toggle-field">
109
- <mat-slide-toggle
134
+ <mat-slide-toggle
110
135
  [checked]="hasBackground()"
111
- (change)="onBackgroundToggle($event.checked)">
136
+ (change)="onBackgroundToggle($event.checked)"
137
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.background"
138
+ >
112
139
  Background
113
140
  </mat-slide-toggle>
114
- <span class="toggle-hint">Adds a background behind the arrow</span>
141
+ <span
142
+ class="toggle-hint"
143
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.backgroundHint"
144
+ >Adds a background behind the arrow</span
145
+ >
115
146
  </div>
116
147
  </mat-dialog-content>
117
148
 
118
149
  <mat-dialog-actions align="end">
119
- <button mat-button (click)="onCancel()">Cancel</button>
120
- <button mat-flat-button (click)="save()" [disabled]="!hasChanged()">
150
+ <button
151
+ mat-button
152
+ (click)="onCancel()"
153
+ i18n="@@ngx.dashboard.common.cancel"
154
+ >
155
+ Cancel
156
+ </button>
157
+ <button
158
+ mat-flat-button
159
+ (click)="save()"
160
+ [disabled]="!hasChanged()"
161
+ i18n="@@ngx.dashboard.common.save"
162
+ >
121
163
  Save
122
164
  </button>
123
165
  </mat-dialog-actions>
@@ -135,25 +177,50 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
135
177
  MatSliderModule,
136
178
  MatSlideToggleModule,
137
179
  ], template: `
138
- <h2 mat-dialog-title>Arrow Settings</h2>
180
+ <h2 mat-dialog-title i18n="@@ngx.dashboard.widgets.arrow.dialog.title">
181
+ Arrow Settings
182
+ </h2>
139
183
  <mat-dialog-content>
140
184
  <!-- Direction Selection -->
141
185
  <mat-form-field appearance="outline" class="direction-field">
142
- <mat-label>Arrow Direction</mat-label>
186
+ <mat-label i18n="@@ngx.dashboard.widgets.arrow.dialog.direction"
187
+ >Arrow Direction</mat-label
188
+ >
143
189
  <mat-select
144
190
  [value]="direction()"
145
191
  (selectionChange)="direction.set($any($event.value))"
146
192
  >
147
- <mat-option value="up">Up</mat-option>
148
- <mat-option value="right">Right</mat-option>
149
- <mat-option value="down">Down</mat-option>
150
- <mat-option value="left">Left</mat-option>
193
+ <mat-option
194
+ value="up"
195
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.direction.up"
196
+ >Up</mat-option
197
+ >
198
+ <mat-option
199
+ value="right"
200
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.direction.right"
201
+ >Right</mat-option
202
+ >
203
+ <mat-option
204
+ value="down"
205
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.direction.down"
206
+ >Down</mat-option
207
+ >
208
+ <mat-option
209
+ value="left"
210
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.direction.left"
211
+ >Left</mat-option
212
+ >
151
213
  </mat-select>
152
214
  </mat-form-field>
153
215
 
154
216
  <!-- Opacity Slider -->
155
217
  <div class="slider-field">
156
- <div class="field-label">Opacity: {{ formatOpacity(opacity()) }}%</div>
218
+ <div
219
+ class="field-label"
220
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.opacity"
221
+ >
222
+ Opacity: {{ formatOpacity(opacity()) }}%
223
+ </div>
157
224
  <mat-slider [min]="0.1" [max]="1" [step]="0.1">
158
225
  <input matSliderThumb [(ngModel)]="opacity" />
159
226
  </mat-slider>
@@ -161,18 +228,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
161
228
 
162
229
  <!-- Background Toggle -->
163
230
  <div class="toggle-field">
164
- <mat-slide-toggle
231
+ <mat-slide-toggle
165
232
  [checked]="hasBackground()"
166
- (change)="onBackgroundToggle($event.checked)">
233
+ (change)="onBackgroundToggle($event.checked)"
234
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.background"
235
+ >
167
236
  Background
168
237
  </mat-slide-toggle>
169
- <span class="toggle-hint">Adds a background behind the arrow</span>
238
+ <span
239
+ class="toggle-hint"
240
+ i18n="@@ngx.dashboard.widgets.arrow.dialog.backgroundHint"
241
+ >Adds a background behind the arrow</span
242
+ >
170
243
  </div>
171
244
  </mat-dialog-content>
172
245
 
173
246
  <mat-dialog-actions align="end">
174
- <button mat-button (click)="onCancel()">Cancel</button>
175
- <button mat-flat-button (click)="save()" [disabled]="!hasChanged()">
247
+ <button
248
+ mat-button
249
+ (click)="onCancel()"
250
+ i18n="@@ngx.dashboard.common.cancel"
251
+ >
252
+ Cancel
253
+ </button>
254
+ <button
255
+ mat-flat-button
256
+ (click)="save()"
257
+ [disabled]="!hasChanged()"
258
+ i18n="@@ngx.dashboard.common.save"
259
+ >
176
260
  Save
177
261
  </button>
178
262
  </mat-dialog-actions>
@@ -183,8 +267,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
183
267
  class ArrowWidgetComponent {
184
268
  static metadata = {
185
269
  widgetTypeid: '@ngx-dashboard/arrow-widget',
186
- name: 'Arrow',
187
- description: 'A generic arrow',
270
+ name: $localize `:@@ngx.dashboard.widgets.arrow.name:Arrow`,
271
+ description: $localize `:@@ngx.dashboard.widgets.arrow.description:A generic arrow`,
188
272
  svgIcon: svgIcon$3,
189
273
  };
190
274
  #sanitizer = inject(DomSanitizer);
@@ -256,6 +340,7 @@ class LabelStateDialogComponent {
256
340
  // Responsive font size constraints
257
341
  minFontSize = signal(this.data.minFontSize ?? 8, ...(ngDevMode ? [{ debugName: "minFontSize" }] : []));
258
342
  maxFontSize = signal(this.data.maxFontSize ?? 64, ...(ngDevMode ? [{ debugName: "maxFontSize" }] : []));
343
+ templateString = signal(this.data.templateString, ...(ngDevMode ? [{ debugName: "templateString" }] : []));
259
344
  // Store original values for comparison
260
345
  originalLabel = this.data.label ?? '';
261
346
  originalFontSize = this.data.fontSize ?? 16;
@@ -266,6 +351,7 @@ class LabelStateDialogComponent {
266
351
  originalResponsive = this.data.responsive ?? false;
267
352
  originalMinFontSize = this.data.minFontSize ?? 8;
268
353
  originalMaxFontSize = this.data.maxFontSize ?? 64;
354
+ originalTemplateString = this.data.templateString;
269
355
  // Validation computed properties
270
356
  isMinFontSizeValid = computed(() => {
271
357
  const min = this.minFontSize();
@@ -288,7 +374,8 @@ class LabelStateDialogComponent {
288
374
  this.hasBackground() !== this.originalHasBackground ||
289
375
  this.responsive() !== this.originalResponsive ||
290
376
  this.minFontSize() !== this.originalMinFontSize ||
291
- this.maxFontSize() !== this.originalMaxFontSize, ...(ngDevMode ? [{ debugName: "hasChanged" }] : []));
377
+ this.maxFontSize() !== this.originalMaxFontSize ||
378
+ this.templateString() !== this.originalTemplateString, ...(ngDevMode ? [{ debugName: "hasChanged" }] : []));
292
379
  formatOpacity(value) {
293
380
  return Math.round(value * 100);
294
381
  }
@@ -324,7 +411,7 @@ class LabelStateDialogComponent {
324
411
  this.dialogRef.close();
325
412
  }
326
413
  save() {
327
- this.dialogRef.close({
414
+ const state = {
328
415
  label: this.label(),
329
416
  fontSize: this.fontSize(),
330
417
  alignment: this.alignment(),
@@ -334,96 +421,158 @@ class LabelStateDialogComponent {
334
421
  responsive: this.responsive(),
335
422
  minFontSize: this.minFontSize(),
336
423
  maxFontSize: this.maxFontSize(),
337
- });
424
+ };
425
+ // Only include templateString if it has a value
426
+ const templateString = this.templateString();
427
+ if (templateString) {
428
+ state.templateString = templateString;
429
+ }
430
+ this.dialogRef.close(state);
338
431
  }
339
432
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: LabelStateDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
340
433
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: LabelStateDialogComponent, isStandalone: true, selector: "lib-label-state-dialog", ngImport: i0, template: `
341
- <h2 mat-dialog-title>Label Settings</h2>
434
+ <h2 mat-dialog-title i18n="@@ngx.dashboard.widgets.label.dialog.title">
435
+ Label Settings
436
+ </h2>
342
437
  <mat-dialog-content>
343
438
  <mat-form-field appearance="outline" class="label-text-field">
344
- <mat-label>Label Text</mat-label>
439
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.labelText"
440
+ >Label Text</mat-label
441
+ >
345
442
  <input
346
443
  matInput
347
444
  type="text"
348
445
  [value]="label()"
349
446
  (input)="label.set($any($event.target).value)"
447
+ i18n-placeholder="@@ngx.dashboard.widgets.label.dialog.placeholder"
350
448
  placeholder="Enter your label text..."
351
449
  />
352
450
  </mat-form-field>
353
451
 
354
452
  <!-- Responsive Text Toggle -->
355
453
  <div class="toggle-section">
356
- <mat-slide-toggle
454
+ <mat-slide-toggle
357
455
  [checked]="responsive()"
358
- (change)="responsive.set($event.checked)">
456
+ (change)="responsive.set($event.checked)"
457
+ i18n="@@ngx.dashboard.widgets.label.dialog.responsive"
458
+ >
359
459
  Responsive Text
360
460
  </mat-slide-toggle>
361
- <span class="toggle-description"
461
+ <span
462
+ class="toggle-description"
463
+ i18n="@@ngx.dashboard.widgets.label.dialog.responsiveDescription"
362
464
  >Automatically adjust text size to fit the widget</span
363
465
  >
364
466
  </div>
365
467
 
366
468
  <!-- Responsive Font Size Constraints (only shown when responsive is enabled) -->
367
469
  @if (responsive()) {
368
- <div class="responsive-section">
369
- <div class="section-label">Font Size Limits</div>
370
- <div class="row-layout">
371
- <mat-form-field appearance="outline">
372
- <mat-label>Min Size (px)</mat-label>
373
- <input
374
- matInput
375
- type="number"
376
- [value]="minFontSize()"
377
- (input)="validateAndCorrectMinFontSize(+$any($event.target).value)"
378
- (blur)="validateAndCorrectMinFontSize(minFontSize())"
379
- min="8"
380
- max="24"
381
- placeholder="8"
382
- />
383
- @if (!isMinFontSizeValid() || !isFontSizeRangeValid()) {
384
- <mat-error>
385
- @if (!isMinFontSizeValid()) {
386
- Must be between 8-24px
387
- } @else {
388
- Must be less than max size
389
- }
390
- </mat-error>
470
+ <div class="responsive-section">
471
+ <div
472
+ class="section-label"
473
+ i18n="@@ngx.dashboard.widgets.label.dialog.fontSizeLimits"
474
+ >
475
+ Font Size Limits
476
+ </div>
477
+ <div class="row-layout">
478
+ <mat-form-field appearance="outline">
479
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.minSize"
480
+ >Min Size (px)</mat-label
481
+ >
482
+ <input
483
+ matInput
484
+ type="number"
485
+ [value]="minFontSize()"
486
+ (input)="
487
+ validateAndCorrectMinFontSize(+$any($event.target).value)
488
+ "
489
+ (blur)="validateAndCorrectMinFontSize(minFontSize())"
490
+ min="8"
491
+ max="24"
492
+ placeholder="8"
493
+ />
494
+ @if (!isMinFontSizeValid() || !isFontSizeRangeValid()) {
495
+ <mat-error>
496
+ @if (!isMinFontSizeValid()) {
497
+ <span i18n="@@ngx.dashboard.widgets.label.dialog.minSizeError"
498
+ >Must be between 8-24px</span
499
+ >
391
500
  } @else {
392
- <mat-hint>8-24px range</mat-hint>
501
+ <span
502
+ i18n="@@ngx.dashboard.widgets.label.dialog.minSizeRangeError"
503
+ >Must be less than max size</span
504
+ >
393
505
  }
394
- </mat-form-field>
506
+ </mat-error>
507
+ } @else {
508
+ <mat-hint i18n="@@ngx.dashboard.widgets.label.dialog.minSizeHint"
509
+ >8-24px range</mat-hint
510
+ >
511
+ }
512
+ </mat-form-field>
395
513
 
396
- <mat-form-field appearance="outline">
397
- <mat-label>Max Size (px)</mat-label>
398
- <input
399
- matInput
400
- type="number"
401
- [value]="maxFontSize()"
402
- (input)="validateAndCorrectMaxFontSize(+$any($event.target).value)"
403
- (blur)="validateAndCorrectMaxFontSize(maxFontSize())"
404
- min="16"
405
- max="128"
406
- placeholder="64"
407
- />
408
- @if (!isMaxFontSizeValid() || !isFontSizeRangeValid()) {
409
- <mat-error>
410
- @if (!isMaxFontSizeValid()) {
411
- Must be between 16-128px
412
- } @else {
413
- Must be greater than min size
414
- }
415
- </mat-error>
514
+ <mat-form-field appearance="outline">
515
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.maxSize"
516
+ >Max Size (px)</mat-label
517
+ >
518
+ <input
519
+ matInput
520
+ type="number"
521
+ [value]="maxFontSize()"
522
+ (input)="
523
+ validateAndCorrectMaxFontSize(+$any($event.target).value)
524
+ "
525
+ (blur)="validateAndCorrectMaxFontSize(maxFontSize())"
526
+ min="16"
527
+ max="128"
528
+ placeholder="64"
529
+ />
530
+ @if (!isMaxFontSizeValid() || !isFontSizeRangeValid()) {
531
+ <mat-error>
532
+ @if (!isMaxFontSizeValid()) {
533
+ <span i18n="@@ngx.dashboard.widgets.label.dialog.maxSizeError"
534
+ >Must be between 16-128px</span
535
+ >
416
536
  } @else {
417
- <mat-hint>16-128px range</mat-hint>
537
+ <span
538
+ i18n="@@ngx.dashboard.widgets.label.dialog.maxSizeRangeError"
539
+ >Must be greater than min size</span
540
+ >
418
541
  }
419
- </mat-form-field>
420
- </div>
542
+ </mat-error>
543
+ } @else {
544
+ <mat-hint i18n="@@ngx.dashboard.widgets.label.dialog.maxSizeHint"
545
+ >16-128px range</mat-hint
546
+ >
547
+ }
548
+ </mat-form-field>
421
549
  </div>
550
+
551
+ <!-- Template String field -->
552
+ <mat-form-field appearance="outline">
553
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.templateString"
554
+ >Template String</mat-label
555
+ >
556
+ <input
557
+ matInput
558
+ type="text"
559
+ [value]="templateString() || ''"
560
+ (input)="templateString.set($any($event.target).value || undefined)"
561
+ i18n-placeholder="@@ngx.dashboard.widgets.label.dialog.templateStringPlaceholder"
562
+ placeholder="Optional: Text to use for size calculation"
563
+ />
564
+ <mat-hint i18n="@@ngx.dashboard.widgets.label.dialog.templateStringHint"
565
+ >Use when displayed text varies but size should remain consistent</mat-hint
566
+ >
567
+ </mat-form-field>
568
+ </div>
422
569
  }
423
570
 
424
571
  <div class="row-layout">
425
572
  <mat-form-field appearance="outline">
426
- <mat-label>Font Size (px)</mat-label>
573
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.fontSize"
574
+ >Font Size (px)</mat-label
575
+ >
427
576
  <input
428
577
  matInput
429
578
  type="number"
@@ -437,32 +586,61 @@ class LabelStateDialogComponent {
437
586
  </mat-form-field>
438
587
 
439
588
  <mat-form-field appearance="outline">
440
- <mat-label>Alignment</mat-label>
589
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.alignment"
590
+ >Alignment</mat-label
591
+ >
441
592
  <mat-select
442
593
  [value]="alignment()"
443
594
  (selectionChange)="alignment.set($any($event.value))"
444
595
  >
445
- <mat-option value="left">Left</mat-option>
446
- <mat-option value="center">Center</mat-option>
447
- <mat-option value="right">Right</mat-option>
596
+ <mat-option
597
+ value="left"
598
+ i18n="@@ngx.dashboard.widgets.label.dialog.alignment.left"
599
+ >Left</mat-option
600
+ >
601
+ <mat-option
602
+ value="center"
603
+ i18n="@@ngx.dashboard.widgets.label.dialog.alignment.center"
604
+ >Center</mat-option
605
+ >
606
+ <mat-option
607
+ value="right"
608
+ i18n="@@ngx.dashboard.widgets.label.dialog.alignment.right"
609
+ >Right</mat-option
610
+ >
448
611
  </mat-select>
449
612
  </mat-form-field>
450
613
  </div>
451
614
 
452
615
  <mat-form-field appearance="outline">
453
- <mat-label>Font Weight</mat-label>
616
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.fontWeight"
617
+ >Font Weight</mat-label
618
+ >
454
619
  <mat-select
455
620
  [value]="fontWeight()"
456
621
  (selectionChange)="fontWeight.set($any($event.value))"
457
622
  >
458
- <mat-option value="normal">Normal</mat-option>
459
- <mat-option value="bold">Bold</mat-option>
623
+ <mat-option
624
+ value="normal"
625
+ i18n="@@ngx.dashboard.widgets.label.dialog.fontWeight.normal"
626
+ >Normal</mat-option
627
+ >
628
+ <mat-option
629
+ value="bold"
630
+ i18n="@@ngx.dashboard.widgets.label.dialog.fontWeight.bold"
631
+ >Bold</mat-option
632
+ >
460
633
  </mat-select>
461
634
  </mat-form-field>
462
635
 
463
636
  <!-- Opacity Slider -->
464
637
  <div class="slider-section">
465
- <div class="slider-label">Opacity: {{ formatOpacity(opacity()) }}%</div>
638
+ <div
639
+ class="slider-label"
640
+ i18n="@@ngx.dashboard.widgets.label.dialog.opacity"
641
+ >
642
+ Opacity: {{ formatOpacity(opacity()) }}%
643
+ </div>
466
644
  <mat-slider [min]="0.1" [max]="1" [step]="0.1">
467
645
  <input matSliderThumb [(ngModel)]="opacity" />
468
646
  </mat-slider>
@@ -470,24 +648,39 @@ class LabelStateDialogComponent {
470
648
 
471
649
  <!-- Background Toggle -->
472
650
  <div class="toggle-section">
473
- <mat-slide-toggle
651
+ <mat-slide-toggle
474
652
  [checked]="!transparentBackground()"
475
- (change)="onBackgroundToggle($event.checked)">
653
+ (change)="onBackgroundToggle($event.checked)"
654
+ i18n="@@ngx.dashboard.widgets.label.dialog.background"
655
+ >
476
656
  Background
477
657
  </mat-slide-toggle>
478
- <span class="toggle-description"
658
+ <span
659
+ class="toggle-description"
660
+ i18n="@@ngx.dashboard.widgets.label.dialog.backgroundDescription"
479
661
  >Adds a background behind the text</span
480
662
  >
481
663
  </div>
482
664
  </mat-dialog-content>
483
665
 
484
666
  <mat-dialog-actions align="end">
485
- <button mat-button (click)="onCancel()">Cancel</button>
486
- <button mat-flat-button (click)="save()" [disabled]="!hasChanged() || !isFormValid()">
667
+ <button
668
+ mat-button
669
+ (click)="onCancel()"
670
+ i18n="@@ngx.dashboard.common.cancel"
671
+ >
672
+ Cancel
673
+ </button>
674
+ <button
675
+ mat-flat-button
676
+ (click)="save()"
677
+ [disabled]="!hasChanged() || !isFormValid()"
678
+ i18n="@@ngx.dashboard.common.save"
679
+ >
487
680
  Save
488
681
  </button>
489
682
  </mat-dialog-actions>
490
- `, isInline: true, styles: ["mat-dialog-content{display:block;overflow-y:auto;overflow-x:hidden}mat-form-field{width:100%;display:block;margin-bottom:1rem}.label-text-field{margin-top:1rem}.row-layout{display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem}.row-layout mat-form-field{margin-bottom:0}.slider-section{margin-bottom:1.5rem;margin-right:1rem}.slider-label{display:block;margin-bottom:.5rem}mat-slider{width:100%;display:block}.toggle-section{display:flex;align-items:center;gap:.75rem;margin-bottom:1rem}.toggle-description{margin:0}.responsive-section{margin-bottom:1.5rem;padding:1rem;border-radius:12px;background-color:var(--mat-app-surface-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .05));border:1px solid var(--mat-app-outline-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .12))}.section-label{display:block;margin-bottom:.75rem;font-weight:500;color:var(--mat-app-on-surface-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .6))}.responsive-section .row-layout{margin-bottom:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSliderModule }, { kind: "component", type: i6.MatSlider, selector: "mat-slider", inputs: ["disabled", "discrete", "showTickMarks", "min", "color", "disableRipple", "max", "step", "displayWith"], exportAs: ["matSlider"] }, { kind: "directive", type: i6.MatSliderThumb, selector: "input[matSliderThumb]", inputs: ["value"], outputs: ["valueChange", "dragStart", "dragEnd"], exportAs: ["matSliderThumb"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }] });
683
+ `, isInline: true, styles: ["mat-dialog-content{display:block;overflow-y:auto;overflow-x:hidden}mat-form-field{width:100%;display:block;margin-bottom:1rem}.label-text-field{margin-top:1rem}.row-layout{display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem}.row-layout mat-form-field{margin-bottom:0}.slider-section{margin-bottom:1.5rem;margin-right:1rem}.slider-label{display:block;margin-bottom:.5rem}mat-slider{width:100%;display:block}.toggle-section{display:flex;align-items:center;gap:.75rem;margin-bottom:1rem}.toggle-description{margin:0}.responsive-section{margin-bottom:1.5rem;padding:1rem;border-radius:12px;background-color:var( --mat-app-surface-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .05) );border:1px solid var( --mat-app-outline-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .12) )}.section-label{display:block;margin-bottom:.75rem;font-weight:500;color:var( --mat-app-on-surface-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .6) )}.responsive-section .row-layout{margin-bottom:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSliderModule }, { kind: "component", type: i6.MatSlider, selector: "mat-slider", inputs: ["disabled", "discrete", "showTickMarks", "min", "color", "disableRipple", "max", "step", "displayWith"], exportAs: ["matSlider"] }, { kind: "directive", type: i6.MatSliderThumb, selector: "input[matSliderThumb]", inputs: ["value"], outputs: ["valueChange", "dragStart", "dragEnd"], exportAs: ["matSliderThumb"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }] });
491
684
  }
492
685
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: LabelStateDialogComponent, decorators: [{
493
686
  type: Component,
@@ -502,92 +695,148 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
502
695
  MatSliderModule,
503
696
  MatSlideToggleModule, // Add this import
504
697
  ], template: `
505
- <h2 mat-dialog-title>Label Settings</h2>
698
+ <h2 mat-dialog-title i18n="@@ngx.dashboard.widgets.label.dialog.title">
699
+ Label Settings
700
+ </h2>
506
701
  <mat-dialog-content>
507
702
  <mat-form-field appearance="outline" class="label-text-field">
508
- <mat-label>Label Text</mat-label>
703
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.labelText"
704
+ >Label Text</mat-label
705
+ >
509
706
  <input
510
707
  matInput
511
708
  type="text"
512
709
  [value]="label()"
513
710
  (input)="label.set($any($event.target).value)"
711
+ i18n-placeholder="@@ngx.dashboard.widgets.label.dialog.placeholder"
514
712
  placeholder="Enter your label text..."
515
713
  />
516
714
  </mat-form-field>
517
715
 
518
716
  <!-- Responsive Text Toggle -->
519
717
  <div class="toggle-section">
520
- <mat-slide-toggle
718
+ <mat-slide-toggle
521
719
  [checked]="responsive()"
522
- (change)="responsive.set($event.checked)">
720
+ (change)="responsive.set($event.checked)"
721
+ i18n="@@ngx.dashboard.widgets.label.dialog.responsive"
722
+ >
523
723
  Responsive Text
524
724
  </mat-slide-toggle>
525
- <span class="toggle-description"
725
+ <span
726
+ class="toggle-description"
727
+ i18n="@@ngx.dashboard.widgets.label.dialog.responsiveDescription"
526
728
  >Automatically adjust text size to fit the widget</span
527
729
  >
528
730
  </div>
529
731
 
530
732
  <!-- Responsive Font Size Constraints (only shown when responsive is enabled) -->
531
733
  @if (responsive()) {
532
- <div class="responsive-section">
533
- <div class="section-label">Font Size Limits</div>
534
- <div class="row-layout">
535
- <mat-form-field appearance="outline">
536
- <mat-label>Min Size (px)</mat-label>
537
- <input
538
- matInput
539
- type="number"
540
- [value]="minFontSize()"
541
- (input)="validateAndCorrectMinFontSize(+$any($event.target).value)"
542
- (blur)="validateAndCorrectMinFontSize(minFontSize())"
543
- min="8"
544
- max="24"
545
- placeholder="8"
546
- />
547
- @if (!isMinFontSizeValid() || !isFontSizeRangeValid()) {
548
- <mat-error>
549
- @if (!isMinFontSizeValid()) {
550
- Must be between 8-24px
551
- } @else {
552
- Must be less than max size
553
- }
554
- </mat-error>
734
+ <div class="responsive-section">
735
+ <div
736
+ class="section-label"
737
+ i18n="@@ngx.dashboard.widgets.label.dialog.fontSizeLimits"
738
+ >
739
+ Font Size Limits
740
+ </div>
741
+ <div class="row-layout">
742
+ <mat-form-field appearance="outline">
743
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.minSize"
744
+ >Min Size (px)</mat-label
745
+ >
746
+ <input
747
+ matInput
748
+ type="number"
749
+ [value]="minFontSize()"
750
+ (input)="
751
+ validateAndCorrectMinFontSize(+$any($event.target).value)
752
+ "
753
+ (blur)="validateAndCorrectMinFontSize(minFontSize())"
754
+ min="8"
755
+ max="24"
756
+ placeholder="8"
757
+ />
758
+ @if (!isMinFontSizeValid() || !isFontSizeRangeValid()) {
759
+ <mat-error>
760
+ @if (!isMinFontSizeValid()) {
761
+ <span i18n="@@ngx.dashboard.widgets.label.dialog.minSizeError"
762
+ >Must be between 8-24px</span
763
+ >
555
764
  } @else {
556
- <mat-hint>8-24px range</mat-hint>
765
+ <span
766
+ i18n="@@ngx.dashboard.widgets.label.dialog.minSizeRangeError"
767
+ >Must be less than max size</span
768
+ >
557
769
  }
558
- </mat-form-field>
770
+ </mat-error>
771
+ } @else {
772
+ <mat-hint i18n="@@ngx.dashboard.widgets.label.dialog.minSizeHint"
773
+ >8-24px range</mat-hint
774
+ >
775
+ }
776
+ </mat-form-field>
559
777
 
560
- <mat-form-field appearance="outline">
561
- <mat-label>Max Size (px)</mat-label>
562
- <input
563
- matInput
564
- type="number"
565
- [value]="maxFontSize()"
566
- (input)="validateAndCorrectMaxFontSize(+$any($event.target).value)"
567
- (blur)="validateAndCorrectMaxFontSize(maxFontSize())"
568
- min="16"
569
- max="128"
570
- placeholder="64"
571
- />
572
- @if (!isMaxFontSizeValid() || !isFontSizeRangeValid()) {
573
- <mat-error>
574
- @if (!isMaxFontSizeValid()) {
575
- Must be between 16-128px
576
- } @else {
577
- Must be greater than min size
578
- }
579
- </mat-error>
778
+ <mat-form-field appearance="outline">
779
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.maxSize"
780
+ >Max Size (px)</mat-label
781
+ >
782
+ <input
783
+ matInput
784
+ type="number"
785
+ [value]="maxFontSize()"
786
+ (input)="
787
+ validateAndCorrectMaxFontSize(+$any($event.target).value)
788
+ "
789
+ (blur)="validateAndCorrectMaxFontSize(maxFontSize())"
790
+ min="16"
791
+ max="128"
792
+ placeholder="64"
793
+ />
794
+ @if (!isMaxFontSizeValid() || !isFontSizeRangeValid()) {
795
+ <mat-error>
796
+ @if (!isMaxFontSizeValid()) {
797
+ <span i18n="@@ngx.dashboard.widgets.label.dialog.maxSizeError"
798
+ >Must be between 16-128px</span
799
+ >
580
800
  } @else {
581
- <mat-hint>16-128px range</mat-hint>
801
+ <span
802
+ i18n="@@ngx.dashboard.widgets.label.dialog.maxSizeRangeError"
803
+ >Must be greater than min size</span
804
+ >
582
805
  }
583
- </mat-form-field>
584
- </div>
806
+ </mat-error>
807
+ } @else {
808
+ <mat-hint i18n="@@ngx.dashboard.widgets.label.dialog.maxSizeHint"
809
+ >16-128px range</mat-hint
810
+ >
811
+ }
812
+ </mat-form-field>
585
813
  </div>
814
+
815
+ <!-- Template String field -->
816
+ <mat-form-field appearance="outline">
817
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.templateString"
818
+ >Template String</mat-label
819
+ >
820
+ <input
821
+ matInput
822
+ type="text"
823
+ [value]="templateString() || ''"
824
+ (input)="templateString.set($any($event.target).value || undefined)"
825
+ i18n-placeholder="@@ngx.dashboard.widgets.label.dialog.templateStringPlaceholder"
826
+ placeholder="Optional: Text to use for size calculation"
827
+ />
828
+ <mat-hint i18n="@@ngx.dashboard.widgets.label.dialog.templateStringHint"
829
+ >Use when displayed text varies but size should remain consistent</mat-hint
830
+ >
831
+ </mat-form-field>
832
+ </div>
586
833
  }
587
834
 
588
835
  <div class="row-layout">
589
836
  <mat-form-field appearance="outline">
590
- <mat-label>Font Size (px)</mat-label>
837
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.fontSize"
838
+ >Font Size (px)</mat-label
839
+ >
591
840
  <input
592
841
  matInput
593
842
  type="number"
@@ -601,32 +850,61 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
601
850
  </mat-form-field>
602
851
 
603
852
  <mat-form-field appearance="outline">
604
- <mat-label>Alignment</mat-label>
853
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.alignment"
854
+ >Alignment</mat-label
855
+ >
605
856
  <mat-select
606
857
  [value]="alignment()"
607
858
  (selectionChange)="alignment.set($any($event.value))"
608
859
  >
609
- <mat-option value="left">Left</mat-option>
610
- <mat-option value="center">Center</mat-option>
611
- <mat-option value="right">Right</mat-option>
860
+ <mat-option
861
+ value="left"
862
+ i18n="@@ngx.dashboard.widgets.label.dialog.alignment.left"
863
+ >Left</mat-option
864
+ >
865
+ <mat-option
866
+ value="center"
867
+ i18n="@@ngx.dashboard.widgets.label.dialog.alignment.center"
868
+ >Center</mat-option
869
+ >
870
+ <mat-option
871
+ value="right"
872
+ i18n="@@ngx.dashboard.widgets.label.dialog.alignment.right"
873
+ >Right</mat-option
874
+ >
612
875
  </mat-select>
613
876
  </mat-form-field>
614
877
  </div>
615
878
 
616
879
  <mat-form-field appearance="outline">
617
- <mat-label>Font Weight</mat-label>
880
+ <mat-label i18n="@@ngx.dashboard.widgets.label.dialog.fontWeight"
881
+ >Font Weight</mat-label
882
+ >
618
883
  <mat-select
619
884
  [value]="fontWeight()"
620
885
  (selectionChange)="fontWeight.set($any($event.value))"
621
886
  >
622
- <mat-option value="normal">Normal</mat-option>
623
- <mat-option value="bold">Bold</mat-option>
887
+ <mat-option
888
+ value="normal"
889
+ i18n="@@ngx.dashboard.widgets.label.dialog.fontWeight.normal"
890
+ >Normal</mat-option
891
+ >
892
+ <mat-option
893
+ value="bold"
894
+ i18n="@@ngx.dashboard.widgets.label.dialog.fontWeight.bold"
895
+ >Bold</mat-option
896
+ >
624
897
  </mat-select>
625
898
  </mat-form-field>
626
899
 
627
900
  <!-- Opacity Slider -->
628
901
  <div class="slider-section">
629
- <div class="slider-label">Opacity: {{ formatOpacity(opacity()) }}%</div>
902
+ <div
903
+ class="slider-label"
904
+ i18n="@@ngx.dashboard.widgets.label.dialog.opacity"
905
+ >
906
+ Opacity: {{ formatOpacity(opacity()) }}%
907
+ </div>
630
908
  <mat-slider [min]="0.1" [max]="1" [step]="0.1">
631
909
  <input matSliderThumb [(ngModel)]="opacity" />
632
910
  </mat-slider>
@@ -634,24 +912,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
634
912
 
635
913
  <!-- Background Toggle -->
636
914
  <div class="toggle-section">
637
- <mat-slide-toggle
915
+ <mat-slide-toggle
638
916
  [checked]="!transparentBackground()"
639
- (change)="onBackgroundToggle($event.checked)">
917
+ (change)="onBackgroundToggle($event.checked)"
918
+ i18n="@@ngx.dashboard.widgets.label.dialog.background"
919
+ >
640
920
  Background
641
921
  </mat-slide-toggle>
642
- <span class="toggle-description"
922
+ <span
923
+ class="toggle-description"
924
+ i18n="@@ngx.dashboard.widgets.label.dialog.backgroundDescription"
643
925
  >Adds a background behind the text</span
644
926
  >
645
927
  </div>
646
928
  </mat-dialog-content>
647
929
 
648
930
  <mat-dialog-actions align="end">
649
- <button mat-button (click)="onCancel()">Cancel</button>
650
- <button mat-flat-button (click)="save()" [disabled]="!hasChanged() || !isFormValid()">
931
+ <button
932
+ mat-button
933
+ (click)="onCancel()"
934
+ i18n="@@ngx.dashboard.common.cancel"
935
+ >
936
+ Cancel
937
+ </button>
938
+ <button
939
+ mat-flat-button
940
+ (click)="save()"
941
+ [disabled]="!hasChanged() || !isFormValid()"
942
+ i18n="@@ngx.dashboard.common.save"
943
+ >
651
944
  Save
652
945
  </button>
653
946
  </mat-dialog-actions>
654
- `, styles: ["mat-dialog-content{display:block;overflow-y:auto;overflow-x:hidden}mat-form-field{width:100%;display:block;margin-bottom:1rem}.label-text-field{margin-top:1rem}.row-layout{display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem}.row-layout mat-form-field{margin-bottom:0}.slider-section{margin-bottom:1.5rem;margin-right:1rem}.slider-label{display:block;margin-bottom:.5rem}mat-slider{width:100%;display:block}.toggle-section{display:flex;align-items:center;gap:.75rem;margin-bottom:1rem}.toggle-description{margin:0}.responsive-section{margin-bottom:1.5rem;padding:1rem;border-radius:12px;background-color:var(--mat-app-surface-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .05));border:1px solid var(--mat-app-outline-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .12))}.section-label{display:block;margin-bottom:.75rem;font-weight:500;color:var(--mat-app-on-surface-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .6))}.responsive-section .row-layout{margin-bottom:0}\n"] }]
947
+ `, styles: ["mat-dialog-content{display:block;overflow-y:auto;overflow-x:hidden}mat-form-field{width:100%;display:block;margin-bottom:1rem}.label-text-field{margin-top:1rem}.row-layout{display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem}.row-layout mat-form-field{margin-bottom:0}.slider-section{margin-bottom:1.5rem;margin-right:1rem}.slider-label{display:block;margin-bottom:.5rem}mat-slider{width:100%;display:block}.toggle-section{display:flex;align-items:center;gap:.75rem;margin-bottom:1rem}.toggle-description{margin:0}.responsive-section{margin-bottom:1.5rem;padding:1rem;border-radius:12px;background-color:var( --mat-app-surface-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .05) );border:1px solid var( --mat-app-outline-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .12) )}.section-label{display:block;margin-bottom:.75rem;font-weight:500;color:var( --mat-app-on-surface-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), .6) )}.responsive-section .row-layout{margin-bottom:0}\n"] }]
655
948
  }] });
656
949
 
657
950
  /**
@@ -660,7 +953,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
660
953
  *
661
954
  * @example
662
955
  * <div class="container">
663
- * <span responsiveText [minFontSize]="12" [maxFontSize]="72">Dynamic text here</span>
956
+ * <span libResponsiveText [minFontSize]="12" [maxFontSize]="72">Dynamic text here</span>
957
+ * <span libResponsiveText [templateString]="'Template for sizing'">Shorter text</span>
664
958
  * </div>
665
959
  */
666
960
  class ResponsiveTextDirective {
@@ -678,6 +972,8 @@ class ResponsiveTextDirective {
678
972
  observeMutations = input(true, ...(ngDevMode ? [{ debugName: "observeMutations", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
679
973
  /** Debounce delay in ms for resize/mutation callbacks */
680
974
  debounceMs = input(16, ...(ngDevMode ? [{ debugName: "debounceMs", transform: numberAttribute }] : [{ transform: numberAttribute }]));
975
+ /** Template string to use for size calculations instead of actual content */
976
+ templateString = input(undefined, ...(ngDevMode ? [{ debugName: "templateString" }] : []));
681
977
  /* ───────────────────────── Private state ───────────────────────── */
682
978
  el = inject(ElementRef);
683
979
  zone = inject(NgZone);
@@ -700,14 +996,29 @@ class ResponsiveTextDirective {
700
996
  fitTimeout;
701
997
  // Cache for performance
702
998
  lastText = '';
999
+ lastTemplateString = '';
703
1000
  lastMaxW = 0;
704
1001
  lastMaxH = 0;
705
1002
  lastFontSize = 0;
1003
+ isViewInitialized = false;
706
1004
  constructor() {
707
1005
  // Set up cleanup on component destruction using modern DestroyRef
708
1006
  this.destroyRef.onDestroy(() => {
709
1007
  this.cleanup();
710
1008
  });
1009
+ // Watch for input changes and trigger refit
1010
+ effect(() => {
1011
+ // Access the signals to track them (triggers when they change)
1012
+ this.templateString();
1013
+ this.minFontSize();
1014
+ this.maxFontSize();
1015
+ // Only trigger refit if directive is initialized and view is ready
1016
+ if (this.isViewInitialized && isPlatformBrowser(this.platformId)) {
1017
+ this.zone.runOutsideAngular(() => {
1018
+ this.requestFit();
1019
+ });
1020
+ }
1021
+ });
711
1022
  }
712
1023
  ngAfterViewInit() {
713
1024
  if (!isPlatformBrowser(this.platformId))
@@ -715,6 +1026,8 @@ class ResponsiveTextDirective {
715
1026
  // Set initial styles
716
1027
  const span = this.el.nativeElement;
717
1028
  span.style.transition = 'font-size 0.1s ease-out';
1029
+ // Mark as initialized for the effect to start watching
1030
+ this.isViewInitialized = true;
718
1031
  // All observer callbacks run outside Angular's zone
719
1032
  this.zone.runOutsideAngular(() => {
720
1033
  this.fit();
@@ -744,26 +1057,30 @@ class ResponsiveTextDirective {
744
1057
  const parent = span.parentElement;
745
1058
  if (!parent)
746
1059
  return;
747
- const text = span.textContent?.trim() || '';
748
- if (!text) {
1060
+ const actualText = span.textContent?.trim() || '';
1061
+ const templateString = this.templateString()?.trim();
1062
+ const measureText = templateString || actualText;
1063
+ if (!measureText) {
749
1064
  span.style.fontSize = `${this.minFontSize()}px`;
750
1065
  return;
751
1066
  }
752
1067
  const { maxW, maxH } = this.getAvailableSpace(parent);
753
1068
  // Check cache to avoid redundant calculations
754
- if (text === this.lastText &&
1069
+ if (actualText === this.lastText &&
1070
+ (templateString || '') === this.lastTemplateString &&
755
1071
  maxW === this.lastMaxW &&
756
1072
  maxH === this.lastMaxH &&
757
1073
  this.lastFontSize > 0) {
758
1074
  return;
759
1075
  }
760
1076
  // Calculate with conservative buffer for sub-pixel accuracy
761
- const ideal = this.calcFit(text, maxW * 0.98, maxH * 0.98);
1077
+ const ideal = this.calcFit(measureText, maxW * 0.98, maxH * 0.98);
762
1078
  span.style.fontSize = `${ideal}px`;
763
1079
  // DOM verification pass
764
1080
  this.verifyFit(span, maxW, maxH, ideal);
765
1081
  // Update cache
766
- this.lastText = text;
1082
+ this.lastText = actualText;
1083
+ this.lastTemplateString = templateString || '';
767
1084
  this.lastMaxW = maxW;
768
1085
  this.lastMaxH = maxH;
769
1086
  this.lastFontSize = parseFloat(span.style.fontSize);
@@ -901,7 +1218,7 @@ class ResponsiveTextDirective {
901
1218
  this._ctx = undefined;
902
1219
  }
903
1220
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: ResponsiveTextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
904
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.2.1", type: ResponsiveTextDirective, isStandalone: true, selector: "[libResponsiveText]", inputs: { minFontSize: { classPropertyName: "minFontSize", publicName: "minFontSize", isSignal: true, isRequired: false, transformFunction: null }, maxFontSize: { classPropertyName: "maxFontSize", publicName: "maxFontSize", isSignal: true, isRequired: false, transformFunction: null }, lineHeight: { classPropertyName: "lineHeight", publicName: "lineHeight", isSignal: true, isRequired: false, transformFunction: null }, observeMutations: { classPropertyName: "observeMutations", publicName: "observeMutations", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.display": "\"block\"", "style.width": "\"100%\"", "style.white-space": "\"nowrap\"", "style.overflow": "\"visible\"" } }, ngImport: i0 });
1221
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.2.1", type: ResponsiveTextDirective, isStandalone: true, selector: "[libResponsiveText]", inputs: { minFontSize: { classPropertyName: "minFontSize", publicName: "minFontSize", isSignal: true, isRequired: false, transformFunction: null }, maxFontSize: { classPropertyName: "maxFontSize", publicName: "maxFontSize", isSignal: true, isRequired: false, transformFunction: null }, lineHeight: { classPropertyName: "lineHeight", publicName: "lineHeight", isSignal: true, isRequired: false, transformFunction: null }, observeMutations: { classPropertyName: "observeMutations", publicName: "observeMutations", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, templateString: { classPropertyName: "templateString", publicName: "templateString", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.display": "\"block\"", "style.width": "\"100%\"", "style.white-space": "\"nowrap\"", "style.overflow": "\"visible\"" } }, ngImport: i0 });
905
1222
  }
906
1223
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: ResponsiveTextDirective, decorators: [{
907
1224
  type: Directive,
@@ -921,8 +1238,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
921
1238
  class LabelWidgetComponent {
922
1239
  static metadata = {
923
1240
  widgetTypeid: '@ngx-dashboard/label-widget',
924
- name: 'Label',
925
- description: 'A generic text label',
1241
+ name: $localize `:@@ngx.dashboard.widgets.label.name:Label`,
1242
+ description: $localize `:@@ngx.dashboard.widgets.label.description:A generic text label`,
926
1243
  svgIcon: svgIcon$2,
927
1244
  };
928
1245
  #sanitizer = inject(DomSanitizer);
@@ -948,7 +1265,12 @@ class LabelWidgetComponent {
948
1265
  }
949
1266
  }
950
1267
  dashboardGetState() {
951
- return { ...this.state() };
1268
+ const state = { ...this.state() };
1269
+ // Remove templateString if undefined to maintain backward compatibility
1270
+ if (state.templateString === undefined) {
1271
+ delete state.templateString;
1272
+ }
1273
+ return state;
952
1274
  }
953
1275
  dashboardEditState() {
954
1276
  const dialogRef = this.#dialog.open(LabelStateDialogComponent, {
@@ -975,12 +1297,13 @@ class LabelWidgetComponent {
975
1297
  // Computed properties for responsive font size limits with fallbacks
976
1298
  minFontSize = computed(() => this.state().minFontSize ?? 8, ...(ngDevMode ? [{ debugName: "minFontSize" }] : []));
977
1299
  maxFontSize = computed(() => this.state().maxFontSize ?? 64, ...(ngDevMode ? [{ debugName: "maxFontSize" }] : []));
1300
+ templateString = computed(() => this.state().templateString, ...(ngDevMode ? [{ debugName: "templateString" }] : []));
978
1301
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: LabelWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
979
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: LabelWidgetComponent, isStandalone: true, selector: "ngx-dashboard-label-widget", ngImport: i0, template: "@if (hasContent) {\r\n<div\r\n class=\"label-widget\"\r\n [style.fontSize.rem]=\"state().responsive ? null : state().fontSize! / 16\"\r\n [style.--widget-opacity]=\"state().opacity\"\r\n [class.text-left]=\"state().alignment === 'left'\"\r\n [class.text-right]=\"state().alignment === 'right'\"\r\n [class.font-bold]=\"state().fontWeight === 'bold'\"\r\n [class.has-background]=\"state().hasBackground\"\r\n>\r\n @if (state().responsive) {\r\n <div class=\"label-text\" libResponsiveText [minFontSize]=\"minFontSize()\" [maxFontSize]=\"maxFontSize()\">{{ label }}</div>\r\n } @else {\r\n <div class=\"label-text\">{{ label }}</div>\r\n }\r\n</div>\r\n} @else {\r\n<div class=\"svg-wrapper\" [class.has-background]=\"state().hasBackground\">\r\n <div class=\"svg-placeholder\" [innerHTML]=\"safeSvgIcon\"></div>\r\n</div>\r\n}\r\n", styles: [":host{display:block;container-type:size;width:100%;height:100%;overflow:hidden}.svg-wrapper,.label-widget{display:flex;align-items:center;justify-content:center;height:100%;width:100%;box-sizing:border-box;transition:background-color var(--mat-sys-motion-duration-medium2) var(--mat-sys-motion-easing-standard)}.has-background.svg-wrapper,.has-background.label-widget{background-color:var(--mat-sys-surface-container-high);border-radius:4px}.label-widget{overflow:hidden;container-type:size;padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d);opacity:var(--widget-opacity, 1)}.label-widget.text-left{justify-content:flex-start}.label-widget.text-right{justify-content:flex-end}.label-widget.has-background{color:var(--mat-sys-on-surface, #1f1f1f)}.label-widget:hover{opacity:.3;color:var(--mat-sys-primary, #6750a4)}.label-text{width:100%;text-align:center;overflow-wrap:break-word;transition:color .2s ease}.text-left .label-text{text-align:left}.text-right .label-text{text-align:right}.font-bold .label-text{font-weight:700}.label-text[responsiveText]{overflow-wrap:normal}.svg-wrapper{overflow:hidden}.svg-placeholder{width:min(80cqw,80cqh);aspect-ratio:1/1;opacity:.3;transition:transform .3s ease-in-out,opacity .3s ease,color .2s ease;transform-origin:center center;color:var(--mat-sys-on-surface-variant, #6c757d)}.has-background .svg-placeholder{color:var(--mat-sys-on-surface, #1f1f1f)}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block}.svg-wrapper:hover .svg-placeholder{color:var(--mat-sys-primary, #6750a4)}\n"], dependencies: [{ kind: "directive", type: ResponsiveTextDirective, selector: "[libResponsiveText]", inputs: ["minFontSize", "maxFontSize", "lineHeight", "observeMutations", "debounceMs"] }] });
1302
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: LabelWidgetComponent, isStandalone: true, selector: "ngx-dashboard-label-widget", ngImport: i0, template: "@if (hasContent) {\r\n<div\r\n class=\"label-widget\"\r\n [style.fontSize.rem]=\"state().responsive ? null : state().fontSize! / 16\"\r\n [style.--widget-opacity]=\"state().opacity\"\r\n [class.text-left]=\"state().alignment === 'left'\"\r\n [class.text-right]=\"state().alignment === 'right'\"\r\n [class.font-bold]=\"state().fontWeight === 'bold'\"\r\n [class.has-background]=\"state().hasBackground\"\r\n>\r\n @if (state().responsive) {\r\n <div class=\"label-text\" libResponsiveText [minFontSize]=\"minFontSize()\" [maxFontSize]=\"maxFontSize()\" [templateString]=\"templateString()\">{{ label }}</div>\r\n } @else {\r\n <div class=\"label-text\">{{ label }}</div>\r\n }\r\n</div>\r\n} @else {\r\n<div class=\"svg-wrapper\" [class.has-background]=\"state().hasBackground\">\r\n <div class=\"svg-placeholder\" [innerHTML]=\"safeSvgIcon\"></div>\r\n</div>\r\n}\r\n", styles: [":host{display:block;container-type:size;width:100%;height:100%;overflow:hidden}.svg-wrapper,.label-widget{display:flex;align-items:center;justify-content:center;height:100%;width:100%;box-sizing:border-box;transition:background-color var(--mat-sys-motion-duration-medium2) var(--mat-sys-motion-easing-standard)}.has-background.svg-wrapper,.has-background.label-widget{background-color:var(--mat-sys-surface-container-high);border-radius:4px}.label-widget{overflow:hidden;container-type:size;padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d);opacity:var(--widget-opacity, 1)}.label-widget.text-left{justify-content:flex-start}.label-widget.text-right{justify-content:flex-end}.label-widget.has-background{color:var(--mat-sys-on-surface, #1f1f1f)}.label-widget:hover{opacity:.3;color:var(--mat-sys-primary, #6750a4)}.label-text{width:100%;text-align:center;overflow-wrap:break-word;transition:color .2s ease}.text-left .label-text{text-align:left}.text-right .label-text{text-align:right}.font-bold .label-text{font-weight:700}.label-text[responsiveText]{overflow-wrap:normal}.svg-wrapper{overflow:hidden}.svg-placeholder{width:min(80cqw,80cqh);aspect-ratio:1/1;opacity:.3;transition:transform .3s ease-in-out,opacity .3s ease,color .2s ease;transform-origin:center center;color:var(--mat-sys-on-surface-variant, #6c757d)}.has-background .svg-placeholder{color:var(--mat-sys-on-surface, #1f1f1f)}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block}.svg-wrapper:hover .svg-placeholder{color:var(--mat-sys-primary, #6750a4)}\n"], dependencies: [{ kind: "directive", type: ResponsiveTextDirective, selector: "[libResponsiveText]", inputs: ["minFontSize", "maxFontSize", "lineHeight", "observeMutations", "debounceMs", "templateString"] }] });
980
1303
  }
981
1304
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: LabelWidgetComponent, decorators: [{
982
1305
  type: Component,
983
- args: [{ selector: 'ngx-dashboard-label-widget', imports: [ResponsiveTextDirective], template: "@if (hasContent) {\r\n<div\r\n class=\"label-widget\"\r\n [style.fontSize.rem]=\"state().responsive ? null : state().fontSize! / 16\"\r\n [style.--widget-opacity]=\"state().opacity\"\r\n [class.text-left]=\"state().alignment === 'left'\"\r\n [class.text-right]=\"state().alignment === 'right'\"\r\n [class.font-bold]=\"state().fontWeight === 'bold'\"\r\n [class.has-background]=\"state().hasBackground\"\r\n>\r\n @if (state().responsive) {\r\n <div class=\"label-text\" libResponsiveText [minFontSize]=\"minFontSize()\" [maxFontSize]=\"maxFontSize()\">{{ label }}</div>\r\n } @else {\r\n <div class=\"label-text\">{{ label }}</div>\r\n }\r\n</div>\r\n} @else {\r\n<div class=\"svg-wrapper\" [class.has-background]=\"state().hasBackground\">\r\n <div class=\"svg-placeholder\" [innerHTML]=\"safeSvgIcon\"></div>\r\n</div>\r\n}\r\n", styles: [":host{display:block;container-type:size;width:100%;height:100%;overflow:hidden}.svg-wrapper,.label-widget{display:flex;align-items:center;justify-content:center;height:100%;width:100%;box-sizing:border-box;transition:background-color var(--mat-sys-motion-duration-medium2) var(--mat-sys-motion-easing-standard)}.has-background.svg-wrapper,.has-background.label-widget{background-color:var(--mat-sys-surface-container-high);border-radius:4px}.label-widget{overflow:hidden;container-type:size;padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d);opacity:var(--widget-opacity, 1)}.label-widget.text-left{justify-content:flex-start}.label-widget.text-right{justify-content:flex-end}.label-widget.has-background{color:var(--mat-sys-on-surface, #1f1f1f)}.label-widget:hover{opacity:.3;color:var(--mat-sys-primary, #6750a4)}.label-text{width:100%;text-align:center;overflow-wrap:break-word;transition:color .2s ease}.text-left .label-text{text-align:left}.text-right .label-text{text-align:right}.font-bold .label-text{font-weight:700}.label-text[responsiveText]{overflow-wrap:normal}.svg-wrapper{overflow:hidden}.svg-placeholder{width:min(80cqw,80cqh);aspect-ratio:1/1;opacity:.3;transition:transform .3s ease-in-out,opacity .3s ease,color .2s ease;transform-origin:center center;color:var(--mat-sys-on-surface-variant, #6c757d)}.has-background .svg-placeholder{color:var(--mat-sys-on-surface, #1f1f1f)}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block}.svg-wrapper:hover .svg-placeholder{color:var(--mat-sys-primary, #6750a4)}\n"] }]
1306
+ args: [{ selector: 'ngx-dashboard-label-widget', imports: [ResponsiveTextDirective], template: "@if (hasContent) {\r\n<div\r\n class=\"label-widget\"\r\n [style.fontSize.rem]=\"state().responsive ? null : state().fontSize! / 16\"\r\n [style.--widget-opacity]=\"state().opacity\"\r\n [class.text-left]=\"state().alignment === 'left'\"\r\n [class.text-right]=\"state().alignment === 'right'\"\r\n [class.font-bold]=\"state().fontWeight === 'bold'\"\r\n [class.has-background]=\"state().hasBackground\"\r\n>\r\n @if (state().responsive) {\r\n <div class=\"label-text\" libResponsiveText [minFontSize]=\"minFontSize()\" [maxFontSize]=\"maxFontSize()\" [templateString]=\"templateString()\">{{ label }}</div>\r\n } @else {\r\n <div class=\"label-text\">{{ label }}</div>\r\n }\r\n</div>\r\n} @else {\r\n<div class=\"svg-wrapper\" [class.has-background]=\"state().hasBackground\">\r\n <div class=\"svg-placeholder\" [innerHTML]=\"safeSvgIcon\"></div>\r\n</div>\r\n}\r\n", styles: [":host{display:block;container-type:size;width:100%;height:100%;overflow:hidden}.svg-wrapper,.label-widget{display:flex;align-items:center;justify-content:center;height:100%;width:100%;box-sizing:border-box;transition:background-color var(--mat-sys-motion-duration-medium2) var(--mat-sys-motion-easing-standard)}.has-background.svg-wrapper,.has-background.label-widget{background-color:var(--mat-sys-surface-container-high);border-radius:4px}.label-widget{overflow:hidden;container-type:size;padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d);opacity:var(--widget-opacity, 1)}.label-widget.text-left{justify-content:flex-start}.label-widget.text-right{justify-content:flex-end}.label-widget.has-background{color:var(--mat-sys-on-surface, #1f1f1f)}.label-widget:hover{opacity:.3;color:var(--mat-sys-primary, #6750a4)}.label-text{width:100%;text-align:center;overflow-wrap:break-word;transition:color .2s ease}.text-left .label-text{text-align:left}.text-right .label-text{text-align:right}.font-bold .label-text{font-weight:700}.label-text[responsiveText]{overflow-wrap:normal}.svg-wrapper{overflow:hidden}.svg-placeholder{width:min(80cqw,80cqh);aspect-ratio:1/1;opacity:.3;transition:transform .3s ease-in-out,opacity .3s ease,color .2s ease;transform-origin:center center;color:var(--mat-sys-on-surface-variant, #6c757d)}.has-background .svg-placeholder{color:var(--mat-sys-on-surface, #1f1f1f)}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block}.svg-wrapper:hover .svg-placeholder{color:var(--mat-sys-primary, #6750a4)}\n"] }]
984
1307
  }] });
985
1308
 
986
1309
  const svgIcon$1 = `
@@ -1059,67 +1382,120 @@ class ClockStateDialogComponent {
1059
1382
  }
1060
1383
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: ClockStateDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1061
1384
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.2.1", type: ClockStateDialogComponent, isStandalone: true, selector: "lib-clock-state-dialog", ngImport: i0, template: `
1062
- <h2 mat-dialog-title>Clock Settings</h2>
1385
+ <h2 mat-dialog-title i18n="@@ngx.dashboard.widgets.clock.dialog.title">
1386
+ Clock Settings
1387
+ </h2>
1063
1388
  <mat-dialog-content>
1064
1389
  <div class="mode-selection">
1065
- <label class="section-label" for="mode-selection-group">Display Mode</label>
1390
+ <label
1391
+ class="section-label"
1392
+ for="mode-selection-group"
1393
+ i18n="@@ngx.dashboard.widgets.clock.dialog.displayMode"
1394
+ >Display Mode</label
1395
+ >
1066
1396
  <mat-radio-group
1067
1397
  id="mode-selection-group"
1068
1398
  [value]="mode()"
1069
1399
  (change)="mode.set($any($event.value))"
1070
1400
  >
1071
- <mat-radio-button value="digital">Digital</mat-radio-button>
1072
- <mat-radio-button value="analog">Analog</mat-radio-button>
1401
+ <mat-radio-button
1402
+ value="digital"
1403
+ i18n="@@ngx.dashboard.widgets.clock.dialog.mode.digital"
1404
+ >Digital</mat-radio-button
1405
+ >
1406
+ <mat-radio-button
1407
+ value="analog"
1408
+ i18n="@@ngx.dashboard.widgets.clock.dialog.mode.analog"
1409
+ >Analog</mat-radio-button
1410
+ >
1073
1411
  </mat-radio-group>
1074
1412
  </div>
1075
1413
 
1076
1414
  <!-- Time Format (only for digital mode) -->
1077
1415
  @if (mode() === 'digital') {
1078
1416
  <div class="format-selection">
1079
- <label class="section-label" for="time-format-group">Time Format</label>
1417
+ <label
1418
+ class="section-label"
1419
+ for="time-format-group"
1420
+ i18n="@@ngx.dashboard.widgets.clock.dialog.timeFormat"
1421
+ >Time Format</label
1422
+ >
1080
1423
  <mat-radio-group
1081
1424
  id="time-format-group"
1082
1425
  [value]="timeFormat()"
1083
1426
  (change)="timeFormat.set($any($event.value))"
1084
1427
  >
1085
- <mat-radio-button value="24h">24 Hour (14:30:45)</mat-radio-button>
1086
- <mat-radio-button value="12h">12 Hour (2:30:45 PM)</mat-radio-button>
1428
+ <mat-radio-button
1429
+ value="24h"
1430
+ i18n="@@ngx.dashboard.widgets.clock.dialog.format.24h"
1431
+ >24 Hour (14:30:45)</mat-radio-button
1432
+ >
1433
+ <mat-radio-button
1434
+ value="12h"
1435
+ i18n="@@ngx.dashboard.widgets.clock.dialog.format.12h"
1436
+ >12 Hour (2:30:45 PM)</mat-radio-button
1437
+ >
1087
1438
  </mat-radio-group>
1088
1439
  </div>
1089
1440
  }
1090
1441
 
1091
1442
  <!-- Show Seconds Toggle (for both digital and analog modes) -->
1092
1443
  <div class="toggle-section">
1093
- <mat-slide-toggle
1444
+ <mat-slide-toggle
1094
1445
  [checked]="showSeconds()"
1095
- (change)="showSeconds.set($event.checked)">
1446
+ (change)="showSeconds.set($event.checked)"
1447
+ i18n="@@ngx.dashboard.widgets.clock.dialog.showSeconds"
1448
+ >
1096
1449
  Show Seconds
1097
1450
  </mat-slide-toggle>
1098
1451
  <span class="toggle-description">
1099
1452
  @if (mode() === 'digital') {
1100
- Display seconds in the time
1453
+ <span
1454
+ i18n="
1455
+ @@ngx.dashboard.widgets.clock.dialog.showSecondsDescription.digital"
1456
+ >Display seconds in the time</span
1457
+ >
1101
1458
  } @else {
1102
- Show the second hand on the clock
1459
+ <span
1460
+ i18n="
1461
+ @@ngx.dashboard.widgets.clock.dialog.showSecondsDescription.analog"
1462
+ >Show the second hand on the clock</span
1463
+ >
1103
1464
  }
1104
1465
  </span>
1105
1466
  </div>
1106
1467
 
1107
1468
  <!-- Background Toggle -->
1108
1469
  <div class="toggle-section">
1109
- <mat-slide-toggle
1470
+ <mat-slide-toggle
1110
1471
  [checked]="hasBackground()"
1111
- (change)="hasBackground.set($event.checked)">
1472
+ (change)="hasBackground.set($event.checked)"
1473
+ i18n="@@ngx.dashboard.widgets.clock.dialog.background"
1474
+ >
1112
1475
  Background
1113
1476
  </mat-slide-toggle>
1114
- <span class="toggle-description"
1477
+ <span
1478
+ class="toggle-description"
1479
+ i18n="@@ngx.dashboard.widgets.clock.dialog.backgroundDescription"
1115
1480
  >Adds a background behind the clock</span
1116
1481
  >
1117
1482
  </div>
1118
1483
  </mat-dialog-content>
1119
1484
 
1120
1485
  <mat-dialog-actions align="end">
1121
- <button mat-button (click)="onCancel()">Cancel</button>
1122
- <button mat-flat-button (click)="save()" [disabled]="!hasChanged()">
1486
+ <button
1487
+ mat-button
1488
+ (click)="onCancel()"
1489
+ i18n="@@ngx.dashboard.common.cancel"
1490
+ >
1491
+ Cancel
1492
+ </button>
1493
+ <button
1494
+ mat-flat-button
1495
+ (click)="save()"
1496
+ [disabled]="!hasChanged()"
1497
+ i18n="@@ngx.dashboard.common.save"
1498
+ >
1123
1499
  Save
1124
1500
  </button>
1125
1501
  </mat-dialog-actions>
@@ -1135,67 +1511,120 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
1135
1511
  MatRadioModule,
1136
1512
  MatSlideToggleModule,
1137
1513
  ], template: `
1138
- <h2 mat-dialog-title>Clock Settings</h2>
1514
+ <h2 mat-dialog-title i18n="@@ngx.dashboard.widgets.clock.dialog.title">
1515
+ Clock Settings
1516
+ </h2>
1139
1517
  <mat-dialog-content>
1140
1518
  <div class="mode-selection">
1141
- <label class="section-label" for="mode-selection-group">Display Mode</label>
1519
+ <label
1520
+ class="section-label"
1521
+ for="mode-selection-group"
1522
+ i18n="@@ngx.dashboard.widgets.clock.dialog.displayMode"
1523
+ >Display Mode</label
1524
+ >
1142
1525
  <mat-radio-group
1143
1526
  id="mode-selection-group"
1144
1527
  [value]="mode()"
1145
1528
  (change)="mode.set($any($event.value))"
1146
1529
  >
1147
- <mat-radio-button value="digital">Digital</mat-radio-button>
1148
- <mat-radio-button value="analog">Analog</mat-radio-button>
1530
+ <mat-radio-button
1531
+ value="digital"
1532
+ i18n="@@ngx.dashboard.widgets.clock.dialog.mode.digital"
1533
+ >Digital</mat-radio-button
1534
+ >
1535
+ <mat-radio-button
1536
+ value="analog"
1537
+ i18n="@@ngx.dashboard.widgets.clock.dialog.mode.analog"
1538
+ >Analog</mat-radio-button
1539
+ >
1149
1540
  </mat-radio-group>
1150
1541
  </div>
1151
1542
 
1152
1543
  <!-- Time Format (only for digital mode) -->
1153
1544
  @if (mode() === 'digital') {
1154
1545
  <div class="format-selection">
1155
- <label class="section-label" for="time-format-group">Time Format</label>
1546
+ <label
1547
+ class="section-label"
1548
+ for="time-format-group"
1549
+ i18n="@@ngx.dashboard.widgets.clock.dialog.timeFormat"
1550
+ >Time Format</label
1551
+ >
1156
1552
  <mat-radio-group
1157
1553
  id="time-format-group"
1158
1554
  [value]="timeFormat()"
1159
1555
  (change)="timeFormat.set($any($event.value))"
1160
1556
  >
1161
- <mat-radio-button value="24h">24 Hour (14:30:45)</mat-radio-button>
1162
- <mat-radio-button value="12h">12 Hour (2:30:45 PM)</mat-radio-button>
1557
+ <mat-radio-button
1558
+ value="24h"
1559
+ i18n="@@ngx.dashboard.widgets.clock.dialog.format.24h"
1560
+ >24 Hour (14:30:45)</mat-radio-button
1561
+ >
1562
+ <mat-radio-button
1563
+ value="12h"
1564
+ i18n="@@ngx.dashboard.widgets.clock.dialog.format.12h"
1565
+ >12 Hour (2:30:45 PM)</mat-radio-button
1566
+ >
1163
1567
  </mat-radio-group>
1164
1568
  </div>
1165
1569
  }
1166
1570
 
1167
1571
  <!-- Show Seconds Toggle (for both digital and analog modes) -->
1168
1572
  <div class="toggle-section">
1169
- <mat-slide-toggle
1573
+ <mat-slide-toggle
1170
1574
  [checked]="showSeconds()"
1171
- (change)="showSeconds.set($event.checked)">
1575
+ (change)="showSeconds.set($event.checked)"
1576
+ i18n="@@ngx.dashboard.widgets.clock.dialog.showSeconds"
1577
+ >
1172
1578
  Show Seconds
1173
1579
  </mat-slide-toggle>
1174
1580
  <span class="toggle-description">
1175
1581
  @if (mode() === 'digital') {
1176
- Display seconds in the time
1582
+ <span
1583
+ i18n="
1584
+ @@ngx.dashboard.widgets.clock.dialog.showSecondsDescription.digital"
1585
+ >Display seconds in the time</span
1586
+ >
1177
1587
  } @else {
1178
- Show the second hand on the clock
1588
+ <span
1589
+ i18n="
1590
+ @@ngx.dashboard.widgets.clock.dialog.showSecondsDescription.analog"
1591
+ >Show the second hand on the clock</span
1592
+ >
1179
1593
  }
1180
1594
  </span>
1181
1595
  </div>
1182
1596
 
1183
1597
  <!-- Background Toggle -->
1184
1598
  <div class="toggle-section">
1185
- <mat-slide-toggle
1599
+ <mat-slide-toggle
1186
1600
  [checked]="hasBackground()"
1187
- (change)="hasBackground.set($event.checked)">
1601
+ (change)="hasBackground.set($event.checked)"
1602
+ i18n="@@ngx.dashboard.widgets.clock.dialog.background"
1603
+ >
1188
1604
  Background
1189
1605
  </mat-slide-toggle>
1190
- <span class="toggle-description"
1606
+ <span
1607
+ class="toggle-description"
1608
+ i18n="@@ngx.dashboard.widgets.clock.dialog.backgroundDescription"
1191
1609
  >Adds a background behind the clock</span
1192
1610
  >
1193
1611
  </div>
1194
1612
  </mat-dialog-content>
1195
1613
 
1196
1614
  <mat-dialog-actions align="end">
1197
- <button mat-button (click)="onCancel()">Cancel</button>
1198
- <button mat-flat-button (click)="save()" [disabled]="!hasChanged()">
1615
+ <button
1616
+ mat-button
1617
+ (click)="onCancel()"
1618
+ i18n="@@ngx.dashboard.common.cancel"
1619
+ >
1620
+ Cancel
1621
+ </button>
1622
+ <button
1623
+ mat-flat-button
1624
+ (click)="save()"
1625
+ [disabled]="!hasChanged()"
1626
+ i18n="@@ngx.dashboard.common.save"
1627
+ >
1199
1628
  Save
1200
1629
  </button>
1201
1630
  </mat-dialog-actions>
@@ -1369,8 +1798,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
1369
1798
  class ClockWidgetComponent {
1370
1799
  static metadata = {
1371
1800
  widgetTypeid: '@ngx-dashboard/clock-widget',
1372
- name: 'Clock',
1373
- description: 'Display time in analog or digital format',
1801
+ name: $localize `:@@ngx.dashboard.widgets.clock.name:Clock`,
1802
+ description: $localize `:@@ngx.dashboard.widgets.clock.description:Display time in analog or digital format`,
1374
1803
  svgIcon: svgIcon$1,
1375
1804
  };
1376
1805
  #sanitizer = inject(DomSanitizer);
@@ -2057,10 +2486,17 @@ class RadialGaugeStateDialogComponent {
2057
2486
  }
2058
2487
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.1", ngImport: i0, type: RadialGaugeStateDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2059
2488
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.2.1", type: RadialGaugeStateDialogComponent, isStandalone: true, selector: "lib-radial-gauge-state-dialog", ngImport: i0, template: `
2060
- <h2 mat-dialog-title>Radial Gauge Settings</h2>
2489
+ <h2
2490
+ mat-dialog-title
2491
+ i18n="@@ngx.dashboard.widgets.radialGauge.dialog.title"
2492
+ >
2493
+ Radial Gauge Settings
2494
+ </h2>
2061
2495
  <mat-dialog-content>
2062
2496
  <mat-form-field>
2063
- <mat-label>Value (0-100)</mat-label>
2497
+ <mat-label i18n="@@ngx.dashboard.widgets.radialGauge.dialog.value"
2498
+ >Value (0-100)</mat-label
2499
+ >
2064
2500
  <input
2065
2501
  matInput
2066
2502
  type="number"
@@ -2071,38 +2507,89 @@ class RadialGaugeStateDialogComponent {
2071
2507
  </mat-form-field>
2072
2508
 
2073
2509
  <div class="section">
2074
- <h4>Color Profile</h4>
2510
+ <h4 i18n="@@ngx.dashboard.widgets.radialGauge.dialog.colorProfile">
2511
+ Color Profile
2512
+ </h4>
2075
2513
  <mat-radio-group [(ngModel)]="localState.colorProfile">
2076
- <mat-radio-button value="dynamic">Dynamic (Theme Colors)</mat-radio-button>
2077
- <mat-radio-button value="static">Static (Performance Colors)</mat-radio-button>
2514
+ <mat-radio-button
2515
+ value="dynamic"
2516
+ i18n="
2517
+ @@ngx.dashboard.widgets.radialGauge.dialog.colorProfile.dynamic"
2518
+ >Dynamic (Theme Colors)</mat-radio-button
2519
+ >
2520
+ <mat-radio-button
2521
+ value="static"
2522
+ i18n="
2523
+ @@ngx.dashboard.widgets.radialGauge.dialog.colorProfile.static"
2524
+ >Static (Performance Colors)</mat-radio-button
2525
+ >
2078
2526
  </mat-radio-group>
2079
2527
  </div>
2080
2528
 
2081
2529
  <div class="toggle-section">
2082
- <mat-slide-toggle [(ngModel)]="localState.active">
2530
+ <mat-slide-toggle
2531
+ [(ngModel)]="localState.active"
2532
+ i18n="@@ngx.dashboard.widgets.radialGauge.dialog.activeDisplay"
2533
+ >
2083
2534
  Active Display
2084
2535
  </mat-slide-toggle>
2085
- <p class="toggle-description">Display live gauge instead of passive icon</p>
2536
+ <p
2537
+ class="toggle-description"
2538
+ i18n="
2539
+ @@ngx.dashboard.widgets.radialGauge.dialog.activeDisplayDescription"
2540
+ >
2541
+ Display live gauge instead of passive icon
2542
+ </p>
2086
2543
  </div>
2087
2544
 
2088
2545
  <div class="toggle-section">
2089
- <mat-slide-toggle [(ngModel)]="localState.hasBackground">
2546
+ <mat-slide-toggle
2547
+ [(ngModel)]="localState.hasBackground"
2548
+ i18n="@@ngx.dashboard.widgets.radialGauge.dialog.background"
2549
+ >
2090
2550
  Background
2091
2551
  </mat-slide-toggle>
2092
- <p class="toggle-description">Add a background color to the widget</p>
2552
+ <p
2553
+ class="toggle-description"
2554
+ i18n="
2555
+ @@ngx.dashboard.widgets.radialGauge.dialog.backgroundDescription"
2556
+ >
2557
+ Add a background color to the widget
2558
+ </p>
2093
2559
  </div>
2094
2560
 
2095
2561
  <div class="toggle-section">
2096
- <mat-slide-toggle [(ngModel)]="localState.showValueLabel">
2562
+ <mat-slide-toggle
2563
+ [(ngModel)]="localState.showValueLabel"
2564
+ i18n="@@ngx.dashboard.widgets.radialGauge.dialog.showValueLabel"
2565
+ >
2097
2566
  Show Value Label
2098
2567
  </mat-slide-toggle>
2099
- <p class="toggle-description">Display numeric value in gauge center</p>
2568
+ <p
2569
+ class="toggle-description"
2570
+ i18n="
2571
+ @@ngx.dashboard.widgets.radialGauge.dialog.showValueLabelDescription"
2572
+ >
2573
+ Display numeric value in gauge center
2574
+ </p>
2100
2575
  </div>
2101
2576
  </mat-dialog-content>
2102
2577
 
2103
2578
  <mat-dialog-actions align="end">
2104
- <button mat-button (click)="onCancel()">Cancel</button>
2105
- <button mat-flat-button (click)="onSave()">Save</button>
2579
+ <button
2580
+ mat-button
2581
+ (click)="onCancel()"
2582
+ i18n="@@ngx.dashboard.common.cancel"
2583
+ >
2584
+ Cancel
2585
+ </button>
2586
+ <button
2587
+ mat-flat-button
2588
+ (click)="onSave()"
2589
+ i18n="@@ngx.dashboard.common.save"
2590
+ >
2591
+ Save
2592
+ </button>
2106
2593
  </mat-dialog-actions>
2107
2594
  `, isInline: true, styles: ["mat-dialog-content{display:block;overflow-y:auto;overflow-x:hidden}mat-form-field{width:100%;display:block;margin-bottom:1rem}.section{margin-bottom:1.5rem}.section h4{margin:0 0 .5rem;font-size:.875rem;font-weight:500;color:var(--mat-sys-on-surface, #1f1f1f)}mat-radio-group{display:flex;flex-direction:column;gap:.5rem}.toggle-section{display:flex;align-items:center;gap:.75rem;margin-bottom:.5rem}.toggle-description{margin:0;flex:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i3$1.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i3$1.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
2108
2595
  }
@@ -2118,10 +2605,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
2118
2605
  MatRadioModule,
2119
2606
  FormsModule,
2120
2607
  ], template: `
2121
- <h2 mat-dialog-title>Radial Gauge Settings</h2>
2608
+ <h2
2609
+ mat-dialog-title
2610
+ i18n="@@ngx.dashboard.widgets.radialGauge.dialog.title"
2611
+ >
2612
+ Radial Gauge Settings
2613
+ </h2>
2122
2614
  <mat-dialog-content>
2123
2615
  <mat-form-field>
2124
- <mat-label>Value (0-100)</mat-label>
2616
+ <mat-label i18n="@@ngx.dashboard.widgets.radialGauge.dialog.value"
2617
+ >Value (0-100)</mat-label
2618
+ >
2125
2619
  <input
2126
2620
  matInput
2127
2621
  type="number"
@@ -2132,38 +2626,89 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
2132
2626
  </mat-form-field>
2133
2627
 
2134
2628
  <div class="section">
2135
- <h4>Color Profile</h4>
2629
+ <h4 i18n="@@ngx.dashboard.widgets.radialGauge.dialog.colorProfile">
2630
+ Color Profile
2631
+ </h4>
2136
2632
  <mat-radio-group [(ngModel)]="localState.colorProfile">
2137
- <mat-radio-button value="dynamic">Dynamic (Theme Colors)</mat-radio-button>
2138
- <mat-radio-button value="static">Static (Performance Colors)</mat-radio-button>
2633
+ <mat-radio-button
2634
+ value="dynamic"
2635
+ i18n="
2636
+ @@ngx.dashboard.widgets.radialGauge.dialog.colorProfile.dynamic"
2637
+ >Dynamic (Theme Colors)</mat-radio-button
2638
+ >
2639
+ <mat-radio-button
2640
+ value="static"
2641
+ i18n="
2642
+ @@ngx.dashboard.widgets.radialGauge.dialog.colorProfile.static"
2643
+ >Static (Performance Colors)</mat-radio-button
2644
+ >
2139
2645
  </mat-radio-group>
2140
2646
  </div>
2141
2647
 
2142
2648
  <div class="toggle-section">
2143
- <mat-slide-toggle [(ngModel)]="localState.active">
2649
+ <mat-slide-toggle
2650
+ [(ngModel)]="localState.active"
2651
+ i18n="@@ngx.dashboard.widgets.radialGauge.dialog.activeDisplay"
2652
+ >
2144
2653
  Active Display
2145
2654
  </mat-slide-toggle>
2146
- <p class="toggle-description">Display live gauge instead of passive icon</p>
2655
+ <p
2656
+ class="toggle-description"
2657
+ i18n="
2658
+ @@ngx.dashboard.widgets.radialGauge.dialog.activeDisplayDescription"
2659
+ >
2660
+ Display live gauge instead of passive icon
2661
+ </p>
2147
2662
  </div>
2148
2663
 
2149
2664
  <div class="toggle-section">
2150
- <mat-slide-toggle [(ngModel)]="localState.hasBackground">
2665
+ <mat-slide-toggle
2666
+ [(ngModel)]="localState.hasBackground"
2667
+ i18n="@@ngx.dashboard.widgets.radialGauge.dialog.background"
2668
+ >
2151
2669
  Background
2152
2670
  </mat-slide-toggle>
2153
- <p class="toggle-description">Add a background color to the widget</p>
2671
+ <p
2672
+ class="toggle-description"
2673
+ i18n="
2674
+ @@ngx.dashboard.widgets.radialGauge.dialog.backgroundDescription"
2675
+ >
2676
+ Add a background color to the widget
2677
+ </p>
2154
2678
  </div>
2155
2679
 
2156
2680
  <div class="toggle-section">
2157
- <mat-slide-toggle [(ngModel)]="localState.showValueLabel">
2681
+ <mat-slide-toggle
2682
+ [(ngModel)]="localState.showValueLabel"
2683
+ i18n="@@ngx.dashboard.widgets.radialGauge.dialog.showValueLabel"
2684
+ >
2158
2685
  Show Value Label
2159
2686
  </mat-slide-toggle>
2160
- <p class="toggle-description">Display numeric value in gauge center</p>
2687
+ <p
2688
+ class="toggle-description"
2689
+ i18n="
2690
+ @@ngx.dashboard.widgets.radialGauge.dialog.showValueLabelDescription"
2691
+ >
2692
+ Display numeric value in gauge center
2693
+ </p>
2161
2694
  </div>
2162
2695
  </mat-dialog-content>
2163
2696
 
2164
2697
  <mat-dialog-actions align="end">
2165
- <button mat-button (click)="onCancel()">Cancel</button>
2166
- <button mat-flat-button (click)="onSave()">Save</button>
2698
+ <button
2699
+ mat-button
2700
+ (click)="onCancel()"
2701
+ i18n="@@ngx.dashboard.common.cancel"
2702
+ >
2703
+ Cancel
2704
+ </button>
2705
+ <button
2706
+ mat-flat-button
2707
+ (click)="onSave()"
2708
+ i18n="@@ngx.dashboard.common.save"
2709
+ >
2710
+ Save
2711
+ </button>
2167
2712
  </mat-dialog-actions>
2168
2713
  `, styles: ["mat-dialog-content{display:block;overflow-y:auto;overflow-x:hidden}mat-form-field{width:100%;display:block;margin-bottom:1rem}.section{margin-bottom:1.5rem}.section h4{margin:0 0 .5rem;font-size:.875rem;font-weight:500;color:var(--mat-sys-on-surface, #1f1f1f)}mat-radio-group{display:flex;flex-direction:column;gap:.5rem}.toggle-section{display:flex;align-items:center;gap:.75rem;margin-bottom:.5rem}.toggle-description{margin:0;flex:1}\n"] }]
2169
2714
  }] });
@@ -2172,8 +2717,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.1", ngImpor
2172
2717
  class RadialGaugeWidgetComponent {
2173
2718
  static metadata = {
2174
2719
  widgetTypeid: '@ngx-dashboard/radial-gauge-widget',
2175
- name: 'Radial Gauge',
2176
- description: 'A semi-circular gauge indicator',
2720
+ name: $localize `:@@ngx.dashboard.widgets.radialGauge.name:Radial Gauge`,
2721
+ description: $localize `:@@ngx.dashboard.widgets.radialGauge.description:A semi-circular gauge indicator`,
2177
2722
  svgIcon,
2178
2723
  };
2179
2724
  #dialog = inject(MatDialog);