@dragonworks/ngx-dashboard-widgets 20.0.4 → 20.0.5

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.
@@ -251,6 +251,9 @@ class LabelStateDialogComponent {
251
251
  hasBackground = signal(this.data.hasBackground ?? true);
252
252
  transparentBackground = signal(!(this.data.hasBackground ?? true));
253
253
  responsive = signal(this.data.responsive ?? false);
254
+ // Responsive font size constraints
255
+ minFontSize = signal(this.data.minFontSize ?? 8);
256
+ maxFontSize = signal(this.data.maxFontSize ?? 64);
254
257
  // Store original values for comparison
255
258
  originalLabel = this.data.label ?? '';
256
259
  originalFontSize = this.data.fontSize ?? 16;
@@ -259,6 +262,21 @@ class LabelStateDialogComponent {
259
262
  originalOpacity = this.data.opacity ?? 1;
260
263
  originalHasBackground = this.data.hasBackground ?? true;
261
264
  originalResponsive = this.data.responsive ?? false;
265
+ originalMinFontSize = this.data.minFontSize ?? 8;
266
+ originalMaxFontSize = this.data.maxFontSize ?? 64;
267
+ // Validation computed properties
268
+ isMinFontSizeValid = computed(() => {
269
+ const min = this.minFontSize();
270
+ return min >= 8 && min <= 24;
271
+ });
272
+ isMaxFontSizeValid = computed(() => {
273
+ const max = this.maxFontSize();
274
+ return max >= 16 && max <= 128;
275
+ });
276
+ isFontSizeRangeValid = computed(() => this.minFontSize() < this.maxFontSize());
277
+ isFormValid = computed(() => this.isMinFontSizeValid() &&
278
+ this.isMaxFontSizeValid() &&
279
+ this.isFontSizeRangeValid());
262
280
  // Computed values
263
281
  hasChanged = computed(() => this.label() !== this.originalLabel ||
264
282
  this.fontSize() !== this.originalFontSize ||
@@ -266,13 +284,36 @@ class LabelStateDialogComponent {
266
284
  this.fontWeight() !== this.originalFontWeight ||
267
285
  this.opacity() !== this.originalOpacity ||
268
286
  this.hasBackground() !== this.originalHasBackground ||
269
- this.responsive() !== this.originalResponsive);
287
+ this.responsive() !== this.originalResponsive ||
288
+ this.minFontSize() !== this.originalMinFontSize ||
289
+ this.maxFontSize() !== this.originalMaxFontSize);
270
290
  formatOpacity(value) {
271
291
  return Math.round(value * 100);
272
292
  }
273
293
  formatOpacitySlider = (value) => {
274
294
  return `${Math.round(value * 100)}%`;
275
295
  };
296
+ // Validation methods with robust min < max enforcement
297
+ validateAndCorrectMinFontSize(value) {
298
+ // Clamp to valid range
299
+ const corrected = Math.max(8, Math.min(24, value));
300
+ this.minFontSize.set(corrected);
301
+ // Ensure min < max with adequate gap
302
+ if (corrected >= this.maxFontSize()) {
303
+ const newMax = Math.min(128, corrected + 8); // Ensure at least 8px gap
304
+ this.maxFontSize.set(newMax);
305
+ }
306
+ }
307
+ validateAndCorrectMaxFontSize(value) {
308
+ // Clamp to valid range
309
+ const corrected = Math.max(16, Math.min(128, value));
310
+ this.maxFontSize.set(corrected);
311
+ // Ensure min < max with adequate gap
312
+ if (corrected <= this.minFontSize()) {
313
+ const newMin = Math.max(8, corrected - 8); // Ensure at least 8px gap
314
+ this.minFontSize.set(newMin);
315
+ }
316
+ }
276
317
  onBackgroundToggle(hasWhiteBackground) {
277
318
  this.hasBackground.set(hasWhiteBackground);
278
319
  this.transparentBackground.set(!hasWhiteBackground);
@@ -289,10 +330,12 @@ class LabelStateDialogComponent {
289
330
  opacity: this.opacity(),
290
331
  hasBackground: this.hasBackground(),
291
332
  responsive: this.responsive(),
333
+ minFontSize: this.minFontSize(),
334
+ maxFontSize: this.maxFontSize(),
292
335
  });
293
336
  }
294
337
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: LabelStateDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
295
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.6", type: LabelStateDialogComponent, isStandalone: true, selector: "lib-label-state-dialog", ngImport: i0, template: `
338
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: LabelStateDialogComponent, isStandalone: true, selector: "lib-label-state-dialog", ngImport: i0, template: `
296
339
  <h2 mat-dialog-title>Label Settings</h2>
297
340
  <mat-dialog-content>
298
341
  <mat-form-field appearance="outline" class="label-text-field">
@@ -318,6 +361,64 @@ class LabelStateDialogComponent {
318
361
  >
319
362
  </div>
320
363
 
364
+ <!-- Responsive Font Size Constraints (only shown when responsive is enabled) -->
365
+ @if (responsive()) {
366
+ <div class="responsive-section">
367
+ <div class="section-label">Font Size Limits</div>
368
+ <div class="row-layout">
369
+ <mat-form-field appearance="outline">
370
+ <mat-label>Min Size (px)</mat-label>
371
+ <input
372
+ matInput
373
+ type="number"
374
+ [value]="minFontSize()"
375
+ (input)="validateAndCorrectMinFontSize(+$any($event.target).value)"
376
+ (blur)="validateAndCorrectMinFontSize(minFontSize())"
377
+ min="8"
378
+ max="24"
379
+ placeholder="8"
380
+ />
381
+ @if (!isMinFontSizeValid() || !isFontSizeRangeValid()) {
382
+ <mat-error>
383
+ @if (!isMinFontSizeValid()) {
384
+ Must be between 8-24px
385
+ } @else {
386
+ Must be less than max size
387
+ }
388
+ </mat-error>
389
+ } @else {
390
+ <mat-hint>8-24px range</mat-hint>
391
+ }
392
+ </mat-form-field>
393
+
394
+ <mat-form-field appearance="outline">
395
+ <mat-label>Max Size (px)</mat-label>
396
+ <input
397
+ matInput
398
+ type="number"
399
+ [value]="maxFontSize()"
400
+ (input)="validateAndCorrectMaxFontSize(+$any($event.target).value)"
401
+ (blur)="validateAndCorrectMaxFontSize(maxFontSize())"
402
+ min="16"
403
+ max="128"
404
+ placeholder="64"
405
+ />
406
+ @if (!isMaxFontSizeValid() || !isFontSizeRangeValid()) {
407
+ <mat-error>
408
+ @if (!isMaxFontSizeValid()) {
409
+ Must be between 16-128px
410
+ } @else {
411
+ Must be greater than min size
412
+ }
413
+ </mat-error>
414
+ } @else {
415
+ <mat-hint>16-128px range</mat-hint>
416
+ }
417
+ </mat-form-field>
418
+ </div>
419
+ </div>
420
+ }
421
+
321
422
  <div class="row-layout">
322
423
  <mat-form-field appearance="outline">
323
424
  <mat-label>Font Size (px)</mat-label>
@@ -380,11 +481,11 @@ class LabelStateDialogComponent {
380
481
 
381
482
  <mat-dialog-actions align="end">
382
483
  <button mat-button (click)="onCancel()">Cancel</button>
383
- <button mat-flat-button (click)="save()" [disabled]="!hasChanged()">
484
+ <button mat-flat-button (click)="save()" [disabled]="!hasChanged() || !isFormValid()">
384
485
  Save
385
486
  </button>
386
487
  </mat-dialog-actions>
387
- `, 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}\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: "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"] }] });
488
+ `, 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"] }] });
388
489
  }
389
490
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: LabelStateDialogComponent, decorators: [{
390
491
  type: Component,
@@ -424,6 +525,64 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
424
525
  >
425
526
  </div>
426
527
 
528
+ <!-- Responsive Font Size Constraints (only shown when responsive is enabled) -->
529
+ @if (responsive()) {
530
+ <div class="responsive-section">
531
+ <div class="section-label">Font Size Limits</div>
532
+ <div class="row-layout">
533
+ <mat-form-field appearance="outline">
534
+ <mat-label>Min Size (px)</mat-label>
535
+ <input
536
+ matInput
537
+ type="number"
538
+ [value]="minFontSize()"
539
+ (input)="validateAndCorrectMinFontSize(+$any($event.target).value)"
540
+ (blur)="validateAndCorrectMinFontSize(minFontSize())"
541
+ min="8"
542
+ max="24"
543
+ placeholder="8"
544
+ />
545
+ @if (!isMinFontSizeValid() || !isFontSizeRangeValid()) {
546
+ <mat-error>
547
+ @if (!isMinFontSizeValid()) {
548
+ Must be between 8-24px
549
+ } @else {
550
+ Must be less than max size
551
+ }
552
+ </mat-error>
553
+ } @else {
554
+ <mat-hint>8-24px range</mat-hint>
555
+ }
556
+ </mat-form-field>
557
+
558
+ <mat-form-field appearance="outline">
559
+ <mat-label>Max Size (px)</mat-label>
560
+ <input
561
+ matInput
562
+ type="number"
563
+ [value]="maxFontSize()"
564
+ (input)="validateAndCorrectMaxFontSize(+$any($event.target).value)"
565
+ (blur)="validateAndCorrectMaxFontSize(maxFontSize())"
566
+ min="16"
567
+ max="128"
568
+ placeholder="64"
569
+ />
570
+ @if (!isMaxFontSizeValid() || !isFontSizeRangeValid()) {
571
+ <mat-error>
572
+ @if (!isMaxFontSizeValid()) {
573
+ Must be between 16-128px
574
+ } @else {
575
+ Must be greater than min size
576
+ }
577
+ </mat-error>
578
+ } @else {
579
+ <mat-hint>16-128px range</mat-hint>
580
+ }
581
+ </mat-form-field>
582
+ </div>
583
+ </div>
584
+ }
585
+
427
586
  <div class="row-layout">
428
587
  <mat-form-field appearance="outline">
429
588
  <mat-label>Font Size (px)</mat-label>
@@ -486,11 +645,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
486
645
 
487
646
  <mat-dialog-actions align="end">
488
647
  <button mat-button (click)="onCancel()">Cancel</button>
489
- <button mat-flat-button (click)="save()" [disabled]="!hasChanged()">
648
+ <button mat-flat-button (click)="save()" [disabled]="!hasChanged() || !isFormValid()">
490
649
  Save
491
650
  </button>
492
651
  </mat-dialog-actions>
493
- `, 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}\n"] }]
652
+ `, 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"] }]
494
653
  }] });
495
654
 
496
655
  /**
@@ -499,15 +658,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
499
658
  *
500
659
  * @example
501
660
  * <div class="container">
502
- * <span responsiveText [min]="12" [max]="72">Dynamic text here</span>
661
+ * <span responsiveText [minFontSize]="12" [maxFontSize]="72">Dynamic text here</span>
503
662
  * </div>
504
663
  */
505
664
  class ResponsiveTextDirective {
506
665
  /* ───────────────────────── Inputs with transforms ─────────────── */
507
666
  /** Minimum font-size in pixels (accessibility floor) */
508
- min = input(8, { transform: numberAttribute });
667
+ minFontSize = input(8, { transform: numberAttribute });
509
668
  /** Maximum font-size in pixels (layout ceiling) */
510
- max = input(512, { transform: numberAttribute });
669
+ maxFontSize = input(512, { transform: numberAttribute });
511
670
  /**
512
671
  * Line-height: pass a multiplier (e.g. 1.1) or absolute px value.
513
672
  * For single-line text a multiplier < 10 is treated as unitless.
@@ -583,10 +742,9 @@ class ResponsiveTextDirective {
583
742
  return;
584
743
  const text = span.textContent?.trim() || '';
585
744
  if (!text) {
586
- span.style.fontSize = `${this.min()}px`;
745
+ span.style.fontSize = `${this.minFontSize()}px`;
587
746
  return;
588
747
  }
589
- // Get available space
590
748
  const { maxW, maxH } = this.getAvailableSpace(parent);
591
749
  // Check cache to avoid redundant calculations
592
750
  if (text === this.lastText &&
@@ -595,8 +753,8 @@ class ResponsiveTextDirective {
595
753
  this.lastFontSize > 0) {
596
754
  return;
597
755
  }
598
- // Calculate ideal font size
599
- const ideal = this.calcFit(text, maxW, maxH);
756
+ // Calculate with conservative buffer for sub-pixel accuracy
757
+ const ideal = this.calcFit(text, maxW * 0.98, maxH * 0.98);
600
758
  span.style.fontSize = `${ideal}px`;
601
759
  // DOM verification pass
602
760
  this.verifyFit(span, maxW, maxH, ideal);
@@ -623,17 +781,21 @@ class ResponsiveTextDirective {
623
781
  * DOM-based verification to handle sub-pixel discrepancies
624
782
  */
625
783
  verifyFit(span, maxW, maxH, ideal) {
626
- // Use requestAnimationFrame to ensure layout is complete
627
- requestAnimationFrame(() => {
628
- if (span.scrollWidth > maxW || span.scrollHeight > maxH) {
629
- let safe = ideal;
630
- while (safe > this.min() &&
631
- (span.scrollWidth > maxW || span.scrollHeight > maxH)) {
632
- safe -= 0.5; // Finer adjustments
633
- span.style.fontSize = `${safe}px`;
634
- }
784
+ // Simple synchronous verification
785
+ if (span.scrollWidth > maxW || span.scrollHeight > maxH) {
786
+ let safe = ideal;
787
+ let iterations = 0;
788
+ const maxIterations = 10;
789
+ while (iterations < maxIterations &&
790
+ safe > this.minFontSize() &&
791
+ (span.scrollWidth > maxW || span.scrollHeight > maxH)) {
792
+ safe -= 0.25;
793
+ span.style.fontSize = `${safe}px`;
794
+ iterations++;
635
795
  }
636
- });
796
+ // Update cache with verified size
797
+ this.lastFontSize = safe;
798
+ }
637
799
  }
638
800
  /* ───────────────────── Binary search algorithm ────────────────── */
639
801
  /**
@@ -641,13 +803,13 @@ class ResponsiveTextDirective {
641
803
  */
642
804
  calcFit(text, maxW, maxH, precision = 0.1) {
643
805
  if (maxW <= 0 || maxH <= 0)
644
- return this.min();
806
+ return this.minFontSize();
645
807
  const computedStyle = getComputedStyle(this.el.nativeElement);
646
808
  const fontFamily = computedStyle.fontFamily || 'sans-serif';
647
809
  const fontWeight = computedStyle.fontWeight || '400';
648
- let lo = this.min();
649
- let hi = this.max();
650
- let bestFit = this.min();
810
+ let lo = this.minFontSize();
811
+ let hi = this.maxFontSize();
812
+ let bestFit = this.minFontSize();
651
813
  while (hi - lo > precision) {
652
814
  const mid = (hi + lo) / 2;
653
815
  this.ctx.font = `${fontWeight} ${mid}px ${fontFamily}`;
@@ -735,7 +897,7 @@ class ResponsiveTextDirective {
735
897
  this._ctx = undefined;
736
898
  }
737
899
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: ResponsiveTextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
738
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.6", type: ResponsiveTextDirective, isStandalone: true, selector: "[responsiveText]", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", 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": "\"hidden\"", "style.text-overflow": "\"ellipsis\"" } }, ngImport: i0 });
900
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.0.6", type: ResponsiveTextDirective, isStandalone: true, selector: "[responsiveText]", 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 });
739
901
  }
740
902
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: ResponsiveTextDirective, decorators: [{
741
903
  type: Directive,
@@ -746,8 +908,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
746
908
  '[style.display]': '"block"',
747
909
  '[style.width]': '"100%"',
748
910
  '[style.white-space]': '"nowrap"',
749
- '[style.overflow]': '"hidden"',
750
- '[style.text-overflow]': '"ellipsis"',
911
+ '[style.overflow]': '"visible"',
751
912
  },
752
913
  }]
753
914
  }] });
@@ -771,6 +932,8 @@ class LabelWidgetComponent {
771
932
  opacity: 1,
772
933
  hasBackground: true,
773
934
  responsive: false,
935
+ minFontSize: 8, // Accessible minimum for responsive text
936
+ maxFontSize: 64, // Practical maximum for widget display
774
937
  });
775
938
  dashboardSetState(state) {
776
939
  if (state) {
@@ -805,37 +968,57 @@ class LabelWidgetComponent {
805
968
  get label() {
806
969
  return this.state().label?.trim();
807
970
  }
971
+ // Computed properties for responsive font size limits with fallbacks
972
+ minFontSize = computed(() => this.state().minFontSize ?? 8);
973
+ maxFontSize = computed(() => this.state().maxFontSize ?? 64);
808
974
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: LabelWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
809
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", 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\" responsiveText>{{ 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;transform-origin:center center}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block;fill:var(--mat-sys-on-surface-variant, #6c757d);transition:fill .2s ease}.has-background .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-on-surface, #1f1f1f)}.svg-wrapper:hover .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-primary, #6750a4)}\n"], dependencies: [{ kind: "directive", type: ResponsiveTextDirective, selector: "[responsiveText]", inputs: ["min", "max", "lineHeight", "observeMutations", "debounceMs"] }] });
975
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", 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\" responsiveText [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;transform-origin:center center}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block;fill:var(--mat-sys-on-surface-variant, #6c757d);transition:fill .2s ease}.has-background .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-on-surface, #1f1f1f)}.svg-wrapper:hover .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-primary, #6750a4)}\n"], dependencies: [{ kind: "directive", type: ResponsiveTextDirective, selector: "[responsiveText]", inputs: ["minFontSize", "maxFontSize", "lineHeight", "observeMutations", "debounceMs"] }] });
810
976
  }
811
977
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: LabelWidgetComponent, decorators: [{
812
978
  type: Component,
813
- 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\" responsiveText>{{ 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;transform-origin:center center}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block;fill:var(--mat-sys-on-surface-variant, #6c757d);transition:fill .2s ease}.has-background .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-on-surface, #1f1f1f)}.svg-wrapper:hover .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-primary, #6750a4)}\n"] }]
979
+ 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\" responsiveText [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;transform-origin:center center}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block;fill:var(--mat-sys-on-surface-variant, #6c757d);transition:fill .2s ease}.has-background .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-on-surface, #1f1f1f)}.svg-wrapper:hover .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-primary, #6750a4)}\n"] }]
814
980
  }] });
815
981
 
816
- // clock-widget.metadata.ts
817
982
  const svgIcon = `
818
- <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 800 800">
819
- <circle cx="400" cy="400" r="400" fill="#fff"/>
820
- <use transform="matrix(-1,0,0,1,800,0)" xlink:href="#one-half"/>
821
- <g id="one-half">
822
- <g id="one-fourth">
823
- <path d="m400 40v107" stroke="#000" stroke-width="26.7"/>
824
- <g id="one-twelfth">
825
- <path d="m580 88.233-42.5 73.612" stroke="#000" stroke-width="26.7"/>
826
- <g id="one-thirtieth">
827
- <path id="one-sixtieth" d="m437.63 41.974-3.6585 34.808" stroke="#000" stroke-width="13.6" />
828
- <use transform="rotate(6 400 400)" xlink:href="#one-sixtieth"/>
829
- </g>
830
- <use transform="rotate(12 400 400)" xlink:href="#one-thirtieth"/>
831
- </g>
832
- <use transform="rotate(30 400 400)" xlink:href="#one-twelfth"/>
833
- <use transform="rotate(60 400 400)" xlink:href="#one-twelfth"/>
834
- </g>
835
- <use transform="rotate(90 400 400)" xlink:href="#one-fourth"/>
836
- </g>
837
- <path class="clock-hour-hand" id="anim-clock-hour-hand" d="m 381.925,476 h 36.15 l 5e-4,-300.03008 L 400,156.25 381.9245,175.96992 Z" transform="rotate(110.2650694444, 400, 400)" />
838
- <path class="clock-minute-hand" id="anim-clock-minute-hand" d="M 412.063,496.87456 H 387.937 L 385.249,65.68306 400,52.75 414.751,65.68306 Z" transform="rotate(243.1808333333, 400, 400)" />
983
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" preserveAspectRatio="xMidYMid meet">
984
+ <use transform="matrix(-1,0,0,1,800,0)" href="#one-half" />
985
+ <g id="one-half">
986
+ <g id="one-fourth">
987
+ <path d="m400 40v107" stroke-width="26.7" stroke="currentColor" />
988
+ <g id="one-twelfth">
989
+ <path
990
+ d="m580 88.233-42.5 73.612"
991
+ stroke-width="26.7"
992
+ stroke="currentColor"
993
+ />
994
+ <g id="one-thirtieth">
995
+ <path
996
+ id="one-sixtieth"
997
+ d="m437.63 41.974-3.6585 34.808"
998
+ stroke-width="13.6"
999
+ stroke="currentColor"
1000
+ />
1001
+ <use transform="rotate(6 400 400)" href="#one-sixtieth" />
1002
+ </g>
1003
+ <use transform="rotate(12 400 400)" href="#one-thirtieth" />
1004
+ </g>
1005
+ <use transform="rotate(30 400 400)" href="#one-twelfth" />
1006
+ <use transform="rotate(60 400 400)" href="#one-twelfth" />
1007
+ </g>
1008
+ <use transform="rotate(90 400 400)" href="#one-fourth" />
1009
+ </g>
1010
+ <path
1011
+ class="clock-hour-hand"
1012
+ id="anim-clock-hour-hand"
1013
+ d="m 381.925,476 h 36.15 l 5e-4,-300.03008 L 400,156.25 381.9245,175.96992 Z"
1014
+ transform="rotate(110.2650694444, 400, 400)"
1015
+ />
1016
+ <path
1017
+ class="clock-minute-hand"
1018
+ id="anim-clock-minute-hand"
1019
+ d="M 412.063,496.87456 H 387.937 L 385.249,65.68306 400,52.75 414.751,65.68306 Z"
1020
+ transform="rotate(243.1808333333, 400, 400)"
1021
+ />
839
1022
  </svg>
840
1023
  `;
841
1024
 
@@ -1038,22 +1221,12 @@ class DigitalClockComponent {
1038
1221
  if (hours === 0)
1039
1222
  hours = 12; // Convert 0 to 12 for 12 AM/PM
1040
1223
  const hh = hours.toString().padStart(2, '0');
1041
- if (showSecs) {
1042
- return `${hh}:${mm}:${ss} ${ampm}`;
1043
- }
1044
- else {
1045
- return `${hh}:${mm} ${ampm}`;
1046
- }
1224
+ return showSecs ? `${hh}:${mm}:${ss} ${ampm}` : `${hh}:${mm} ${ampm}`;
1047
1225
  }
1048
1226
  else {
1049
1227
  // 24-hour format
1050
1228
  const hh = hours.toString().padStart(2, '0');
1051
- if (showSecs) {
1052
- return `${hh}:${mm}:${ss}`;
1053
- }
1054
- else {
1055
- return `${hh}:${mm}`;
1056
- }
1229
+ return showSecs ? `${hh}:${mm}:${ss}` : `${hh}:${mm}`;
1057
1230
  }
1058
1231
  }
1059
1232
  constructor() {
@@ -1083,7 +1256,7 @@ class DigitalClockComponent {
1083
1256
  }
1084
1257
  }
1085
1258
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DigitalClockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1086
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.0.6", type: DigitalClockComponent, isStandalone: true, selector: "ngx-digital-clock", inputs: { timeFormat: { classPropertyName: "timeFormat", publicName: "timeFormat", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, hasBackground: { classPropertyName: "hasBackground", publicName: "hasBackground", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.has-background": "hasBackground()", "class.show-pm": "timeFormat() === \"12h\"", "class.show-seconds": "showSeconds()" }, classAttribute: "clock-widget digital" }, ngImport: i0, template: "<div class=\"digital-time\">{{ formattedTime() }}</div>", styles: [":host{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);padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d)}:host.has-background{background-color:var(--mat-sys-surface-container-high);border-radius:4px;color:var(--mat-sys-on-surface, #1f1f1f)}:host:hover{opacity:.8;color:var(--mat-sys-primary, #6750a4)}.digital-time{font-size:clamp(12px,min(20cqw,50cqh),200px);font-family:monospace;font-weight:500;letter-spacing:.05em;transition:color .2s ease}:host.show-pm.show-seconds .digital-time{font-size:clamp(12px,min(15cqw,50cqh),200px)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1259
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.0.6", type: DigitalClockComponent, isStandalone: true, selector: "ngx-digital-clock", inputs: { timeFormat: { classPropertyName: "timeFormat", publicName: "timeFormat", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, hasBackground: { classPropertyName: "hasBackground", publicName: "hasBackground", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.has-background": "hasBackground()", "class.show-pm": "timeFormat() === \"12h\"", "class.show-seconds": "showSeconds()" }, classAttribute: "clock-widget digital" }, ngImport: i0, template: "<div responsiveText class=\"digital-time\">{{ formattedTime() }}</div>\r\n", styles: [":host{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);padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d)}:host.has-background{background-color:var(--mat-sys-surface-container-high);border-radius:4px;color:var(--mat-sys-on-surface, #1f1f1f)}:host:hover{opacity:.8;color:var(--mat-sys-primary, #6750a4)}.digital-time{font-size:clamp(8px,min(20cqw,50cqh),200px);font-family:monospace;font-weight:500;letter-spacing:.05em;transition:color .2s ease}:host.show-pm.show-seconds .digital-time{font-size:clamp(8px,min(15cqw,50cqh),200px)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1087
1260
  }
1088
1261
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: DigitalClockComponent, decorators: [{
1089
1262
  type: Component,
@@ -1091,8 +1264,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
1091
1264
  '[class.has-background]': 'hasBackground()',
1092
1265
  '[class.show-pm]': 'timeFormat() === "12h"',
1093
1266
  '[class.show-seconds]': 'showSeconds()',
1094
- 'class': 'clock-widget digital'
1095
- }, template: "<div class=\"digital-time\">{{ formattedTime() }}</div>", styles: [":host{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);padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d)}:host.has-background{background-color:var(--mat-sys-surface-container-high);border-radius:4px;color:var(--mat-sys-on-surface, #1f1f1f)}:host:hover{opacity:.8;color:var(--mat-sys-primary, #6750a4)}.digital-time{font-size:clamp(12px,min(20cqw,50cqh),200px);font-family:monospace;font-weight:500;letter-spacing:.05em;transition:color .2s ease}:host.show-pm.show-seconds .digital-time{font-size:clamp(12px,min(15cqw,50cqh),200px)}\n"] }]
1267
+ class: 'clock-widget digital',
1268
+ }, template: "<div responsiveText class=\"digital-time\">{{ formattedTime() }}</div>\r\n", styles: [":host{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);padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d)}:host.has-background{background-color:var(--mat-sys-surface-container-high);border-radius:4px;color:var(--mat-sys-on-surface, #1f1f1f)}:host:hover{opacity:.8;color:var(--mat-sys-primary, #6750a4)}.digital-time{font-size:clamp(8px,min(20cqw,50cqh),200px);font-family:monospace;font-weight:500;letter-spacing:.05em;transition:color .2s ease}:host.show-pm.show-seconds .digital-time{font-size:clamp(8px,min(15cqw,50cqh),200px)}\n"] }]
1096
1269
  }], ctorParameters: () => [] });
1097
1270
 
1098
1271
  class AnalogClockComponent {
@@ -1171,7 +1344,7 @@ class AnalogClockComponent {
1171
1344
  }
1172
1345
  }
1173
1346
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AnalogClockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1174
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.0.6", type: AnalogClockComponent, isStandalone: true, selector: "ngx-analog-clock", inputs: { hasBackground: { classPropertyName: "hasBackground", publicName: "hasBackground", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.has-background": "hasBackground()", "class.show-seconds": "showSeconds()" }, classAttribute: "clock-widget analog" }, viewQueries: [{ propertyName: "hourHand", first: true, predicate: ["hourHand"], descendants: true, isSignal: true }, { propertyName: "minuteHand", first: true, predicate: ["minuteHand"], descendants: true, isSignal: true }, { propertyName: "secondHand", first: true, predicate: ["secondHand"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"analog-clock-container\">\r\n <div class=\"aspect-ratio-box\">\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n viewBox=\"0 0 800 800\"\r\n preserveAspectRatio=\"xMidYMid meet\"\r\n >\r\n <!-- <circle cx=\"400\" cy=\"400\" r=\"400\" fill=\"#fff\"/> -->\r\n <use transform=\"matrix(-1,0,0,1,800,0)\" xlink:href=\"#one-half\" />\r\n <g id=\"one-half\">\r\n <g id=\"one-fourth\">\r\n <path d=\"m400 40v107\" stroke=\"#000\" stroke-width=\"26.7\" />\r\n <g id=\"one-twelfth\">\r\n <path\r\n d=\"m580 88.233-42.5 73.612\"\r\n stroke=\"#000\"\r\n stroke-width=\"26.7\"\r\n />\r\n <g id=\"one-thirtieth\">\r\n <path\r\n id=\"one-sixtieth\"\r\n d=\"m437.63 41.974-3.6585 34.808\"\r\n stroke=\"#000\"\r\n stroke-width=\"13.6\"\r\n />\r\n <use transform=\"rotate(6 400 400)\" xlink:href=\"#one-sixtieth\" />\r\n </g>\r\n <use transform=\"rotate(12 400 400)\" xlink:href=\"#one-thirtieth\" />\r\n </g>\r\n <use transform=\"rotate(30 400 400)\" xlink:href=\"#one-twelfth\" />\r\n <use transform=\"rotate(60 400 400)\" xlink:href=\"#one-twelfth\" />\r\n </g>\r\n <use transform=\"rotate(90 400 400)\" xlink:href=\"#one-fourth\" />\r\n </g>\r\n <path\r\n class=\"clock-hour-hand\"\r\n id=\"anim-clock-hour-hand\"\r\n #hourHand\r\n d=\"m 381.925,476 h 36.15 l 5e-4,-300.03008 L 400,156.25 381.9245,175.96992 Z\"\r\n transform=\"rotate(110.2650694444, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-minute-hand\"\r\n id=\"anim-clock-minute-hand\"\r\n #minuteHand\r\n d=\"M 412.063,496.87456 H 387.937 L 385.249,65.68306 400,52.75 414.751,65.68306 Z\"\r\n transform=\"rotate(243.1808333333, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-second-hand\"\r\n id=\"anim-clock-second-hand\"\r\n #secondHand\r\n fill=\"#a40000\"\r\n d=\"M 397.317,63.51744 395.91962,168.4 C 374.575,170.5125 358.2,188.365 358.2,210 c 0,21.635 16.3,39 36.61214,41.47594 L 391.52847,498 h 16.94306 L 405.1868,251.47593 C 425.5,249 441.8,231.635 441.8,210 c 2e-5,-21.635 -16.375,-39.4875 -37.71971,-41.6 L 402.683,63.51744 400,60 Z M 400,190.534 c 10.888,0 19.466,8.866 19.466,19.466 0,10.6 -8.578,19.466 -19.466,19.466 -10.888,0 -19.466,-8.866 -19.466,-19.466 0,-10.6 8.578,-19.466 19.466,-19.466 z\"\r\n transform=\"rotate(190.85, 400, 400)\"\r\n />\r\n </svg>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block;width:100%;height:100%}.analog-clock-container{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.analog-clock-container .aspect-ratio-box{position:relative;width:100%;max-width:100%;max-height:100%;aspect-ratio:1/1}@supports not (aspect-ratio: 1/1){.analog-clock-container .aspect-ratio-box:before{content:\"\";display:block;padding-bottom:100%}.analog-clock-container .aspect-ratio-box svg{position:absolute;top:0;left:0;width:100%;height:100%}}.analog-clock-container .aspect-ratio-box svg{display:block;width:100%;height:100%}.analog-clock-container .aspect-ratio-box svg path:not(.clock-hour-hand):not(.clock-minute-hand):not(.clock-second-hand){stroke:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-hour-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-minute-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-second-hand{fill:var(--mat-sys-primary, #6750a4)}:host:not(.show-seconds) .clock-second-hand{display:none}:host.has-background svg circle{fill:var(--mat-sys-surface, #fffbfe)}:host.clock-widget.analog{container-type:size;container-name:analog-clock}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1347
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.0.6", type: AnalogClockComponent, isStandalone: true, selector: "ngx-analog-clock", inputs: { hasBackground: { classPropertyName: "hasBackground", publicName: "hasBackground", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.has-background": "hasBackground()", "class.show-seconds": "showSeconds()" }, classAttribute: "clock-widget analog" }, viewQueries: [{ propertyName: "hourHand", first: true, predicate: ["hourHand"], descendants: true, isSignal: true }, { propertyName: "minuteHand", first: true, predicate: ["minuteHand"], descendants: true, isSignal: true }, { propertyName: "secondHand", first: true, predicate: ["secondHand"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"analog-clock-container\">\r\n <div class=\"aspect-ratio-box\">\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 800 800\"\r\n preserveAspectRatio=\"xMidYMid meet\"\r\n >\r\n <!-- Optional face circle; uncomment if you want a visible outline by default -->\r\n <!-- <circle cx=\"400\" cy=\"400\" r=\"400\" fill=\"transparent\" stroke=\"currentColor\" stroke-width=\"2\" /> -->\r\n\r\n <use transform=\"matrix(-1,0,0,1,800,0)\" href=\"#one-half\" />\r\n <g id=\"one-half\">\r\n <g id=\"one-fourth\">\r\n <!-- 12 / 3 / 6 / 9 heavy marks -->\r\n <path d=\"m400 40v107\" stroke-width=\"26.7\" stroke=\"currentColor\" />\r\n <g id=\"one-twelfth\">\r\n <!-- 30\u00B0 heavy marks -->\r\n <path\r\n d=\"m580 88.233-42.5 73.612\"\r\n stroke-width=\"26.7\"\r\n stroke=\"currentColor\"\r\n />\r\n <g id=\"one-thirtieth\">\r\n <!-- minute/second ticks -->\r\n <path\r\n id=\"one-sixtieth\"\r\n d=\"m437.63 41.974-3.6585 34.808\"\r\n stroke-width=\"13.6\"\r\n stroke=\"currentColor\"\r\n />\r\n <use transform=\"rotate(6 400 400)\" href=\"#one-sixtieth\" />\r\n </g>\r\n <use transform=\"rotate(12 400 400)\" href=\"#one-thirtieth\" />\r\n </g>\r\n <use transform=\"rotate(30 400 400)\" href=\"#one-twelfth\" />\r\n <use transform=\"rotate(60 400 400)\" href=\"#one-twelfth\" />\r\n </g>\r\n <use transform=\"rotate(90 400 400)\" href=\"#one-fourth\" />\r\n </g>\r\n\r\n <!-- Hands -->\r\n <path\r\n class=\"clock-hour-hand\"\r\n id=\"anim-clock-hour-hand\"\r\n #hourHand\r\n d=\"m 381.925,476 h 36.15 l 5e-4,-300.03008 L 400,156.25 381.9245,175.96992 Z\"\r\n transform=\"rotate(110.2650694444, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-minute-hand\"\r\n id=\"anim-clock-minute-hand\"\r\n #minuteHand\r\n d=\"M 412.063,496.87456 H 387.937 L 385.249,65.68306 400,52.75 414.751,65.68306 Z\"\r\n transform=\"rotate(243.1808333333, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-second-hand\"\r\n id=\"anim-clock-second-hand\"\r\n #secondHand\r\n d=\"M 397.317,63.51744 395.91962,168.4 C 374.575,170.5125 358.2,188.365 358.2,210 c 0,21.635 16.3,39 36.61214,41.47594 L 391.52847,498 h 16.94306 L 405.1868,251.47593 C 425.5,249 441.8,231.635 441.8,210 c 2e-5,-21.635 -16.375,-39.4875 -37.71971,-41.6 L 402.683,63.51744 400,60 Z M 400,190.534 c 10.888,0 19.466,8.866 19.466,19.466 0,10.6 -8.578,19.466 -19.466,19.466 -10.888,0 -19.466,-8.866 -19.466,-19.466 0,-10.6 8.578,-19.466 19.466,-19.466 z\"\r\n transform=\"rotate(190.85, 400, 400)\"\r\n />\r\n </svg>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block;width:100%;height:100%}.analog-clock-container{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.analog-clock-container .aspect-ratio-box{position:relative;width:100%;max-width:100%;max-height:100%;aspect-ratio:1/1}@supports not (aspect-ratio: 1/1){.analog-clock-container .aspect-ratio-box:before{content:\"\";display:block;padding-bottom:100%}.analog-clock-container .aspect-ratio-box svg{position:absolute;top:0;left:0;width:100%;height:100%}}.analog-clock-container .aspect-ratio-box svg{display:block;width:100%;height:100%}.analog-clock-container .aspect-ratio-box svg path:not(.clock-hour-hand):not(.clock-minute-hand):not(.clock-second-hand){stroke:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-hour-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-minute-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-second-hand{fill:var(--mat-sys-primary, #6750a4)}:host:not(.show-seconds) .clock-second-hand{display:none}:host.has-background svg circle{fill:var(--mat-sys-surface, #fffbfe)}:host:hover{opacity:.8}:host:hover svg .clock-hour-hand,:host:hover svg .clock-minute-hand{fill:var(--mat-sys-primary, #6750a4)}:host.clock-widget.analog{container-type:size;container-name:analog-clock}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1175
1348
  }
1176
1349
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: AnalogClockComponent, decorators: [{
1177
1350
  type: Component,
@@ -1179,7 +1352,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
1179
1352
  '[class.has-background]': 'hasBackground()',
1180
1353
  '[class.show-seconds]': 'showSeconds()',
1181
1354
  'class': 'clock-widget analog'
1182
- }, template: "<div class=\"analog-clock-container\">\r\n <div class=\"aspect-ratio-box\">\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n viewBox=\"0 0 800 800\"\r\n preserveAspectRatio=\"xMidYMid meet\"\r\n >\r\n <!-- <circle cx=\"400\" cy=\"400\" r=\"400\" fill=\"#fff\"/> -->\r\n <use transform=\"matrix(-1,0,0,1,800,0)\" xlink:href=\"#one-half\" />\r\n <g id=\"one-half\">\r\n <g id=\"one-fourth\">\r\n <path d=\"m400 40v107\" stroke=\"#000\" stroke-width=\"26.7\" />\r\n <g id=\"one-twelfth\">\r\n <path\r\n d=\"m580 88.233-42.5 73.612\"\r\n stroke=\"#000\"\r\n stroke-width=\"26.7\"\r\n />\r\n <g id=\"one-thirtieth\">\r\n <path\r\n id=\"one-sixtieth\"\r\n d=\"m437.63 41.974-3.6585 34.808\"\r\n stroke=\"#000\"\r\n stroke-width=\"13.6\"\r\n />\r\n <use transform=\"rotate(6 400 400)\" xlink:href=\"#one-sixtieth\" />\r\n </g>\r\n <use transform=\"rotate(12 400 400)\" xlink:href=\"#one-thirtieth\" />\r\n </g>\r\n <use transform=\"rotate(30 400 400)\" xlink:href=\"#one-twelfth\" />\r\n <use transform=\"rotate(60 400 400)\" xlink:href=\"#one-twelfth\" />\r\n </g>\r\n <use transform=\"rotate(90 400 400)\" xlink:href=\"#one-fourth\" />\r\n </g>\r\n <path\r\n class=\"clock-hour-hand\"\r\n id=\"anim-clock-hour-hand\"\r\n #hourHand\r\n d=\"m 381.925,476 h 36.15 l 5e-4,-300.03008 L 400,156.25 381.9245,175.96992 Z\"\r\n transform=\"rotate(110.2650694444, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-minute-hand\"\r\n id=\"anim-clock-minute-hand\"\r\n #minuteHand\r\n d=\"M 412.063,496.87456 H 387.937 L 385.249,65.68306 400,52.75 414.751,65.68306 Z\"\r\n transform=\"rotate(243.1808333333, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-second-hand\"\r\n id=\"anim-clock-second-hand\"\r\n #secondHand\r\n fill=\"#a40000\"\r\n d=\"M 397.317,63.51744 395.91962,168.4 C 374.575,170.5125 358.2,188.365 358.2,210 c 0,21.635 16.3,39 36.61214,41.47594 L 391.52847,498 h 16.94306 L 405.1868,251.47593 C 425.5,249 441.8,231.635 441.8,210 c 2e-5,-21.635 -16.375,-39.4875 -37.71971,-41.6 L 402.683,63.51744 400,60 Z M 400,190.534 c 10.888,0 19.466,8.866 19.466,19.466 0,10.6 -8.578,19.466 -19.466,19.466 -10.888,0 -19.466,-8.866 -19.466,-19.466 0,-10.6 8.578,-19.466 19.466,-19.466 z\"\r\n transform=\"rotate(190.85, 400, 400)\"\r\n />\r\n </svg>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block;width:100%;height:100%}.analog-clock-container{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.analog-clock-container .aspect-ratio-box{position:relative;width:100%;max-width:100%;max-height:100%;aspect-ratio:1/1}@supports not (aspect-ratio: 1/1){.analog-clock-container .aspect-ratio-box:before{content:\"\";display:block;padding-bottom:100%}.analog-clock-container .aspect-ratio-box svg{position:absolute;top:0;left:0;width:100%;height:100%}}.analog-clock-container .aspect-ratio-box svg{display:block;width:100%;height:100%}.analog-clock-container .aspect-ratio-box svg path:not(.clock-hour-hand):not(.clock-minute-hand):not(.clock-second-hand){stroke:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-hour-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-minute-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-second-hand{fill:var(--mat-sys-primary, #6750a4)}:host:not(.show-seconds) .clock-second-hand{display:none}:host.has-background svg circle{fill:var(--mat-sys-surface, #fffbfe)}:host.clock-widget.analog{container-type:size;container-name:analog-clock}\n"] }]
1355
+ }, template: "<div class=\"analog-clock-container\">\r\n <div class=\"aspect-ratio-box\">\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 800 800\"\r\n preserveAspectRatio=\"xMidYMid meet\"\r\n >\r\n <!-- Optional face circle; uncomment if you want a visible outline by default -->\r\n <!-- <circle cx=\"400\" cy=\"400\" r=\"400\" fill=\"transparent\" stroke=\"currentColor\" stroke-width=\"2\" /> -->\r\n\r\n <use transform=\"matrix(-1,0,0,1,800,0)\" href=\"#one-half\" />\r\n <g id=\"one-half\">\r\n <g id=\"one-fourth\">\r\n <!-- 12 / 3 / 6 / 9 heavy marks -->\r\n <path d=\"m400 40v107\" stroke-width=\"26.7\" stroke=\"currentColor\" />\r\n <g id=\"one-twelfth\">\r\n <!-- 30\u00B0 heavy marks -->\r\n <path\r\n d=\"m580 88.233-42.5 73.612\"\r\n stroke-width=\"26.7\"\r\n stroke=\"currentColor\"\r\n />\r\n <g id=\"one-thirtieth\">\r\n <!-- minute/second ticks -->\r\n <path\r\n id=\"one-sixtieth\"\r\n d=\"m437.63 41.974-3.6585 34.808\"\r\n stroke-width=\"13.6\"\r\n stroke=\"currentColor\"\r\n />\r\n <use transform=\"rotate(6 400 400)\" href=\"#one-sixtieth\" />\r\n </g>\r\n <use transform=\"rotate(12 400 400)\" href=\"#one-thirtieth\" />\r\n </g>\r\n <use transform=\"rotate(30 400 400)\" href=\"#one-twelfth\" />\r\n <use transform=\"rotate(60 400 400)\" href=\"#one-twelfth\" />\r\n </g>\r\n <use transform=\"rotate(90 400 400)\" href=\"#one-fourth\" />\r\n </g>\r\n\r\n <!-- Hands -->\r\n <path\r\n class=\"clock-hour-hand\"\r\n id=\"anim-clock-hour-hand\"\r\n #hourHand\r\n d=\"m 381.925,476 h 36.15 l 5e-4,-300.03008 L 400,156.25 381.9245,175.96992 Z\"\r\n transform=\"rotate(110.2650694444, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-minute-hand\"\r\n id=\"anim-clock-minute-hand\"\r\n #minuteHand\r\n d=\"M 412.063,496.87456 H 387.937 L 385.249,65.68306 400,52.75 414.751,65.68306 Z\"\r\n transform=\"rotate(243.1808333333, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-second-hand\"\r\n id=\"anim-clock-second-hand\"\r\n #secondHand\r\n d=\"M 397.317,63.51744 395.91962,168.4 C 374.575,170.5125 358.2,188.365 358.2,210 c 0,21.635 16.3,39 36.61214,41.47594 L 391.52847,498 h 16.94306 L 405.1868,251.47593 C 425.5,249 441.8,231.635 441.8,210 c 2e-5,-21.635 -16.375,-39.4875 -37.71971,-41.6 L 402.683,63.51744 400,60 Z M 400,190.534 c 10.888,0 19.466,8.866 19.466,19.466 0,10.6 -8.578,19.466 -19.466,19.466 -10.888,0 -19.466,-8.866 -19.466,-19.466 0,-10.6 8.578,-19.466 19.466,-19.466 z\"\r\n transform=\"rotate(190.85, 400, 400)\"\r\n />\r\n </svg>\r\n </div>\r\n</div>\r\n", styles: [":host{display:block;width:100%;height:100%}.analog-clock-container{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.analog-clock-container .aspect-ratio-box{position:relative;width:100%;max-width:100%;max-height:100%;aspect-ratio:1/1}@supports not (aspect-ratio: 1/1){.analog-clock-container .aspect-ratio-box:before{content:\"\";display:block;padding-bottom:100%}.analog-clock-container .aspect-ratio-box svg{position:absolute;top:0;left:0;width:100%;height:100%}}.analog-clock-container .aspect-ratio-box svg{display:block;width:100%;height:100%}.analog-clock-container .aspect-ratio-box svg path:not(.clock-hour-hand):not(.clock-minute-hand):not(.clock-second-hand){stroke:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-hour-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-minute-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.analog-clock-container .aspect-ratio-box svg .clock-second-hand{fill:var(--mat-sys-primary, #6750a4)}:host:not(.show-seconds) .clock-second-hand{display:none}:host.has-background svg circle{fill:var(--mat-sys-surface, #fffbfe)}:host:hover{opacity:.8}:host:hover svg .clock-hour-hand,:host:hover svg .clock-minute-hand{fill:var(--mat-sys-primary, #6750a4)}:host.clock-widget.analog{container-type:size;container-name:analog-clock}\n"] }]
1183
1356
  }], ctorParameters: () => [] });
1184
1357
 
1185
1358
  // clock-widget.component.ts
@@ -1236,11 +1409,11 @@ class ClockWidgetComponent {
1236
1409
  return this.state().mode === 'digital';
1237
1410
  }
1238
1411
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: ClockWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1239
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: ClockWidgetComponent, isStandalone: true, selector: "ngx-dashboard-clock-widget", ngImport: i0, template: "@if (isDigital) {\r\n <ngx-digital-clock\r\n [timeFormat]=\"state().timeFormat || '24h'\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n />\r\n} @else if (isAnalog) {\r\n <ngx-analog-clock\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n />\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}", styles: [":host{display:block;container-type:size;width:100%;height:100%;overflow:hidden}.svg-wrapper,.clock-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.clock-widget{background-color:var(--mat-sys-surface-container-high);border-radius:4px}.clock-widget{padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d)}.clock-widget.has-background{color:var(--mat-sys-on-surface, #1f1f1f)}.clock-widget:hover{opacity:.8;color:var(--mat-sys-primary, #6750a4)}.analog-clock{width:min(80cqw,80cqh);aspect-ratio:1/1;position:relative}.clock-face{width:100%;height:100%;border:2px solid currentColor;border-radius:50%;position:relative}.clock-face:before,.clock-face:after{content:\"\";position:absolute;background-color:currentColor;left:50%;transform:translate(-50%)}.clock-face:before{width:2px;height:10%;top:0}.clock-face:after{width:2px;height:10%;bottom:0}.hour-hand,.minute-hand{position:absolute;background-color:currentColor;left:50%;bottom:50%;transform-origin:50% 100%;border-radius:2px}.hour-hand{width:4px;height:25%;transform:translate(-50%) rotate(30deg)}.minute-hand{width:2px;height:35%;transform:translate(-50%) rotate(90deg)}.center-dot{position:absolute;width:8px;height:8px;background-color:currentColor;border-radius:50%;top:50%;left:50%;transform:translate(-50%,-50%)}.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;transform-origin:center center}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block;fill:var(--mat-sys-on-surface-variant, #6c757d);transition:fill .2s ease}.has-background .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-on-surface, #1f1f1f)}.svg-wrapper:hover .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-primary, #6750a4)}\n"], dependencies: [{ kind: "component", type: DigitalClockComponent, selector: "ngx-digital-clock", inputs: ["timeFormat", "showSeconds", "hasBackground"] }, { kind: "component", type: AnalogClockComponent, selector: "ngx-analog-clock", inputs: ["hasBackground", "showSeconds"] }] });
1412
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: ClockWidgetComponent, isStandalone: true, selector: "ngx-dashboard-clock-widget", ngImport: i0, template: "@if (isDigital) {\r\n <ngx-digital-clock\r\n [timeFormat]=\"state().timeFormat || '24h'\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n />\r\n} @else if (isAnalog) {\r\n <ngx-analog-clock\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n />\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}", styles: [":host{display:block;container-type:size;width:100%;height:100%;overflow:hidden}.svg-wrapper,.clock-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.clock-widget{background-color:var(--mat-sys-surface-container-high);border-radius:4px}.clock-widget{padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d)}.clock-widget.has-background{color:var(--mat-sys-on-surface, #1f1f1f)}.clock-widget:hover{opacity:.8;color:var(--mat-sys-primary, #6750a4)}.analog-clock{width:min(80cqw,80cqh);aspect-ratio:1/1;position:relative}.clock-face{width:100%;height:100%;border:2px solid currentColor;border-radius:50%;position:relative}.clock-face:before,.clock-face:after{content:\"\";position:absolute;background-color:currentColor;left:50%;transform:translate(-50%)}.clock-face:before{width:2px;height:10%;top:0}.clock-face:after{width:2px;height:10%;bottom:0}.hour-hand,.minute-hand{position:absolute;background-color:currentColor;left:50%;bottom:50%;transform-origin:50% 100%;border-radius:2px}.hour-hand{width:4px;height:25%;transform:translate(-50%) rotate(30deg)}.minute-hand{width:2px;height:35%;transform:translate(-50%) rotate(90deg)}.center-dot{position:absolute;width:8px;height:8px;background-color:currentColor;border-radius:50%;top:50%;left:50%;transform:translate(-50%,-50%)}.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;transform-origin:center center}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block}.svg-placeholder ::ng-deep svg .clock-face{stroke:var(--mat-sys-on-surface, #1d1b20)}.svg-placeholder ::ng-deep svg .clock-hour-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.svg-placeholder ::ng-deep svg .clock-minute-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.svg-placeholder ::ng-deep svg .clock-second-hand{fill:var(--mat-sys-primary, #6750a4)}.has-background .svg-placeholder ::ng-deep svg circle{fill:var(--mat-sys-surface, #fffbfe)}\n"], dependencies: [{ kind: "component", type: DigitalClockComponent, selector: "ngx-digital-clock", inputs: ["timeFormat", "showSeconds", "hasBackground"] }, { kind: "component", type: AnalogClockComponent, selector: "ngx-analog-clock", inputs: ["hasBackground", "showSeconds"] }] });
1240
1413
  }
1241
1414
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: ClockWidgetComponent, decorators: [{
1242
1415
  type: Component,
1243
- args: [{ selector: 'ngx-dashboard-clock-widget', standalone: true, imports: [DigitalClockComponent, AnalogClockComponent], template: "@if (isDigital) {\r\n <ngx-digital-clock\r\n [timeFormat]=\"state().timeFormat || '24h'\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n />\r\n} @else if (isAnalog) {\r\n <ngx-analog-clock\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n />\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}", styles: [":host{display:block;container-type:size;width:100%;height:100%;overflow:hidden}.svg-wrapper,.clock-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.clock-widget{background-color:var(--mat-sys-surface-container-high);border-radius:4px}.clock-widget{padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d)}.clock-widget.has-background{color:var(--mat-sys-on-surface, #1f1f1f)}.clock-widget:hover{opacity:.8;color:var(--mat-sys-primary, #6750a4)}.analog-clock{width:min(80cqw,80cqh);aspect-ratio:1/1;position:relative}.clock-face{width:100%;height:100%;border:2px solid currentColor;border-radius:50%;position:relative}.clock-face:before,.clock-face:after{content:\"\";position:absolute;background-color:currentColor;left:50%;transform:translate(-50%)}.clock-face:before{width:2px;height:10%;top:0}.clock-face:after{width:2px;height:10%;bottom:0}.hour-hand,.minute-hand{position:absolute;background-color:currentColor;left:50%;bottom:50%;transform-origin:50% 100%;border-radius:2px}.hour-hand{width:4px;height:25%;transform:translate(-50%) rotate(30deg)}.minute-hand{width:2px;height:35%;transform:translate(-50%) rotate(90deg)}.center-dot{position:absolute;width:8px;height:8px;background-color:currentColor;border-radius:50%;top:50%;left:50%;transform:translate(-50%,-50%)}.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;transform-origin:center center}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block;fill:var(--mat-sys-on-surface-variant, #6c757d);transition:fill .2s ease}.has-background .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-on-surface, #1f1f1f)}.svg-wrapper:hover .svg-placeholder ::ng-deep svg{fill:var(--mat-sys-primary, #6750a4)}\n"] }]
1416
+ args: [{ selector: 'ngx-dashboard-clock-widget', standalone: true, imports: [DigitalClockComponent, AnalogClockComponent], template: "@if (isDigital) {\r\n <ngx-digital-clock\r\n [timeFormat]=\"state().timeFormat || '24h'\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n />\r\n} @else if (isAnalog) {\r\n <ngx-analog-clock\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n />\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}", styles: [":host{display:block;container-type:size;width:100%;height:100%;overflow:hidden}.svg-wrapper,.clock-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.clock-widget{background-color:var(--mat-sys-surface-container-high);border-radius:4px}.clock-widget{padding:var(--mat-sys-spacing-4);color:var(--mat-sys-on-surface-variant, #6c757d)}.clock-widget.has-background{color:var(--mat-sys-on-surface, #1f1f1f)}.clock-widget:hover{opacity:.8;color:var(--mat-sys-primary, #6750a4)}.analog-clock{width:min(80cqw,80cqh);aspect-ratio:1/1;position:relative}.clock-face{width:100%;height:100%;border:2px solid currentColor;border-radius:50%;position:relative}.clock-face:before,.clock-face:after{content:\"\";position:absolute;background-color:currentColor;left:50%;transform:translate(-50%)}.clock-face:before{width:2px;height:10%;top:0}.clock-face:after{width:2px;height:10%;bottom:0}.hour-hand,.minute-hand{position:absolute;background-color:currentColor;left:50%;bottom:50%;transform-origin:50% 100%;border-radius:2px}.hour-hand{width:4px;height:25%;transform:translate(-50%) rotate(30deg)}.minute-hand{width:2px;height:35%;transform:translate(-50%) rotate(90deg)}.center-dot{position:absolute;width:8px;height:8px;background-color:currentColor;border-radius:50%;top:50%;left:50%;transform:translate(-50%,-50%)}.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;transform-origin:center center}.svg-placeholder ::ng-deep svg{width:100%;height:100%;display:block}.svg-placeholder ::ng-deep svg .clock-face{stroke:var(--mat-sys-on-surface, #1d1b20)}.svg-placeholder ::ng-deep svg .clock-hour-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.svg-placeholder ::ng-deep svg .clock-minute-hand{fill:var(--mat-sys-on-surface, #1d1b20)}.svg-placeholder ::ng-deep svg .clock-second-hand{fill:var(--mat-sys-primary, #6750a4)}.has-background .svg-placeholder ::ng-deep svg circle{fill:var(--mat-sys-surface, #fffbfe)}\n"] }]
1244
1417
  }], ctorParameters: () => [] });
1245
1418
 
1246
1419
  /*
@@ -1 +1 @@
1
- {"version":3,"file":"dragonworks-ngx-dashboard-widgets.mjs","sources":["../../../projects/ngx-dashboard-widgets/src/lib/arrow-widget/arrow-widget.metadata.ts","../../../projects/ngx-dashboard-widgets/src/lib/arrow-widget/arrow-state-dialog.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/arrow-widget/arrow-widget.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/arrow-widget/arrow-widget.component.html","../../../projects/ngx-dashboard-widgets/src/lib/label-widget/label-widget.metadata.ts","../../../projects/ngx-dashboard-widgets/src/lib/label-widget/label-state-dialog.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/directives/responsive-text.directive.ts","../../../projects/ngx-dashboard-widgets/src/lib/label-widget/label-widget.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/label-widget/label-widget.component.html","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/clock-widget.metadata.ts","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/clock-state-dialog.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/digital-clock/digital-clock.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/digital-clock/digital-clock.component.html","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/analog-clock/analog-clock.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/analog-clock/analog-clock.component.html","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/clock-widget.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/clock-widget.component.html","../../../projects/ngx-dashboard-widgets/src/public-api.ts","../../../projects/ngx-dashboard-widgets/src/dragonworks-ngx-dashboard-widgets.ts"],"sourcesContent":["// arrow-widget.metadata.ts\r\nexport const svgIcon =\r\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"><path d=\"M320-120v-320H120l360-440 360 440H640v320H320Zm80-80h160v-320h111L480-754 289-520h111v320Zm80-320Z\"/></svg>';\r\n","import { Component, inject, signal, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport {\r\n MAT_DIALOG_DATA,\r\n MatDialogRef,\r\n MatDialogModule,\r\n} from '@angular/material/dialog';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { ArrowWidgetState } from './arrow-widget.component';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatSelectModule } from '@angular/material/select';\r\nimport { MatSliderModule } from '@angular/material/slider';\r\nimport { MatSlideToggleModule } from '@angular/material/slide-toggle';\r\n\r\n@Component({\r\n selector: 'lib-arrow-state-dialog',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n MatDialogModule,\r\n MatButtonModule,\r\n MatFormFieldModule,\r\n MatSelectModule,\r\n MatSliderModule,\r\n MatSlideToggleModule,\r\n ],\r\n template: `\r\n <h2 mat-dialog-title>Arrow Settings</h2>\r\n <mat-dialog-content>\r\n <!-- Direction Selection -->\r\n <mat-form-field appearance=\"outline\" class=\"direction-field\">\r\n <mat-label>Arrow Direction</mat-label>\r\n <mat-select\r\n [value]=\"direction()\"\r\n (selectionChange)=\"direction.set($any($event.value))\"\r\n >\r\n <mat-option value=\"up\">Up</mat-option>\r\n <mat-option value=\"right\">Right</mat-option>\r\n <mat-option value=\"down\">Down</mat-option>\r\n <mat-option value=\"left\">Left</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- Opacity Slider -->\r\n <div class=\"slider-field\">\r\n <div class=\"field-label\">Opacity: {{ formatOpacity(opacity()) }}%</div>\r\n <mat-slider [min]=\"0.1\" [max]=\"1\" [step]=\"0.1\">\r\n <input matSliderThumb [(ngModel)]=\"opacity\" />\r\n </mat-slider>\r\n </div>\r\n\r\n <!-- Background Toggle -->\r\n <div class=\"toggle-field\">\r\n <mat-slide-toggle \r\n [checked]=\"hasBackground()\"\r\n (change)=\"onBackgroundToggle($event.checked)\">\r\n Background\r\n </mat-slide-toggle>\r\n <span class=\"toggle-hint\">Adds a background behind the arrow</span>\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\">\r\n <button mat-button (click)=\"onCancel()\">Cancel</button>\r\n <button mat-flat-button (click)=\"save()\" [disabled]=\"!hasChanged()\">\r\n Save\r\n </button>\r\n </mat-dialog-actions>\r\n `,\r\n styles: [\r\n `\r\n mat-dialog-content {\r\n display: block;\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n }\r\n\r\n mat-form-field {\r\n width: 100%;\r\n display: block;\r\n margin-bottom: 1rem;\r\n }\r\n\r\n .direction-field {\r\n margin-top: 1rem;\r\n }\r\n\r\n /* Opacity slider section */\r\n .slider-field {\r\n margin-bottom: 1.5rem;\r\n margin-right: 1rem;\r\n }\r\n\r\n .field-label {\r\n display: block;\r\n margin-bottom: 0.5rem;\r\n }\r\n\r\n mat-slider {\r\n width: 100%;\r\n display: block;\r\n }\r\n\r\n /* Toggle section */\r\n .toggle-field {\r\n display: flex;\r\n align-items: center;\r\n gap: 0.75rem;\r\n margin-bottom: 0.5rem;\r\n }\r\n\r\n .toggle-hint {\r\n margin: 0;\r\n }\r\n `,\r\n ],\r\n})\r\nexport class ArrowStateDialogComponent {\r\n private readonly data = inject<ArrowWidgetState>(MAT_DIALOG_DATA);\r\n private readonly dialogRef = inject(MatDialogRef<ArrowStateDialogComponent>);\r\n\r\n // State signals\r\n readonly direction = signal<'left' | 'up' | 'right' | 'down'>(\r\n this.data.direction\r\n );\r\n readonly opacity = signal<number>(this.data.opacity ?? 1);\r\n readonly hasBackground = signal<boolean>(this.data.hasBackground ?? true);\r\n readonly transparentBackground = signal<boolean>(!(this.data.hasBackground ?? true));\r\n\r\n // Store original values for comparison\r\n private readonly originalDirection = this.data.direction;\r\n private readonly originalOpacity = this.data.opacity ?? 1;\r\n private readonly originalHasBackground = this.data.hasBackground ?? true;\r\n\r\n // Computed values\r\n readonly rotation = computed(() => {\r\n const rotationMap = {\r\n up: 0,\r\n right: 90,\r\n down: 180,\r\n left: 270,\r\n };\r\n return rotationMap[this.direction()];\r\n });\r\n\r\n readonly rotationTransform = computed(() => `rotate(${this.rotation()}deg)`);\r\n\r\n readonly directionName = computed(() => {\r\n const nameMap = {\r\n up: 'Up',\r\n right: 'Right',\r\n down: 'Down',\r\n left: 'Left',\r\n };\r\n return nameMap[this.direction()];\r\n });\r\n\r\n readonly hasChanged = computed(\r\n () =>\r\n this.direction() !== this.originalDirection ||\r\n this.opacity() !== this.originalOpacity ||\r\n this.hasBackground() !== this.originalHasBackground\r\n );\r\n\r\n formatOpacity(value: number): number {\r\n return Math.round(value * 100);\r\n }\r\n\r\n onBackgroundToggle(hasBackground: boolean): void {\r\n this.hasBackground.set(hasBackground);\r\n this.transparentBackground.set(!hasBackground);\r\n }\r\n\r\n onCancel(): void {\r\n this.dialogRef.close();\r\n }\r\n\r\n save(): void {\r\n this.dialogRef.close({\r\n direction: this.direction(),\r\n opacity: this.opacity(),\r\n hasBackground: this.hasBackground(),\r\n } as ArrowWidgetState);\r\n }\r\n}\r\n","// arrow-widget.component.ts\r\nimport { Component, inject, signal, computed } from '@angular/core';\r\nimport { Widget, WidgetMetadata } from '@dragonworks/ngx-dashboard';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { svgIcon } from './arrow-widget.metadata';\r\nimport { ArrowStateDialogComponent } from './arrow-state-dialog.component';\r\n\r\nexport interface ArrowWidgetState {\r\n direction: 'left' | 'up' | 'right' | 'down';\r\n opacity?: number;\r\n hasBackground?: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'ngx-dashboard-arrow-widget',\r\n imports: [],\r\n templateUrl: './arrow-widget.component.html',\r\n styleUrl: './arrow-widget.component.scss',\r\n})\r\nexport class ArrowWidgetComponent implements Widget {\r\n static metadata: WidgetMetadata = {\r\n widgetTypeid: '@default/arrow-widget',\r\n name: 'Arrow',\r\n description: 'A generic arrow',\r\n svgIcon,\r\n };\r\n\r\n readonly #sanitizer = inject(DomSanitizer);\r\n readonly #dialog = inject(MatDialog);\r\n\r\n readonly safeSvgIcon = this.#sanitizer.bypassSecurityTrustHtml(svgIcon);\r\n\r\n readonly state = signal<ArrowWidgetState>({\r\n direction: 'up',\r\n opacity: 0.3,\r\n hasBackground: true,\r\n });\r\n // Computed rotation\r\n readonly rotationAngle = computed(() => {\r\n const rotationMap = {\r\n up: 0,\r\n right: 90,\r\n down: 180,\r\n left: 270,\r\n };\r\n return rotationMap[this.state().direction];\r\n });\r\n\r\n dashboardSetState(state?: unknown): void {\r\n if (state) {\r\n this.state.update((current) => ({\r\n ...current,\r\n ...(state as ArrowWidgetState),\r\n }));\r\n }\r\n }\r\n\r\n dashboardGetState(): ArrowWidgetState {\r\n return this.state();\r\n }\r\n\r\n dashboardEditState(): void {\r\n const dialogRef = this.#dialog.open(ArrowStateDialogComponent, {\r\n data: this.state(),\r\n width: '400px',\r\n maxWidth: '90vw',\r\n disableClose: false,\r\n autoFocus: false,\r\n });\r\n\r\n dialogRef.afterClosed().subscribe((result) => {\r\n if (result) {\r\n this.state.set(result);\r\n }\r\n });\r\n }\r\n}\r\n","<!-- arrow-widget.component.html -->\r\n<div class=\"svg-wrapper\" [class.has-background]=\"state().hasBackground\">\r\n <div\r\n class=\"svg-placeholder\"\r\n [innerHTML]=\"safeSvgIcon\"\r\n [style.transform]=\"'rotate(' + rotationAngle() + 'deg)'\"\r\n [style.opacity]=\"state().opacity\"\r\n ></div>\r\n</div>\r\n","// label-widget.metadata.ts\r\nexport const svgIcon =\r\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"><path d=\"M280-280h280v-80H280v80Zm0-160h400v-80H280v80Zm0-160h400v-80H280v80Zm-80 480q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm0-560v560-560Z\"/></svg>';\r\n","import { Component, inject, signal, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport {\r\n MAT_DIALOG_DATA,\r\n MatDialogRef,\r\n MatDialogModule,\r\n} from '@angular/material/dialog';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatSelectModule } from '@angular/material/select';\r\nimport { MatSliderModule } from '@angular/material/slider';\r\nimport { MatSlideToggleModule } from '@angular/material/slide-toggle'; // Add this import\r\nimport { LabelWidgetState } from './label-widget.component';\r\n\r\n@Component({\r\n selector: 'lib-label-state-dialog',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n MatDialogModule,\r\n MatButtonModule,\r\n MatFormFieldModule,\r\n MatInputModule,\r\n MatSelectModule,\r\n MatSliderModule,\r\n MatSlideToggleModule, // Add this import\r\n ],\r\n template: `\r\n <h2 mat-dialog-title>Label Settings</h2>\r\n <mat-dialog-content>\r\n <mat-form-field appearance=\"outline\" class=\"label-text-field\">\r\n <mat-label>Label Text</mat-label>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [value]=\"label()\"\r\n (input)=\"label.set($any($event.target).value)\"\r\n placeholder=\"Enter your label text...\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- Responsive Text Toggle -->\r\n <div class=\"toggle-section\">\r\n <mat-slide-toggle \r\n [checked]=\"responsive()\"\r\n (change)=\"responsive.set($event.checked)\">\r\n Responsive Text\r\n </mat-slide-toggle>\r\n <span class=\"toggle-description\"\r\n >Automatically adjust text size to fit the widget</span\r\n >\r\n </div>\r\n\r\n <div class=\"row-layout\">\r\n <mat-form-field appearance=\"outline\">\r\n <mat-label>Font Size (px)</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [value]=\"fontSize()\"\r\n (input)=\"fontSize.set(+$any($event.target).value)\"\r\n [disabled]=\"responsive()\"\r\n min=\"8\"\r\n max=\"48\"\r\n placeholder=\"16\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\">\r\n <mat-label>Alignment</mat-label>\r\n <mat-select\r\n [value]=\"alignment()\"\r\n (selectionChange)=\"alignment.set($any($event.value))\"\r\n >\r\n <mat-option value=\"left\">Left</mat-option>\r\n <mat-option value=\"center\">Center</mat-option>\r\n <mat-option value=\"right\">Right</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <mat-form-field appearance=\"outline\">\r\n <mat-label>Font Weight</mat-label>\r\n <mat-select\r\n [value]=\"fontWeight()\"\r\n (selectionChange)=\"fontWeight.set($any($event.value))\"\r\n >\r\n <mat-option value=\"normal\">Normal</mat-option>\r\n <mat-option value=\"bold\">Bold</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- Opacity Slider -->\r\n <div class=\"slider-section\">\r\n <div class=\"slider-label\">Opacity: {{ formatOpacity(opacity()) }}%</div>\r\n <mat-slider [min]=\"0.1\" [max]=\"1\" [step]=\"0.1\">\r\n <input matSliderThumb [(ngModel)]=\"opacity\" />\r\n </mat-slider>\r\n </div>\r\n\r\n <!-- Background Toggle -->\r\n <div class=\"toggle-section\">\r\n <mat-slide-toggle \r\n [checked]=\"!transparentBackground()\"\r\n (change)=\"onBackgroundToggle($event.checked)\">\r\n Background\r\n </mat-slide-toggle>\r\n <span class=\"toggle-description\"\r\n >Adds a background behind the text</span\r\n >\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\">\r\n <button mat-button (click)=\"onCancel()\">Cancel</button>\r\n <button mat-flat-button (click)=\"save()\" [disabled]=\"!hasChanged()\">\r\n Save\r\n </button>\r\n </mat-dialog-actions>\r\n `,\r\n styles: [\r\n `\r\n mat-dialog-content {\r\n display: block;\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n }\r\n\r\n mat-form-field {\r\n width: 100%;\r\n display: block;\r\n margin-bottom: 1rem;\r\n }\r\n\r\n .label-text-field {\r\n margin-top: 1rem;\r\n }\r\n\r\n /* Side-by-side layout for font size and alignment */\r\n .row-layout {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 1rem;\r\n margin-bottom: 1rem;\r\n }\r\n\r\n .row-layout mat-form-field {\r\n margin-bottom: 0;\r\n }\r\n\r\n /* Opacity slider section */\r\n .slider-section {\r\n margin-bottom: 1.5rem;\r\n margin-right: 1rem;\r\n }\r\n\r\n .slider-label {\r\n display: block;\r\n margin-bottom: 0.5rem;\r\n }\r\n\r\n mat-slider {\r\n width: 100%;\r\n display: block;\r\n }\r\n\r\n /* Toggle section */\r\n .toggle-section {\r\n display: flex;\r\n align-items: center;\r\n gap: 0.75rem;\r\n margin-bottom: 1rem;\r\n }\r\n\r\n .toggle-description {\r\n margin: 0;\r\n }\r\n `,\r\n ],\r\n})\r\nexport class LabelStateDialogComponent {\r\n private readonly data = inject<LabelWidgetState>(MAT_DIALOG_DATA);\r\n private readonly dialogRef = inject(MatDialogRef<LabelStateDialogComponent>);\r\n\r\n // State signals\r\n readonly label = signal<string>(this.data.label ?? '');\r\n readonly fontSize = signal<number>(this.data.fontSize ?? 16);\r\n readonly alignment = signal<'left' | 'center' | 'right'>(\r\n this.data.alignment ?? 'center'\r\n );\r\n readonly fontWeight = signal<'normal' | 'bold'>(\r\n this.data.fontWeight ?? 'normal'\r\n );\r\n readonly opacity = signal<number>(this.data.opacity ?? 1);\r\n readonly hasBackground = signal<boolean>(this.data.hasBackground ?? true);\r\n readonly transparentBackground = signal<boolean>(!(this.data.hasBackground ?? true));\r\n readonly responsive = signal<boolean>(this.data.responsive ?? false);\r\n\r\n // Store original values for comparison\r\n private readonly originalLabel = this.data.label ?? '';\r\n private readonly originalFontSize = this.data.fontSize ?? 16;\r\n private readonly originalAlignment = this.data.alignment ?? 'center';\r\n private readonly originalFontWeight = this.data.fontWeight ?? 'normal';\r\n private readonly originalOpacity = this.data.opacity ?? 1;\r\n private readonly originalHasBackground = this.data.hasBackground ?? true;\r\n private readonly originalResponsive = this.data.responsive ?? false;\r\n\r\n // Computed values\r\n readonly hasChanged = computed(\r\n () =>\r\n this.label() !== this.originalLabel ||\r\n this.fontSize() !== this.originalFontSize ||\r\n this.alignment() !== this.originalAlignment ||\r\n this.fontWeight() !== this.originalFontWeight ||\r\n this.opacity() !== this.originalOpacity ||\r\n this.hasBackground() !== this.originalHasBackground ||\r\n this.responsive() !== this.originalResponsive\r\n );\r\n\r\n formatOpacity(value: number): number {\r\n return Math.round(value * 100);\r\n }\r\n\r\n formatOpacitySlider = (value: number): string => {\r\n return `${Math.round(value * 100)}%`;\r\n };\r\n\r\n onBackgroundToggle(hasWhiteBackground: boolean): void {\r\n this.hasBackground.set(hasWhiteBackground);\r\n this.transparentBackground.set(!hasWhiteBackground);\r\n }\r\n\r\n onCancel(): void {\r\n this.dialogRef.close();\r\n }\r\n\r\n save(): void {\r\n this.dialogRef.close({\r\n label: this.label(),\r\n fontSize: this.fontSize(),\r\n alignment: this.alignment(),\r\n fontWeight: this.fontWeight(),\r\n opacity: this.opacity(),\r\n hasBackground: this.hasBackground(),\r\n responsive: this.responsive(),\r\n } as LabelWidgetState);\r\n }\r\n}\r\n","import {\r\n Directive,\r\n ElementRef,\r\n AfterViewInit,\r\n OnDestroy,\r\n inject,\r\n DestroyRef,\r\n numberAttribute,\r\n booleanAttribute,\r\n input,\r\n} from '@angular/core';\r\nimport { NgZone, PLATFORM_ID } from '@angular/core';\r\nimport { isPlatformBrowser } from '@angular/common';\r\n\r\n/**\r\n * Directive that automatically adjusts font size to fit text within its parent container.\r\n * Uses canvas-based measurement for performance and DOM verification for accuracy.\r\n *\r\n * @example\r\n * <div class=\"container\">\r\n * <span responsiveText [min]=\"12\" [max]=\"72\">Dynamic text here</span>\r\n * </div>\r\n */\r\n@Directive({\r\n selector: '[responsiveText]',\r\n standalone: true,\r\n host: {\r\n '[style.display]': '\"block\"',\r\n '[style.width]': '\"100%\"',\r\n '[style.white-space]': '\"nowrap\"',\r\n '[style.overflow]': '\"hidden\"',\r\n '[style.text-overflow]': '\"ellipsis\"',\r\n },\r\n})\r\nexport class ResponsiveTextDirective implements AfterViewInit, OnDestroy {\r\n /* ───────────────────────── Inputs with transforms ─────────────── */\r\n /** Minimum font-size in pixels (accessibility floor) */\r\n min = input(8, { transform: numberAttribute });\r\n\r\n /** Maximum font-size in pixels (layout ceiling) */\r\n max = input(512, { transform: numberAttribute });\r\n\r\n /**\r\n * Line-height: pass a multiplier (e.g. 1.1) or absolute px value.\r\n * For single-line text a multiplier < 10 is treated as unitless.\r\n */\r\n lineHeight = input(1.1, { transform: numberAttribute });\r\n\r\n /** Whether to observe text mutations after first render */\r\n observeMutations = input(true, { transform: booleanAttribute });\r\n\r\n /** Debounce delay in ms for resize/mutation callbacks */\r\n debounceMs = input(16, { transform: numberAttribute });\r\n\r\n /* ───────────────────────── Private state ───────────────────────── */\r\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly zone = inject(NgZone);\r\n private readonly platformId = inject(PLATFORM_ID);\r\n private readonly destroyRef = inject(DestroyRef);\r\n\r\n // Canvas context - lazy initialization\r\n private _ctx?: CanvasRenderingContext2D;\r\n private get ctx(): CanvasRenderingContext2D {\r\n if (!this._ctx) {\r\n const canvas = document.createElement('canvas');\r\n this._ctx = canvas.getContext('2d', {\r\n willReadFrequently: true,\r\n alpha: false,\r\n })!;\r\n }\r\n return this._ctx;\r\n }\r\n\r\n private ro?: ResizeObserver;\r\n private mo?: MutationObserver;\r\n private fitTimeout?: number;\r\n\r\n // Cache for performance\r\n private lastText = '';\r\n private lastMaxW = 0;\r\n private lastMaxH = 0;\r\n private lastFontSize = 0;\r\n\r\n /* ───────────────────────── Lifecycle ──────────────────────────── */\r\n ngAfterViewInit() {\r\n if (!isPlatformBrowser(this.platformId)) return;\r\n\r\n // Set initial styles\r\n const span = this.el.nativeElement;\r\n span.style.transition = 'font-size 0.1s ease-out';\r\n\r\n // All observer callbacks run outside Angular's zone\r\n this.zone.runOutsideAngular(() => {\r\n this.fit();\r\n this.observeResize();\r\n if (this.observeMutations()) {\r\n this.observeText();\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.cleanup();\r\n }\r\n\r\n /* ───────────────────── Core fitting logic ───────────────────── */\r\n /**\r\n * Debounced fit handler to prevent excessive recalculations\r\n */\r\n private requestFit = () => {\r\n if (this.fitTimeout) {\r\n cancelAnimationFrame(this.fitTimeout);\r\n }\r\n\r\n this.fitTimeout = requestAnimationFrame(() => {\r\n this.fit();\r\n });\r\n };\r\n\r\n /**\r\n * Recalculate & apply the ideal font-size\r\n */\r\n private fit = () => {\r\n const span = this.el.nativeElement;\r\n const parent = span.parentElement;\r\n\r\n if (!parent) return;\r\n\r\n const text = span.textContent?.trim() || '';\r\n if (!text) {\r\n span.style.fontSize = `${this.min()}px`;\r\n return;\r\n }\r\n\r\n // Get available space\r\n const { maxW, maxH } = this.getAvailableSpace(parent);\r\n\r\n // Check cache to avoid redundant calculations\r\n if (\r\n text === this.lastText &&\r\n maxW === this.lastMaxW &&\r\n maxH === this.lastMaxH &&\r\n this.lastFontSize > 0\r\n ) {\r\n return;\r\n }\r\n\r\n // Calculate ideal font size\r\n const ideal = this.calcFit(text, maxW, maxH);\r\n span.style.fontSize = `${ideal}px`;\r\n\r\n // DOM verification pass\r\n this.verifyFit(span, maxW, maxH, ideal);\r\n\r\n // Update cache\r\n this.lastText = text;\r\n this.lastMaxW = maxW;\r\n this.lastMaxH = maxH;\r\n this.lastFontSize = parseFloat(span.style.fontSize);\r\n };\r\n\r\n /**\r\n * Calculate available space accounting for padding and borders\r\n */\r\n private getAvailableSpace(parent: HTMLElement): {\r\n maxW: number;\r\n maxH: number;\r\n } {\r\n const cs = getComputedStyle(parent);\r\n const maxW =\r\n parent.clientWidth -\r\n parseFloat(cs.paddingLeft) -\r\n parseFloat(cs.paddingRight);\r\n const maxH =\r\n parent.clientHeight -\r\n parseFloat(cs.paddingTop) -\r\n parseFloat(cs.paddingBottom);\r\n\r\n return { maxW: Math.max(0, maxW), maxH: Math.max(0, maxH) };\r\n }\r\n\r\n /**\r\n * DOM-based verification to handle sub-pixel discrepancies\r\n */\r\n private verifyFit(\r\n span: HTMLElement,\r\n maxW: number,\r\n maxH: number,\r\n ideal: number\r\n ) {\r\n // Use requestAnimationFrame to ensure layout is complete\r\n requestAnimationFrame(() => {\r\n if (span.scrollWidth > maxW || span.scrollHeight > maxH) {\r\n let safe = ideal;\r\n while (\r\n safe > this.min() &&\r\n (span.scrollWidth > maxW || span.scrollHeight > maxH)\r\n ) {\r\n safe -= 0.5; // Finer adjustments\r\n span.style.fontSize = `${safe}px`;\r\n }\r\n }\r\n });\r\n }\r\n\r\n /* ───────────────────── Binary search algorithm ────────────────── */\r\n /**\r\n * Binary search for optimal font size using canvas measurements\r\n */\r\n private calcFit(\r\n text: string,\r\n maxW: number,\r\n maxH: number,\r\n precision = 0.1\r\n ): number {\r\n if (maxW <= 0 || maxH <= 0) return this.min();\r\n\r\n const computedStyle = getComputedStyle(this.el.nativeElement);\r\n const fontFamily = computedStyle.fontFamily || 'sans-serif';\r\n const fontWeight = computedStyle.fontWeight || '400';\r\n\r\n let lo = this.min();\r\n let hi = this.max();\r\n let bestFit = this.min();\r\n\r\n while (hi - lo > precision) {\r\n const mid = (hi + lo) / 2;\r\n this.ctx.font = `${fontWeight} ${mid}px ${fontFamily}`;\r\n\r\n const metrics = this.ctx.measureText(text);\r\n const width = metrics.width;\r\n\r\n // Calculate height based on available metrics\r\n const height = this.calculateTextHeight(metrics, mid);\r\n\r\n if (width <= maxW && height <= maxH) {\r\n bestFit = mid;\r\n lo = mid;\r\n } else {\r\n hi = mid;\r\n }\r\n }\r\n\r\n return Math.floor(bestFit * 100) / 100;\r\n }\r\n\r\n /**\r\n * Calculate text height from metrics\r\n */\r\n private calculateTextHeight(metrics: TextMetrics, fontSize: number): number {\r\n // Use font bounding box metrics if available\r\n if (metrics.fontBoundingBoxAscent && metrics.fontBoundingBoxDescent) {\r\n return metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;\r\n }\r\n\r\n // Fallback to actual bounding box\r\n if (metrics.actualBoundingBoxAscent && metrics.actualBoundingBoxDescent) {\r\n return metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;\r\n }\r\n\r\n // Final fallback using line height\r\n return this.lineHeight() < 10\r\n ? fontSize * this.lineHeight()\r\n : this.lineHeight();\r\n }\r\n\r\n /* ───────────────────────── Observers ─────────────────────────── */\r\n /**\r\n * Observe parent container resizes\r\n */\r\n private observeResize() {\r\n if (!('ResizeObserver' in window)) return;\r\n\r\n this.ro = new ResizeObserver((entries) => {\r\n // Only trigger if size actually changed\r\n const entry = entries[0];\r\n if (entry?.contentRect) {\r\n this.requestFit();\r\n }\r\n });\r\n\r\n const parent = this.el.nativeElement.parentElement;\r\n if (parent) {\r\n this.ro.observe(parent);\r\n }\r\n }\r\n\r\n /**\r\n * Observe text content changes\r\n */\r\n private observeText() {\r\n if (!('MutationObserver' in window)) return;\r\n\r\n this.mo = new MutationObserver((mutations) => {\r\n // Check if text actually changed\r\n const hasTextChange = mutations.some(\r\n (m) =>\r\n m.type === 'characterData' ||\r\n (m.type === 'childList' &&\r\n (m.addedNodes.length > 0 || m.removedNodes.length > 0))\r\n );\r\n\r\n if (hasTextChange) {\r\n this.requestFit();\r\n }\r\n });\r\n\r\n this.mo.observe(this.el.nativeElement, {\r\n characterData: true,\r\n childList: true,\r\n subtree: true,\r\n });\r\n }\r\n\r\n /**\r\n * Cleanup resources\r\n */\r\n private cleanup() {\r\n this.ro?.disconnect();\r\n this.mo?.disconnect();\r\n\r\n if (this.fitTimeout) {\r\n cancelAnimationFrame(this.fitTimeout);\r\n }\r\n\r\n // Clear canvas context\r\n this._ctx = undefined;\r\n }\r\n}\r\n","// label-widget.component.ts\r\nimport { Component, inject, signal } from '@angular/core';\r\nimport { Widget, WidgetMetadata } from '@dragonworks/ngx-dashboard';\r\nimport { svgIcon } from './label-widget.metadata';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { LabelStateDialogComponent } from './label-state-dialog.component';\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { ResponsiveTextDirective } from '../directives/responsive-text.directive';\r\n\r\nexport interface LabelWidgetState {\r\n label: string;\r\n fontSize?: number;\r\n alignment?: 'left' | 'center' | 'right';\r\n fontWeight?: 'normal' | 'bold';\r\n opacity?: number;\r\n hasBackground?: boolean;\r\n responsive?: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'ngx-dashboard-label-widget',\r\n imports: [ResponsiveTextDirective],\r\n templateUrl: './label-widget.component.html',\r\n styleUrl: './label-widget.component.scss',\r\n})\r\nexport class LabelWidgetComponent implements Widget {\r\n static metadata: WidgetMetadata = {\r\n widgetTypeid: '@default/label-widget',\r\n name: 'Label',\r\n description: 'A generic text label',\r\n svgIcon,\r\n };\r\n\r\n readonly #sanitizer = inject(DomSanitizer);\r\n readonly #dialog = inject(MatDialog);\r\n\r\n safeSvgIcon = this.#sanitizer.bypassSecurityTrustHtml(svgIcon);\r\n\r\n state = signal<LabelWidgetState>({\r\n label: '',\r\n fontSize: 16,\r\n alignment: 'center',\r\n fontWeight: 'normal',\r\n opacity: 1,\r\n hasBackground: true,\r\n responsive: false,\r\n });\r\n\r\n dashboardSetState(state?: unknown) {\r\n if (state) {\r\n this.state.update((current) => ({\r\n ...current,\r\n ...(state as LabelWidgetState),\r\n }));\r\n }\r\n }\r\n\r\n dashboardGetState(): LabelWidgetState {\r\n return { ...this.state() };\r\n }\r\n\r\n dashboardEditState(): void {\r\n const dialogRef = this.#dialog.open(LabelStateDialogComponent, {\r\n data: this.dashboardGetState(),\r\n width: '400px',\r\n maxWidth: '90vw',\r\n disableClose: false,\r\n autoFocus: false,\r\n });\r\n\r\n dialogRef\r\n .afterClosed()\r\n .subscribe((result: LabelWidgetState | undefined) => {\r\n if (result) {\r\n this.state.set(result);\r\n }\r\n });\r\n }\r\n\r\n get hasContent(): boolean {\r\n return !!this.state().label?.trim();\r\n }\r\n\r\n get label(): string {\r\n return this.state().label?.trim();\r\n }\r\n}\r\n","@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\" responsiveText>{{ 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","// clock-widget.metadata.ts\r\nexport const svgIcon = `\r\n<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 800 800\">\r\n\t<circle cx=\"400\" cy=\"400\" r=\"400\" fill=\"#fff\"/>\r\n\t<use transform=\"matrix(-1,0,0,1,800,0)\" xlink:href=\"#one-half\"/>\r\n\t<g id=\"one-half\">\r\n\t\t<g id=\"one-fourth\">\r\n\t\t\t<path d=\"m400 40v107\" stroke=\"#000\" stroke-width=\"26.7\"/>\r\n\t\t\t<g id=\"one-twelfth\">\r\n\t\t\t\t<path d=\"m580 88.233-42.5 73.612\" stroke=\"#000\" stroke-width=\"26.7\"/>\r\n\t\t\t\t<g id=\"one-thirtieth\">\r\n\t\t\t\t\t<path id=\"one-sixtieth\" d=\"m437.63 41.974-3.6585 34.808\" stroke=\"#000\" stroke-width=\"13.6\" />\r\n\t\t\t\t\t<use transform=\"rotate(6 400 400)\" xlink:href=\"#one-sixtieth\"/>\r\n\t\t\t\t</g>\r\n\t\t\t\t<use transform=\"rotate(12 400 400)\" xlink:href=\"#one-thirtieth\"/>\r\n\t\t\t</g>\r\n\t\t\t<use transform=\"rotate(30 400 400)\" xlink:href=\"#one-twelfth\"/>\r\n\t\t\t<use transform=\"rotate(60 400 400)\" xlink:href=\"#one-twelfth\"/>\r\n\t\t</g>\r\n\t\t<use transform=\"rotate(90 400 400)\" xlink:href=\"#one-fourth\"/>\r\n\t</g>\r\n\t<path class=\"clock-hour-hand\" id=\"anim-clock-hour-hand\" d=\"m 381.925,476 h 36.15 l 5e-4,-300.03008 L 400,156.25 381.9245,175.96992 Z\" transform=\"rotate(110.2650694444, 400, 400)\" />\r\n\t<path class=\"clock-minute-hand\" id=\"anim-clock-minute-hand\" d=\"M 412.063,496.87456 H 387.937 L 385.249,65.68306 400,52.75 414.751,65.68306 Z\" transform=\"rotate(243.1808333333, 400, 400)\" />\r\n</svg>\r\n`;\r\n","import { Component, inject, signal, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport {\r\n MAT_DIALOG_DATA,\r\n MatDialogRef,\r\n MatDialogModule,\r\n} from '@angular/material/dialog';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatRadioModule } from '@angular/material/radio';\r\nimport { MatSlideToggleModule } from '@angular/material/slide-toggle';\r\nimport { ClockWidgetState } from './clock-widget.component';\r\n\r\n@Component({\r\n selector: 'demo-clock-state-dialog',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n MatDialogModule,\r\n MatButtonModule,\r\n MatRadioModule,\r\n MatSlideToggleModule,\r\n ],\r\n template: `\r\n <h2 mat-dialog-title>Clock Settings</h2>\r\n <mat-dialog-content>\r\n <div class=\"mode-selection\">\r\n <label class=\"section-label\">Display Mode</label>\r\n <mat-radio-group\r\n [value]=\"mode()\"\r\n (change)=\"mode.set($any($event.value))\"\r\n >\r\n <mat-radio-button value=\"digital\">Digital</mat-radio-button>\r\n <mat-radio-button value=\"analog\">Analog</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n\r\n <!-- Time Format (only for digital mode) -->\r\n @if (mode() === 'digital') {\r\n <div class=\"format-selection\">\r\n <label class=\"section-label\">Time Format</label>\r\n <mat-radio-group\r\n [value]=\"timeFormat()\"\r\n (change)=\"timeFormat.set($any($event.value))\"\r\n >\r\n <mat-radio-button value=\"24h\">24 Hour (14:30:45)</mat-radio-button>\r\n <mat-radio-button value=\"12h\">12 Hour (2:30:45 PM)</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n\r\n <!-- Show Seconds Toggle (for both digital and analog modes) -->\r\n <div class=\"toggle-section\">\r\n <mat-slide-toggle \r\n [checked]=\"showSeconds()\"\r\n (change)=\"showSeconds.set($event.checked)\">\r\n Show Seconds\r\n </mat-slide-toggle>\r\n <span class=\"toggle-description\">\r\n @if (mode() === 'digital') {\r\n Display seconds in the time\r\n } @else {\r\n Show the second hand on the clock\r\n }\r\n </span>\r\n </div>\r\n\r\n <!-- Background Toggle -->\r\n <div class=\"toggle-section\">\r\n <mat-slide-toggle \r\n [checked]=\"hasBackground()\"\r\n (change)=\"hasBackground.set($event.checked)\">\r\n Background\r\n </mat-slide-toggle>\r\n <span class=\"toggle-description\"\r\n >Adds a background behind the clock</span\r\n >\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\">\r\n <button mat-button (click)=\"onCancel()\">Cancel</button>\r\n <button mat-flat-button (click)=\"save()\" [disabled]=\"!hasChanged()\">\r\n Save\r\n </button>\r\n </mat-dialog-actions>\r\n `,\r\n styles: [\r\n `\r\n mat-dialog-content {\r\n display: block;\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n }\r\n\r\n .mode-selection,\r\n .format-selection {\r\n margin-top: 1rem;\r\n margin-bottom: 2rem;\r\n }\r\n\r\n .section-label {\r\n display: block;\r\n margin-bottom: 0.75rem;\r\n font-weight: 500;\r\n }\r\n\r\n mat-radio-group {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0.75rem;\r\n }\r\n\r\n mat-radio-button {\r\n margin: 0;\r\n }\r\n\r\n /* Toggle section */\r\n .toggle-section {\r\n display: flex;\r\n align-items: center;\r\n gap: 0.75rem;\r\n margin-bottom: 0.5rem;\r\n }\r\n\r\n .toggle-description {\r\n margin: 0;\r\n }\r\n `,\r\n ],\r\n})\r\nexport class ClockStateDialogComponent {\r\n private readonly data = inject<ClockWidgetState>(MAT_DIALOG_DATA);\r\n private readonly dialogRef = inject(MatDialogRef<ClockStateDialogComponent>);\r\n\r\n // State signals\r\n readonly mode = signal<'analog' | 'digital'>(this.data.mode ?? 'digital');\r\n readonly hasBackground = signal<boolean>(this.data.hasBackground ?? true);\r\n readonly timeFormat = signal<'12h' | '24h'>(this.data.timeFormat ?? '24h');\r\n readonly showSeconds = signal<boolean>(this.data.showSeconds ?? true);\r\n\r\n // Store original values for comparison\r\n private readonly originalMode = this.data.mode ?? 'digital';\r\n private readonly originalHasBackground = this.data.hasBackground ?? true;\r\n private readonly originalTimeFormat = this.data.timeFormat ?? '24h';\r\n private readonly originalShowSeconds = this.data.showSeconds ?? true;\r\n\r\n // Computed values\r\n readonly hasChanged = computed(\r\n () =>\r\n this.mode() !== this.originalMode ||\r\n this.hasBackground() !== this.originalHasBackground ||\r\n this.timeFormat() !== this.originalTimeFormat ||\r\n this.showSeconds() !== this.originalShowSeconds\r\n );\r\n\r\n onCancel(): void {\r\n this.dialogRef.close();\r\n }\r\n\r\n save(): void {\r\n this.dialogRef.close({\r\n mode: this.mode(),\r\n hasBackground: this.hasBackground(),\r\n timeFormat: this.timeFormat(),\r\n showSeconds: this.showSeconds(),\r\n } as ClockWidgetState);\r\n }\r\n}","import { Component, inject, signal, computed, DestroyRef, input, ChangeDetectionStrategy } from '@angular/core';\r\n\r\nexport interface DigitalClockConfig {\r\n timeFormat: '12h' | '24h';\r\n showSeconds: boolean;\r\n hasBackground: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'ngx-digital-clock',\r\n standalone: true,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './digital-clock.component.html',\r\n styleUrl: './digital-clock.component.scss',\r\n host: {\r\n '[class.has-background]': 'hasBackground()',\r\n '[class.show-pm]': 'timeFormat() === \"12h\"',\r\n '[class.show-seconds]': 'showSeconds()',\r\n 'class': 'clock-widget digital'\r\n }\r\n})\r\nexport class DigitalClockComponent {\r\n readonly #destroyRef = inject(DestroyRef);\r\n\r\n // Inputs\r\n timeFormat = input<'12h' | '24h'>('24h');\r\n showSeconds = input<boolean>(true);\r\n hasBackground = input<boolean>(false);\r\n\r\n // Time tracking\r\n currentTime = signal(new Date());\r\n \r\n formattedTime = computed(() => {\r\n const time = this.currentTime();\r\n const format = this.timeFormat();\r\n const showSecs = this.showSeconds();\r\n return this.#formatTime(time, format, showSecs);\r\n });\r\n\r\n #intervalId: number | null = null;\r\n\r\n #formatTime(time: Date, format: '12h' | '24h', showSecs: boolean): string {\r\n let hours = time.getHours();\r\n const minutes = time.getMinutes();\r\n const seconds = time.getSeconds();\r\n \r\n // Pad with leading zeros\r\n const mm = minutes.toString().padStart(2, '0');\r\n const ss = seconds.toString().padStart(2, '0');\r\n \r\n if (format === '12h') {\r\n // 12-hour format with AM/PM\r\n const ampm = hours >= 12 ? 'PM' : 'AM';\r\n hours = hours % 12;\r\n if (hours === 0) hours = 12; // Convert 0 to 12 for 12 AM/PM\r\n \r\n const hh = hours.toString().padStart(2, '0');\r\n \r\n if (showSecs) {\r\n return `${hh}:${mm}:${ss} ${ampm}`;\r\n } else {\r\n return `${hh}:${mm} ${ampm}`;\r\n }\r\n } else {\r\n // 24-hour format\r\n const hh = hours.toString().padStart(2, '0');\r\n \r\n if (showSecs) {\r\n return `${hh}:${mm}:${ss}`;\r\n } else {\r\n return `${hh}:${mm}`;\r\n }\r\n }\r\n }\r\n\r\n constructor() {\r\n // Set up time update timer\r\n this.#startTimer();\r\n \r\n // Clean up timer on component destruction\r\n this.#destroyRef.onDestroy(() => {\r\n this.#stopTimer();\r\n });\r\n }\r\n\r\n #startTimer(): void {\r\n // Sync to the next second boundary for smooth start\r\n const now = new Date();\r\n const msUntilNextSecond = 1000 - now.getMilliseconds();\r\n \r\n setTimeout(() => {\r\n this.currentTime.set(new Date());\r\n \r\n // Start the regular 1-second interval\r\n this.#intervalId = window.setInterval(() => {\r\n this.currentTime.set(new Date());\r\n }, 1000);\r\n }, msUntilNextSecond);\r\n }\r\n\r\n #stopTimer(): void {\r\n if (this.#intervalId !== null) {\r\n clearInterval(this.#intervalId);\r\n this.#intervalId = null;\r\n }\r\n }\r\n}","<div class=\"digital-time\">{{ formattedTime() }}</div>","import { Component, ChangeDetectionStrategy, input, inject, signal, computed, DestroyRef, viewChild, ElementRef, Renderer2, effect } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'ngx-analog-clock',\r\n standalone: true,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './analog-clock.component.html',\r\n styleUrl: './analog-clock.component.scss',\r\n host: {\r\n '[class.has-background]': 'hasBackground()',\r\n '[class.show-seconds]': 'showSeconds()',\r\n 'class': 'clock-widget analog'\r\n }\r\n})\r\nexport class AnalogClockComponent {\r\n readonly #destroyRef = inject(DestroyRef);\r\n readonly #renderer = inject(Renderer2);\r\n\r\n // Inputs\r\n hasBackground = input<boolean>(false);\r\n showSeconds = input<boolean>(true);\r\n\r\n // ViewChild references for clock hands\r\n hourHand = viewChild<ElementRef<SVGPathElement>>('hourHand');\r\n minuteHand = viewChild<ElementRef<SVGPathElement>>('minuteHand');\r\n secondHand = viewChild<ElementRef<SVGPathElement>>('secondHand');\r\n\r\n // Time tracking\r\n currentTime = signal(new Date());\r\n\r\n // Computed rotation signals\r\n secondHandRotation = computed(() => {\r\n const seconds = this.currentTime().getSeconds();\r\n return seconds * 6; // 360° / 60s = 6° per second\r\n });\r\n\r\n minuteHandRotation = computed(() => {\r\n const time = this.currentTime();\r\n const minutes = time.getMinutes();\r\n const seconds = time.getSeconds();\r\n return minutes * 6 + seconds / 10; // Smooth minute hand movement\r\n });\r\n\r\n hourHandRotation = computed(() => {\r\n const time = this.currentTime();\r\n const hours = time.getHours() % 12;\r\n const minutes = time.getMinutes();\r\n const seconds = time.getSeconds();\r\n return hours * 30 + minutes / 2 + seconds / 120; // Smooth hour hand movement\r\n });\r\n\r\n #intervalId: number | null = null;\r\n\r\n constructor() {\r\n // Set up time update timer\r\n this.#startTimer();\r\n \r\n // Clean up timer on component destruction\r\n this.#destroyRef.onDestroy(() => {\r\n this.#stopTimer();\r\n });\r\n\r\n // Update DOM when rotations change\r\n effect(() => {\r\n this.#updateClockHands();\r\n });\r\n }\r\n\r\n #startTimer(): void {\r\n // Sync to the next second boundary for smooth start\r\n const now = new Date();\r\n const msUntilNextSecond = 1000 - now.getMilliseconds();\r\n \r\n setTimeout(() => {\r\n this.currentTime.set(new Date());\r\n \r\n // Start the regular 1-second interval\r\n this.#intervalId = window.setInterval(() => {\r\n this.currentTime.set(new Date());\r\n }, 1000);\r\n }, msUntilNextSecond);\r\n }\r\n\r\n #stopTimer(): void {\r\n if (this.#intervalId !== null) {\r\n clearInterval(this.#intervalId);\r\n this.#intervalId = null;\r\n }\r\n }\r\n\r\n #updateClockHands(): void {\r\n const hourElement = this.hourHand()?.nativeElement;\r\n const minuteElement = this.minuteHand()?.nativeElement;\r\n const secondElement = this.secondHand()?.nativeElement;\r\n\r\n if (hourElement) {\r\n this.#renderer.setAttribute(\r\n hourElement,\r\n 'transform',\r\n `rotate(${this.hourHandRotation()}, 400, 400)`\r\n );\r\n }\r\n\r\n if (minuteElement) {\r\n this.#renderer.setAttribute(\r\n minuteElement,\r\n 'transform',\r\n `rotate(${this.minuteHandRotation()}, 400, 400)`\r\n );\r\n }\r\n\r\n if (secondElement && this.showSeconds()) {\r\n this.#renderer.setAttribute(\r\n secondElement,\r\n 'transform',\r\n `rotate(${this.secondHandRotation()}, 400, 400)`\r\n );\r\n }\r\n }\r\n}","<div class=\"analog-clock-container\">\r\n <div class=\"aspect-ratio-box\">\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\r\n viewBox=\"0 0 800 800\"\r\n preserveAspectRatio=\"xMidYMid meet\"\r\n >\r\n <!-- <circle cx=\"400\" cy=\"400\" r=\"400\" fill=\"#fff\"/> -->\r\n <use transform=\"matrix(-1,0,0,1,800,0)\" xlink:href=\"#one-half\" />\r\n <g id=\"one-half\">\r\n <g id=\"one-fourth\">\r\n <path d=\"m400 40v107\" stroke=\"#000\" stroke-width=\"26.7\" />\r\n <g id=\"one-twelfth\">\r\n <path\r\n d=\"m580 88.233-42.5 73.612\"\r\n stroke=\"#000\"\r\n stroke-width=\"26.7\"\r\n />\r\n <g id=\"one-thirtieth\">\r\n <path\r\n id=\"one-sixtieth\"\r\n d=\"m437.63 41.974-3.6585 34.808\"\r\n stroke=\"#000\"\r\n stroke-width=\"13.6\"\r\n />\r\n <use transform=\"rotate(6 400 400)\" xlink:href=\"#one-sixtieth\" />\r\n </g>\r\n <use transform=\"rotate(12 400 400)\" xlink:href=\"#one-thirtieth\" />\r\n </g>\r\n <use transform=\"rotate(30 400 400)\" xlink:href=\"#one-twelfth\" />\r\n <use transform=\"rotate(60 400 400)\" xlink:href=\"#one-twelfth\" />\r\n </g>\r\n <use transform=\"rotate(90 400 400)\" xlink:href=\"#one-fourth\" />\r\n </g>\r\n <path\r\n class=\"clock-hour-hand\"\r\n id=\"anim-clock-hour-hand\"\r\n #hourHand\r\n d=\"m 381.925,476 h 36.15 l 5e-4,-300.03008 L 400,156.25 381.9245,175.96992 Z\"\r\n transform=\"rotate(110.2650694444, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-minute-hand\"\r\n id=\"anim-clock-minute-hand\"\r\n #minuteHand\r\n d=\"M 412.063,496.87456 H 387.937 L 385.249,65.68306 400,52.75 414.751,65.68306 Z\"\r\n transform=\"rotate(243.1808333333, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-second-hand\"\r\n id=\"anim-clock-second-hand\"\r\n #secondHand\r\n fill=\"#a40000\"\r\n d=\"M 397.317,63.51744 395.91962,168.4 C 374.575,170.5125 358.2,188.365 358.2,210 c 0,21.635 16.3,39 36.61214,41.47594 L 391.52847,498 h 16.94306 L 405.1868,251.47593 C 425.5,249 441.8,231.635 441.8,210 c 2e-5,-21.635 -16.375,-39.4875 -37.71971,-41.6 L 402.683,63.51744 400,60 Z M 400,190.534 c 10.888,0 19.466,8.866 19.466,19.466 0,10.6 -8.578,19.466 -19.466,19.466 -10.888,0 -19.466,-8.866 -19.466,-19.466 0,-10.6 8.578,-19.466 19.466,-19.466 z\"\r\n transform=\"rotate(190.85, 400, 400)\"\r\n />\r\n </svg>\r\n </div>\r\n</div>\r\n","// clock-widget.component.ts\r\nimport { Component, inject, signal } from '@angular/core';\r\nimport { Widget, WidgetMetadata } from '@dragonworks/ngx-dashboard';\r\nimport { svgIcon } from './clock-widget.metadata';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { ClockStateDialogComponent } from './clock-state-dialog.component';\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { DigitalClockComponent } from './digital-clock/digital-clock.component';\r\nimport { AnalogClockComponent } from './analog-clock/analog-clock.component';\r\n\r\nexport interface ClockWidgetState {\r\n mode: 'analog' | 'digital';\r\n hasBackground?: boolean;\r\n timeFormat?: '12h' | '24h';\r\n showSeconds?: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'ngx-dashboard-clock-widget',\r\n standalone: true,\r\n imports: [DigitalClockComponent, AnalogClockComponent],\r\n templateUrl: './clock-widget.component.html',\r\n styleUrl: './clock-widget.component.scss',\r\n})\r\nexport class ClockWidgetComponent implements Widget {\r\n static metadata: WidgetMetadata = {\r\n widgetTypeid: '@default/clock-widget',\r\n name: 'Clock',\r\n description: 'Display time in analog or digital format',\r\n svgIcon,\r\n };\r\n\r\n readonly #sanitizer = inject(DomSanitizer);\r\n readonly #dialog = inject(MatDialog);\r\n\r\n safeSvgIcon = this.#sanitizer.bypassSecurityTrustHtml(svgIcon);\r\n\r\n state = signal<ClockWidgetState>({\r\n mode: 'analog',\r\n hasBackground: true,\r\n timeFormat: '24h',\r\n showSeconds: true,\r\n });\r\n\r\n constructor() {\r\n // No timer logic needed - DigitalClock manages its own time\r\n }\r\n\r\n dashboardSetState(state?: unknown) {\r\n if (state) {\r\n this.state.update((current) => ({\r\n ...current,\r\n ...(state as ClockWidgetState),\r\n }));\r\n }\r\n }\r\n\r\n dashboardGetState(): ClockWidgetState {\r\n return { ...this.state() };\r\n }\r\n\r\n dashboardEditState(): void {\r\n const dialogRef = this.#dialog.open(ClockStateDialogComponent, {\r\n data: this.dashboardGetState(),\r\n width: '400px',\r\n maxWidth: '90vw',\r\n disableClose: false,\r\n autoFocus: false,\r\n });\r\n\r\n dialogRef\r\n .afterClosed()\r\n .subscribe((result: ClockWidgetState | undefined) => {\r\n if (result) {\r\n this.state.set(result);\r\n }\r\n });\r\n }\r\n\r\n get isAnalog(): boolean {\r\n return this.state().mode === 'analog';\r\n }\r\n\r\n get isDigital(): boolean {\r\n return this.state().mode === 'digital';\r\n }\r\n}\r\n","@if (isDigital) {\r\n <ngx-digital-clock\r\n [timeFormat]=\"state().timeFormat || '24h'\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n />\r\n} @else if (isAnalog) {\r\n <ngx-analog-clock\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n />\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 * Public API Surface of ngx-dashboard-widgets\r\n */\r\nexport * from './lib/arrow-widget/arrow-widget.component';\r\nexport * from './lib/label-widget/label-widget.component';\r\nexport * from './lib/clock-widget/clock-widget.component';\r\nexport * from './lib/directives/responsive-text.directive';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["svgIcon","i5","i6","i8","i2","i3","i4"],"mappings":"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"}
1
+ {"version":3,"file":"dragonworks-ngx-dashboard-widgets.mjs","sources":["../../../projects/ngx-dashboard-widgets/src/lib/arrow-widget/arrow-widget.metadata.ts","../../../projects/ngx-dashboard-widgets/src/lib/arrow-widget/arrow-state-dialog.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/arrow-widget/arrow-widget.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/arrow-widget/arrow-widget.component.html","../../../projects/ngx-dashboard-widgets/src/lib/label-widget/label-widget.metadata.ts","../../../projects/ngx-dashboard-widgets/src/lib/label-widget/label-state-dialog.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/directives/responsive-text.directive.ts","../../../projects/ngx-dashboard-widgets/src/lib/label-widget/label-widget.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/label-widget/label-widget.component.html","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/clock-widget.metadata.ts","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/clock-state-dialog.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/digital-clock/digital-clock.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/digital-clock/digital-clock.component.html","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/analog-clock/analog-clock.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/analog-clock/analog-clock.component.html","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/clock-widget.component.ts","../../../projects/ngx-dashboard-widgets/src/lib/clock-widget/clock-widget.component.html","../../../projects/ngx-dashboard-widgets/src/public-api.ts","../../../projects/ngx-dashboard-widgets/src/dragonworks-ngx-dashboard-widgets.ts"],"sourcesContent":["// arrow-widget.metadata.ts\r\nexport const svgIcon =\r\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"><path d=\"M320-120v-320H120l360-440 360 440H640v320H320Zm80-80h160v-320h111L480-754 289-520h111v320Zm80-320Z\"/></svg>';\r\n","import { Component, inject, signal, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport {\r\n MAT_DIALOG_DATA,\r\n MatDialogRef,\r\n MatDialogModule,\r\n} from '@angular/material/dialog';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { ArrowWidgetState } from './arrow-widget.component';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatSelectModule } from '@angular/material/select';\r\nimport { MatSliderModule } from '@angular/material/slider';\r\nimport { MatSlideToggleModule } from '@angular/material/slide-toggle';\r\n\r\n@Component({\r\n selector: 'lib-arrow-state-dialog',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n MatDialogModule,\r\n MatButtonModule,\r\n MatFormFieldModule,\r\n MatSelectModule,\r\n MatSliderModule,\r\n MatSlideToggleModule,\r\n ],\r\n template: `\r\n <h2 mat-dialog-title>Arrow Settings</h2>\r\n <mat-dialog-content>\r\n <!-- Direction Selection -->\r\n <mat-form-field appearance=\"outline\" class=\"direction-field\">\r\n <mat-label>Arrow Direction</mat-label>\r\n <mat-select\r\n [value]=\"direction()\"\r\n (selectionChange)=\"direction.set($any($event.value))\"\r\n >\r\n <mat-option value=\"up\">Up</mat-option>\r\n <mat-option value=\"right\">Right</mat-option>\r\n <mat-option value=\"down\">Down</mat-option>\r\n <mat-option value=\"left\">Left</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- Opacity Slider -->\r\n <div class=\"slider-field\">\r\n <div class=\"field-label\">Opacity: {{ formatOpacity(opacity()) }}%</div>\r\n <mat-slider [min]=\"0.1\" [max]=\"1\" [step]=\"0.1\">\r\n <input matSliderThumb [(ngModel)]=\"opacity\" />\r\n </mat-slider>\r\n </div>\r\n\r\n <!-- Background Toggle -->\r\n <div class=\"toggle-field\">\r\n <mat-slide-toggle \r\n [checked]=\"hasBackground()\"\r\n (change)=\"onBackgroundToggle($event.checked)\">\r\n Background\r\n </mat-slide-toggle>\r\n <span class=\"toggle-hint\">Adds a background behind the arrow</span>\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\">\r\n <button mat-button (click)=\"onCancel()\">Cancel</button>\r\n <button mat-flat-button (click)=\"save()\" [disabled]=\"!hasChanged()\">\r\n Save\r\n </button>\r\n </mat-dialog-actions>\r\n `,\r\n styles: [\r\n `\r\n mat-dialog-content {\r\n display: block;\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n }\r\n\r\n mat-form-field {\r\n width: 100%;\r\n display: block;\r\n margin-bottom: 1rem;\r\n }\r\n\r\n .direction-field {\r\n margin-top: 1rem;\r\n }\r\n\r\n /* Opacity slider section */\r\n .slider-field {\r\n margin-bottom: 1.5rem;\r\n margin-right: 1rem;\r\n }\r\n\r\n .field-label {\r\n display: block;\r\n margin-bottom: 0.5rem;\r\n }\r\n\r\n mat-slider {\r\n width: 100%;\r\n display: block;\r\n }\r\n\r\n /* Toggle section */\r\n .toggle-field {\r\n display: flex;\r\n align-items: center;\r\n gap: 0.75rem;\r\n margin-bottom: 0.5rem;\r\n }\r\n\r\n .toggle-hint {\r\n margin: 0;\r\n }\r\n `,\r\n ],\r\n})\r\nexport class ArrowStateDialogComponent {\r\n private readonly data = inject<ArrowWidgetState>(MAT_DIALOG_DATA);\r\n private readonly dialogRef = inject(MatDialogRef<ArrowStateDialogComponent>);\r\n\r\n // State signals\r\n readonly direction = signal<'left' | 'up' | 'right' | 'down'>(\r\n this.data.direction\r\n );\r\n readonly opacity = signal<number>(this.data.opacity ?? 1);\r\n readonly hasBackground = signal<boolean>(this.data.hasBackground ?? true);\r\n readonly transparentBackground = signal<boolean>(!(this.data.hasBackground ?? true));\r\n\r\n // Store original values for comparison\r\n private readonly originalDirection = this.data.direction;\r\n private readonly originalOpacity = this.data.opacity ?? 1;\r\n private readonly originalHasBackground = this.data.hasBackground ?? true;\r\n\r\n // Computed values\r\n readonly rotation = computed(() => {\r\n const rotationMap = {\r\n up: 0,\r\n right: 90,\r\n down: 180,\r\n left: 270,\r\n };\r\n return rotationMap[this.direction()];\r\n });\r\n\r\n readonly rotationTransform = computed(() => `rotate(${this.rotation()}deg)`);\r\n\r\n readonly directionName = computed(() => {\r\n const nameMap = {\r\n up: 'Up',\r\n right: 'Right',\r\n down: 'Down',\r\n left: 'Left',\r\n };\r\n return nameMap[this.direction()];\r\n });\r\n\r\n readonly hasChanged = computed(\r\n () =>\r\n this.direction() !== this.originalDirection ||\r\n this.opacity() !== this.originalOpacity ||\r\n this.hasBackground() !== this.originalHasBackground\r\n );\r\n\r\n formatOpacity(value: number): number {\r\n return Math.round(value * 100);\r\n }\r\n\r\n onBackgroundToggle(hasBackground: boolean): void {\r\n this.hasBackground.set(hasBackground);\r\n this.transparentBackground.set(!hasBackground);\r\n }\r\n\r\n onCancel(): void {\r\n this.dialogRef.close();\r\n }\r\n\r\n save(): void {\r\n this.dialogRef.close({\r\n direction: this.direction(),\r\n opacity: this.opacity(),\r\n hasBackground: this.hasBackground(),\r\n } as ArrowWidgetState);\r\n }\r\n}\r\n","// arrow-widget.component.ts\r\nimport { Component, inject, signal, computed } from '@angular/core';\r\nimport { Widget, WidgetMetadata } from '@dragonworks/ngx-dashboard';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { svgIcon } from './arrow-widget.metadata';\r\nimport { ArrowStateDialogComponent } from './arrow-state-dialog.component';\r\n\r\nexport interface ArrowWidgetState {\r\n direction: 'left' | 'up' | 'right' | 'down';\r\n opacity?: number;\r\n hasBackground?: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'ngx-dashboard-arrow-widget',\r\n imports: [],\r\n templateUrl: './arrow-widget.component.html',\r\n styleUrl: './arrow-widget.component.scss',\r\n})\r\nexport class ArrowWidgetComponent implements Widget {\r\n static metadata: WidgetMetadata = {\r\n widgetTypeid: '@default/arrow-widget',\r\n name: 'Arrow',\r\n description: 'A generic arrow',\r\n svgIcon,\r\n };\r\n\r\n readonly #sanitizer = inject(DomSanitizer);\r\n readonly #dialog = inject(MatDialog);\r\n\r\n readonly safeSvgIcon = this.#sanitizer.bypassSecurityTrustHtml(svgIcon);\r\n\r\n readonly state = signal<ArrowWidgetState>({\r\n direction: 'up',\r\n opacity: 0.3,\r\n hasBackground: true,\r\n });\r\n // Computed rotation\r\n readonly rotationAngle = computed(() => {\r\n const rotationMap = {\r\n up: 0,\r\n right: 90,\r\n down: 180,\r\n left: 270,\r\n };\r\n return rotationMap[this.state().direction];\r\n });\r\n\r\n dashboardSetState(state?: unknown): void {\r\n if (state) {\r\n this.state.update((current) => ({\r\n ...current,\r\n ...(state as ArrowWidgetState),\r\n }));\r\n }\r\n }\r\n\r\n dashboardGetState(): ArrowWidgetState {\r\n return this.state();\r\n }\r\n\r\n dashboardEditState(): void {\r\n const dialogRef = this.#dialog.open(ArrowStateDialogComponent, {\r\n data: this.state(),\r\n width: '400px',\r\n maxWidth: '90vw',\r\n disableClose: false,\r\n autoFocus: false,\r\n });\r\n\r\n dialogRef.afterClosed().subscribe((result) => {\r\n if (result) {\r\n this.state.set(result);\r\n }\r\n });\r\n }\r\n}\r\n","<!-- arrow-widget.component.html -->\r\n<div class=\"svg-wrapper\" [class.has-background]=\"state().hasBackground\">\r\n <div\r\n class=\"svg-placeholder\"\r\n [innerHTML]=\"safeSvgIcon\"\r\n [style.transform]=\"'rotate(' + rotationAngle() + 'deg)'\"\r\n [style.opacity]=\"state().opacity\"\r\n ></div>\r\n</div>\r\n","// label-widget.metadata.ts\r\nexport const svgIcon =\r\n '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\"><path d=\"M280-280h280v-80H280v80Zm0-160h400v-80H280v80Zm0-160h400v-80H280v80Zm-80 480q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm0-560v560-560Z\"/></svg>';\r\n","import { Component, inject, signal, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport {\r\n MAT_DIALOG_DATA,\r\n MatDialogRef,\r\n MatDialogModule,\r\n} from '@angular/material/dialog';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatSelectModule } from '@angular/material/select';\r\nimport { MatSliderModule } from '@angular/material/slider';\r\nimport { MatSlideToggleModule } from '@angular/material/slide-toggle'; // Add this import\r\nimport { LabelWidgetState } from './label-widget.component';\r\n\r\n@Component({\r\n selector: 'lib-label-state-dialog',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n MatDialogModule,\r\n MatButtonModule,\r\n MatFormFieldModule,\r\n MatInputModule,\r\n MatSelectModule,\r\n MatSliderModule,\r\n MatSlideToggleModule, // Add this import\r\n ],\r\n template: `\r\n <h2 mat-dialog-title>Label Settings</h2>\r\n <mat-dialog-content>\r\n <mat-form-field appearance=\"outline\" class=\"label-text-field\">\r\n <mat-label>Label Text</mat-label>\r\n <input\r\n matInput\r\n type=\"text\"\r\n [value]=\"label()\"\r\n (input)=\"label.set($any($event.target).value)\"\r\n placeholder=\"Enter your label text...\"\r\n />\r\n </mat-form-field>\r\n\r\n <!-- Responsive Text Toggle -->\r\n <div class=\"toggle-section\">\r\n <mat-slide-toggle \r\n [checked]=\"responsive()\"\r\n (change)=\"responsive.set($event.checked)\">\r\n Responsive Text\r\n </mat-slide-toggle>\r\n <span class=\"toggle-description\"\r\n >Automatically adjust text size to fit the widget</span\r\n >\r\n </div>\r\n\r\n <!-- Responsive Font Size Constraints (only shown when responsive is enabled) -->\r\n @if (responsive()) {\r\n <div class=\"responsive-section\">\r\n <div class=\"section-label\">Font Size Limits</div>\r\n <div class=\"row-layout\">\r\n <mat-form-field appearance=\"outline\">\r\n <mat-label>Min Size (px)</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [value]=\"minFontSize()\"\r\n (input)=\"validateAndCorrectMinFontSize(+$any($event.target).value)\"\r\n (blur)=\"validateAndCorrectMinFontSize(minFontSize())\"\r\n min=\"8\"\r\n max=\"24\"\r\n placeholder=\"8\"\r\n />\r\n @if (!isMinFontSizeValid() || !isFontSizeRangeValid()) {\r\n <mat-error>\r\n @if (!isMinFontSizeValid()) {\r\n Must be between 8-24px\r\n } @else {\r\n Must be less than max size\r\n }\r\n </mat-error>\r\n } @else {\r\n <mat-hint>8-24px range</mat-hint>\r\n }\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\">\r\n <mat-label>Max Size (px)</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [value]=\"maxFontSize()\"\r\n (input)=\"validateAndCorrectMaxFontSize(+$any($event.target).value)\"\r\n (blur)=\"validateAndCorrectMaxFontSize(maxFontSize())\"\r\n min=\"16\"\r\n max=\"128\"\r\n placeholder=\"64\"\r\n />\r\n @if (!isMaxFontSizeValid() || !isFontSizeRangeValid()) {\r\n <mat-error>\r\n @if (!isMaxFontSizeValid()) {\r\n Must be between 16-128px\r\n } @else {\r\n Must be greater than min size\r\n }\r\n </mat-error>\r\n } @else {\r\n <mat-hint>16-128px range</mat-hint>\r\n }\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div class=\"row-layout\">\r\n <mat-form-field appearance=\"outline\">\r\n <mat-label>Font Size (px)</mat-label>\r\n <input\r\n matInput\r\n type=\"number\"\r\n [value]=\"fontSize()\"\r\n (input)=\"fontSize.set(+$any($event.target).value)\"\r\n [disabled]=\"responsive()\"\r\n min=\"8\"\r\n max=\"48\"\r\n placeholder=\"16\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\">\r\n <mat-label>Alignment</mat-label>\r\n <mat-select\r\n [value]=\"alignment()\"\r\n (selectionChange)=\"alignment.set($any($event.value))\"\r\n >\r\n <mat-option value=\"left\">Left</mat-option>\r\n <mat-option value=\"center\">Center</mat-option>\r\n <mat-option value=\"right\">Right</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <mat-form-field appearance=\"outline\">\r\n <mat-label>Font Weight</mat-label>\r\n <mat-select\r\n [value]=\"fontWeight()\"\r\n (selectionChange)=\"fontWeight.set($any($event.value))\"\r\n >\r\n <mat-option value=\"normal\">Normal</mat-option>\r\n <mat-option value=\"bold\">Bold</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- Opacity Slider -->\r\n <div class=\"slider-section\">\r\n <div class=\"slider-label\">Opacity: {{ formatOpacity(opacity()) }}%</div>\r\n <mat-slider [min]=\"0.1\" [max]=\"1\" [step]=\"0.1\">\r\n <input matSliderThumb [(ngModel)]=\"opacity\" />\r\n </mat-slider>\r\n </div>\r\n\r\n <!-- Background Toggle -->\r\n <div class=\"toggle-section\">\r\n <mat-slide-toggle \r\n [checked]=\"!transparentBackground()\"\r\n (change)=\"onBackgroundToggle($event.checked)\">\r\n Background\r\n </mat-slide-toggle>\r\n <span class=\"toggle-description\"\r\n >Adds a background behind the text</span\r\n >\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\">\r\n <button mat-button (click)=\"onCancel()\">Cancel</button>\r\n <button mat-flat-button (click)=\"save()\" [disabled]=\"!hasChanged() || !isFormValid()\">\r\n Save\r\n </button>\r\n </mat-dialog-actions>\r\n `,\r\n styles: [\r\n `\r\n mat-dialog-content {\r\n display: block;\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n }\r\n\r\n mat-form-field {\r\n width: 100%;\r\n display: block;\r\n margin-bottom: 1rem;\r\n }\r\n\r\n .label-text-field {\r\n margin-top: 1rem;\r\n }\r\n\r\n /* Side-by-side layout for font size and alignment */\r\n .row-layout {\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: 1rem;\r\n margin-bottom: 1rem;\r\n }\r\n\r\n .row-layout mat-form-field {\r\n margin-bottom: 0;\r\n }\r\n\r\n /* Opacity slider section */\r\n .slider-section {\r\n margin-bottom: 1.5rem;\r\n margin-right: 1rem;\r\n }\r\n\r\n .slider-label {\r\n display: block;\r\n margin-bottom: 0.5rem;\r\n }\r\n\r\n mat-slider {\r\n width: 100%;\r\n display: block;\r\n }\r\n\r\n /* Toggle section */\r\n .toggle-section {\r\n display: flex;\r\n align-items: center;\r\n gap: 0.75rem;\r\n margin-bottom: 1rem;\r\n }\r\n\r\n .toggle-description {\r\n margin: 0;\r\n }\r\n\r\n /* Responsive font size section */\r\n .responsive-section {\r\n margin-bottom: 1.5rem;\r\n padding: 1rem;\r\n border-radius: 12px;\r\n background-color: var(--mat-app-surface-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), 0.05));\r\n border: 1px solid var(--mat-app-outline-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), 0.12));\r\n }\r\n\r\n .section-label {\r\n display: block;\r\n margin-bottom: 0.75rem;\r\n font-weight: 500;\r\n color: var(--mat-app-on-surface-variant, rgba(var(--mat-app-on-surface-rgb, 0, 0, 0), 0.6));\r\n }\r\n\r\n /* Ensure responsive section row layout has no bottom margin */\r\n .responsive-section .row-layout {\r\n margin-bottom: 0;\r\n }\r\n `,\r\n ],\r\n})\r\nexport class LabelStateDialogComponent {\r\n private readonly data = inject<LabelWidgetState>(MAT_DIALOG_DATA);\r\n private readonly dialogRef = inject(MatDialogRef<LabelStateDialogComponent>);\r\n\r\n // State signals\r\n readonly label = signal<string>(this.data.label ?? '');\r\n readonly fontSize = signal<number>(this.data.fontSize ?? 16);\r\n readonly alignment = signal<'left' | 'center' | 'right'>(\r\n this.data.alignment ?? 'center'\r\n );\r\n readonly fontWeight = signal<'normal' | 'bold'>(\r\n this.data.fontWeight ?? 'normal'\r\n );\r\n readonly opacity = signal<number>(this.data.opacity ?? 1);\r\n readonly hasBackground = signal<boolean>(this.data.hasBackground ?? true);\r\n readonly transparentBackground = signal<boolean>(!(this.data.hasBackground ?? true));\r\n readonly responsive = signal<boolean>(this.data.responsive ?? false);\r\n // Responsive font size constraints\r\n readonly minFontSize = signal<number>(this.data.minFontSize ?? 8);\r\n readonly maxFontSize = signal<number>(this.data.maxFontSize ?? 64);\r\n\r\n // Store original values for comparison\r\n private readonly originalLabel = this.data.label ?? '';\r\n private readonly originalFontSize = this.data.fontSize ?? 16;\r\n private readonly originalAlignment = this.data.alignment ?? 'center';\r\n private readonly originalFontWeight = this.data.fontWeight ?? 'normal';\r\n private readonly originalOpacity = this.data.opacity ?? 1;\r\n private readonly originalHasBackground = this.data.hasBackground ?? true;\r\n private readonly originalResponsive = this.data.responsive ?? false;\r\n private readonly originalMinFontSize = this.data.minFontSize ?? 8;\r\n private readonly originalMaxFontSize = this.data.maxFontSize ?? 64;\r\n\r\n // Validation computed properties\r\n readonly isMinFontSizeValid = computed(() => {\r\n const min = this.minFontSize();\r\n return min >= 8 && min <= 24;\r\n });\r\n\r\n readonly isMaxFontSizeValid = computed(() => {\r\n const max = this.maxFontSize();\r\n return max >= 16 && max <= 128;\r\n });\r\n\r\n readonly isFontSizeRangeValid = computed(() =>\r\n this.minFontSize() < this.maxFontSize()\r\n );\r\n\r\n readonly isFormValid = computed(() =>\r\n this.isMinFontSizeValid() &&\r\n this.isMaxFontSizeValid() &&\r\n this.isFontSizeRangeValid()\r\n );\r\n\r\n // Computed values\r\n readonly hasChanged = computed(\r\n () =>\r\n this.label() !== this.originalLabel ||\r\n this.fontSize() !== this.originalFontSize ||\r\n this.alignment() !== this.originalAlignment ||\r\n this.fontWeight() !== this.originalFontWeight ||\r\n this.opacity() !== this.originalOpacity ||\r\n this.hasBackground() !== this.originalHasBackground ||\r\n this.responsive() !== this.originalResponsive ||\r\n this.minFontSize() !== this.originalMinFontSize ||\r\n this.maxFontSize() !== this.originalMaxFontSize\r\n );\r\n\r\n formatOpacity(value: number): number {\r\n return Math.round(value * 100);\r\n }\r\n\r\n formatOpacitySlider = (value: number): string => {\r\n return `${Math.round(value * 100)}%`;\r\n };\r\n\r\n // Validation methods with robust min < max enforcement\r\n validateAndCorrectMinFontSize(value: number): void {\r\n // Clamp to valid range\r\n const corrected = Math.max(8, Math.min(24, value));\r\n this.minFontSize.set(corrected);\r\n \r\n // Ensure min < max with adequate gap\r\n if (corrected >= this.maxFontSize()) {\r\n const newMax = Math.min(128, corrected + 8); // Ensure at least 8px gap\r\n this.maxFontSize.set(newMax);\r\n }\r\n }\r\n\r\n validateAndCorrectMaxFontSize(value: number): void {\r\n // Clamp to valid range\r\n const corrected = Math.max(16, Math.min(128, value));\r\n this.maxFontSize.set(corrected);\r\n \r\n // Ensure min < max with adequate gap\r\n if (corrected <= this.minFontSize()) {\r\n const newMin = Math.max(8, corrected - 8); // Ensure at least 8px gap\r\n this.minFontSize.set(newMin);\r\n }\r\n }\r\n\r\n onBackgroundToggle(hasWhiteBackground: boolean): void {\r\n this.hasBackground.set(hasWhiteBackground);\r\n this.transparentBackground.set(!hasWhiteBackground);\r\n }\r\n\r\n onCancel(): void {\r\n this.dialogRef.close();\r\n }\r\n\r\n save(): void {\r\n this.dialogRef.close({\r\n label: this.label(),\r\n fontSize: this.fontSize(),\r\n alignment: this.alignment(),\r\n fontWeight: this.fontWeight(),\r\n opacity: this.opacity(),\r\n hasBackground: this.hasBackground(),\r\n responsive: this.responsive(),\r\n minFontSize: this.minFontSize(),\r\n maxFontSize: this.maxFontSize(),\r\n } as LabelWidgetState);\r\n }\r\n}\r\n","import {\r\n Directive,\r\n ElementRef,\r\n AfterViewInit,\r\n OnDestroy,\r\n inject,\r\n DestroyRef,\r\n numberAttribute,\r\n booleanAttribute,\r\n input,\r\n} from '@angular/core';\r\nimport { NgZone, PLATFORM_ID } from '@angular/core';\r\nimport { isPlatformBrowser } from '@angular/common';\r\n\r\n/**\r\n * Directive that automatically adjusts font size to fit text within its parent container.\r\n * Uses canvas-based measurement for performance and DOM verification for accuracy.\r\n *\r\n * @example\r\n * <div class=\"container\">\r\n * <span responsiveText [minFontSize]=\"12\" [maxFontSize]=\"72\">Dynamic text here</span>\r\n * </div>\r\n */\r\n@Directive({\r\n selector: '[responsiveText]',\r\n standalone: true,\r\n host: {\r\n '[style.display]': '\"block\"',\r\n '[style.width]': '\"100%\"',\r\n '[style.white-space]': '\"nowrap\"',\r\n '[style.overflow]': '\"visible\"',\r\n },\r\n})\r\nexport class ResponsiveTextDirective implements AfterViewInit, OnDestroy {\r\n /* ───────────────────────── Inputs with transforms ─────────────── */\r\n /** Minimum font-size in pixels (accessibility floor) */\r\n minFontSize = input(8, { transform: numberAttribute });\r\n\r\n /** Maximum font-size in pixels (layout ceiling) */\r\n maxFontSize = input(512, { transform: numberAttribute });\r\n\r\n /**\r\n * Line-height: pass a multiplier (e.g. 1.1) or absolute px value.\r\n * For single-line text a multiplier < 10 is treated as unitless.\r\n */\r\n lineHeight = input(1.1, { transform: numberAttribute });\r\n\r\n /** Whether to observe text mutations after first render */\r\n observeMutations = input(true, { transform: booleanAttribute });\r\n\r\n /** Debounce delay in ms for resize/mutation callbacks */\r\n debounceMs = input(16, { transform: numberAttribute });\r\n\r\n /* ───────────────────────── Private state ───────────────────────── */\r\n private readonly el = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly zone = inject(NgZone);\r\n private readonly platformId = inject(PLATFORM_ID);\r\n private readonly destroyRef = inject(DestroyRef);\r\n\r\n // Canvas context - lazy initialization\r\n private _ctx?: CanvasRenderingContext2D;\r\n private get ctx(): CanvasRenderingContext2D {\r\n if (!this._ctx) {\r\n const canvas = document.createElement('canvas');\r\n this._ctx = canvas.getContext('2d', {\r\n willReadFrequently: true,\r\n alpha: false,\r\n })!;\r\n }\r\n return this._ctx;\r\n }\r\n\r\n private ro?: ResizeObserver;\r\n private mo?: MutationObserver;\r\n private fitTimeout?: number;\r\n\r\n // Cache for performance\r\n private lastText = '';\r\n private lastMaxW = 0;\r\n private lastMaxH = 0;\r\n private lastFontSize = 0;\r\n\r\n /* ───────────────────────── Lifecycle ──────────────────────────── */\r\n ngAfterViewInit() {\r\n if (!isPlatformBrowser(this.platformId)) return;\r\n\r\n // Set initial styles\r\n const span = this.el.nativeElement;\r\n span.style.transition = 'font-size 0.1s ease-out';\r\n\r\n // All observer callbacks run outside Angular's zone\r\n this.zone.runOutsideAngular(() => {\r\n this.fit();\r\n this.observeResize();\r\n if (this.observeMutations()) {\r\n this.observeText();\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.cleanup();\r\n }\r\n\r\n /* ───────────────────── Core fitting logic ───────────────────── */\r\n /**\r\n * Debounced fit handler to prevent excessive recalculations\r\n */\r\n private requestFit = () => {\r\n if (this.fitTimeout) {\r\n cancelAnimationFrame(this.fitTimeout);\r\n }\r\n\r\n this.fitTimeout = requestAnimationFrame(() => {\r\n this.fit();\r\n });\r\n };\r\n\r\n /**\r\n * Recalculate & apply the ideal font-size\r\n */\r\n private fit = () => {\r\n const span = this.el.nativeElement;\r\n const parent = span.parentElement;\r\n\r\n if (!parent) return;\r\n\r\n const text = span.textContent?.trim() || '';\r\n if (!text) {\r\n span.style.fontSize = `${this.minFontSize()}px`;\r\n return;\r\n }\r\n\r\n const { maxW, maxH } = this.getAvailableSpace(parent);\r\n\r\n // Check cache to avoid redundant calculations\r\n if (\r\n text === this.lastText &&\r\n maxW === this.lastMaxW &&\r\n maxH === this.lastMaxH &&\r\n this.lastFontSize > 0\r\n ) {\r\n return;\r\n }\r\n\r\n // Calculate with conservative buffer for sub-pixel accuracy\r\n const ideal = this.calcFit(text, maxW * 0.98, maxH * 0.98);\r\n\r\n span.style.fontSize = `${ideal}px`;\r\n\r\n // DOM verification pass\r\n this.verifyFit(span, maxW, maxH, ideal);\r\n\r\n // Update cache\r\n this.lastText = text;\r\n this.lastMaxW = maxW;\r\n this.lastMaxH = maxH;\r\n this.lastFontSize = parseFloat(span.style.fontSize);\r\n };\r\n\r\n /**\r\n * Calculate available space accounting for padding and borders\r\n */\r\n private getAvailableSpace(parent: HTMLElement): {\r\n maxW: number;\r\n maxH: number;\r\n } {\r\n const cs = getComputedStyle(parent);\r\n const maxW =\r\n parent.clientWidth -\r\n parseFloat(cs.paddingLeft) -\r\n parseFloat(cs.paddingRight);\r\n const maxH =\r\n parent.clientHeight -\r\n parseFloat(cs.paddingTop) -\r\n parseFloat(cs.paddingBottom);\r\n\r\n return { maxW: Math.max(0, maxW), maxH: Math.max(0, maxH) };\r\n }\r\n\r\n /**\r\n * DOM-based verification to handle sub-pixel discrepancies\r\n */\r\n private verifyFit(\r\n span: HTMLElement,\r\n maxW: number,\r\n maxH: number,\r\n ideal: number\r\n ) {\r\n // Simple synchronous verification\r\n if (span.scrollWidth > maxW || span.scrollHeight > maxH) {\r\n let safe = ideal;\r\n let iterations = 0;\r\n const maxIterations = 10;\r\n\r\n while (\r\n iterations < maxIterations &&\r\n safe > this.minFontSize() &&\r\n (span.scrollWidth > maxW || span.scrollHeight > maxH)\r\n ) {\r\n safe -= 0.25;\r\n span.style.fontSize = `${safe}px`;\r\n iterations++;\r\n }\r\n\r\n // Update cache with verified size\r\n this.lastFontSize = safe;\r\n }\r\n }\r\n\r\n /* ───────────────────── Binary search algorithm ────────────────── */\r\n /**\r\n * Binary search for optimal font size using canvas measurements\r\n */\r\n private calcFit(\r\n text: string,\r\n maxW: number,\r\n maxH: number,\r\n precision = 0.1\r\n ): number {\r\n if (maxW <= 0 || maxH <= 0) return this.minFontSize();\r\n\r\n const computedStyle = getComputedStyle(this.el.nativeElement);\r\n const fontFamily = computedStyle.fontFamily || 'sans-serif';\r\n const fontWeight = computedStyle.fontWeight || '400';\r\n\r\n let lo = this.minFontSize();\r\n let hi = this.maxFontSize();\r\n let bestFit = this.minFontSize();\r\n\r\n while (hi - lo > precision) {\r\n const mid = (hi + lo) / 2;\r\n this.ctx.font = `${fontWeight} ${mid}px ${fontFamily}`;\r\n\r\n const metrics = this.ctx.measureText(text);\r\n const width = metrics.width;\r\n\r\n // Calculate height based on available metrics\r\n const height = this.calculateTextHeight(metrics, mid);\r\n\r\n if (width <= maxW && height <= maxH) {\r\n bestFit = mid;\r\n lo = mid;\r\n } else {\r\n hi = mid;\r\n }\r\n }\r\n\r\n return Math.floor(bestFit * 100) / 100;\r\n }\r\n\r\n /**\r\n * Calculate text height from metrics\r\n */\r\n private calculateTextHeight(metrics: TextMetrics, fontSize: number): number {\r\n // Use font bounding box metrics if available\r\n if (metrics.fontBoundingBoxAscent && metrics.fontBoundingBoxDescent) {\r\n return metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;\r\n }\r\n\r\n // Fallback to actual bounding box\r\n if (metrics.actualBoundingBoxAscent && metrics.actualBoundingBoxDescent) {\r\n return metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;\r\n }\r\n\r\n // Final fallback using line height\r\n return this.lineHeight() < 10\r\n ? fontSize * this.lineHeight()\r\n : this.lineHeight();\r\n }\r\n\r\n /* ───────────────────────── Observers ─────────────────────────── */\r\n /**\r\n * Observe parent container resizes\r\n */\r\n private observeResize() {\r\n if (!('ResizeObserver' in window)) return;\r\n\r\n this.ro = new ResizeObserver((entries) => {\r\n // Only trigger if size actually changed\r\n const entry = entries[0];\r\n if (entry?.contentRect) {\r\n this.requestFit();\r\n }\r\n });\r\n\r\n const parent = this.el.nativeElement.parentElement;\r\n if (parent) {\r\n this.ro.observe(parent);\r\n }\r\n }\r\n\r\n /**\r\n * Observe text content changes\r\n */\r\n private observeText() {\r\n if (!('MutationObserver' in window)) return;\r\n\r\n this.mo = new MutationObserver((mutations) => {\r\n // Check if text actually changed\r\n const hasTextChange = mutations.some(\r\n (m) =>\r\n m.type === 'characterData' ||\r\n (m.type === 'childList' &&\r\n (m.addedNodes.length > 0 || m.removedNodes.length > 0))\r\n );\r\n\r\n if (hasTextChange) {\r\n this.requestFit();\r\n }\r\n });\r\n\r\n this.mo.observe(this.el.nativeElement, {\r\n characterData: true,\r\n childList: true,\r\n subtree: true,\r\n });\r\n }\r\n\r\n /**\r\n * Cleanup resources\r\n */\r\n private cleanup() {\r\n this.ro?.disconnect();\r\n this.mo?.disconnect();\r\n\r\n if (this.fitTimeout) {\r\n cancelAnimationFrame(this.fitTimeout);\r\n }\r\n\r\n // Clear canvas context\r\n this._ctx = undefined;\r\n }\r\n}\r\n","// label-widget.component.ts\r\nimport { Component, inject, signal, computed } from '@angular/core';\r\nimport { Widget, WidgetMetadata } from '@dragonworks/ngx-dashboard';\r\nimport { svgIcon } from './label-widget.metadata';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { LabelStateDialogComponent } from './label-state-dialog.component';\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { ResponsiveTextDirective } from '../directives/responsive-text.directive';\r\n\r\nexport interface LabelWidgetState {\r\n label: string;\r\n fontSize?: number;\r\n alignment?: 'left' | 'center' | 'right';\r\n fontWeight?: 'normal' | 'bold';\r\n opacity?: number;\r\n hasBackground?: boolean;\r\n responsive?: boolean;\r\n // Font size constraints for responsive text (px values)\r\n minFontSize?: number; // Default: 8px (accessible minimum)\r\n maxFontSize?: number; // Default: 64px (practical widget maximum)\r\n}\r\n\r\n@Component({\r\n selector: 'ngx-dashboard-label-widget',\r\n imports: [ResponsiveTextDirective],\r\n templateUrl: './label-widget.component.html',\r\n styleUrl: './label-widget.component.scss',\r\n})\r\nexport class LabelWidgetComponent implements Widget {\r\n static metadata: WidgetMetadata = {\r\n widgetTypeid: '@default/label-widget',\r\n name: 'Label',\r\n description: 'A generic text label',\r\n svgIcon,\r\n };\r\n\r\n readonly #sanitizer = inject(DomSanitizer);\r\n readonly #dialog = inject(MatDialog);\r\n\r\n safeSvgIcon = this.#sanitizer.bypassSecurityTrustHtml(svgIcon);\r\n\r\n state = signal<LabelWidgetState>({\r\n label: '',\r\n fontSize: 16,\r\n alignment: 'center',\r\n fontWeight: 'normal',\r\n opacity: 1,\r\n hasBackground: true,\r\n responsive: false,\r\n minFontSize: 8, // Accessible minimum for responsive text\r\n maxFontSize: 64, // Practical maximum for widget display\r\n });\r\n\r\n dashboardSetState(state?: unknown) {\r\n if (state) {\r\n this.state.update((current) => ({\r\n ...current,\r\n ...(state as LabelWidgetState),\r\n }));\r\n }\r\n }\r\n\r\n dashboardGetState(): LabelWidgetState {\r\n return { ...this.state() };\r\n }\r\n\r\n dashboardEditState(): void {\r\n const dialogRef = this.#dialog.open(LabelStateDialogComponent, {\r\n data: this.dashboardGetState(),\r\n width: '400px',\r\n maxWidth: '90vw',\r\n disableClose: false,\r\n autoFocus: false,\r\n });\r\n\r\n dialogRef\r\n .afterClosed()\r\n .subscribe((result: LabelWidgetState | undefined) => {\r\n if (result) {\r\n this.state.set(result);\r\n }\r\n });\r\n }\r\n\r\n get hasContent(): boolean {\r\n return !!this.state().label?.trim();\r\n }\r\n\r\n get label(): string {\r\n return this.state().label?.trim();\r\n }\r\n\r\n // Computed properties for responsive font size limits with fallbacks\r\n readonly minFontSize = computed(() => this.state().minFontSize ?? 8);\r\n readonly maxFontSize = computed(() => this.state().maxFontSize ?? 64);\r\n}\r\n","@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\" responsiveText [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","export const svgIcon = `\r\n<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 800 800\" preserveAspectRatio=\"xMidYMid meet\">\r\n <use transform=\"matrix(-1,0,0,1,800,0)\" href=\"#one-half\" />\r\n <g id=\"one-half\">\r\n <g id=\"one-fourth\">\r\n <path d=\"m400 40v107\" stroke-width=\"26.7\" stroke=\"currentColor\" />\r\n <g id=\"one-twelfth\">\r\n <path\r\n d=\"m580 88.233-42.5 73.612\"\r\n stroke-width=\"26.7\"\r\n stroke=\"currentColor\"\r\n />\r\n <g id=\"one-thirtieth\">\r\n <path\r\n id=\"one-sixtieth\"\r\n d=\"m437.63 41.974-3.6585 34.808\"\r\n stroke-width=\"13.6\"\r\n stroke=\"currentColor\"\r\n />\r\n <use transform=\"rotate(6 400 400)\" href=\"#one-sixtieth\" />\r\n </g>\r\n <use transform=\"rotate(12 400 400)\" href=\"#one-thirtieth\" />\r\n </g>\r\n <use transform=\"rotate(30 400 400)\" href=\"#one-twelfth\" />\r\n <use transform=\"rotate(60 400 400)\" href=\"#one-twelfth\" />\r\n </g>\r\n <use transform=\"rotate(90 400 400)\" href=\"#one-fourth\" />\r\n </g>\r\n <path\r\n class=\"clock-hour-hand\"\r\n id=\"anim-clock-hour-hand\"\r\n d=\"m 381.925,476 h 36.15 l 5e-4,-300.03008 L 400,156.25 381.9245,175.96992 Z\"\r\n transform=\"rotate(110.2650694444, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-minute-hand\"\r\n id=\"anim-clock-minute-hand\"\r\n d=\"M 412.063,496.87456 H 387.937 L 385.249,65.68306 400,52.75 414.751,65.68306 Z\"\r\n transform=\"rotate(243.1808333333, 400, 400)\"\r\n />\r\n</svg>\r\n`;\r\n","import { Component, inject, signal, computed } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { FormsModule } from '@angular/forms';\r\nimport {\r\n MAT_DIALOG_DATA,\r\n MatDialogRef,\r\n MatDialogModule,\r\n} from '@angular/material/dialog';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatRadioModule } from '@angular/material/radio';\r\nimport { MatSlideToggleModule } from '@angular/material/slide-toggle';\r\nimport { ClockWidgetState } from './clock-widget.component';\r\n\r\n@Component({\r\n selector: 'demo-clock-state-dialog',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n MatDialogModule,\r\n MatButtonModule,\r\n MatRadioModule,\r\n MatSlideToggleModule,\r\n ],\r\n template: `\r\n <h2 mat-dialog-title>Clock Settings</h2>\r\n <mat-dialog-content>\r\n <div class=\"mode-selection\">\r\n <label class=\"section-label\">Display Mode</label>\r\n <mat-radio-group\r\n [value]=\"mode()\"\r\n (change)=\"mode.set($any($event.value))\"\r\n >\r\n <mat-radio-button value=\"digital\">Digital</mat-radio-button>\r\n <mat-radio-button value=\"analog\">Analog</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n\r\n <!-- Time Format (only for digital mode) -->\r\n @if (mode() === 'digital') {\r\n <div class=\"format-selection\">\r\n <label class=\"section-label\">Time Format</label>\r\n <mat-radio-group\r\n [value]=\"timeFormat()\"\r\n (change)=\"timeFormat.set($any($event.value))\"\r\n >\r\n <mat-radio-button value=\"24h\">24 Hour (14:30:45)</mat-radio-button>\r\n <mat-radio-button value=\"12h\">12 Hour (2:30:45 PM)</mat-radio-button>\r\n </mat-radio-group>\r\n </div>\r\n }\r\n\r\n <!-- Show Seconds Toggle (for both digital and analog modes) -->\r\n <div class=\"toggle-section\">\r\n <mat-slide-toggle \r\n [checked]=\"showSeconds()\"\r\n (change)=\"showSeconds.set($event.checked)\">\r\n Show Seconds\r\n </mat-slide-toggle>\r\n <span class=\"toggle-description\">\r\n @if (mode() === 'digital') {\r\n Display seconds in the time\r\n } @else {\r\n Show the second hand on the clock\r\n }\r\n </span>\r\n </div>\r\n\r\n <!-- Background Toggle -->\r\n <div class=\"toggle-section\">\r\n <mat-slide-toggle \r\n [checked]=\"hasBackground()\"\r\n (change)=\"hasBackground.set($event.checked)\">\r\n Background\r\n </mat-slide-toggle>\r\n <span class=\"toggle-description\"\r\n >Adds a background behind the clock</span\r\n >\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\">\r\n <button mat-button (click)=\"onCancel()\">Cancel</button>\r\n <button mat-flat-button (click)=\"save()\" [disabled]=\"!hasChanged()\">\r\n Save\r\n </button>\r\n </mat-dialog-actions>\r\n `,\r\n styles: [\r\n `\r\n mat-dialog-content {\r\n display: block;\r\n overflow-y: auto;\r\n overflow-x: hidden;\r\n }\r\n\r\n .mode-selection,\r\n .format-selection {\r\n margin-top: 1rem;\r\n margin-bottom: 2rem;\r\n }\r\n\r\n .section-label {\r\n display: block;\r\n margin-bottom: 0.75rem;\r\n font-weight: 500;\r\n }\r\n\r\n mat-radio-group {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0.75rem;\r\n }\r\n\r\n mat-radio-button {\r\n margin: 0;\r\n }\r\n\r\n /* Toggle section */\r\n .toggle-section {\r\n display: flex;\r\n align-items: center;\r\n gap: 0.75rem;\r\n margin-bottom: 0.5rem;\r\n }\r\n\r\n .toggle-description {\r\n margin: 0;\r\n }\r\n `,\r\n ],\r\n})\r\nexport class ClockStateDialogComponent {\r\n private readonly data = inject<ClockWidgetState>(MAT_DIALOG_DATA);\r\n private readonly dialogRef = inject(MatDialogRef<ClockStateDialogComponent>);\r\n\r\n // State signals\r\n readonly mode = signal<'analog' | 'digital'>(this.data.mode ?? 'digital');\r\n readonly hasBackground = signal<boolean>(this.data.hasBackground ?? true);\r\n readonly timeFormat = signal<'12h' | '24h'>(this.data.timeFormat ?? '24h');\r\n readonly showSeconds = signal<boolean>(this.data.showSeconds ?? true);\r\n\r\n // Store original values for comparison\r\n private readonly originalMode = this.data.mode ?? 'digital';\r\n private readonly originalHasBackground = this.data.hasBackground ?? true;\r\n private readonly originalTimeFormat = this.data.timeFormat ?? '24h';\r\n private readonly originalShowSeconds = this.data.showSeconds ?? true;\r\n\r\n // Computed values\r\n readonly hasChanged = computed(\r\n () =>\r\n this.mode() !== this.originalMode ||\r\n this.hasBackground() !== this.originalHasBackground ||\r\n this.timeFormat() !== this.originalTimeFormat ||\r\n this.showSeconds() !== this.originalShowSeconds\r\n );\r\n\r\n onCancel(): void {\r\n this.dialogRef.close();\r\n }\r\n\r\n save(): void {\r\n this.dialogRef.close({\r\n mode: this.mode(),\r\n hasBackground: this.hasBackground(),\r\n timeFormat: this.timeFormat(),\r\n showSeconds: this.showSeconds(),\r\n } as ClockWidgetState);\r\n }\r\n}","import {\r\n Component,\r\n inject,\r\n signal,\r\n computed,\r\n DestroyRef,\r\n input,\r\n ChangeDetectionStrategy,\r\n} from '@angular/core';\r\n\r\nexport interface DigitalClockConfig {\r\n timeFormat: '12h' | '24h';\r\n showSeconds: boolean;\r\n hasBackground: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'ngx-digital-clock',\r\n standalone: true,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './digital-clock.component.html',\r\n styleUrl: './digital-clock.component.scss',\r\n host: {\r\n '[class.has-background]': 'hasBackground()',\r\n '[class.show-pm]': 'timeFormat() === \"12h\"',\r\n '[class.show-seconds]': 'showSeconds()',\r\n class: 'clock-widget digital',\r\n },\r\n})\r\nexport class DigitalClockComponent {\r\n readonly #destroyRef = inject(DestroyRef);\r\n\r\n // Inputs\r\n timeFormat = input<'12h' | '24h'>('24h');\r\n showSeconds = input<boolean>(true);\r\n hasBackground = input<boolean>(false);\r\n\r\n // Time tracking\r\n currentTime = signal(new Date());\r\n\r\n formattedTime = computed(() => {\r\n const time = this.currentTime();\r\n const format = this.timeFormat();\r\n const showSecs = this.showSeconds();\r\n return this.#formatTime(time, format, showSecs);\r\n });\r\n\r\n #intervalId: number | null = null;\r\n\r\n #formatTime(time: Date, format: '12h' | '24h', showSecs: boolean): string {\r\n let hours = time.getHours();\r\n const minutes = time.getMinutes();\r\n const seconds = time.getSeconds();\r\n\r\n // Pad with leading zeros\r\n const mm = minutes.toString().padStart(2, '0');\r\n const ss = seconds.toString().padStart(2, '0');\r\n\r\n if (format === '12h') {\r\n // 12-hour format with AM/PM\r\n const ampm = hours >= 12 ? 'PM' : 'AM';\r\n hours = hours % 12;\r\n if (hours === 0) hours = 12; // Convert 0 to 12 for 12 AM/PM\r\n\r\n const hh = hours.toString().padStart(2, '0');\r\n return showSecs ? `${hh}:${mm}:${ss} ${ampm}` : `${hh}:${mm} ${ampm}`;\r\n } else {\r\n // 24-hour format\r\n const hh = hours.toString().padStart(2, '0');\r\n return showSecs ? `${hh}:${mm}:${ss}` : `${hh}:${mm}`;\r\n }\r\n }\r\n\r\n constructor() {\r\n // Set up time update timer\r\n this.#startTimer();\r\n\r\n // Clean up timer on component destruction\r\n this.#destroyRef.onDestroy(() => {\r\n this.#stopTimer();\r\n });\r\n }\r\n\r\n #startTimer(): void {\r\n // Sync to the next second boundary for smooth start\r\n const now = new Date();\r\n const msUntilNextSecond = 1000 - now.getMilliseconds();\r\n\r\n setTimeout(() => {\r\n this.currentTime.set(new Date());\r\n\r\n // Start the regular 1-second interval\r\n this.#intervalId = window.setInterval(() => {\r\n this.currentTime.set(new Date());\r\n }, 1000);\r\n }, msUntilNextSecond);\r\n }\r\n\r\n #stopTimer(): void {\r\n if (this.#intervalId !== null) {\r\n clearInterval(this.#intervalId);\r\n this.#intervalId = null;\r\n }\r\n }\r\n}\r\n","<div responsiveText class=\"digital-time\">{{ formattedTime() }}</div>\r\n","import { Component, ChangeDetectionStrategy, input, inject, signal, computed, DestroyRef, viewChild, ElementRef, Renderer2, effect } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'ngx-analog-clock',\r\n standalone: true,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n templateUrl: './analog-clock.component.html',\r\n styleUrl: './analog-clock.component.scss',\r\n host: {\r\n '[class.has-background]': 'hasBackground()',\r\n '[class.show-seconds]': 'showSeconds()',\r\n 'class': 'clock-widget analog'\r\n }\r\n})\r\nexport class AnalogClockComponent {\r\n readonly #destroyRef = inject(DestroyRef);\r\n readonly #renderer = inject(Renderer2);\r\n\r\n // Inputs\r\n hasBackground = input<boolean>(false);\r\n showSeconds = input<boolean>(true);\r\n\r\n // ViewChild references for clock hands\r\n hourHand = viewChild<ElementRef<SVGPathElement>>('hourHand');\r\n minuteHand = viewChild<ElementRef<SVGPathElement>>('minuteHand');\r\n secondHand = viewChild<ElementRef<SVGPathElement>>('secondHand');\r\n\r\n // Time tracking\r\n currentTime = signal(new Date());\r\n\r\n // Computed rotation signals\r\n secondHandRotation = computed(() => {\r\n const seconds = this.currentTime().getSeconds();\r\n return seconds * 6; // 360° / 60s = 6° per second\r\n });\r\n\r\n minuteHandRotation = computed(() => {\r\n const time = this.currentTime();\r\n const minutes = time.getMinutes();\r\n const seconds = time.getSeconds();\r\n return minutes * 6 + seconds / 10; // Smooth minute hand movement\r\n });\r\n\r\n hourHandRotation = computed(() => {\r\n const time = this.currentTime();\r\n const hours = time.getHours() % 12;\r\n const minutes = time.getMinutes();\r\n const seconds = time.getSeconds();\r\n return hours * 30 + minutes / 2 + seconds / 120; // Smooth hour hand movement\r\n });\r\n\r\n #intervalId: number | null = null;\r\n\r\n constructor() {\r\n // Set up time update timer\r\n this.#startTimer();\r\n \r\n // Clean up timer on component destruction\r\n this.#destroyRef.onDestroy(() => {\r\n this.#stopTimer();\r\n });\r\n\r\n // Update DOM when rotations change\r\n effect(() => {\r\n this.#updateClockHands();\r\n });\r\n }\r\n\r\n #startTimer(): void {\r\n // Sync to the next second boundary for smooth start\r\n const now = new Date();\r\n const msUntilNextSecond = 1000 - now.getMilliseconds();\r\n \r\n setTimeout(() => {\r\n this.currentTime.set(new Date());\r\n \r\n // Start the regular 1-second interval\r\n this.#intervalId = window.setInterval(() => {\r\n this.currentTime.set(new Date());\r\n }, 1000);\r\n }, msUntilNextSecond);\r\n }\r\n\r\n #stopTimer(): void {\r\n if (this.#intervalId !== null) {\r\n clearInterval(this.#intervalId);\r\n this.#intervalId = null;\r\n }\r\n }\r\n\r\n #updateClockHands(): void {\r\n const hourElement = this.hourHand()?.nativeElement;\r\n const minuteElement = this.minuteHand()?.nativeElement;\r\n const secondElement = this.secondHand()?.nativeElement;\r\n\r\n if (hourElement) {\r\n this.#renderer.setAttribute(\r\n hourElement,\r\n 'transform',\r\n `rotate(${this.hourHandRotation()}, 400, 400)`\r\n );\r\n }\r\n\r\n if (minuteElement) {\r\n this.#renderer.setAttribute(\r\n minuteElement,\r\n 'transform',\r\n `rotate(${this.minuteHandRotation()}, 400, 400)`\r\n );\r\n }\r\n\r\n if (secondElement && this.showSeconds()) {\r\n this.#renderer.setAttribute(\r\n secondElement,\r\n 'transform',\r\n `rotate(${this.secondHandRotation()}, 400, 400)`\r\n );\r\n }\r\n }\r\n}","<div class=\"analog-clock-container\">\r\n <div class=\"aspect-ratio-box\">\r\n <svg\r\n version=\"1.1\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox=\"0 0 800 800\"\r\n preserveAspectRatio=\"xMidYMid meet\"\r\n >\r\n <!-- Optional face circle; uncomment if you want a visible outline by default -->\r\n <!-- <circle cx=\"400\" cy=\"400\" r=\"400\" fill=\"transparent\" stroke=\"currentColor\" stroke-width=\"2\" /> -->\r\n\r\n <use transform=\"matrix(-1,0,0,1,800,0)\" href=\"#one-half\" />\r\n <g id=\"one-half\">\r\n <g id=\"one-fourth\">\r\n <!-- 12 / 3 / 6 / 9 heavy marks -->\r\n <path d=\"m400 40v107\" stroke-width=\"26.7\" stroke=\"currentColor\" />\r\n <g id=\"one-twelfth\">\r\n <!-- 30° heavy marks -->\r\n <path\r\n d=\"m580 88.233-42.5 73.612\"\r\n stroke-width=\"26.7\"\r\n stroke=\"currentColor\"\r\n />\r\n <g id=\"one-thirtieth\">\r\n <!-- minute/second ticks -->\r\n <path\r\n id=\"one-sixtieth\"\r\n d=\"m437.63 41.974-3.6585 34.808\"\r\n stroke-width=\"13.6\"\r\n stroke=\"currentColor\"\r\n />\r\n <use transform=\"rotate(6 400 400)\" href=\"#one-sixtieth\" />\r\n </g>\r\n <use transform=\"rotate(12 400 400)\" href=\"#one-thirtieth\" />\r\n </g>\r\n <use transform=\"rotate(30 400 400)\" href=\"#one-twelfth\" />\r\n <use transform=\"rotate(60 400 400)\" href=\"#one-twelfth\" />\r\n </g>\r\n <use transform=\"rotate(90 400 400)\" href=\"#one-fourth\" />\r\n </g>\r\n\r\n <!-- Hands -->\r\n <path\r\n class=\"clock-hour-hand\"\r\n id=\"anim-clock-hour-hand\"\r\n #hourHand\r\n d=\"m 381.925,476 h 36.15 l 5e-4,-300.03008 L 400,156.25 381.9245,175.96992 Z\"\r\n transform=\"rotate(110.2650694444, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-minute-hand\"\r\n id=\"anim-clock-minute-hand\"\r\n #minuteHand\r\n d=\"M 412.063,496.87456 H 387.937 L 385.249,65.68306 400,52.75 414.751,65.68306 Z\"\r\n transform=\"rotate(243.1808333333, 400, 400)\"\r\n />\r\n <path\r\n class=\"clock-second-hand\"\r\n id=\"anim-clock-second-hand\"\r\n #secondHand\r\n d=\"M 397.317,63.51744 395.91962,168.4 C 374.575,170.5125 358.2,188.365 358.2,210 c 0,21.635 16.3,39 36.61214,41.47594 L 391.52847,498 h 16.94306 L 405.1868,251.47593 C 425.5,249 441.8,231.635 441.8,210 c 2e-5,-21.635 -16.375,-39.4875 -37.71971,-41.6 L 402.683,63.51744 400,60 Z M 400,190.534 c 10.888,0 19.466,8.866 19.466,19.466 0,10.6 -8.578,19.466 -19.466,19.466 -10.888,0 -19.466,-8.866 -19.466,-19.466 0,-10.6 8.578,-19.466 19.466,-19.466 z\"\r\n transform=\"rotate(190.85, 400, 400)\"\r\n />\r\n </svg>\r\n </div>\r\n</div>\r\n","// clock-widget.component.ts\r\nimport { Component, inject, signal } from '@angular/core';\r\nimport { Widget, WidgetMetadata } from '@dragonworks/ngx-dashboard';\r\nimport { svgIcon } from './clock-widget.metadata';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { ClockStateDialogComponent } from './clock-state-dialog.component';\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { DigitalClockComponent } from './digital-clock/digital-clock.component';\r\nimport { AnalogClockComponent } from './analog-clock/analog-clock.component';\r\n\r\nexport interface ClockWidgetState {\r\n mode: 'analog' | 'digital';\r\n hasBackground?: boolean;\r\n timeFormat?: '12h' | '24h';\r\n showSeconds?: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'ngx-dashboard-clock-widget',\r\n standalone: true,\r\n imports: [DigitalClockComponent, AnalogClockComponent],\r\n templateUrl: './clock-widget.component.html',\r\n styleUrl: './clock-widget.component.scss',\r\n})\r\nexport class ClockWidgetComponent implements Widget {\r\n static metadata: WidgetMetadata = {\r\n widgetTypeid: '@default/clock-widget',\r\n name: 'Clock',\r\n description: 'Display time in analog or digital format',\r\n svgIcon,\r\n };\r\n\r\n readonly #sanitizer = inject(DomSanitizer);\r\n readonly #dialog = inject(MatDialog);\r\n\r\n safeSvgIcon = this.#sanitizer.bypassSecurityTrustHtml(svgIcon);\r\n\r\n state = signal<ClockWidgetState>({\r\n mode: 'analog',\r\n hasBackground: true,\r\n timeFormat: '24h',\r\n showSeconds: true,\r\n });\r\n\r\n constructor() {\r\n // No timer logic needed - DigitalClock manages its own time\r\n }\r\n\r\n dashboardSetState(state?: unknown) {\r\n if (state) {\r\n this.state.update((current) => ({\r\n ...current,\r\n ...(state as ClockWidgetState),\r\n }));\r\n }\r\n }\r\n\r\n dashboardGetState(): ClockWidgetState {\r\n return { ...this.state() };\r\n }\r\n\r\n dashboardEditState(): void {\r\n const dialogRef = this.#dialog.open(ClockStateDialogComponent, {\r\n data: this.dashboardGetState(),\r\n width: '400px',\r\n maxWidth: '90vw',\r\n disableClose: false,\r\n autoFocus: false,\r\n });\r\n\r\n dialogRef\r\n .afterClosed()\r\n .subscribe((result: ClockWidgetState | undefined) => {\r\n if (result) {\r\n this.state.set(result);\r\n }\r\n });\r\n }\r\n\r\n get isAnalog(): boolean {\r\n return this.state().mode === 'analog';\r\n }\r\n\r\n get isDigital(): boolean {\r\n return this.state().mode === 'digital';\r\n }\r\n}\r\n","@if (isDigital) {\r\n <ngx-digital-clock\r\n [timeFormat]=\"state().timeFormat || '24h'\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n />\r\n} @else if (isAnalog) {\r\n <ngx-analog-clock\r\n [hasBackground]=\"state().hasBackground ?? false\"\r\n [showSeconds]=\"state().showSeconds ?? true\"\r\n />\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 * Public API Surface of ngx-dashboard-widgets\r\n */\r\nexport * from './lib/arrow-widget/arrow-widget.component';\r\nexport * from './lib/label-widget/label-widget.component';\r\nexport * from './lib/clock-widget/clock-widget.component';\r\nexport * from './lib/directives/responsive-text.directive';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["svgIcon","i5","i6","i8","i2","i3","i4"],"mappings":"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"}
package/index.d.ts CHANGED
@@ -29,6 +29,8 @@ interface LabelWidgetState {
29
29
  opacity?: number;
30
30
  hasBackground?: boolean;
31
31
  responsive?: boolean;
32
+ minFontSize?: number;
33
+ maxFontSize?: number;
32
34
  }
33
35
  declare class LabelWidgetComponent implements Widget {
34
36
  #private;
@@ -40,6 +42,8 @@ declare class LabelWidgetComponent implements Widget {
40
42
  dashboardEditState(): void;
41
43
  get hasContent(): boolean;
42
44
  get label(): string;
45
+ readonly minFontSize: _angular_core.Signal<number>;
46
+ readonly maxFontSize: _angular_core.Signal<number>;
43
47
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<LabelWidgetComponent, never>;
44
48
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<LabelWidgetComponent, "ngx-dashboard-label-widget", never, {}, {}, never, never, true, never>;
45
49
  }
@@ -71,14 +75,14 @@ declare class ClockWidgetComponent implements Widget {
71
75
  *
72
76
  * @example
73
77
  * <div class="container">
74
- * <span responsiveText [min]="12" [max]="72">Dynamic text here</span>
78
+ * <span responsiveText [minFontSize]="12" [maxFontSize]="72">Dynamic text here</span>
75
79
  * </div>
76
80
  */
77
81
  declare class ResponsiveTextDirective implements AfterViewInit, OnDestroy {
78
82
  /** Minimum font-size in pixels (accessibility floor) */
79
- min: _angular_core.InputSignalWithTransform<number, unknown>;
83
+ minFontSize: _angular_core.InputSignalWithTransform<number, unknown>;
80
84
  /** Maximum font-size in pixels (layout ceiling) */
81
- max: _angular_core.InputSignalWithTransform<number, unknown>;
85
+ maxFontSize: _angular_core.InputSignalWithTransform<number, unknown>;
82
86
  /**
83
87
  * Line-height: pass a multiplier (e.g. 1.1) or absolute px value.
84
88
  * For single-line text a multiplier < 10 is treated as unitless.
@@ -140,7 +144,7 @@ declare class ResponsiveTextDirective implements AfterViewInit, OnDestroy {
140
144
  */
141
145
  private cleanup;
142
146
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<ResponsiveTextDirective, never>;
143
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ResponsiveTextDirective, "[responsiveText]", never, { "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "lineHeight": { "alias": "lineHeight"; "required": false; "isSignal": true; }; "observeMutations": { "alias": "observeMutations"; "required": false; "isSignal": true; }; "debounceMs": { "alias": "debounceMs"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
147
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ResponsiveTextDirective, "[responsiveText]", never, { "minFontSize": { "alias": "minFontSize"; "required": false; "isSignal": true; }; "maxFontSize": { "alias": "maxFontSize"; "required": false; "isSignal": true; }; "lineHeight": { "alias": "lineHeight"; "required": false; "isSignal": true; }; "observeMutations": { "alias": "observeMutations"; "required": false; "isSignal": true; }; "debounceMs": { "alias": "debounceMs"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
144
148
  }
145
149
 
146
150
  export { ArrowWidgetComponent, ClockWidgetComponent, LabelWidgetComponent, ResponsiveTextDirective };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dragonworks/ngx-dashboard-widgets",
3
- "version": "20.0.4",
3
+ "version": "20.0.5",
4
4
  "description": "Widget collection for ngx-dashboard with Material Design 3 compliance including arrow, label, clock widgets and responsive text directive",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^20.0.0",
@@ -20,7 +20,7 @@
20
20
  "bugs": {
21
21
  "url": "https://github.com/TobyBackstrom/ngx-dashboard/issues"
22
22
  },
23
- "homepage": "https://github.com/TobyBackstrom/ngx-dashboard#readme",
23
+ "homepage": "https://dragonworks.dev",
24
24
  "keywords": [
25
25
  "angular",
26
26
  "dashboard",