@dragonworks/ngx-dashboard-widgets 20.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +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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"}
package/index.d.ts ADDED
@@ -0,0 +1,147 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { AfterViewInit, OnDestroy } from '@angular/core';
3
+ import * as _angular_platform_browser from '@angular/platform-browser';
4
+ import { Widget, WidgetMetadata } from '@dragonworks/ngx-dashboard';
5
+
6
+ interface ArrowWidgetState {
7
+ direction: 'left' | 'up' | 'right' | 'down';
8
+ opacity?: number;
9
+ hasBackground?: boolean;
10
+ }
11
+ declare class ArrowWidgetComponent implements Widget {
12
+ #private;
13
+ static metadata: WidgetMetadata;
14
+ readonly safeSvgIcon: _angular_platform_browser.SafeHtml;
15
+ readonly state: _angular_core.WritableSignal<ArrowWidgetState>;
16
+ readonly rotationAngle: _angular_core.Signal<number>;
17
+ dashboardSetState(state?: unknown): void;
18
+ dashboardGetState(): ArrowWidgetState;
19
+ dashboardEditState(): void;
20
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ArrowWidgetComponent, never>;
21
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ArrowWidgetComponent, "ngx-dashboard-arrow-widget", never, {}, {}, never, never, true, never>;
22
+ }
23
+
24
+ interface LabelWidgetState {
25
+ label: string;
26
+ fontSize?: number;
27
+ alignment?: 'left' | 'center' | 'right';
28
+ fontWeight?: 'normal' | 'bold';
29
+ opacity?: number;
30
+ hasBackground?: boolean;
31
+ responsive?: boolean;
32
+ }
33
+ declare class LabelWidgetComponent implements Widget {
34
+ #private;
35
+ static metadata: WidgetMetadata;
36
+ safeSvgIcon: _angular_platform_browser.SafeHtml;
37
+ state: _angular_core.WritableSignal<LabelWidgetState>;
38
+ dashboardSetState(state?: unknown): void;
39
+ dashboardGetState(): LabelWidgetState;
40
+ dashboardEditState(): void;
41
+ get hasContent(): boolean;
42
+ get label(): string;
43
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<LabelWidgetComponent, never>;
44
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LabelWidgetComponent, "ngx-dashboard-label-widget", never, {}, {}, never, never, true, never>;
45
+ }
46
+
47
+ interface ClockWidgetState {
48
+ mode: 'analog' | 'digital';
49
+ hasBackground?: boolean;
50
+ timeFormat?: '12h' | '24h';
51
+ showSeconds?: boolean;
52
+ }
53
+ declare class ClockWidgetComponent implements Widget {
54
+ #private;
55
+ static metadata: WidgetMetadata;
56
+ safeSvgIcon: _angular_platform_browser.SafeHtml;
57
+ state: _angular_core.WritableSignal<ClockWidgetState>;
58
+ constructor();
59
+ dashboardSetState(state?: unknown): void;
60
+ dashboardGetState(): ClockWidgetState;
61
+ dashboardEditState(): void;
62
+ get isAnalog(): boolean;
63
+ get isDigital(): boolean;
64
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ClockWidgetComponent, never>;
65
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ClockWidgetComponent, "ngx-dashboard-clock-widget", never, {}, {}, never, never, true, never>;
66
+ }
67
+
68
+ /**
69
+ * Directive that automatically adjusts font size to fit text within its parent container.
70
+ * Uses canvas-based measurement for performance and DOM verification for accuracy.
71
+ *
72
+ * @example
73
+ * <div class="container">
74
+ * <span responsiveText [min]="12" [max]="72">Dynamic text here</span>
75
+ * </div>
76
+ */
77
+ declare class ResponsiveTextDirective implements AfterViewInit, OnDestroy {
78
+ /** Minimum font-size in pixels (accessibility floor) */
79
+ min: _angular_core.InputSignalWithTransform<number, unknown>;
80
+ /** Maximum font-size in pixels (layout ceiling) */
81
+ max: _angular_core.InputSignalWithTransform<number, unknown>;
82
+ /**
83
+ * Line-height: pass a multiplier (e.g. 1.1) or absolute px value.
84
+ * For single-line text a multiplier < 10 is treated as unitless.
85
+ */
86
+ lineHeight: _angular_core.InputSignalWithTransform<number, unknown>;
87
+ /** Whether to observe text mutations after first render */
88
+ observeMutations: _angular_core.InputSignalWithTransform<boolean, unknown>;
89
+ /** Debounce delay in ms for resize/mutation callbacks */
90
+ debounceMs: _angular_core.InputSignalWithTransform<number, unknown>;
91
+ private readonly el;
92
+ private readonly zone;
93
+ private readonly platformId;
94
+ private readonly destroyRef;
95
+ private _ctx?;
96
+ private get ctx();
97
+ private ro?;
98
+ private mo?;
99
+ private fitTimeout?;
100
+ private lastText;
101
+ private lastMaxW;
102
+ private lastMaxH;
103
+ private lastFontSize;
104
+ ngAfterViewInit(): void;
105
+ ngOnDestroy(): void;
106
+ /**
107
+ * Debounced fit handler to prevent excessive recalculations
108
+ */
109
+ private requestFit;
110
+ /**
111
+ * Recalculate & apply the ideal font-size
112
+ */
113
+ private fit;
114
+ /**
115
+ * Calculate available space accounting for padding and borders
116
+ */
117
+ private getAvailableSpace;
118
+ /**
119
+ * DOM-based verification to handle sub-pixel discrepancies
120
+ */
121
+ private verifyFit;
122
+ /**
123
+ * Binary search for optimal font size using canvas measurements
124
+ */
125
+ private calcFit;
126
+ /**
127
+ * Calculate text height from metrics
128
+ */
129
+ private calculateTextHeight;
130
+ /**
131
+ * Observe parent container resizes
132
+ */
133
+ private observeResize;
134
+ /**
135
+ * Observe text content changes
136
+ */
137
+ private observeText;
138
+ /**
139
+ * Cleanup resources
140
+ */
141
+ private cleanup;
142
+ 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>;
144
+ }
145
+
146
+ export { ArrowWidgetComponent, ClockWidgetComponent, LabelWidgetComponent, ResponsiveTextDirective };
147
+ export type { ArrowWidgetState, ClockWidgetState, LabelWidgetState };
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@dragonworks/ngx-dashboard-widgets",
3
+ "version": "20.0.0",
4
+ "peerDependencies": {
5
+ "@angular/common": "^20.0.0",
6
+ "@angular/core": "^20.0.0",
7
+ "@dragonworks/ngx-dashboard": "^20.0.0"
8
+ },
9
+ "dependencies": {
10
+ "tslib": "^2.3.0"
11
+ },
12
+ "sideEffects": false,
13
+ "module": "fesm2022/dragonworks-ngx-dashboard-widgets.mjs",
14
+ "typings": "index.d.ts",
15
+ "exports": {
16
+ "./package.json": {
17
+ "default": "./package.json"
18
+ },
19
+ ".": {
20
+ "types": "./index.d.ts",
21
+ "default": "./fesm2022/dragonworks-ngx-dashboard-widgets.mjs"
22
+ }
23
+ }
24
+ }