@acorex/modules 19.3.5 → 19.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dashboard-management/lib/features/home-dashboard/dashboard-home/home-dashboard.d.ts +5 -7
  2. package/dashboard-management/lib/features/home-dashboard/dashboard-popups/dashboard-popup.service.d.ts +1 -0
  3. package/dashboard-management/lib/features/home-dashboard/widget-wrapper/dashboard-widget-wrapper.d.ts +2 -1
  4. package/dashboard-management/lib/features/shared/widgets/weather/weather-widget.component.d.ts +5 -0
  5. package/fesm2022/{acorex-modules-auth-acorex-modules-auth-VeeGJcyl.mjs → acorex-modules-auth-acorex-modules-auth-bj5xztse.mjs} +9 -9
  6. package/fesm2022/{acorex-modules-auth-acorex-modules-auth-VeeGJcyl.mjs.map → acorex-modules-auth-acorex-modules-auth-bj5xztse.mjs.map} +1 -1
  7. package/fesm2022/{acorex-modules-auth-app-chooser.component-IhAQfHJU.mjs → acorex-modules-auth-app-chooser.component-BOL3VzC1.mjs} +2 -2
  8. package/fesm2022/{acorex-modules-auth-app-chooser.component-IhAQfHJU.mjs.map → acorex-modules-auth-app-chooser.component-BOL3VzC1.mjs.map} +1 -1
  9. package/fesm2022/{acorex-modules-auth-login.module-B8qqaCq8.mjs → acorex-modules-auth-login.module-C1AoXhCI.mjs} +4 -4
  10. package/fesm2022/{acorex-modules-auth-login.module-B8qqaCq8.mjs.map → acorex-modules-auth-login.module-C1AoXhCI.mjs.map} +1 -1
  11. package/fesm2022/{acorex-modules-auth-master.layout-egA9357P.mjs → acorex-modules-auth-master.layout-vuHfrDxu.mjs} +2 -2
  12. package/fesm2022/{acorex-modules-auth-master.layout-egA9357P.mjs.map → acorex-modules-auth-master.layout-vuHfrDxu.mjs.map} +1 -1
  13. package/fesm2022/{acorex-modules-auth-password.component-BimdcHXP.mjs → acorex-modules-auth-password.component-C71v2x71.mjs} +2 -2
  14. package/fesm2022/{acorex-modules-auth-password.component-BimdcHXP.mjs.map → acorex-modules-auth-password.component-C71v2x71.mjs.map} +1 -1
  15. package/fesm2022/{acorex-modules-auth-password.component-BMWDHmu6.mjs → acorex-modules-auth-password.component-Dtcz95NV.mjs} +2 -2
  16. package/fesm2022/{acorex-modules-auth-password.component-BMWDHmu6.mjs.map → acorex-modules-auth-password.component-Dtcz95NV.mjs.map} +1 -1
  17. package/fesm2022/{acorex-modules-auth-routes-BYT58dkA.mjs → acorex-modules-auth-routes-lJgHFaQR.mjs} +2 -2
  18. package/fesm2022/{acorex-modules-auth-routes-BYT58dkA.mjs.map → acorex-modules-auth-routes-lJgHFaQR.mjs.map} +1 -1
  19. package/fesm2022/{acorex-modules-auth-two-factor.module-B_g4P4is.mjs → acorex-modules-auth-two-factor.module-C9SfEHF7.mjs} +2 -2
  20. package/fesm2022/{acorex-modules-auth-two-factor.module-B_g4P4is.mjs.map → acorex-modules-auth-two-factor.module-C9SfEHF7.mjs.map} +1 -1
  21. package/fesm2022/{acorex-modules-auth-user-sessions.component-DvYAh9cg.mjs → acorex-modules-auth-user-sessions.component-CCsoLecU.mjs} +4 -4
  22. package/fesm2022/acorex-modules-auth-user-sessions.component-CCsoLecU.mjs.map +1 -0
  23. package/fesm2022/acorex-modules-auth.mjs +1 -1
  24. package/fesm2022/acorex-modules-dashboard-management.mjs +335 -232
  25. package/fesm2022/acorex-modules-dashboard-management.mjs.map +1 -1
  26. package/fesm2022/acorex-modules-notification-management.mjs +11 -11
  27. package/fesm2022/acorex-modules-notification-management.mjs.map +1 -1
  28. package/fesm2022/acorex-modules-security-management.mjs +1 -1
  29. package/fesm2022/acorex-modules-security-management.mjs.map +1 -1
  30. package/package.json +1 -1
  31. package/fesm2022/acorex-modules-auth-user-sessions.component-DvYAh9cg.mjs.map +0 -1
@@ -38,14 +38,14 @@ import { AXCheckBoxModule } from '@acorex/components/check-box';
38
38
  import { AXImageModule } from '@acorex/components/image';
39
39
  import { AXLabelModule } from '@acorex/components/label';
40
40
  import { AXTabsModule } from '@acorex/components/tabs';
41
- import * as i6 from '@acorex/core/translation';
41
+ import * as i2$3 from '@acorex/core/translation';
42
42
  import { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';
43
43
  import { HttpClient, HttpClientModule } from '@angular/common/http';
44
44
  import { AXPopupService } from '@acorex/components/popup';
45
45
  import { AXP_GLOBAL_SEARCH_CONFIG_TOKEN } from '@acorex/modules/common';
46
46
  import { AXPDataGenerator, AXPPlatformScope } from '@acorex/platform/core';
47
47
  import { AXPWorkflowService } from '@acorex/platform/workflow';
48
- import { Router, ActivatedRoute } from '@angular/router';
48
+ import { ActivatedRoute, Router } from '@angular/router';
49
49
  import { AXBreadcrumbsModule } from '@acorex/components/breadcrumbs';
50
50
  import { AXButtonGroupModule } from '@acorex/components/button-group';
51
51
  import { AXDialogService } from '@acorex/components/dialog';
@@ -55,12 +55,14 @@ import { AXDropdownButtonModule } from '@acorex/components/dropdown-button';
55
55
  import { AXPWidgetPropertyViewerComponent, AXPWidgetPickerService, AXPDesignerService } from '@acorex/platform/layout/designer';
56
56
  import { AXPBasePageComponent, AXPPageLayoutComponent, AXPBasePage } from '@acorex/platform/themes/default';
57
57
  import { AXPLayoutThemeService, AXPThemeLayoutBlockComponent } from '@acorex/platform/themes/shared';
58
- import * as i2$3 from '@acorex/components/loading';
58
+ import * as i2$4 from '@acorex/components/loading';
59
59
  import { AXLoadingModule } from '@acorex/components/loading';
60
60
  import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
61
61
  import { AXBasePageComponent } from '@acorex/components/page';
62
62
  import * as i7 from '@acorex/components/select-box';
63
63
  import { AXSelectBoxModule } from '@acorex/components/select-box';
64
+ import * as i8 from '@acorex/components/switch';
65
+ import { AXSwitchModule } from '@acorex/components/switch';
64
66
  import * as i3$3 from '@acorex/components/text-box';
65
67
  import { AXTextBoxModule } from '@acorex/components/text-box';
66
68
  import { AXMOrganizationManagementRoleEntityService } from '@acorex/modules/organization-management';
@@ -496,7 +498,7 @@ const AXPBarChartWidget = {
496
498
  // ====== Chart Title ======
497
499
  {
498
500
  name: 'title',
499
- title: 'Chart Title',
501
+ title: '@dashboard:widgets.bar-chart.chart-title',
500
502
  group: AXP_APPEARANCE_PROPERTY_GROUP,
501
503
  schema: {
502
504
  defaultValue: '',
@@ -515,7 +517,7 @@ const AXPBarChartWidget = {
515
517
  // ====== Layout & Dimensions ======
516
518
  {
517
519
  name: 'width',
518
- title: 'Width',
520
+ title: '@dashboard:widgets.bar-chart.width',
519
521
  group: AXP_STYLING_PROPERTY_GROUP,
520
522
  schema: {
521
523
  defaultValue: null,
@@ -534,7 +536,7 @@ const AXPBarChartWidget = {
534
536
  },
535
537
  {
536
538
  name: 'height',
537
- title: 'Height',
539
+ title: '@dashboard:widgets.bar-chart.height',
538
540
  group: AXP_STYLING_PROPERTY_GROUP,
539
541
  schema: {
540
542
  defaultValue: 300,
@@ -554,7 +556,7 @@ const AXPBarChartWidget = {
554
556
  // ====== X Axis Settings ======
555
557
  {
556
558
  name: 'showXAxis',
557
- title: 'Show X Axis',
559
+ title: '@dashboard:widgets.bar-chart.show-x-axis',
558
560
  group: AXP_APPEARANCE_PROPERTY_GROUP,
559
561
  schema: {
560
562
  defaultValue: true,
@@ -569,7 +571,7 @@ const AXPBarChartWidget = {
569
571
  },
570
572
  {
571
573
  name: 'xAxisLabel',
572
- title: 'X Axis Label',
574
+ title: '@dashboard:widgets.bar-chart.x-axis-label',
573
575
  group: AXP_APPEARANCE_PROPERTY_GROUP,
574
576
  schema: {
575
577
  defaultValue: '',
@@ -585,7 +587,7 @@ const AXPBarChartWidget = {
585
587
  // ====== Y Axis Settings ======
586
588
  {
587
589
  name: 'showYAxis',
588
- title: 'Show Y Axis',
590
+ title: '@dashboard:widgets.bar-chart.show-y-axis',
589
591
  group: AXP_APPEARANCE_PROPERTY_GROUP,
590
592
  schema: {
591
593
  defaultValue: true,
@@ -600,7 +602,7 @@ const AXPBarChartWidget = {
600
602
  },
601
603
  {
602
604
  name: 'yAxisLabel',
603
- title: 'Y Axis Label',
605
+ title: '@dashboard:widgets.bar-chart.y-axis-label',
604
606
  group: AXP_APPEARANCE_PROPERTY_GROUP,
605
607
  schema: {
606
608
  defaultValue: '',
@@ -616,7 +618,7 @@ const AXPBarChartWidget = {
616
618
  // ====== Bar Appearance ======
617
619
  {
618
620
  name: 'barWidth',
619
- title: 'Bar Width',
621
+ title: '@dashboard:widgets.bar-chart.bar-width',
620
622
  group: AXP_APPEARANCE_PROPERTY_GROUP,
621
623
  schema: {
622
624
  defaultValue: 80,
@@ -636,7 +638,7 @@ const AXPBarChartWidget = {
636
638
  },
637
639
  {
638
640
  name: 'cornerRadius',
639
- title: 'Corner Radius',
641
+ title: '@dashboard:widgets.bar-chart.corner-radius',
640
642
  group: AXP_APPEARANCE_PROPERTY_GROUP,
641
643
  schema: {
642
644
  defaultValue: 4,
@@ -657,7 +659,7 @@ const AXPBarChartWidget = {
657
659
  // ====== Grid Settings ======
658
660
  {
659
661
  name: 'showGrid',
660
- title: 'Show Grid Lines',
662
+ title: '@dashboard:widgets.bar-chart.show-grid',
661
663
  group: AXP_APPEARANCE_PROPERTY_GROUP,
662
664
  schema: {
663
665
  defaultValue: true,
@@ -672,7 +674,7 @@ const AXPBarChartWidget = {
672
674
  },
673
675
  {
674
676
  name: 'showDataLabels',
675
- title: 'Show Data Labels',
677
+ title: '@dashboard:widgets.bar-chart.show-data-labels',
676
678
  group: AXP_APPEARANCE_PROPERTY_GROUP,
677
679
  schema: {
678
680
  defaultValue: true,
@@ -688,7 +690,7 @@ const AXPBarChartWidget = {
688
690
  // ====== Tooltip Settings ======
689
691
  {
690
692
  name: 'showTooltip',
691
- title: 'Show Tooltip',
693
+ title: '@dashboard:widgets.bar-chart.show-tooltip',
692
694
  group: AXP_APPEARANCE_PROPERTY_GROUP,
693
695
  schema: {
694
696
  defaultValue: true,
@@ -704,7 +706,7 @@ const AXPBarChartWidget = {
704
706
  // ====== Animation Settings ======
705
707
  {
706
708
  name: 'animationEasing',
707
- title: 'Animation Easing',
709
+ title: '@dashboard:widgets.bar-chart.animation-easing',
708
710
  group: AXP_APPEARANCE_PROPERTY_GROUP,
709
711
  schema: {
710
712
  defaultValue: 'cubic-out',
@@ -734,7 +736,7 @@ const AXPBarChartWidget = {
734
736
  },
735
737
  {
736
738
  name: 'animationDuration',
737
- title: 'Animation Duration',
739
+ title: '@dashboard:widgets.bar-chart.animation-duration',
738
740
  group: AXP_APPEARANCE_PROPERTY_GROUP,
739
741
  schema: {
740
742
  defaultValue: 800,
@@ -803,7 +805,7 @@ class AXPClockCalendarWidgetViewComponent extends AXPValueWidgetComponent {
803
805
  this.showDayOfWeek = computed(() => this.options()?.showDayOfWeek !== false);
804
806
  this.use24Hour = computed(() => this.options()?.use24Hour === true);
805
807
  this.showSeconds = computed(() => this.options()?.showSeconds !== false);
806
- this.dateFormat = computed(() => this.options()?.dateFormat?.id ?? 'dd MMM yyyy');
808
+ this.dateFormat = computed(() => this.options()?.dateFormat?.id ?? 'DD MMM YYYY');
807
809
  this.timezone = computed(() => this.options()?.timezone?.id ?? 'local');
808
810
  // protected readonly showTimezoneIndicator: Signal<boolean> = computed(() => this.timezone() !== 'local');
809
811
  this.displayTimezone = computed(() => {
@@ -893,11 +895,11 @@ class AXPClockCalendarWidgetViewComponent extends AXPValueWidgetComponent {
893
895
  return days[this.currentDate.getDay()];
894
896
  }
895
897
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPClockCalendarWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
896
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AXPClockCalendarWidgetViewComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<div class=\"axp-clock-calendar-container\">\n <!-- Timezone indicator (only shown when not local) -->\n <!-- @if (showTimezoneIndicator()) {\n <div class=\"axp-clock-calendar-timezone-badge\"><i class=\"fa-solid fa-globe\"></i> {{ displayTimezone() }}</div>\n } -->\n\n <!-- Day of week display -->\n @if (showDayOfWeek()) {\n <div class=\"axp-clock-calendar-day-label\">{{ getDayOfWeek() }}</div>\n }\n\n <div class=\"axp-clock-calendar-content\">\n <!-- Digital Clock Display -->\n @if (showDigitalClock()) {\n <div class=\"axp-clock-calendar-digital-clock\">\n {{ currentTime | format : 'datetime' : timeFormat() | async }}\n </div>\n }\n\n <!-- Analog Clock Display -->\n @if (showAnalogClock()) {\n <div class=\"axp-clock-calendar-analog-clock\">\n <!-- Hour markers -->\n @for (hour of clockHours; track hour) {\n <div\n class=\"axp-clock-calendar-hour-marker\"\n [style.transform]=\"'rotate(' + hour * 30 + 'deg) translateY(-80px)'\"\n ></div>\n }\n\n <!-- Clock Numbers -->\n <div class=\"axp-clock-calendar-numbers-container\">\n @for (hour of clockHourNumbers; track hour) {\n <div\n class=\"axp-clock-calendar-hour-number\"\n [style.transform]=\"'rotate(' + hour.angle + 'deg) translateY(-82px)'\"\n >\n <span [style.transform]=\"'rotate(' + -hour.angle + 'deg)'\">{{ hour.number }}</span>\n </div>\n }\n </div>\n\n <!-- Clock Hands -->\n <div class=\"axp-clock-calendar-hands-container\">\n <div class=\"axp-clock-calendar-hour-hand\" [style.transform]=\"'rotate(' + hourRotation + 'deg)'\"></div>\n <div class=\"axp-clock-calendar-minute-hand\" [style.transform]=\"'rotate(' + minuteRotation + 'deg)'\"></div>\n @if (showSeconds()) {\n <div class=\"axp-clock-calendar-second-hand\" [style.transform]=\"'rotate(' + secondRotation + 'deg)'\"></div>\n }\n <div class=\"axp-clock-calendar-center-dot\"></div>\n </div>\n </div>\n }\n\n <!-- Date Display -->\n @if (showDate()) {\n <div class=\"axp-clock-calendar-date-display\">\n <i class=\"fa-regular fa-calendar\"></i>\n {{ currentDate | format : 'datetime' : dateFormat() | async }}\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.axp-clock-calendar-container{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:100%;padding:1rem;position:relative;overflow:hidden;box-shadow:var(--ax-shadow-sm);background-color:var(--ax-surface-color);color:var(--ax-text-color)}.axp-clock-calendar-content{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;width:100%;height:100%;position:relative}.axp-clock-calendar-timezone-badge{position:absolute;top:.5rem;right:.5rem;font-size:.75rem;padding:.25rem;border-radius:1rem;border-width:1px;border-color:rgba(23,23,23,.5)}.axp-clock-calendar-timezone-badge:is(.ax-dark *){border-color:rgba(245,245,245,.5)}.axp-clock-calendar-timezone-badge{display:flex;align-items:center;gap:.25rem}.axp-clock-calendar-timezone-badge i{font-size:.75rem}.axp-clock-calendar-day-label{font-size:.9rem;font-weight:600;text-transform:uppercase;letter-spacing:.05rem;margin-bottom:.25rem}.axp-clock-calendar-digital-clock{font-size:1.5rem;font-weight:500;letter-spacing:.05rem;font-family:monospace;padding:.5rem .75rem;border-radius:.25rem}.axp-clock-calendar-analog-clock{position:relative;border-radius:50%;border-width:1px;border-color:rgba(23,23,23,.5)}.axp-clock-calendar-analog-clock:is(.ax-dark *){border-color:rgba(245,245,245,.5)}.axp-clock-calendar-analog-clock{display:flex;align-items:center;justify-content:center;background:var(--ax-surface-color);width:min(180px,100%);height:0;padding-bottom:min(180px,100%);margin:.5rem auto;min-width:120px;min-height:120px;box-shadow:var(--ax-shadow-sm)}.axp-clock-calendar-hands-container,.axp-clock-calendar-numbers-container{position:absolute;top:0;left:0;width:100%;height:100%;border-radius:50%}.axp-clock-calendar-hour-marker{position:absolute;left:50%;top:50%;width:2px;height:4%;margin-left:-1px;border-radius:1px;background-color:var(--ax-text-muted);transform-origin:50% 0}.axp-clock-calendar-hour-number{position:absolute;left:50%;top:50%;transform-origin:50% 0;font-size:clamp(.7rem,2.5vw,.9rem);font-weight:600;color:var(--ax-text-color)}.axp-clock-calendar-hour-number span{display:block}.axp-clock-calendar-hour-hand{position:absolute;top:50%;left:50%;width:4px;height:25%;margin-left:-2px;background-color:rgba(23,23,23,.75)}.axp-clock-calendar-hour-hand:is(.ax-dark *){background-color:rgba(245,245,245,.75)}.axp-clock-calendar-hour-hand{transform-origin:50% 0;border-radius:3px;box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-minute-hand{position:absolute;top:50%;left:50%;width:3px;height:38%;margin-left:-1.5px;background-color:rgba(23,23,23,.5)}.axp-clock-calendar-minute-hand:is(.ax-dark *){background-color:rgba(245,245,245,.5)}.axp-clock-calendar-minute-hand{transform-origin:50% 0;border-radius:2px;box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-second-hand{position:absolute;top:50%;left:50%;width:2px;height:42%;margin-left:-1px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-danger-500),var(--tw-bg-opacity, 1))}.axp-clock-calendar-second-hand:is(.ax-dark *){--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-danger-400),var(--tw-bg-opacity, 1))}.axp-clock-calendar-second-hand{transform-origin:50% 0;border-radius:1px;box-shadow:0 0 3px rgba(0,0,0,.2)}.axp-clock-calendar-center-dot{position:absolute;top:50%;left:50%;width:10px;height:10px;border-radius:50%;margin-top:-5px;margin-left:-5px;background-color:#d81159;border:2px solid var(--ax-surface-color);box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-date-display{display:flex;align-items:center;gap:.5rem;font-size:.85rem;padding:.25rem .6rem;border-radius:.25rem;background-color:var(--ax-surface-hover);color:var(--ax-text-color)}.axp-clock-calendar-date-display i{font-size:.85rem;opacity:.7}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "pipe", type: i2.AXFormatPipe, name: "format" }, { kind: "ngmodule", type: AXTagModule }, { kind: "ngmodule", type: AXDecoratorModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
898
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AXPClockCalendarWidgetViewComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<div class=\"axp-clock-calendar-container\">\n <!-- Timezone indicator (only shown when not local) -->\n <!-- @if (showTimezoneIndicator()) {\n <div class=\"axp-clock-calendar-timezone-badge\"><i class=\"fa-solid fa-globe\"></i> {{ displayTimezone() }}</div>\n } -->\n\n <!-- Day of week display -->\n @if (showDayOfWeek()) {\n <div class=\"axp-clock-calendar-day-label\">{{ getDayOfWeek() }}</div>\n }\n\n <div class=\"axp-clock-calendar-content\">\n <!-- Digital Clock Display -->\n @if (showDigitalClock()) {\n <div class=\"axp-clock-calendar-digital-clock\">\n {{ currentTime | format: 'datetime' : timeFormat() | async }}\n </div>\n }\n\n <!-- Analog Clock Display -->\n @if (showAnalogClock()) {\n <div class=\"axp-clock-calendar-analog-clock\">\n <!-- Hour markers -->\n @for (hour of clockHours; track hour) {\n <div\n class=\"axp-clock-calendar-hour-marker\"\n [style.transform]=\"'rotate(' + hour * 30 + 'deg) translateY(-80px)'\"\n ></div>\n }\n\n <!-- Clock Numbers -->\n <div class=\"axp-clock-calendar-numbers-container\">\n @for (hour of clockHourNumbers; track hour) {\n <div\n class=\"axp-clock-calendar-hour-number\"\n [style.transform]=\"'rotate(' + hour.angle + 'deg) translateY(-82px)'\"\n >\n <span [style.transform]=\"'rotate(' + -hour.angle + 'deg)'\">{{ hour.number }}</span>\n </div>\n }\n </div>\n\n <!-- Clock Hands -->\n <div class=\"axp-clock-calendar-hands-container\">\n <div class=\"axp-clock-calendar-hour-hand\" [style.transform]=\"'rotate(' + hourRotation + 'deg)'\"></div>\n <div class=\"axp-clock-calendar-minute-hand\" [style.transform]=\"'rotate(' + minuteRotation + 'deg)'\"></div>\n @if (showSeconds()) {\n <div class=\"axp-clock-calendar-second-hand\" [style.transform]=\"'rotate(' + secondRotation + 'deg)'\"></div>\n }\n <div class=\"axp-clock-calendar-center-dot\"></div>\n </div>\n </div>\n }\n\n <!-- Date Display -->\n @if (showDate()) {\n <div class=\"axp-clock-calendar-date-display\">\n <i class=\"fa-regular fa-calendar\"></i>\n {{ currentDate | format: 'datetime' : dateFormat() | async }}\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.axp-clock-calendar-container{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:100%;padding:1rem;position:relative;overflow:hidden;box-shadow:var(--ax-shadow-sm);background-color:var(--ax-surface-color);color:var(--ax-text-color)}.axp-clock-calendar-content{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;width:100%;height:100%;position:relative}.axp-clock-calendar-timezone-badge{position:absolute;top:.5rem;right:.5rem;font-size:.75rem;padding:.25rem;border-radius:1rem;border-width:1px;border-color:rgba(23,23,23,.5)}.axp-clock-calendar-timezone-badge:is(.ax-dark *){border-color:rgba(245,245,245,.5)}.axp-clock-calendar-timezone-badge{display:flex;align-items:center;gap:.25rem}.axp-clock-calendar-timezone-badge i{font-size:.75rem}.axp-clock-calendar-day-label{font-size:.9rem;font-weight:600;text-transform:uppercase;letter-spacing:.05rem;margin-bottom:.25rem}.axp-clock-calendar-digital-clock{font-size:1.5rem;font-weight:500;letter-spacing:.05rem;font-family:monospace;padding:.5rem .75rem;border-radius:.25rem}.axp-clock-calendar-analog-clock{position:relative;border-radius:50%;border-width:1px;border-color:rgba(23,23,23,.5)}.axp-clock-calendar-analog-clock:is(.ax-dark *){border-color:rgba(245,245,245,.5)}.axp-clock-calendar-analog-clock{display:flex;align-items:center;justify-content:center;background:var(--ax-surface-color);width:min(180px,100%);height:0;padding-bottom:min(180px,100%);margin:.5rem auto;min-width:120px;min-height:120px;box-shadow:var(--ax-shadow-sm)}.axp-clock-calendar-hands-container,.axp-clock-calendar-numbers-container{position:absolute;top:0;left:0;width:100%;height:100%;border-radius:50%}.axp-clock-calendar-hour-marker{position:absolute;left:50%;top:50%;width:2px;height:4%;margin-left:-1px;border-radius:1px;background-color:var(--ax-text-muted);transform-origin:50% 0}.axp-clock-calendar-hour-number{position:absolute;left:50%;top:50%;transform-origin:50% 0;font-size:clamp(.7rem,2.5vw,.9rem);font-weight:600;color:var(--ax-text-color)}.axp-clock-calendar-hour-number span{display:block}.axp-clock-calendar-hour-hand{position:absolute;top:50%;left:50%;width:4px;height:25%;margin-left:-2px;background-color:rgba(23,23,23,.75)}.axp-clock-calendar-hour-hand:is(.ax-dark *){background-color:rgba(245,245,245,.75)}.axp-clock-calendar-hour-hand{transform-origin:50% 0;border-radius:3px;box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-minute-hand{position:absolute;top:50%;left:50%;width:3px;height:38%;margin-left:-1.5px;background-color:rgba(23,23,23,.5)}.axp-clock-calendar-minute-hand:is(.ax-dark *){background-color:rgba(245,245,245,.5)}.axp-clock-calendar-minute-hand{transform-origin:50% 0;border-radius:2px;box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-second-hand{position:absolute;top:50%;left:50%;width:2px;height:42%;margin-left:-1px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-danger-500),var(--tw-bg-opacity, 1))}.axp-clock-calendar-second-hand:is(.ax-dark *){--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-danger-400),var(--tw-bg-opacity, 1))}.axp-clock-calendar-second-hand{transform-origin:50% 0;border-radius:1px;box-shadow:0 0 3px rgba(0,0,0,.2)}.axp-clock-calendar-center-dot{position:absolute;top:50%;left:50%;width:10px;height:10px;border-radius:50%;margin-top:-5px;margin-left:-5px;background-color:#d81159;border:2px solid var(--ax-surface-color);box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-date-display{display:flex;align-items:center;gap:.5rem;font-size:.85rem;padding:.25rem .6rem;border-radius:.25rem;background-color:var(--ax-surface-hover);color:var(--ax-text-color)}.axp-clock-calendar-date-display i{font-size:.85rem;opacity:.7}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "pipe", type: i2.AXFormatPipe, name: "format" }, { kind: "ngmodule", type: AXTagModule }, { kind: "ngmodule", type: AXDecoratorModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
897
899
  }
898
900
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPClockCalendarWidgetViewComponent, decorators: [{
899
901
  type: Component,
900
- args: [{ standalone: true, imports: [CommonModule, AXDateTimeModule, AXFormatModule, AXTagModule, AXDecoratorModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"axp-clock-calendar-container\">\n <!-- Timezone indicator (only shown when not local) -->\n <!-- @if (showTimezoneIndicator()) {\n <div class=\"axp-clock-calendar-timezone-badge\"><i class=\"fa-solid fa-globe\"></i> {{ displayTimezone() }}</div>\n } -->\n\n <!-- Day of week display -->\n @if (showDayOfWeek()) {\n <div class=\"axp-clock-calendar-day-label\">{{ getDayOfWeek() }}</div>\n }\n\n <div class=\"axp-clock-calendar-content\">\n <!-- Digital Clock Display -->\n @if (showDigitalClock()) {\n <div class=\"axp-clock-calendar-digital-clock\">\n {{ currentTime | format : 'datetime' : timeFormat() | async }}\n </div>\n }\n\n <!-- Analog Clock Display -->\n @if (showAnalogClock()) {\n <div class=\"axp-clock-calendar-analog-clock\">\n <!-- Hour markers -->\n @for (hour of clockHours; track hour) {\n <div\n class=\"axp-clock-calendar-hour-marker\"\n [style.transform]=\"'rotate(' + hour * 30 + 'deg) translateY(-80px)'\"\n ></div>\n }\n\n <!-- Clock Numbers -->\n <div class=\"axp-clock-calendar-numbers-container\">\n @for (hour of clockHourNumbers; track hour) {\n <div\n class=\"axp-clock-calendar-hour-number\"\n [style.transform]=\"'rotate(' + hour.angle + 'deg) translateY(-82px)'\"\n >\n <span [style.transform]=\"'rotate(' + -hour.angle + 'deg)'\">{{ hour.number }}</span>\n </div>\n }\n </div>\n\n <!-- Clock Hands -->\n <div class=\"axp-clock-calendar-hands-container\">\n <div class=\"axp-clock-calendar-hour-hand\" [style.transform]=\"'rotate(' + hourRotation + 'deg)'\"></div>\n <div class=\"axp-clock-calendar-minute-hand\" [style.transform]=\"'rotate(' + minuteRotation + 'deg)'\"></div>\n @if (showSeconds()) {\n <div class=\"axp-clock-calendar-second-hand\" [style.transform]=\"'rotate(' + secondRotation + 'deg)'\"></div>\n }\n <div class=\"axp-clock-calendar-center-dot\"></div>\n </div>\n </div>\n }\n\n <!-- Date Display -->\n @if (showDate()) {\n <div class=\"axp-clock-calendar-date-display\">\n <i class=\"fa-regular fa-calendar\"></i>\n {{ currentDate | format : 'datetime' : dateFormat() | async }}\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.axp-clock-calendar-container{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:100%;padding:1rem;position:relative;overflow:hidden;box-shadow:var(--ax-shadow-sm);background-color:var(--ax-surface-color);color:var(--ax-text-color)}.axp-clock-calendar-content{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;width:100%;height:100%;position:relative}.axp-clock-calendar-timezone-badge{position:absolute;top:.5rem;right:.5rem;font-size:.75rem;padding:.25rem;border-radius:1rem;border-width:1px;border-color:rgba(23,23,23,.5)}.axp-clock-calendar-timezone-badge:is(.ax-dark *){border-color:rgba(245,245,245,.5)}.axp-clock-calendar-timezone-badge{display:flex;align-items:center;gap:.25rem}.axp-clock-calendar-timezone-badge i{font-size:.75rem}.axp-clock-calendar-day-label{font-size:.9rem;font-weight:600;text-transform:uppercase;letter-spacing:.05rem;margin-bottom:.25rem}.axp-clock-calendar-digital-clock{font-size:1.5rem;font-weight:500;letter-spacing:.05rem;font-family:monospace;padding:.5rem .75rem;border-radius:.25rem}.axp-clock-calendar-analog-clock{position:relative;border-radius:50%;border-width:1px;border-color:rgba(23,23,23,.5)}.axp-clock-calendar-analog-clock:is(.ax-dark *){border-color:rgba(245,245,245,.5)}.axp-clock-calendar-analog-clock{display:flex;align-items:center;justify-content:center;background:var(--ax-surface-color);width:min(180px,100%);height:0;padding-bottom:min(180px,100%);margin:.5rem auto;min-width:120px;min-height:120px;box-shadow:var(--ax-shadow-sm)}.axp-clock-calendar-hands-container,.axp-clock-calendar-numbers-container{position:absolute;top:0;left:0;width:100%;height:100%;border-radius:50%}.axp-clock-calendar-hour-marker{position:absolute;left:50%;top:50%;width:2px;height:4%;margin-left:-1px;border-radius:1px;background-color:var(--ax-text-muted);transform-origin:50% 0}.axp-clock-calendar-hour-number{position:absolute;left:50%;top:50%;transform-origin:50% 0;font-size:clamp(.7rem,2.5vw,.9rem);font-weight:600;color:var(--ax-text-color)}.axp-clock-calendar-hour-number span{display:block}.axp-clock-calendar-hour-hand{position:absolute;top:50%;left:50%;width:4px;height:25%;margin-left:-2px;background-color:rgba(23,23,23,.75)}.axp-clock-calendar-hour-hand:is(.ax-dark *){background-color:rgba(245,245,245,.75)}.axp-clock-calendar-hour-hand{transform-origin:50% 0;border-radius:3px;box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-minute-hand{position:absolute;top:50%;left:50%;width:3px;height:38%;margin-left:-1.5px;background-color:rgba(23,23,23,.5)}.axp-clock-calendar-minute-hand:is(.ax-dark *){background-color:rgba(245,245,245,.5)}.axp-clock-calendar-minute-hand{transform-origin:50% 0;border-radius:2px;box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-second-hand{position:absolute;top:50%;left:50%;width:2px;height:42%;margin-left:-1px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-danger-500),var(--tw-bg-opacity, 1))}.axp-clock-calendar-second-hand:is(.ax-dark *){--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-danger-400),var(--tw-bg-opacity, 1))}.axp-clock-calendar-second-hand{transform-origin:50% 0;border-radius:1px;box-shadow:0 0 3px rgba(0,0,0,.2)}.axp-clock-calendar-center-dot{position:absolute;top:50%;left:50%;width:10px;height:10px;border-radius:50%;margin-top:-5px;margin-left:-5px;background-color:#d81159;border:2px solid var(--ax-surface-color);box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-date-display{display:flex;align-items:center;gap:.5rem;font-size:.85rem;padding:.25rem .6rem;border-radius:.25rem;background-color:var(--ax-surface-hover);color:var(--ax-text-color)}.axp-clock-calendar-date-display i{font-size:.85rem;opacity:.7}\n"] }]
902
+ args: [{ standalone: true, imports: [CommonModule, AXDateTimeModule, AXFormatModule, AXTagModule, AXDecoratorModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"axp-clock-calendar-container\">\n <!-- Timezone indicator (only shown when not local) -->\n <!-- @if (showTimezoneIndicator()) {\n <div class=\"axp-clock-calendar-timezone-badge\"><i class=\"fa-solid fa-globe\"></i> {{ displayTimezone() }}</div>\n } -->\n\n <!-- Day of week display -->\n @if (showDayOfWeek()) {\n <div class=\"axp-clock-calendar-day-label\">{{ getDayOfWeek() }}</div>\n }\n\n <div class=\"axp-clock-calendar-content\">\n <!-- Digital Clock Display -->\n @if (showDigitalClock()) {\n <div class=\"axp-clock-calendar-digital-clock\">\n {{ currentTime | format: 'datetime' : timeFormat() | async }}\n </div>\n }\n\n <!-- Analog Clock Display -->\n @if (showAnalogClock()) {\n <div class=\"axp-clock-calendar-analog-clock\">\n <!-- Hour markers -->\n @for (hour of clockHours; track hour) {\n <div\n class=\"axp-clock-calendar-hour-marker\"\n [style.transform]=\"'rotate(' + hour * 30 + 'deg) translateY(-80px)'\"\n ></div>\n }\n\n <!-- Clock Numbers -->\n <div class=\"axp-clock-calendar-numbers-container\">\n @for (hour of clockHourNumbers; track hour) {\n <div\n class=\"axp-clock-calendar-hour-number\"\n [style.transform]=\"'rotate(' + hour.angle + 'deg) translateY(-82px)'\"\n >\n <span [style.transform]=\"'rotate(' + -hour.angle + 'deg)'\">{{ hour.number }}</span>\n </div>\n }\n </div>\n\n <!-- Clock Hands -->\n <div class=\"axp-clock-calendar-hands-container\">\n <div class=\"axp-clock-calendar-hour-hand\" [style.transform]=\"'rotate(' + hourRotation + 'deg)'\"></div>\n <div class=\"axp-clock-calendar-minute-hand\" [style.transform]=\"'rotate(' + minuteRotation + 'deg)'\"></div>\n @if (showSeconds()) {\n <div class=\"axp-clock-calendar-second-hand\" [style.transform]=\"'rotate(' + secondRotation + 'deg)'\"></div>\n }\n <div class=\"axp-clock-calendar-center-dot\"></div>\n </div>\n </div>\n }\n\n <!-- Date Display -->\n @if (showDate()) {\n <div class=\"axp-clock-calendar-date-display\">\n <i class=\"fa-regular fa-calendar\"></i>\n {{ currentDate | format: 'datetime' : dateFormat() | async }}\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.axp-clock-calendar-container{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:100%;padding:1rem;position:relative;overflow:hidden;box-shadow:var(--ax-shadow-sm);background-color:var(--ax-surface-color);color:var(--ax-text-color)}.axp-clock-calendar-content{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;width:100%;height:100%;position:relative}.axp-clock-calendar-timezone-badge{position:absolute;top:.5rem;right:.5rem;font-size:.75rem;padding:.25rem;border-radius:1rem;border-width:1px;border-color:rgba(23,23,23,.5)}.axp-clock-calendar-timezone-badge:is(.ax-dark *){border-color:rgba(245,245,245,.5)}.axp-clock-calendar-timezone-badge{display:flex;align-items:center;gap:.25rem}.axp-clock-calendar-timezone-badge i{font-size:.75rem}.axp-clock-calendar-day-label{font-size:.9rem;font-weight:600;text-transform:uppercase;letter-spacing:.05rem;margin-bottom:.25rem}.axp-clock-calendar-digital-clock{font-size:1.5rem;font-weight:500;letter-spacing:.05rem;font-family:monospace;padding:.5rem .75rem;border-radius:.25rem}.axp-clock-calendar-analog-clock{position:relative;border-radius:50%;border-width:1px;border-color:rgba(23,23,23,.5)}.axp-clock-calendar-analog-clock:is(.ax-dark *){border-color:rgba(245,245,245,.5)}.axp-clock-calendar-analog-clock{display:flex;align-items:center;justify-content:center;background:var(--ax-surface-color);width:min(180px,100%);height:0;padding-bottom:min(180px,100%);margin:.5rem auto;min-width:120px;min-height:120px;box-shadow:var(--ax-shadow-sm)}.axp-clock-calendar-hands-container,.axp-clock-calendar-numbers-container{position:absolute;top:0;left:0;width:100%;height:100%;border-radius:50%}.axp-clock-calendar-hour-marker{position:absolute;left:50%;top:50%;width:2px;height:4%;margin-left:-1px;border-radius:1px;background-color:var(--ax-text-muted);transform-origin:50% 0}.axp-clock-calendar-hour-number{position:absolute;left:50%;top:50%;transform-origin:50% 0;font-size:clamp(.7rem,2.5vw,.9rem);font-weight:600;color:var(--ax-text-color)}.axp-clock-calendar-hour-number span{display:block}.axp-clock-calendar-hour-hand{position:absolute;top:50%;left:50%;width:4px;height:25%;margin-left:-2px;background-color:rgba(23,23,23,.75)}.axp-clock-calendar-hour-hand:is(.ax-dark *){background-color:rgba(245,245,245,.75)}.axp-clock-calendar-hour-hand{transform-origin:50% 0;border-radius:3px;box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-minute-hand{position:absolute;top:50%;left:50%;width:3px;height:38%;margin-left:-1.5px;background-color:rgba(23,23,23,.5)}.axp-clock-calendar-minute-hand:is(.ax-dark *){background-color:rgba(245,245,245,.5)}.axp-clock-calendar-minute-hand{transform-origin:50% 0;border-radius:2px;box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-second-hand{position:absolute;top:50%;left:50%;width:2px;height:42%;margin-left:-1px;--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-danger-500),var(--tw-bg-opacity, 1))}.axp-clock-calendar-second-hand:is(.ax-dark *){--tw-bg-opacity: 1;background-color:rgba(var(--ax-sys-color-danger-400),var(--tw-bg-opacity, 1))}.axp-clock-calendar-second-hand{transform-origin:50% 0;border-radius:1px;box-shadow:0 0 3px rgba(0,0,0,.2)}.axp-clock-calendar-center-dot{position:absolute;top:50%;left:50%;width:10px;height:10px;border-radius:50%;margin-top:-5px;margin-left:-5px;background-color:#d81159;border:2px solid var(--ax-surface-color);box-shadow:0 0 4px rgba(0,0,0,.3)}.axp-clock-calendar-date-display{display:flex;align-items:center;gap:.5rem;font-size:.85rem;padding:.25rem .6rem;border-radius:.25rem;background-color:var(--ax-surface-hover);color:var(--ax-text-color)}.axp-clock-calendar-date-display i{font-size:.85rem;opacity:.7}\n"] }]
901
903
  }] });
902
904
 
903
905
  var clockCalendarWidget_component = /*#__PURE__*/Object.freeze({
@@ -932,10 +934,10 @@ const AXP_TIMEZONE_OPTIONS = [
932
934
  * Common date format options for the widget configuration
933
935
  */
934
936
  const AXP_DATE_FORMAT_OPTIONS = [
935
- { id: 'dd MMM yyyy', title: '31 Dec 2023' },
936
- { id: 'MMM dd, yyyy', title: 'Dec 31, 2023' },
937
- { id: 'dd/MM/yyyy', title: '31/12/2023' },
938
- { id: 'MM/dd/yyyy', title: '12/31/2023' },
937
+ { id: 'DD MMM YYYY', title: '31 Dec 2023' },
938
+ { id: 'MMM DD, YYYY', title: 'Dec 31, 2023' },
939
+ { id: 'DD/MM/YYYY', title: '31/12/2023' },
940
+ { id: 'MM/DD/YYYY', title: '12/31/2023' },
939
941
  ];
940
942
 
941
943
  const AXPClockCalendarWidget = {
@@ -949,7 +951,7 @@ const AXPClockCalendarWidget = {
949
951
  // ====== Title ======
950
952
  {
951
953
  name: 'title',
952
- title: 'Chart Title',
954
+ title: '@dashboard:widgets.clock-calendar.chart-title',
953
955
  group: AXP_APPEARANCE_PROPERTY_GROUP,
954
956
  schema: {
955
957
  defaultValue: '',
@@ -968,7 +970,7 @@ const AXPClockCalendarWidget = {
968
970
  // ====== Display Settings ======
969
971
  {
970
972
  name: 'displayLayout',
971
- title: 'Display Layout',
973
+ title: '@dashboard:widgets.clock-calendar.display-layout',
972
974
  group: AXP_APPEARANCE_PROPERTY_GROUP,
973
975
  schema: {
974
976
  dataType: 'string',
@@ -990,7 +992,7 @@ const AXPClockCalendarWidget = {
990
992
  },
991
993
  {
992
994
  name: 'showDate',
993
- title: 'Show Date',
995
+ title: '@dashboard:widgets.clock-calendar.show-date',
994
996
  group: AXP_APPEARANCE_PROPERTY_GROUP,
995
997
  schema: {
996
998
  defaultValue: true,
@@ -1005,7 +1007,7 @@ const AXPClockCalendarWidget = {
1005
1007
  },
1006
1008
  {
1007
1009
  name: 'showDayOfWeek',
1008
- title: 'Show Day of Week',
1010
+ title: '@dashboard:widgets.clock-calendar.show-day-of-week',
1009
1011
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1010
1012
  schema: {
1011
1013
  defaultValue: true,
@@ -1021,7 +1023,7 @@ const AXPClockCalendarWidget = {
1021
1023
  // ====== Time Format Settings ======
1022
1024
  {
1023
1025
  name: 'use24Hour',
1024
- title: 'Use 24 Hour Format',
1026
+ title: '@dashboard:widgets.clock-calendar.use-24-hour',
1025
1027
  group: AXP_BEHAVIOR_PROPERTY_GROUP,
1026
1028
  schema: {
1027
1029
  defaultValue: false,
@@ -1036,7 +1038,7 @@ const AXPClockCalendarWidget = {
1036
1038
  },
1037
1039
  {
1038
1040
  name: 'showSeconds',
1039
- title: 'Show Seconds',
1041
+ title: '@dashboard:widgets.clock-calendar.show-seconds',
1040
1042
  group: AXP_BEHAVIOR_PROPERTY_GROUP,
1041
1043
  schema: {
1042
1044
  defaultValue: true,
@@ -1066,10 +1068,10 @@ const AXPClockCalendarWidget = {
1066
1068
  // },
1067
1069
  {
1068
1070
  name: 'dateFormat',
1069
- title: 'Date Format',
1071
+ title: '@dashboard:widgets.clock-calendar.date-format',
1070
1072
  group: AXP_BEHAVIOR_PROPERTY_GROUP,
1071
1073
  schema: {
1072
- defaultValue: 'dd MMM yyyy',
1074
+ defaultValue: 'DD MMM YYYY',
1073
1075
  dataType: 'string',
1074
1076
  interface: {
1075
1077
  name: 'dateFormat',
@@ -1084,7 +1086,7 @@ const AXPClockCalendarWidget = {
1084
1086
  },
1085
1087
  {
1086
1088
  name: 'timezone',
1087
- title: 'Timezone',
1089
+ title: '@dashboard:widgets.clock-calendar.timezone',
1088
1090
  group: AXP_BEHAVIOR_PROPERTY_GROUP,
1089
1091
  schema: {
1090
1092
  defaultValue: 'local',
@@ -1157,7 +1159,7 @@ const AXPDonutChartWidget = {
1157
1159
  // ====== Chart Title ======
1158
1160
  {
1159
1161
  name: 'title',
1160
- title: 'Chart Title',
1162
+ title: '@dashboard:widgets.donut-chart.chart-title',
1161
1163
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1162
1164
  schema: {
1163
1165
  defaultValue: '',
@@ -1176,7 +1178,7 @@ const AXPDonutChartWidget = {
1176
1178
  // ====== Size & Layout ======
1177
1179
  {
1178
1180
  name: 'width',
1179
- title: 'Width',
1181
+ title: '@dashboard:widgets.donut-chart.width',
1180
1182
  group: AXP_STYLING_PROPERTY_GROUP,
1181
1183
  schema: {
1182
1184
  defaultValue: 300,
@@ -1195,7 +1197,7 @@ const AXPDonutChartWidget = {
1195
1197
  },
1196
1198
  {
1197
1199
  name: 'height',
1198
- title: 'Height',
1200
+ title: '@dashboard:widgets.donut-chart.height',
1199
1201
  group: AXP_STYLING_PROPERTY_GROUP,
1200
1202
  schema: {
1201
1203
  defaultValue: 300,
@@ -1215,7 +1217,7 @@ const AXPDonutChartWidget = {
1215
1217
  // ====== Donut Appearance ======
1216
1218
  {
1217
1219
  name: 'showDataLabels',
1218
- title: 'Show Data Labels',
1220
+ title: '@dashboard:widgets.donut-chart.show-data-labels',
1219
1221
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1220
1222
  schema: {
1221
1223
  defaultValue: true,
@@ -1230,7 +1232,7 @@ const AXPDonutChartWidget = {
1230
1232
  },
1231
1233
  {
1232
1234
  name: 'donutWidth',
1233
- title: 'Donut Width',
1235
+ title: '@dashboard:widgets.donut-chart.donut-width',
1234
1236
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1235
1237
  schema: {
1236
1238
  defaultValue: 35,
@@ -1250,7 +1252,7 @@ const AXPDonutChartWidget = {
1250
1252
  },
1251
1253
  {
1252
1254
  name: 'cornerRadius',
1253
- title: 'Corner Radius',
1255
+ title: '@dashboard:widgets.donut-chart.corner-radius',
1254
1256
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1255
1257
  schema: {
1256
1258
  defaultValue: 4,
@@ -1305,7 +1307,7 @@ const AXPDonutChartWidget = {
1305
1307
  // ====== Tooltip ======
1306
1308
  {
1307
1309
  name: 'showTooltip',
1308
- title: 'Show Tooltip',
1310
+ title: '@dashboard:widgets.donut-chart.show-tooltip',
1309
1311
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1310
1312
  schema: {
1311
1313
  defaultValue: true,
@@ -1321,7 +1323,7 @@ const AXPDonutChartWidget = {
1321
1323
  // ====== Animation Settings ======
1322
1324
  {
1323
1325
  name: 'animationEasing',
1324
- title: 'Animation Easing',
1326
+ title: '@dashboard:widgets.donut-chart.animation-easing',
1325
1327
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1326
1328
  schema: {
1327
1329
  defaultValue: 'cubic-out',
@@ -1351,7 +1353,7 @@ const AXPDonutChartWidget = {
1351
1353
  },
1352
1354
  {
1353
1355
  name: 'animationDuration',
1354
- title: 'Animation Duration',
1356
+ title: '@dashboard:widgets.donut-chart.animation-duration',
1355
1357
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1356
1358
  schema: {
1357
1359
  defaultValue: 800,
@@ -1422,7 +1424,7 @@ const AXPGaugeChartWidget = {
1422
1424
  // ====== Chart Title ======
1423
1425
  {
1424
1426
  name: 'title',
1425
- title: 'Chart Title',
1427
+ title: '@dashboard:widgets.gauge-chart.chart-title',
1426
1428
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1427
1429
  schema: {
1428
1430
  defaultValue: '',
@@ -1441,7 +1443,7 @@ const AXPGaugeChartWidget = {
1441
1443
  // ====== Layout & Dimensions ======
1442
1444
  {
1443
1445
  name: 'width',
1444
- title: 'Width',
1446
+ title: '@dashboard:widgets.gauge-chart.width',
1445
1447
  group: AXP_STYLING_PROPERTY_GROUP,
1446
1448
  schema: {
1447
1449
  defaultValue: null,
@@ -1461,7 +1463,7 @@ const AXPGaugeChartWidget = {
1461
1463
  },
1462
1464
  {
1463
1465
  name: 'height',
1464
- title: 'Height',
1466
+ title: '@dashboard:widgets.gauge-chart.height',
1465
1467
  group: AXP_STYLING_PROPERTY_GROUP,
1466
1468
  schema: {
1467
1469
  defaultValue: 300,
@@ -1482,7 +1484,7 @@ const AXPGaugeChartWidget = {
1482
1484
  // ====== Gauge Configuration ======
1483
1485
  {
1484
1486
  name: 'minValue',
1485
- title: 'Minimum Value',
1487
+ title: '@dashboard:widgets.gauge-chart.min-value',
1486
1488
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1487
1489
  schema: {
1488
1490
  defaultValue: 0,
@@ -1497,7 +1499,7 @@ const AXPGaugeChartWidget = {
1497
1499
  },
1498
1500
  {
1499
1501
  name: 'maxValue',
1500
- title: 'Maximum Value',
1502
+ title: '@dashboard:widgets.gauge-chart.max-value',
1501
1503
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1502
1504
  schema: {
1503
1505
  defaultValue: 100,
@@ -1513,7 +1515,7 @@ const AXPGaugeChartWidget = {
1513
1515
  // ====== Gauge Appearance ======
1514
1516
  {
1515
1517
  name: 'showTooltip',
1516
- title: 'Show Tooltip',
1518
+ title: '@dashboard:widgets.gauge-chart.show-tooltip',
1517
1519
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1518
1520
  schema: {
1519
1521
  defaultValue: true,
@@ -1528,7 +1530,7 @@ const AXPGaugeChartWidget = {
1528
1530
  },
1529
1531
  {
1530
1532
  name: 'gaugeWidth',
1531
- title: 'Gauge Width',
1533
+ title: '@dashboard:widgets.gauge-chart.gauge-width',
1532
1534
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1533
1535
  schema: {
1534
1536
  defaultValue: 30,
@@ -1548,7 +1550,7 @@ const AXPGaugeChartWidget = {
1548
1550
  },
1549
1551
  {
1550
1552
  name: 'cornerRadius',
1551
- title: 'Corner Radius',
1553
+ title: '@dashboard:widgets.gauge-chart.corner-radius',
1552
1554
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1553
1555
  schema: {
1554
1556
  defaultValue: 4,
@@ -1569,7 +1571,7 @@ const AXPGaugeChartWidget = {
1569
1571
  // ====== Label Display ======
1570
1572
  {
1571
1573
  name: 'label',
1572
- title: 'Label Text',
1574
+ title: '@dashboard:widgets.gauge-chart.label',
1573
1575
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1574
1576
  schema: {
1575
1577
  defaultValue: '',
@@ -1585,7 +1587,7 @@ const AXPGaugeChartWidget = {
1585
1587
  // ====== Animation Settings ======
1586
1588
  {
1587
1589
  name: 'animationEasing',
1588
- title: 'Animation Easing',
1590
+ title: '@dashboard:widgets.gauge-chart.animation-easing',
1589
1591
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1590
1592
  schema: {
1591
1593
  defaultValue: 'cubic-out',
@@ -1615,7 +1617,7 @@ const AXPGaugeChartWidget = {
1615
1617
  },
1616
1618
  {
1617
1619
  name: 'animationDuration',
1618
- title: 'Animation Duration',
1620
+ title: '@dashboard:widgets.gauge-chart.animation-duration',
1619
1621
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1620
1622
  schema: {
1621
1623
  defaultValue: 800,
@@ -1690,7 +1692,7 @@ const AXPLineChartWidget = {
1690
1692
  // ====== Chart Title ======
1691
1693
  {
1692
1694
  name: 'title',
1693
- title: 'Chart Title',
1695
+ title: '@dashboard:widgets.line-chart.chart-title',
1694
1696
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1695
1697
  schema: {
1696
1698
  defaultValue: '',
@@ -1709,7 +1711,7 @@ const AXPLineChartWidget = {
1709
1711
  // ====== Layout & Dimensions ======
1710
1712
  {
1711
1713
  name: 'width',
1712
- title: 'Width',
1714
+ title: '@dashboard:widgets.line-chart.width',
1713
1715
  group: AXP_STYLING_PROPERTY_GROUP,
1714
1716
  schema: {
1715
1717
  defaultValue: null,
@@ -1728,7 +1730,7 @@ const AXPLineChartWidget = {
1728
1730
  },
1729
1731
  {
1730
1732
  name: 'height',
1731
- title: 'Height',
1733
+ title: '@dashboard:widgets.line-chart.height',
1732
1734
  group: AXP_STYLING_PROPERTY_GROUP,
1733
1735
  schema: {
1734
1736
  defaultValue: 300,
@@ -1748,7 +1750,7 @@ const AXPLineChartWidget = {
1748
1750
  // ====== Axis Settings ======
1749
1751
  {
1750
1752
  name: 'showXAxis',
1751
- title: 'Show X Axis',
1753
+ title: '@dashboard:widgets.line-chart.show-x-axis',
1752
1754
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1753
1755
  schema: {
1754
1756
  defaultValue: true,
@@ -1763,7 +1765,7 @@ const AXPLineChartWidget = {
1763
1765
  },
1764
1766
  {
1765
1767
  name: 'xAxisLabel',
1766
- title: 'X Axis Label',
1768
+ title: '@dashboard:widgets.line-chart.x-axis-label',
1767
1769
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1768
1770
  schema: {
1769
1771
  defaultValue: '',
@@ -1778,7 +1780,7 @@ const AXPLineChartWidget = {
1778
1780
  },
1779
1781
  {
1780
1782
  name: 'showYAxis',
1781
- title: 'Show Y Axis',
1783
+ title: '@dashboard:widgets.line-chart.show-y-axis',
1782
1784
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1783
1785
  schema: {
1784
1786
  defaultValue: true,
@@ -1793,7 +1795,7 @@ const AXPLineChartWidget = {
1793
1795
  },
1794
1796
  {
1795
1797
  name: 'yAxisLabel',
1796
- title: 'Y Axis Label',
1798
+ title: '@dashboard:widgets.line-chart.y-axis-label',
1797
1799
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1798
1800
  schema: {
1799
1801
  defaultValue: '',
@@ -1808,7 +1810,7 @@ const AXPLineChartWidget = {
1808
1810
  },
1809
1811
  {
1810
1812
  name: 'yAxisStartsAtZero',
1811
- title: 'Y Axis Starts At Zero',
1813
+ title: '@dashboard:widgets.line-chart.y-axis-starts-at-zero',
1812
1814
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1813
1815
  schema: {
1814
1816
  defaultValue: true,
@@ -1823,7 +1825,7 @@ const AXPLineChartWidget = {
1823
1825
  },
1824
1826
  {
1825
1827
  name: 'showGrid',
1826
- title: 'Show Grid Lines',
1828
+ title: '@dashboard:widgets.line-chart.show-grid',
1827
1829
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1828
1830
  schema: {
1829
1831
  defaultValue: true,
@@ -1838,7 +1840,7 @@ const AXPLineChartWidget = {
1838
1840
  },
1839
1841
  {
1840
1842
  name: 'showVerticalGrid',
1841
- title: 'Show Vertical Grid',
1843
+ title: '@dashboard:widgets.line-chart.show-vertical-grid',
1842
1844
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1843
1845
  schema: {
1844
1846
  defaultValue: true,
@@ -1854,7 +1856,7 @@ const AXPLineChartWidget = {
1854
1856
  // ====== Line Appearance ======
1855
1857
  {
1856
1858
  name: 'lineWidth',
1857
- title: 'Line Width',
1859
+ title: '@dashboard:widgets.line-chart.line-width',
1858
1860
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1859
1861
  schema: {
1860
1862
  defaultValue: 2,
@@ -1874,7 +1876,7 @@ const AXPLineChartWidget = {
1874
1876
  },
1875
1877
  {
1876
1878
  name: 'smoothLine',
1877
- title: 'Smooth Line',
1879
+ title: '@dashboard:widgets.line-chart.smooth-line',
1878
1880
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1879
1881
  schema: {
1880
1882
  defaultValue: true,
@@ -1889,7 +1891,7 @@ const AXPLineChartWidget = {
1889
1891
  },
1890
1892
  {
1891
1893
  name: 'showPoints',
1892
- title: 'Show Points',
1894
+ title: '@dashboard:widgets.line-chart.show-points',
1893
1895
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1894
1896
  schema: {
1895
1897
  defaultValue: true,
@@ -1904,7 +1906,7 @@ const AXPLineChartWidget = {
1904
1906
  },
1905
1907
  {
1906
1908
  name: 'pointRadius',
1907
- title: 'Point Size',
1909
+ title: '@dashboard:widgets.line-chart.point-radius',
1908
1910
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1909
1911
  schema: {
1910
1912
  defaultValue: 4,
@@ -1924,7 +1926,7 @@ const AXPLineChartWidget = {
1924
1926
  },
1925
1927
  {
1926
1928
  name: 'fillArea',
1927
- title: 'Fill Area',
1929
+ title: '@dashboard:widgets.line-chart.fill-area',
1928
1930
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1929
1931
  schema: {
1930
1932
  defaultValue: false,
@@ -1939,19 +1941,20 @@ const AXPLineChartWidget = {
1939
1941
  },
1940
1942
  {
1941
1943
  name: 'fillOpacity',
1942
- title: 'Fill Opacity',
1944
+ title: '@dashboard:widgets.line-chart.fill-opacity',
1943
1945
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1944
1946
  schema: {
1945
- defaultValue: 10,
1947
+ defaultValue: 0.1,
1946
1948
  dataType: 'number',
1947
1949
  interface: {
1948
1950
  name: 'fillOpacity',
1949
1951
  path: 'options.fillOpacity',
1950
1952
  type: AXPWidgetsCatalog.number,
1951
1953
  options: {
1952
- placeholder: '0-100',
1954
+ placeholder: '0-1',
1953
1955
  minValue: 0,
1954
- maxValue: 100,
1956
+ maxValue: 1,
1957
+ step: 0.1,
1955
1958
  },
1956
1959
  },
1957
1960
  },
@@ -1960,7 +1963,7 @@ const AXPLineChartWidget = {
1960
1963
  // ====== Tooltip Settings ======
1961
1964
  {
1962
1965
  name: 'showTooltip',
1963
- title: 'Show Tooltip',
1966
+ title: '@dashboard:widgets.line-chart.show-tooltip',
1964
1967
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1965
1968
  schema: {
1966
1969
  defaultValue: true,
@@ -1975,10 +1978,10 @@ const AXPLineChartWidget = {
1975
1978
  },
1976
1979
  {
1977
1980
  name: 'showCrosshair',
1978
- title: 'Show Crosshair',
1981
+ title: '@dashboard:widgets.line-chart.show-crosshair',
1979
1982
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1980
1983
  schema: {
1981
- defaultValue: false,
1984
+ defaultValue: true,
1982
1985
  dataType: 'boolean',
1983
1986
  interface: {
1984
1987
  name: 'showCrosshair',
@@ -1991,7 +1994,7 @@ const AXPLineChartWidget = {
1991
1994
  // ====== Animation Settings ======
1992
1995
  {
1993
1996
  name: 'animationEasing',
1994
- title: 'Animation Easing',
1997
+ title: '@dashboard:widgets.line-chart.animation-easing',
1995
1998
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1996
1999
  schema: {
1997
2000
  defaultValue: 'cubic-out',
@@ -2021,7 +2024,7 @@ const AXPLineChartWidget = {
2021
2024
  },
2022
2025
  {
2023
2026
  name: 'animationDuration',
2024
- title: 'Animation Duration',
2027
+ title: '@dashboard:widgets.line-chart.animation-duration',
2025
2028
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2026
2029
  schema: {
2027
2030
  defaultValue: 800,
@@ -2047,12 +2050,12 @@ const AXPLineChartWidget = {
2047
2050
  },
2048
2051
  meta: {
2049
2052
  dimensions: {
2050
- width: 5,
2051
- height: 6,
2053
+ width: 3,
2054
+ height: 4,
2052
2055
  minWidth: 2,
2053
2056
  minHeight: 2,
2054
- maxWidth: 6,
2055
- maxHeight: 7,
2057
+ maxWidth: 4,
2058
+ maxHeight: 5,
2056
2059
  },
2057
2060
  },
2058
2061
  };
@@ -2150,7 +2153,17 @@ const AXPStickyNoteWidget = {
2150
2153
  groups: [AXPWidgetGroupEnum.DashboardWidget],
2151
2154
  type: 'dashboard',
2152
2155
  icon: 'fa-light fa-sticky-note',
2153
- properties: [AXP_DATA_PATH_PROPERTY, AXP_BG_COLOR_PROPERTY, plainTextDefaultProperty()],
2156
+ properties: [
2157
+ AXP_DATA_PATH_PROPERTY,
2158
+ {
2159
+ ...AXP_BG_COLOR_PROPERTY,
2160
+ title: '@dashboard:widgets.sticky-note.background-color',
2161
+ },
2162
+ {
2163
+ ...plainTextDefaultProperty(),
2164
+ title: '@dashboard:widgets.sticky-note.note-text',
2165
+ },
2166
+ ],
2154
2167
  components: {
2155
2168
  view: {
2156
2169
  component: () => Promise.resolve().then(function () { return stickyNoteWidget_component; }).then((c) => c.AXPStickyNoteWidgetViewComponent),
@@ -2263,7 +2276,7 @@ class AXPTaskListWidgetViewComponent extends AXPValueWidgetComponent {
2263
2276
  return 'Tomorrow';
2264
2277
  if (diffDays < 7)
2265
2278
  return this.datePipe.transform(dateObj, 'EEE') || '';
2266
- return this.datePipe.transform(dateObj, 'MM/dd/yyyy') || '';
2279
+ return this.datePipe.transform(dateObj, 'MM/DD/YYYY') || '';
2267
2280
  }
2268
2281
  getPriorityColor(priority) {
2269
2282
  if (!priority)
@@ -2291,7 +2304,7 @@ class AXPTaskListWidgetViewComponent extends AXPValueWidgetComponent {
2291
2304
  return Math.floor(diffMs / (1000 * 60 * 60 * 24));
2292
2305
  }
2293
2306
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPTaskListWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2294
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AXPTaskListWidgetViewComponent, isStandalone: true, selector: "ng-component", outputs: { taskClick: "taskClick", taskCompleted: "taskCompleted" }, providers: [DatePipe], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-size-full ax-p-4\">\n <!-- Header -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-3\">\n <h3 class=\"ax-text-lg ax-font-semibold\">{{ 'widget.tasklist.title' | translate | async }}</h3>\n <div class=\"ax-flex ax-gap-2\">\n @if(getPendingTaskCount() > 0){\n <ax-badge\n [text]=\"getPendingTaskCount() + ' ' + ('widget.tasklist.pending' | translate | async)\"\n [color]=\"'warning'\"\n size=\"sm\"\n class=\"ax-ml-1\"\n >\n </ax-badge>\n } @if(getCompletedTaskCount() > 0){\n <ax-badge\n [text]=\"getCompletedTaskCount() + ' ' + ('widget.tasklist.completed' | translate | async)\"\n [color]=\"'success'\"\n size=\"sm\"\n class=\"ax-ml-1\"\n >\n </ax-badge>\n }\n </div>\n </div>\n\n <!-- Task List -->\n <div class=\"ax-space-y-4 ax-my-4 ax-px-2\">\n @if (showCategories() && hasCategories()) {\n <!-- Categorized Tasks -->\n @for (category of getCategories(); track category) {\n <div class=\"ax-mb-3\">\n <!-- Category Header -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-2 ax-h-5\">\n <h4 class=\"ax-font-medium ax-text-gray-700\">{{ category }}</h4>\n @if(getCategoryTaskCount(category)){\n <ax-badge [text]=\"getCategoryTaskCount(category).toString()\" [color]=\"'primary'\" size=\"sm\"></ax-badge>\n }\n </div>\n <!-- Tasks in Category -->\n @for (task of getTasksByCategory(category); track task.id) {\n <ng-container\n [ngTemplateOutlet]=\"taskItemTemplateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: task }\"\n ></ng-container>\n }\n </div>\n } } @else {\n <!-- Uncategorized Tasks -->\n @for (task of taskItems(); track task.id) {\n <ng-container\n [ngTemplateOutlet]=\"taskItemTemplateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: task }\"\n ></ng-container>\n } @empty {\n <!-- Empty State -->\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-py-12 ax-px-4 ax-text-gray-400\">\n <ax-icon class=\"ax-text-4xl ax-mb-3 ax-text-gray-300\">\n <i class=\"fa-light fa-clipboard-list-check\"></i>\n </ax-icon>\n <p class=\"ax-text-center\">{{ 'widget.tasklist.noTasks' | translate | async }}</p>\n </div>\n } }\n </div>\n</div>\n\n<!-- Task Item Template -->\n<ng-template #taskItemTemplateRef let-task>\n <div class=\"ax-flex ax-gap-3 ax-items-center ax-py-2 ax-border-b ax-border-gray-100 last:ax-border-0\">\n <!-- Checkbox -->\n <ax-check-box\n class=\"ax-flex-shrink-0\"\n [value]=\"task.completed\"\n [disabled]=\"!allowMarkComplete()\"\n (valueChange)=\"onTaskCompletionChange(task, $event)\"\n >\n </ax-check-box>\n\n <!-- Task Details -->\n <div class=\"ax-overflow-hidden ax-grow ax-text-start\" (click)=\"onTaskClick(task)\">\n <!-- Title and Priority -->\n <div class=\"ax-flex ax-items-center ax-gap-2\">\n <h6\n class=\"ax-font-semibold ax-truncate ax-pb-1\"\n [class.ax-line-through]=\"task.completed\"\n [class.ax-text-gray-400]=\"task.completed\"\n >\n {{ task.title }}\n </h6>\n @if(showPriority() && task.priority) {\n <ax-badge [color]=\"getPriorityColor(task.priority)\" [text]=\"task.priority\" size=\"sm\" class=\"ax-ml-1\"></ax-badge>\n }\n </div>\n\n <!-- Metadata -->\n <div class=\"ax-flex ax-flex-wrap ax-gap-x-3 ax-gap-y-1 ax-mt-1 ax-text-xs ax-text-gray-500\">\n @if(showDate() && task.dueDate) {\n <span class=\"ax-flex ax-items-center ax-gap-1\" [class.ax-text-danger-500]=\"getDaysDifference(task.dueDate) < 0\">\n <ax-icon><i class=\"fa-light fa-calendar\"></i></ax-icon>\n {{ formatDueDate(task.dueDate) }}\n </span>\n } @if(showAssignee() && task.assignedTo) {\n <span class=\"ax-flex ax-items-center ax-gap-1\">\n <ax-icon><i class=\"fa-light fa-user\"></i></ax-icon>\n {{ task.assignedTo.name }}\n </span>\n }\n </div>\n </div>\n </div>\n</ng-template>\n", styles: [":host{display:block;height:100%;width:100%}.task-completed{text-decoration:line-through;color:var(--ax-text-secondary)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXTabsModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i3.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "component", type: i4.AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "checked", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { kind: "ngmodule", type: AXLabelModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2307
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AXPTaskListWidgetViewComponent, isStandalone: true, selector: "ng-component", outputs: { taskClick: "taskClick", taskCompleted: "taskCompleted" }, providers: [DatePipe], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-size-full ax-p-4 ax-flex ax-flex-col\">\n <!-- Header -->\n <div class=\"ax-flex ax-justify-between ax-items-center\">\n <h3 class=\"ax-text-lg ax-font-semibold ax-flex ax-items-center ax-gap-2\">\n <ax-icon class=\"ax-text-primary-500\">\n <i class=\"fa-light fa-clipboard-list-check\"></i>\n </ax-icon>\n {{ 'tasklist.title' | translate: { scope: 'dashboard' } | async }}\n </h3>\n <div class=\"ax-flex ax-gap-2\">\n @if (getPendingTaskCount() > 0) {\n <ax-badge\n [text]=\"getPendingTaskCount() + ' ' + ('tasklist.pending' | translate: { scope: 'dashboard' } | async)\"\n [color]=\"'warning'\"\n size=\"sm\"\n class=\"ax-ml-1\"\n >\n </ax-badge>\n }\n @if (getCompletedTaskCount() > 0) {\n <ax-badge\n [text]=\"getCompletedTaskCount() + ' ' + ('tasklist.completed' | translate: { scope: 'dashboard' } | async)\"\n [color]=\"'success'\"\n size=\"sm\"\n class=\"ax-ml-1\"\n >\n </ax-badge>\n }\n </div>\n </div>\n\n <!-- Task List -->\n <div class=\"ax-space-y-4 ax-my-4 ax-px-1 ax-overflow-auto ax-grow\">\n @if (showCategories() && hasCategories()) {\n <!-- Categorized Tasks -->\n @for (category of getCategories(); track category) {\n <div class=\"ax-mb-5\">\n <!-- Category Header -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-3 ax-h-5\">\n <h4 class=\"ax-font-medium category-header\">{{ category }}</h4>\n @if (getCategoryTaskCount(category)) {\n <ax-badge\n [text]=\"getCategoryTaskCount(category).toString()\"\n [color]=\"'primary'\"\n size=\"sm\"\n class=\"ax-rounded-full\"\n ></ax-badge>\n }\n </div>\n <!-- Tasks in Category -->\n <div class=\"ax-space-y-2\">\n @for (task of getTasksByCategory(category); track task.id) {\n <ng-container\n [ngTemplateOutlet]=\"taskItemTemplateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: task }\"\n ></ng-container>\n }\n </div>\n </div>\n }\n } @else {\n <!-- Uncategorized Tasks -->\n <div class=\"ax-space-y-2\">\n @for (task of taskItems(); track task.id) {\n <ng-container\n [ngTemplateOutlet]=\"taskItemTemplateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: task }\"\n ></ng-container>\n } @empty {\n <!-- Empty State -->\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-py-14 ax-px-4 ax-text-gray-400 empty-state\"\n >\n <ax-icon class=\"ax-text-5xl ax-mb-3 ax-text-gray-300\">\n <i class=\"fa-light fa-clipboard-list-check\"></i>\n </ax-icon>\n <p class=\"ax-text-center ax-font-medium\">\n {{ 'tasklist.noTasks' | translate: { scope: 'dashboard' } | async }}\n </p>\n <p class=\"ax-text-center ax-text-sm ax-mt-2\">\n {{ 'tasklist.addTask' | translate: { scope: 'dashboard' } | async }}\n </p>\n </div>\n }\n </div>\n }\n </div>\n</div>\n\n<!-- Task Item Template -->\n<ng-template #taskItemTemplateRef let-task>\n <div\n class=\"ax-flex ax-gap-3 ax-items-start ax-p-3 ax-rounded-lg task-item\"\n [class.priority-high]=\"task.priority === 'high'\"\n [class.priority-medium]=\"task.priority === 'medium'\"\n [class.priority-low]=\"task.priority === 'low'\"\n [class.ax-bg-surface]=\"task.completed\"\n >\n <!-- Checkbox -->\n <ax-check-box\n class=\"ax-flex-shrink-0 ax-mt-1 task-checkbox\"\n [value]=\"task.completed\"\n [disabled]=\"!allowMarkComplete()\"\n (valueChange)=\"onTaskCompletionChange(task, $event)\"\n >\n </ax-check-box>\n\n <!-- Task Details -->\n <div class=\"ax-overflow-hidden ax-grow ax-text-start\" (click)=\"onTaskClick(task)\">\n <!-- Title and Priority -->\n <div class=\"ax-flex ax-items-center ax-gap-2\">\n <h6 class=\"ax-font-medium ax-truncate ax-pb-1\" [title]=\"task.title\" [class.task-completed]=\"task.completed\">\n {{ task.title }}\n </h6>\n @if (showPriority() && task.priority) {\n <ax-badge\n [color]=\"getPriorityColor(task.priority)\"\n [text]=\"task.priority\"\n size=\"sm\"\n class=\"ax-ml-1 ax-rounded-full\"\n ></ax-badge>\n }\n </div>\n\n <!-- Metadata -->\n <div class=\"ax-flex ax-flex-wrap ax-gap-x-3 ax-gap-y-1 ax-mt-2 ax-text-xs ax-text-gray-500\">\n @if (showDate() && task.dueDate) {\n <span\n class=\"ax-flex ax-items-center ax-gap-1 due-date\"\n [class.ax-text-danger-500]=\"getDaysDifference(task.dueDate) < 0\"\n [class.overdue]=\"getDaysDifference(task.dueDate) < 0\"\n >\n <ax-icon><i class=\"fa-light fa-calendar\"></i></ax-icon>\n {{ formatDueDate(task.dueDate) }}\n </span>\n }\n @if (showAssignee() && task.assignedTo) {\n <span class=\"ax-flex ax-items-center ax-gap-1\">\n @if (task.assignedTo.image) {\n <ax-icon class=\"ax-bg-primary-100 ax-text-primary-500 ax-rounded-full ax-p-1\">\n <i class=\"fa-light fa-user\"></i>\n </ax-icon>\n } @else {\n <ax-icon><i class=\"fa-light fa-user\"></i></ax-icon>\n }\n {{ task.assignedTo.name }}\n </span>\n }\n </div>\n </div>\n </div>\n</ng-template>\n", styles: [":host{display:block;height:100%;width:100%}.task-item{border-radius:8px;transition:all .2s ease-in-out;border-left:3px solid transparent}.task-item:hover{background-color:rgba(var(--ax-sys-color-on-surface),.1);transform:translateY(-2px);box-shadow:0 2px 8px rgba(0,0,0,.05)}.task-item.priority-high{border-left-color:rgb(var(--ax-sys-color-danger-500))}.task-item.priority-medium{border-left-color:rgb(var(--ax-sys-color-warning-500))}.task-item.priority-low{border-left-color:rgb(var(--ax-sys-color-success-500))}.task-item:active{transform:translateY(0);box-shadow:0 1px 3px rgba(0,0,0,.05)}.task-completed{text-decoration:line-through;color:var(--ax-text-secondary);opacity:.7;transition:all .3s ease}.category-header{position:relative}.category-header:after{content:\"\";position:absolute;bottom:-8px;left:0;width:40px;height:3px;background-color:var(--ax-primary-500);border-radius:3px;transition:width .3s ease}.category-header:hover:after{width:60px}.empty-state{animation:fadeIn .5s ease}@keyframes fadeIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.task-checkbox ::ng-deep .ax-checkbox{transition:all .2s ease}.task-checkbox ::ng-deep .ax-checkbox:hover{transform:scale(1.1)}.due-date.overdue{animation:pulse 2s infinite}@keyframes pulse{0%{opacity:.7}50%{opacity:1}to{opacity:.7}}.ax-space-y-2>*{animation:slideInRight .3s ease forwards;opacity:0}.ax-space-y-2>*:nth-child(1){animation-delay:.05s}.ax-space-y-2>*:nth-child(2){animation-delay:.1s}.ax-space-y-2>*:nth-child(3){animation-delay:.15s}.ax-space-y-2>*:nth-child(4){animation-delay:.2s}.ax-space-y-2>*:nth-child(5){animation-delay:.25s}.ax-space-y-2>*:nth-child(6){animation-delay:.3s}.ax-space-y-2>*:nth-child(7){animation-delay:.35s}.ax-space-y-2>*:nth-child(8){animation-delay:.4s}.ax-space-y-2>*:nth-child(9){animation-delay:.45s}.ax-space-y-2>*:nth-child(10){animation-delay:.5s}@keyframes slideInRight{0%{opacity:0;transform:translate(10px)}to{opacity:1;transform:translate(0)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXTabsModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i3.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "component", type: i4.AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "checked", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { kind: "ngmodule", type: AXLabelModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2$3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2295
2308
  }
2296
2309
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPTaskListWidgetViewComponent, decorators: [{
2297
2310
  type: Component,
@@ -2306,7 +2319,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
2306
2319
  AXCheckBoxModule,
2307
2320
  AXLabelModule,
2308
2321
  AXTranslationModule,
2309
- ], providers: [DatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-size-full ax-p-4\">\n <!-- Header -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-3\">\n <h3 class=\"ax-text-lg ax-font-semibold\">{{ 'widget.tasklist.title' | translate | async }}</h3>\n <div class=\"ax-flex ax-gap-2\">\n @if(getPendingTaskCount() > 0){\n <ax-badge\n [text]=\"getPendingTaskCount() + ' ' + ('widget.tasklist.pending' | translate | async)\"\n [color]=\"'warning'\"\n size=\"sm\"\n class=\"ax-ml-1\"\n >\n </ax-badge>\n } @if(getCompletedTaskCount() > 0){\n <ax-badge\n [text]=\"getCompletedTaskCount() + ' ' + ('widget.tasklist.completed' | translate | async)\"\n [color]=\"'success'\"\n size=\"sm\"\n class=\"ax-ml-1\"\n >\n </ax-badge>\n }\n </div>\n </div>\n\n <!-- Task List -->\n <div class=\"ax-space-y-4 ax-my-4 ax-px-2\">\n @if (showCategories() && hasCategories()) {\n <!-- Categorized Tasks -->\n @for (category of getCategories(); track category) {\n <div class=\"ax-mb-3\">\n <!-- Category Header -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-2 ax-h-5\">\n <h4 class=\"ax-font-medium ax-text-gray-700\">{{ category }}</h4>\n @if(getCategoryTaskCount(category)){\n <ax-badge [text]=\"getCategoryTaskCount(category).toString()\" [color]=\"'primary'\" size=\"sm\"></ax-badge>\n }\n </div>\n <!-- Tasks in Category -->\n @for (task of getTasksByCategory(category); track task.id) {\n <ng-container\n [ngTemplateOutlet]=\"taskItemTemplateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: task }\"\n ></ng-container>\n }\n </div>\n } } @else {\n <!-- Uncategorized Tasks -->\n @for (task of taskItems(); track task.id) {\n <ng-container\n [ngTemplateOutlet]=\"taskItemTemplateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: task }\"\n ></ng-container>\n } @empty {\n <!-- Empty State -->\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-py-12 ax-px-4 ax-text-gray-400\">\n <ax-icon class=\"ax-text-4xl ax-mb-3 ax-text-gray-300\">\n <i class=\"fa-light fa-clipboard-list-check\"></i>\n </ax-icon>\n <p class=\"ax-text-center\">{{ 'widget.tasklist.noTasks' | translate | async }}</p>\n </div>\n } }\n </div>\n</div>\n\n<!-- Task Item Template -->\n<ng-template #taskItemTemplateRef let-task>\n <div class=\"ax-flex ax-gap-3 ax-items-center ax-py-2 ax-border-b ax-border-gray-100 last:ax-border-0\">\n <!-- Checkbox -->\n <ax-check-box\n class=\"ax-flex-shrink-0\"\n [value]=\"task.completed\"\n [disabled]=\"!allowMarkComplete()\"\n (valueChange)=\"onTaskCompletionChange(task, $event)\"\n >\n </ax-check-box>\n\n <!-- Task Details -->\n <div class=\"ax-overflow-hidden ax-grow ax-text-start\" (click)=\"onTaskClick(task)\">\n <!-- Title and Priority -->\n <div class=\"ax-flex ax-items-center ax-gap-2\">\n <h6\n class=\"ax-font-semibold ax-truncate ax-pb-1\"\n [class.ax-line-through]=\"task.completed\"\n [class.ax-text-gray-400]=\"task.completed\"\n >\n {{ task.title }}\n </h6>\n @if(showPriority() && task.priority) {\n <ax-badge [color]=\"getPriorityColor(task.priority)\" [text]=\"task.priority\" size=\"sm\" class=\"ax-ml-1\"></ax-badge>\n }\n </div>\n\n <!-- Metadata -->\n <div class=\"ax-flex ax-flex-wrap ax-gap-x-3 ax-gap-y-1 ax-mt-1 ax-text-xs ax-text-gray-500\">\n @if(showDate() && task.dueDate) {\n <span class=\"ax-flex ax-items-center ax-gap-1\" [class.ax-text-danger-500]=\"getDaysDifference(task.dueDate) < 0\">\n <ax-icon><i class=\"fa-light fa-calendar\"></i></ax-icon>\n {{ formatDueDate(task.dueDate) }}\n </span>\n } @if(showAssignee() && task.assignedTo) {\n <span class=\"ax-flex ax-items-center ax-gap-1\">\n <ax-icon><i class=\"fa-light fa-user\"></i></ax-icon>\n {{ task.assignedTo.name }}\n </span>\n }\n </div>\n </div>\n </div>\n</ng-template>\n", styles: [":host{display:block;height:100%;width:100%}.task-completed{text-decoration:line-through;color:var(--ax-text-secondary)}\n"] }]
2322
+ ], providers: [DatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-size-full ax-p-4 ax-flex ax-flex-col\">\n <!-- Header -->\n <div class=\"ax-flex ax-justify-between ax-items-center\">\n <h3 class=\"ax-text-lg ax-font-semibold ax-flex ax-items-center ax-gap-2\">\n <ax-icon class=\"ax-text-primary-500\">\n <i class=\"fa-light fa-clipboard-list-check\"></i>\n </ax-icon>\n {{ 'tasklist.title' | translate: { scope: 'dashboard' } | async }}\n </h3>\n <div class=\"ax-flex ax-gap-2\">\n @if (getPendingTaskCount() > 0) {\n <ax-badge\n [text]=\"getPendingTaskCount() + ' ' + ('tasklist.pending' | translate: { scope: 'dashboard' } | async)\"\n [color]=\"'warning'\"\n size=\"sm\"\n class=\"ax-ml-1\"\n >\n </ax-badge>\n }\n @if (getCompletedTaskCount() > 0) {\n <ax-badge\n [text]=\"getCompletedTaskCount() + ' ' + ('tasklist.completed' | translate: { scope: 'dashboard' } | async)\"\n [color]=\"'success'\"\n size=\"sm\"\n class=\"ax-ml-1\"\n >\n </ax-badge>\n }\n </div>\n </div>\n\n <!-- Task List -->\n <div class=\"ax-space-y-4 ax-my-4 ax-px-1 ax-overflow-auto ax-grow\">\n @if (showCategories() && hasCategories()) {\n <!-- Categorized Tasks -->\n @for (category of getCategories(); track category) {\n <div class=\"ax-mb-5\">\n <!-- Category Header -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-3 ax-h-5\">\n <h4 class=\"ax-font-medium category-header\">{{ category }}</h4>\n @if (getCategoryTaskCount(category)) {\n <ax-badge\n [text]=\"getCategoryTaskCount(category).toString()\"\n [color]=\"'primary'\"\n size=\"sm\"\n class=\"ax-rounded-full\"\n ></ax-badge>\n }\n </div>\n <!-- Tasks in Category -->\n <div class=\"ax-space-y-2\">\n @for (task of getTasksByCategory(category); track task.id) {\n <ng-container\n [ngTemplateOutlet]=\"taskItemTemplateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: task }\"\n ></ng-container>\n }\n </div>\n </div>\n }\n } @else {\n <!-- Uncategorized Tasks -->\n <div class=\"ax-space-y-2\">\n @for (task of taskItems(); track task.id) {\n <ng-container\n [ngTemplateOutlet]=\"taskItemTemplateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: task }\"\n ></ng-container>\n } @empty {\n <!-- Empty State -->\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-py-14 ax-px-4 ax-text-gray-400 empty-state\"\n >\n <ax-icon class=\"ax-text-5xl ax-mb-3 ax-text-gray-300\">\n <i class=\"fa-light fa-clipboard-list-check\"></i>\n </ax-icon>\n <p class=\"ax-text-center ax-font-medium\">\n {{ 'tasklist.noTasks' | translate: { scope: 'dashboard' } | async }}\n </p>\n <p class=\"ax-text-center ax-text-sm ax-mt-2\">\n {{ 'tasklist.addTask' | translate: { scope: 'dashboard' } | async }}\n </p>\n </div>\n }\n </div>\n }\n </div>\n</div>\n\n<!-- Task Item Template -->\n<ng-template #taskItemTemplateRef let-task>\n <div\n class=\"ax-flex ax-gap-3 ax-items-start ax-p-3 ax-rounded-lg task-item\"\n [class.priority-high]=\"task.priority === 'high'\"\n [class.priority-medium]=\"task.priority === 'medium'\"\n [class.priority-low]=\"task.priority === 'low'\"\n [class.ax-bg-surface]=\"task.completed\"\n >\n <!-- Checkbox -->\n <ax-check-box\n class=\"ax-flex-shrink-0 ax-mt-1 task-checkbox\"\n [value]=\"task.completed\"\n [disabled]=\"!allowMarkComplete()\"\n (valueChange)=\"onTaskCompletionChange(task, $event)\"\n >\n </ax-check-box>\n\n <!-- Task Details -->\n <div class=\"ax-overflow-hidden ax-grow ax-text-start\" (click)=\"onTaskClick(task)\">\n <!-- Title and Priority -->\n <div class=\"ax-flex ax-items-center ax-gap-2\">\n <h6 class=\"ax-font-medium ax-truncate ax-pb-1\" [title]=\"task.title\" [class.task-completed]=\"task.completed\">\n {{ task.title }}\n </h6>\n @if (showPriority() && task.priority) {\n <ax-badge\n [color]=\"getPriorityColor(task.priority)\"\n [text]=\"task.priority\"\n size=\"sm\"\n class=\"ax-ml-1 ax-rounded-full\"\n ></ax-badge>\n }\n </div>\n\n <!-- Metadata -->\n <div class=\"ax-flex ax-flex-wrap ax-gap-x-3 ax-gap-y-1 ax-mt-2 ax-text-xs ax-text-gray-500\">\n @if (showDate() && task.dueDate) {\n <span\n class=\"ax-flex ax-items-center ax-gap-1 due-date\"\n [class.ax-text-danger-500]=\"getDaysDifference(task.dueDate) < 0\"\n [class.overdue]=\"getDaysDifference(task.dueDate) < 0\"\n >\n <ax-icon><i class=\"fa-light fa-calendar\"></i></ax-icon>\n {{ formatDueDate(task.dueDate) }}\n </span>\n }\n @if (showAssignee() && task.assignedTo) {\n <span class=\"ax-flex ax-items-center ax-gap-1\">\n @if (task.assignedTo.image) {\n <ax-icon class=\"ax-bg-primary-100 ax-text-primary-500 ax-rounded-full ax-p-1\">\n <i class=\"fa-light fa-user\"></i>\n </ax-icon>\n } @else {\n <ax-icon><i class=\"fa-light fa-user\"></i></ax-icon>\n }\n {{ task.assignedTo.name }}\n </span>\n }\n </div>\n </div>\n </div>\n</ng-template>\n", styles: [":host{display:block;height:100%;width:100%}.task-item{border-radius:8px;transition:all .2s ease-in-out;border-left:3px solid transparent}.task-item:hover{background-color:rgba(var(--ax-sys-color-on-surface),.1);transform:translateY(-2px);box-shadow:0 2px 8px rgba(0,0,0,.05)}.task-item.priority-high{border-left-color:rgb(var(--ax-sys-color-danger-500))}.task-item.priority-medium{border-left-color:rgb(var(--ax-sys-color-warning-500))}.task-item.priority-low{border-left-color:rgb(var(--ax-sys-color-success-500))}.task-item:active{transform:translateY(0);box-shadow:0 1px 3px rgba(0,0,0,.05)}.task-completed{text-decoration:line-through;color:var(--ax-text-secondary);opacity:.7;transition:all .3s ease}.category-header{position:relative}.category-header:after{content:\"\";position:absolute;bottom:-8px;left:0;width:40px;height:3px;background-color:var(--ax-primary-500);border-radius:3px;transition:width .3s ease}.category-header:hover:after{width:60px}.empty-state{animation:fadeIn .5s ease}@keyframes fadeIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.task-checkbox ::ng-deep .ax-checkbox{transition:all .2s ease}.task-checkbox ::ng-deep .ax-checkbox:hover{transform:scale(1.1)}.due-date.overdue{animation:pulse 2s infinite}@keyframes pulse{0%{opacity:.7}50%{opacity:1}to{opacity:.7}}.ax-space-y-2>*{animation:slideInRight .3s ease forwards;opacity:0}.ax-space-y-2>*:nth-child(1){animation-delay:.05s}.ax-space-y-2>*:nth-child(2){animation-delay:.1s}.ax-space-y-2>*:nth-child(3){animation-delay:.15s}.ax-space-y-2>*:nth-child(4){animation-delay:.2s}.ax-space-y-2>*:nth-child(5){animation-delay:.25s}.ax-space-y-2>*:nth-child(6){animation-delay:.3s}.ax-space-y-2>*:nth-child(7){animation-delay:.35s}.ax-space-y-2>*:nth-child(8){animation-delay:.4s}.ax-space-y-2>*:nth-child(9){animation-delay:.45s}.ax-space-y-2>*:nth-child(10){animation-delay:.5s}@keyframes slideInRight{0%{opacity:0;transform:translate(10px)}to{opacity:1;transform:translate(0)}}\n"] }]
2310
2323
  }] });
2311
2324
 
2312
2325
  var tasklistWidget_component = /*#__PURE__*/Object.freeze({
@@ -2326,7 +2339,7 @@ const AXPTaskListWidget = {
2326
2339
  // ====== Title ======
2327
2340
  {
2328
2341
  name: 'title',
2329
- title: 'Chart Title',
2342
+ title: '@dashboard:widgets.task-list.chart-title',
2330
2343
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2331
2344
  schema: {
2332
2345
  defaultValue: '',
@@ -2345,7 +2358,7 @@ const AXPTaskListWidget = {
2345
2358
  // Display options
2346
2359
  {
2347
2360
  name: 'maxItems',
2348
- title: 'Max Items',
2361
+ title: '@dashboard:widgets.task-list.max-items',
2349
2362
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2350
2363
  schema: {
2351
2364
  defaultValue: 10,
@@ -2364,7 +2377,7 @@ const AXPTaskListWidget = {
2364
2377
  },
2365
2378
  {
2366
2379
  name: 'showDate',
2367
- title: 'Show Date',
2380
+ title: '@dashboard:widgets.task-list.show-date',
2368
2381
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2369
2382
  schema: {
2370
2383
  defaultValue: true,
@@ -2379,7 +2392,7 @@ const AXPTaskListWidget = {
2379
2392
  },
2380
2393
  {
2381
2394
  name: 'showAssignee',
2382
- title: 'Show Assignee',
2395
+ title: '@dashboard:widgets.task-list.show-assignee',
2383
2396
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2384
2397
  schema: {
2385
2398
  defaultValue: true,
@@ -2394,7 +2407,7 @@ const AXPTaskListWidget = {
2394
2407
  },
2395
2408
  {
2396
2409
  name: 'groupByCategory',
2397
- title: 'Group by Category',
2410
+ title: '@dashboard:widgets.task-list.group-by-category',
2398
2411
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2399
2412
  schema: {
2400
2413
  defaultValue: true,
@@ -2409,7 +2422,7 @@ const AXPTaskListWidget = {
2409
2422
  },
2410
2423
  {
2411
2424
  name: 'showPriority',
2412
- title: 'Show Priority',
2425
+ title: '@dashboard:widgets.task-list.show-priority',
2413
2426
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2414
2427
  schema: {
2415
2428
  defaultValue: true,
@@ -2424,7 +2437,7 @@ const AXPTaskListWidget = {
2424
2437
  },
2425
2438
  {
2426
2439
  name: 'allowMarkComplete',
2427
- title: 'Allow Complete',
2440
+ title: '@dashboard:widgets.task-list.allow-complete',
2428
2441
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2429
2442
  schema: {
2430
2443
  defaultValue: true,
@@ -2445,7 +2458,7 @@ const AXPTaskListWidget = {
2445
2458
  },
2446
2459
  meta: {
2447
2460
  dimensions: {
2448
- width: 5,
2461
+ width: 3,
2449
2462
  height: 7,
2450
2463
  minWidth: 3,
2451
2464
  minHeight: 4,
@@ -3080,8 +3093,7 @@ class AXPWeatherWidgetViewComponent extends AXPValueWidgetComponent {
3080
3093
  setTimeout(() => this.cdr.detectChanges());
3081
3094
  },
3082
3095
  error: (error) => {
3083
- this.hasError.set(true);
3084
- this.errorMessage.set(error.message || 'Failed to load weather data. Please try again.');
3096
+ this.handleError(error);
3085
3097
  this.isLoading.set(false);
3086
3098
  this.isForecastLoading.set(false);
3087
3099
  this.cdr.detectChanges();
@@ -3102,8 +3114,7 @@ class AXPWeatherWidgetViewComponent extends AXPValueWidgetComponent {
3102
3114
  setTimeout(() => this.cdr.detectChanges());
3103
3115
  },
3104
3116
  error: (error) => {
3105
- this.hasError.set(true);
3106
- this.errorMessage.set(error.message || 'Failed to load weather data. Please try again.');
3117
+ this.handleError(error);
3107
3118
  this.isLoading.set(false);
3108
3119
  this.cdr.detectChanges();
3109
3120
  },
@@ -3208,7 +3219,11 @@ class AXPWeatherWidgetViewComponent extends AXPValueWidgetComponent {
3208
3219
  */
3209
3220
  getConditionName(conditionId) {
3210
3221
  const condition = this.weatherService.getCondition(conditionId);
3211
- return condition?.name || 'Unknown';
3222
+ if (!condition?.name)
3223
+ return 'weather.conditions.sunny';
3224
+ // Convert condition name to lowercase and replace spaces with hyphens
3225
+ const formattedName = condition.name.toLowerCase().replace(/\s+/g, '-');
3226
+ return `weather.conditions.${formattedName}`;
3212
3227
  }
3213
3228
  /**
3214
3229
  * Gets the color for a weather condition
@@ -3226,22 +3241,60 @@ class AXPWeatherWidgetViewComponent extends AXPValueWidgetComponent {
3226
3241
  cleanupChart() {
3227
3242
  this.clearRefreshTimer();
3228
3243
  }
3244
+ handleError(error) {
3245
+ console.error('Weather widget error:', error);
3246
+ this.hasError.set(true);
3247
+ // Check if it's a network error
3248
+ if (error.status === 0) {
3249
+ this.errorMessage.set('weather.error.network');
3250
+ return;
3251
+ }
3252
+ // Check if it's an API error
3253
+ if (error.status >= 400 && error.status < 500) {
3254
+ this.errorMessage.set('weather.error.api');
3255
+ return;
3256
+ }
3257
+ // Default error message
3258
+ this.errorMessage.set('weather.error.general');
3259
+ }
3260
+ getTemperatureUnit() {
3261
+ return this.temperatureUnit() === '°C' ? 'weather.units.celsius' : 'weather.units.fahrenheit';
3262
+ }
3263
+ getWindSpeedUnit() {
3264
+ return this.windSpeedUnit() === 'km/h' ? 'weather.units.kmh' : 'weather.units.mph';
3265
+ }
3266
+ getDayName(date) {
3267
+ const today = new Date();
3268
+ const tomorrow = new Date(today);
3269
+ tomorrow.setDate(tomorrow.getDate() + 1);
3270
+ if (date.toDateString() === today.toDateString()) {
3271
+ return 'weather.days.today';
3272
+ }
3273
+ if (date.toDateString() === tomorrow.toDateString()) {
3274
+ return 'weather.days.tomorrow';
3275
+ }
3276
+ const days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
3277
+ return `weather.days.${days[date.getDay()]}`;
3278
+ }
3279
+ parseDate(dateStr) {
3280
+ return new Date(dateStr);
3281
+ }
3229
3282
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPWeatherWidgetViewComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
3230
3283
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AXPWeatherWidgetViewComponent, isStandalone: true, selector: "ng-component", providers: [
3231
3284
  {
3232
3285
  provide: AXPWeatherApiAbstract,
3233
3286
  useClass: AXPWeatherApiService,
3234
3287
  },
3235
- ], viewQueries: [{ propertyName: "containerEl", first: true, predicate: ["containerElement"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Weather Widget Component Template -->\n<div class=\"axp-weather-container\" #containerElement>\n <!-- Loading indicator -->\n @if (isLoading()) {\n <div class=\"axp-weather-loading-overlay\">\n <div class=\"axp-weather-loading-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading weather data...</span>\n </div>\n </div>\n }\n\n <!-- Error message -->\n @if (hasError()) {\n <div class=\"axp-weather-error-overlay\">\n <div class=\"axp-weather-error-message\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ errorMessage() }}</span>\n <button class=\"axp-weather-retry-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>Retry</span>\n </button>\n </div>\n </div>\n }\n\n <!-- Weather content - only show when we have data -->\n @if (weatherData()) {\n <!-- Background decorations based on weather condition -->\n <div class=\"axp-weather-background-decorations\">\n <div class=\"axp-weather-decoration\" [ngClass]=\"weatherData()?.current?.condition?.toLowerCase()\"></div>\n <div class=\"axp-weather-gradient-overlay\"></div>\n </div>\n\n <div class=\"axp-weather-inner\">\n <!-- Location information section -->\n <div class=\"axp-weather-location-info\">\n <div class=\"axp-weather-location-icon\">\n <i class=\"fa-solid fa-location-dot\"></i>\n </div>\n <div class=\"axp-weather-location-text\">\n <h2 class=\"axp-weather-location-name\">{{ city() }}</h2>\n </div>\n </div>\n\n <!-- Current weather conditions section -->\n <div class=\"axp-weather-current-weather\">\n <!-- Weather icon and condition name -->\n @if (showCurrentCondition()) {\n <div class=\"axp-weather-condition\">\n <div class=\"axp-weather-icon-wrapper\">\n <div class=\"axp-weather-icon\">\n <i\n [class]=\"getConditionIcon(weatherData()?.current?.condition || '')\"\n [style.color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></i>\n </div>\n <div\n class=\"axp-weather-icon-glow\"\n [style.background-color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></div>\n </div>\n <div class=\"axp-weather-condition-name\">{{ getCurrentCondition() }}</div>\n </div>\n }\n\n <!-- Temperature display -->\n @if (showTemperature()) {\n <div class=\"axp-weather-temperature\">\n <span class=\"axp-weather-temperature-value\">{{ getCurrentTemperature() }}</span>\n <span class=\"axp-weather-temperature-unit\">{{ temperatureUnit() }}</span>\n </div>\n }\n </div>\n\n <!-- Weather details section (humidity and wind) -->\n @if (showHumidity() || showWind()) {\n <div class=\"axp-weather-details\">\n <!-- Humidity information -->\n @if (showHumidity()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-droplet\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">Humidity</div>\n <div class=\"axp-weather-detail-value\">{{ getHumidity() }}%</div>\n </div>\n </div>\n }\n\n <!-- Wind speed information -->\n @if (showWind()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-wind\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">Wind</div>\n <div class=\"axp-weather-detail-value\">{{ getWindSpeed() }} {{ windSpeedUnit() }}</div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Weather forecast section -->\n @if (showForecast() && weatherData()?.forecast) {\n <div class=\"axp-weather-forecast\">\n <div class=\"axp-weather-forecast-header\">\n <h3 class=\"axp-weather-forecast-title\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n <span>Forecast</span>\n </h3>\n <!-- <div class=\"axp-weather-scroll-indicator\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </div> -->\n </div>\n <!-- Loading indicator for forecast -->\n @if (isForecastLoading()) {\n <div class=\"axp-weather-forecast-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading forecast...</span>\n </div>\n }\n <!-- Scrollable forecast days display -->\n <div class=\"axp-weather-forecast-items\">\n @for (day of displayedForecast(); track day.day) {\n <div class=\"axp-weather-forecast-day\">\n <div class=\"axp-weather-forecast-day-name\">{{ day.day }}</div>\n <div class=\"axp-weather-forecast-icon\" title=\"{{ getConditionName(day.condition) }}\">\n <i [class]=\"getConditionIcon(day.condition)\" [style.color]=\"getConditionColor(day.condition)\"></i>\n </div>\n <div class=\"axp-weather-forecast-temps\">\n <span class=\"axp-weather-forecast-low\">\n {{ temperatureUnit() === '\u00B0C' ? day.minTempC : day.minTempF }}\u00B0\n </span>\n <span class=\"axp-weather-forecast-high\">\n {{ temperatureUnit() === '\u00B0C' ? day.maxTempC : day.maxTempF }}\u00B0\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Last updated timestamp -->\n <div class=\"axp-weather-last-updated\">\n <span>Last updated: {{ getLastUpdated() }}</span>\n </div>\n\n <!-- Manual refresh button -->\n <div class=\"axp-weather-refresh-action\">\n <button\n class=\"axp-weather-refresh-button\"\n (click)=\"refreshWeather()\"\n [attr.aria-label]=\"'Refresh weather data'\"\n title=\"Refresh weather data\"\n >\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>Refresh</span>\n </button>\n </div>\n </div>\n } @else if (!isLoading() && !hasError()) {\n <!-- No data state (not loading, no error) -->\n <div class=\"axp-weather-no-data-state\">\n <i class=\"fa-solid fa-cloud-sun\"></i>\n <p>No weather data available</p>\n <button class=\"axp-weather-refresh-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>Load Data</span>\n </button>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%;--primary-gradient-start: #2196f3;--primary-gradient-end: #1976d2;--shadow-color: rgba(0, 0, 0, .2);--glass-bg: rgba(255, 255, 255, .15);--glass-border: rgba(255, 255, 255, .2);--text-primary: rgba(255, 255, 255, .95);--text-secondary: rgba(255, 255, 255, .75);--transition-speed: .3s}.axp-weather-container{width:100%;height:100%;border-radius:8px;overflow:hidden;position:relative;box-shadow:0 4px 8px rgba(0,0,0,.1);color:#fff;min-height:300px;background-color:#2c3e50}.axp-weather-loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(44,62,80,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-loading-spinner{text-align:center}.axp-weather-loading-spinner i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-loading-spinner span{display:block;color:#fff;font-size:1rem}.axp-weather-error-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(189,54,47,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-error-message{text-align:center;padding:1rem}.axp-weather-error-message i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-error-message span{display:block;color:#fff;font-size:1.1rem;margin-bottom:1rem}.axp-weather-error-message .axp-weather-retry-button{color:#bd362f;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-error-message .axp-weather-retry-button:hover{transform:translateY(-1px)}.axp-weather-no-data-state{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;padding:2rem;text-align:center}.axp-weather-no-data-state i{font-size:3rem;margin-bottom:1rem;color:rgba(255,255,255,.8)}.axp-weather-no-data-state p{margin-bottom:1.5rem;font-size:1.1rem}.axp-weather-no-data-state .axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-no-data-state .axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-background-decorations{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.axp-weather-decoration{position:absolute;top:0;left:0;width:100%;height:100%;background-size:cover;background-position:center}.axp-weather-decoration.sunny{background:linear-gradient(135deg,#ff7e00,#f7d358)}.axp-weather-decoration.partlyCloudy{background:linear-gradient(135deg,#7ba2e7,#b4d2f7)}.axp-weather-decoration.cloudy{background:linear-gradient(135deg,#717e8c,#919eab)}.axp-weather-decoration.rain{background:linear-gradient(135deg,#6a8caf,#567a9e)}.axp-weather-decoration.snow{background:linear-gradient(135deg,#99b3cc,#c6d4e1)}.axp-weather-decoration.thunder{background:linear-gradient(135deg,#425777,#2c3e50)}.axp-weather-decoration.mist{background:linear-gradient(135deg,#94a3b8,#cbd5e1)}.axp-weather-gradient-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,.5))}.axp-weather-inner{position:relative;z-index:2;height:100%;padding:1.5rem;display:flex;flex-direction:column}.axp-weather-location-info{display:flex;align-items:center;margin-bottom:1.5rem}.axp-weather-location-icon{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,.2);border-radius:50%;margin-right:.75rem}.axp-weather-location-icon i{color:#fff}.axp-weather-location-name{margin:0;font-size:1.5rem;font-weight:500;text-shadow:1px 1px 3px rgba(0,0,0,.2);text-transform:capitalize}.axp-weather-current-weather{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;flex-wrap:wrap}.axp-weather-condition{display:flex;flex-direction:column;align-items:center}.axp-weather-icon-wrapper{position:relative;margin-bottom:.5rem}.axp-weather-icon{position:relative;z-index:2}.axp-weather-icon i{font-size:2.75rem;filter:drop-shadow(0 0 8px rgba(0,0,0,.3))}.axp-weather-icon-glow{position:absolute;z-index:1;top:50%;left:50%;transform:translate(-50%,-50%);width:45px;height:45px;border-radius:50%;filter:blur(15px);opacity:.75}.axp-weather-condition-name{font-size:1.1rem;text-align:center;text-shadow:1px 1px 2px rgba(0,0,0,.2)}.axp-weather-temperature{display:flex;align-items:flex-start;text-shadow:1px 1px 3px rgba(0,0,0,.3)}.axp-weather-temperature-value{font-size:3.5rem;font-weight:500;line-height:1}.axp-weather-temperature-unit{font-size:1.5rem;margin-top:.25rem}.axp-weather-details{display:flex;flex-wrap:wrap;gap:1.5rem;margin-bottom:1.5rem;padding:1rem;background-color:rgba(0,0,0,.15);border-radius:8px}.axp-weather-detail-item{display:flex;align-items:center;flex:1;min-width:120px}.axp-weather-detail-icon{width:40px;height:40px;border-radius:50%;background-color:rgba(255,255,255,.2);display:flex;align-items:center;justify-content:center;margin-right:.75rem}.axp-weather-detail-icon i{font-size:1.25rem}.axp-weather-detail-info{display:flex;flex-direction:column}.axp-weather-detail-label{font-size:.875rem;color:rgba(255,255,255,.8);margin-bottom:.25rem}.axp-weather-detail-value{font-size:1.125rem;font-weight:500}.axp-weather-forecast{margin-top:auto;margin-bottom:1rem;background-color:rgba(0,0,0,.15);border-radius:8px;padding:1rem}.axp-weather-forecast-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.axp-weather-forecast-title{margin:0;font-size:1.125rem;font-weight:500;display:flex;align-items:center}.axp-weather-forecast-title i{margin-right:.5rem;opacity:.8}.axp-weather-scroll-indicator{color:rgba(255,255,255,.6)}.axp-weather-forecast-items{display:flex;overflow-x:auto;gap:.75rem;padding-bottom:.5rem}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.3);border-radius:4px}.axp-weather-forecast-items::-webkit-scrollbar-track{background-color:rgba(0,0,0,.1);border-radius:4px}.axp-weather-forecast-day{min-width:80px;display:flex;flex-direction:column;align-items:center;padding:.75rem .5rem;background-color:rgba(255,255,255,.1);border-radius:6px;transition:all .3s ease}.axp-weather-forecast-day:hover{background-color:rgba(255,255,255,.15);transform:translateY(-2px)}.axp-weather-forecast-day-name{font-size:.875rem;margin-bottom:.5rem;font-weight:500}.axp-weather-forecast-icon{font-size:1.5rem;margin-bottom:.5rem}.axp-weather-forecast-icon i{filter:drop-shadow(0 0 5px rgba(0,0,0,.2))}.axp-weather-forecast-temps{display:flex;flex-direction:row;gap:.75rem;align-items:center;font-size:.875rem}.axp-weather-last-updated{text-align:center;font-size:.75rem;opacity:.7;margin-bottom:.5rem}.axp-weather-refresh-action{text-align:center}.axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:.875rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-refresh-button i{font-size:.875rem}@media (max-width: 576px){.axp-weather-inner{padding:.8rem;gap:.4rem}.axp-weather-location-name{font-size:1.1rem}.axp-weather-temperature{font-size:2.5rem}.axp-weather-temperature-unit{font-size:1.1rem}.axp-weather-weather-details{flex-direction:column;gap:.5rem}.axp-weather-forecast-items{flex-wrap:nowrap;overflow-x:auto;padding-bottom:.5rem;margin:0 -.4rem;scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scrollbar-width:thin;mask-image:linear-gradient(to right,#000 95%,rgba(0,0,0,0));-webkit-mask-image:linear-gradient(to right,rgb(0,0,0) 95%,rgba(0,0,0,0))}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.2);border-radius:4px}.axp-weather-forecast-day{min-width:60px;flex:0 0 auto;padding:.4rem .6rem}.axp-weather-forecast-day-name{font-size:.7rem}.axp-weather-forecast-icon{padding:.3rem;height:1.6rem}.axp-weather-forecast-temps{font-size:.7rem}.axp-weather-scroll-indicator{display:block}}:host-context(.theme-dark){--glass-bg: rgba(0, 0, 0, .3);--glass-border: rgba(255, 255, 255, .1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: HttpClientModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3288
+ ], viewQueries: [{ propertyName: "containerEl", first: true, predicate: ["containerElement"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Weather Widget Component Template -->\n<div class=\"axp-weather-container\" #containerElement>\n <!-- Loading indicator -->\n @if (isLoading()) {\n <div class=\"axp-weather-loading-overlay\">\n <div class=\"axp-weather-loading-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n </div>\n }\n\n <!-- Error message -->\n @if (hasError()) {\n <div class=\"axp-weather-error-overlay\">\n <div class=\"axp-weather-error-message\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ errorMessage() | translate: { scope: 'dashboard' } | async }}</span>\n <button class=\"axp-weather-retry-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.retry' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n }\n\n <!-- Weather content - only show when we have data -->\n @if (weatherData()) {\n <!-- Background decorations based on weather condition -->\n <div class=\"axp-weather-background-decorations\">\n <div class=\"axp-weather-decoration\" [ngClass]=\"weatherData()?.current?.condition?.toLowerCase()\"></div>\n <div class=\"axp-weather-gradient-overlay\"></div>\n </div>\n\n <div class=\"axp-weather-inner\">\n <!-- Location information section -->\n <div class=\"axp-weather-location-info\">\n <div class=\"axp-weather-location-icon\">\n <i class=\"fa-solid fa-location-dot\"></i>\n </div>\n <div class=\"axp-weather-location-text\">\n <h2 class=\"axp-weather-location-name\">{{ city() }}</h2>\n </div>\n </div>\n\n <!-- Current weather conditions section -->\n <div class=\"axp-weather-current-weather\">\n <!-- Weather icon and condition name -->\n @if (showCurrentCondition()) {\n <div class=\"axp-weather-condition\">\n <div class=\"axp-weather-icon-wrapper\">\n <div class=\"axp-weather-icon\">\n <i\n [class]=\"getConditionIcon(weatherData()?.current?.condition || '')\"\n [style.color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></i>\n </div>\n <div\n class=\"axp-weather-icon-glow\"\n [style.background-color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></div>\n </div>\n <div class=\"axp-weather-condition-name\">\n {{ getCurrentCondition() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n }\n\n <!-- Temperature display -->\n @if (showTemperature()) {\n <div class=\"axp-weather-temperature\">\n <span class=\"axp-weather-temperature-value\">{{ getCurrentTemperature() }}</span>\n <span class=\"axp-weather-temperature-unit\">{{\n getTemperatureUnit() | translate: { scope: 'dashboard' } | async\n }}</span>\n </div>\n }\n </div>\n\n <!-- Weather details section (humidity and wind) -->\n @if (showHumidity() || showWind()) {\n <div class=\"axp-weather-details\">\n <!-- Humidity information -->\n @if (showHumidity()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-droplet\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.humidity' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">{{ getHumidity() }}%</div>\n </div>\n </div>\n }\n\n <!-- Wind speed information -->\n @if (showWind()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-wind\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.wind' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">\n {{ getWindSpeed() }} {{ getWindSpeedUnit() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Weather forecast section -->\n @if (showForecast() && weatherData()?.forecast) {\n <div class=\"axp-weather-forecast\">\n <div class=\"axp-weather-forecast-header\">\n <h3 class=\"axp-weather-forecast-title\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n <span class=\"ax-px-1\">{{ 'weather.forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </h3>\n </div>\n <!-- Loading indicator for forecast -->\n <!-- @if (isForecastLoading()) {\n <div class=\"axp-weather-forecast-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading-forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n } -->\n <!-- Scrollable forecast days display -->\n <div class=\"axp-weather-forecast-items\">\n @for (day of displayedForecast(); track day.day) {\n <div class=\"axp-weather-forecast-day\">\n <div class=\"axp-weather-forecast-day-name\">\n {{ getDayName(parseDate(day.date)) | translate: { scope: 'dashboard' } | async }}\n </div>\n <div\n class=\"axp-weather-forecast-icon\"\n [title]=\"getConditionName(day.condition) | translate: { scope: 'dashboard' } | async\"\n >\n <i [class]=\"getConditionIcon(day.condition)\" [style.color]=\"getConditionColor(day.condition)\"></i>\n </div>\n <div class=\"axp-weather-forecast-temps\">\n <span class=\"axp-weather-forecast-low\">\n {{ temperatureUnit() === '\u00B0C' ? day.minTempC : day.minTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n <span class=\"axp-weather-forecast-high\">\n {{ temperatureUnit() === '\u00B0C' ? day.maxTempC : day.maxTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Last updated timestamp -->\n <div class=\"axp-weather-last-updated\">\n <span>{{ 'weather.last-updated' | translate: { scope: 'dashboard' } | async }}: {{ getLastUpdated() }}</span>\n </div>\n\n <!-- Manual refresh button -->\n <div class=\"axp-weather-refresh-action\">\n <button\n class=\"axp-weather-refresh-button\"\n (click)=\"refreshWeather()\"\n [attr.aria-label]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n [title]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n >\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.refresh' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n } @else if (!isLoading() && !hasError()) {\n <!-- No data state (not loading, no error) -->\n <div class=\"axp-weather-no-data-state\">\n <i class=\"fa-solid fa-cloud-sun\"></i>\n <p>{{ 'weather.no-data' | translate: { scope: 'dashboard' } | async }}</p>\n <button class=\"axp-weather-refresh-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.load-data' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%;--primary-gradient-start: #2196f3;--primary-gradient-end: #1976d2;--shadow-color: rgba(0, 0, 0, .2);--glass-bg: rgba(255, 255, 255, .15);--glass-border: rgba(255, 255, 255, .2);--text-primary: rgba(255, 255, 255, .95);--text-secondary: rgba(255, 255, 255, .75);--transition-speed: .3s}.axp-weather-container{width:100%;height:100%;overflow:hidden;position:relative;box-shadow:0 4px 8px rgba(0,0,0,.1);color:#fff;min-height:300px;background-color:#2c3e50}.axp-weather-loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(44,62,80,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-loading-spinner{text-align:center}.axp-weather-loading-spinner i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-loading-spinner span{display:block;color:#fff;font-size:1rem}.axp-weather-error-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(189,54,47,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-error-message{text-align:center;padding:1rem}.axp-weather-error-message i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-error-message span{display:block;color:#fff;font-size:1.1rem;margin-bottom:1rem}.axp-weather-error-message .axp-weather-retry-button{color:#bd362f;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-error-message .axp-weather-retry-button:hover{transform:translateY(-1px)}.axp-weather-no-data-state{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;padding:2rem;text-align:center}.axp-weather-no-data-state i{font-size:3rem;margin-bottom:1rem;color:rgba(255,255,255,.8)}.axp-weather-no-data-state p{margin-bottom:1.5rem;font-size:1.1rem}.axp-weather-no-data-state .axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-no-data-state .axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-background-decorations{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.axp-weather-decoration{position:absolute;top:0;left:0;width:100%;height:100%;background-size:cover;background-position:center}.axp-weather-decoration.sunny{background:linear-gradient(135deg,#ff7e00,#f7d358)}.axp-weather-decoration.partlyCloudy{background:linear-gradient(135deg,#7ba2e7,#b4d2f7)}.axp-weather-decoration.cloudy{background:linear-gradient(135deg,#717e8c,#919eab)}.axp-weather-decoration.rain{background:linear-gradient(135deg,#6a8caf,#567a9e)}.axp-weather-decoration.snow{background:linear-gradient(135deg,#99b3cc,#c6d4e1)}.axp-weather-decoration.thunder{background:linear-gradient(135deg,#425777,#2c3e50)}.axp-weather-decoration.mist{background:linear-gradient(135deg,#94a3b8,#cbd5e1)}.axp-weather-gradient-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,.5))}.axp-weather-inner{position:relative;z-index:2;height:100%;padding:1.5rem;display:flex;flex-direction:column;justify-content:space-between}.axp-weather-location-info{display:flex;align-items:center;margin-bottom:1.5rem}.axp-weather-location-icon{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,.2);border-radius:50%;margin-right:.75rem}.axp-weather-location-icon i{color:#fff}.axp-weather-location-name{margin:0;font-size:1.5rem;font-weight:500;text-shadow:1px 1px 3px rgba(0,0,0,.2);text-transform:capitalize}.axp-weather-current-weather{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;flex-wrap:wrap}.axp-weather-condition{display:flex;flex-direction:column;align-items:center}.axp-weather-icon-wrapper{position:relative;margin-bottom:.5rem}.axp-weather-icon{position:relative;z-index:2}.axp-weather-icon i{font-size:2.75rem;filter:drop-shadow(0 0 8px rgba(0,0,0,.3))}.axp-weather-icon-glow{position:absolute;z-index:1;top:50%;left:50%;transform:translate(-50%,-50%);width:45px;height:45px;border-radius:50%;filter:blur(15px);opacity:.75}.axp-weather-condition-name{font-size:1.1rem;text-align:center;text-shadow:1px 1px 2px rgba(0,0,0,.2)}.axp-weather-temperature{display:flex;align-items:flex-start;text-shadow:1px 1px 3px rgba(0,0,0,.3)}.axp-weather-temperature-value{font-size:3.5rem;font-weight:500;line-height:1}.axp-weather-temperature-unit{font-size:1.5rem;margin-top:.25rem}.axp-weather-details{display:flex;flex-wrap:wrap;gap:1.5rem;margin-bottom:1rem;padding:1rem;background-color:rgba(0,0,0,.15);border-radius:8px}.axp-weather-detail-item{display:flex;align-items:center;flex:1;min-width:120px}.axp-weather-detail-icon{width:40px;height:40px;border-radius:50%;background-color:rgba(255,255,255,.2);display:flex;align-items:center;justify-content:center;margin-right:.75rem}.axp-weather-detail-icon i{font-size:1.25rem}.axp-weather-detail-info{display:flex;padding-inline:.25rem;flex-direction:column}.axp-weather-detail-label{font-size:.875rem;color:rgba(255,255,255,.8);margin-bottom:.25rem}.axp-weather-detail-value{font-size:1.125rem;font-weight:500}.axp-weather-forecast{margin-bottom:.5rem;background-color:rgba(0,0,0,.15);border-radius:8px;padding:1rem}.axp-weather-forecast-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.axp-weather-forecast-title{margin:0;font-size:1.125rem;font-weight:500;display:flex;align-items:center}.axp-weather-forecast-title i{margin-right:.5rem;opacity:.8}.axp-weather-scroll-indicator{color:rgba(255,255,255,.6)}.axp-weather-forecast-items{display:flex;overflow-x:auto;gap:.75rem;padding-bottom:.5rem}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.3);border-radius:4px}.axp-weather-forecast-items::-webkit-scrollbar-track{background-color:rgba(0,0,0,.1);border-radius:4px}.axp-weather-forecast-day{min-width:90px;display:flex;flex-direction:column;align-items:center;padding:.75rem .5rem;background-color:rgba(255,255,255,.1);border-radius:6px;transition:all .3s ease}.axp-weather-forecast-day:hover{background-color:rgba(255,255,255,.15);transform:translateY(-2px)}.axp-weather-forecast-day-name{font-size:.875rem;margin-bottom:.5rem;font-weight:500}.axp-weather-forecast-icon{font-size:1.5rem;margin-bottom:.5rem}.axp-weather-forecast-icon i{filter:drop-shadow(0 0 5px rgba(0,0,0,.2))}.axp-weather-forecast-temps{display:flex;flex-direction:row;gap:.75rem;align-items:center;font-size:.775rem}.axp-weather-last-updated{text-align:center;font-size:.75rem;opacity:.7;margin-bottom:.5rem}.axp-weather-refresh-action{text-align:center}.axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:.875rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-refresh-button i{font-size:.875rem}@media (max-width: 576px){.axp-weather-inner{padding:.8rem;gap:.4rem}.axp-weather-location-name{font-size:1.1rem;padding-inline:.25rem}.axp-weather-temperature{font-size:2.5rem}.axp-weather-temperature-unit{font-size:1.1rem}.axp-weather-weather-details{flex-direction:column;gap:.5rem}.axp-weather-forecast-items{flex-wrap:nowrap;overflow-x:auto;padding-bottom:.5rem;margin:0 -.4rem;scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scrollbar-width:thin;mask-image:linear-gradient(to right,#000 95%,rgba(0,0,0,0));-webkit-mask-image:linear-gradient(to right,rgb(0,0,0) 95%,rgba(0,0,0,0))}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.2);border-radius:4px}.axp-weather-forecast-day{min-width:60px;flex:0 0 auto;padding:.4rem .6rem}.axp-weather-forecast-day-name{font-size:.7rem}.axp-weather-forecast-icon{padding:.3rem;height:1.6rem}.axp-weather-forecast-temps{font-size:.7rem}.axp-weather-scroll-indicator{display:block}}:host-context(.theme-dark){--glass-bg: rgba(0, 0, 0, .3);--glass-border: rgba(255, 255, 255, .1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: HttpClientModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2$3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3236
3289
  }
3237
3290
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPWeatherWidgetViewComponent, decorators: [{
3238
3291
  type: Component,
3239
- args: [{ standalone: true, imports: [CommonModule, AXDateTimeModule, AXFormatModule, HttpClientModule], providers: [
3292
+ args: [{ standalone: true, imports: [CommonModule, AXDateTimeModule, AXFormatModule, HttpClientModule, AXTranslationModule], providers: [
3240
3293
  {
3241
3294
  provide: AXPWeatherApiAbstract,
3242
3295
  useClass: AXPWeatherApiService,
3243
3296
  },
3244
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Weather Widget Component Template -->\n<div class=\"axp-weather-container\" #containerElement>\n <!-- Loading indicator -->\n @if (isLoading()) {\n <div class=\"axp-weather-loading-overlay\">\n <div class=\"axp-weather-loading-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading weather data...</span>\n </div>\n </div>\n }\n\n <!-- Error message -->\n @if (hasError()) {\n <div class=\"axp-weather-error-overlay\">\n <div class=\"axp-weather-error-message\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ errorMessage() }}</span>\n <button class=\"axp-weather-retry-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>Retry</span>\n </button>\n </div>\n </div>\n }\n\n <!-- Weather content - only show when we have data -->\n @if (weatherData()) {\n <!-- Background decorations based on weather condition -->\n <div class=\"axp-weather-background-decorations\">\n <div class=\"axp-weather-decoration\" [ngClass]=\"weatherData()?.current?.condition?.toLowerCase()\"></div>\n <div class=\"axp-weather-gradient-overlay\"></div>\n </div>\n\n <div class=\"axp-weather-inner\">\n <!-- Location information section -->\n <div class=\"axp-weather-location-info\">\n <div class=\"axp-weather-location-icon\">\n <i class=\"fa-solid fa-location-dot\"></i>\n </div>\n <div class=\"axp-weather-location-text\">\n <h2 class=\"axp-weather-location-name\">{{ city() }}</h2>\n </div>\n </div>\n\n <!-- Current weather conditions section -->\n <div class=\"axp-weather-current-weather\">\n <!-- Weather icon and condition name -->\n @if (showCurrentCondition()) {\n <div class=\"axp-weather-condition\">\n <div class=\"axp-weather-icon-wrapper\">\n <div class=\"axp-weather-icon\">\n <i\n [class]=\"getConditionIcon(weatherData()?.current?.condition || '')\"\n [style.color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></i>\n </div>\n <div\n class=\"axp-weather-icon-glow\"\n [style.background-color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></div>\n </div>\n <div class=\"axp-weather-condition-name\">{{ getCurrentCondition() }}</div>\n </div>\n }\n\n <!-- Temperature display -->\n @if (showTemperature()) {\n <div class=\"axp-weather-temperature\">\n <span class=\"axp-weather-temperature-value\">{{ getCurrentTemperature() }}</span>\n <span class=\"axp-weather-temperature-unit\">{{ temperatureUnit() }}</span>\n </div>\n }\n </div>\n\n <!-- Weather details section (humidity and wind) -->\n @if (showHumidity() || showWind()) {\n <div class=\"axp-weather-details\">\n <!-- Humidity information -->\n @if (showHumidity()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-droplet\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">Humidity</div>\n <div class=\"axp-weather-detail-value\">{{ getHumidity() }}%</div>\n </div>\n </div>\n }\n\n <!-- Wind speed information -->\n @if (showWind()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-wind\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">Wind</div>\n <div class=\"axp-weather-detail-value\">{{ getWindSpeed() }} {{ windSpeedUnit() }}</div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Weather forecast section -->\n @if (showForecast() && weatherData()?.forecast) {\n <div class=\"axp-weather-forecast\">\n <div class=\"axp-weather-forecast-header\">\n <h3 class=\"axp-weather-forecast-title\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n <span>Forecast</span>\n </h3>\n <!-- <div class=\"axp-weather-scroll-indicator\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </div> -->\n </div>\n <!-- Loading indicator for forecast -->\n @if (isForecastLoading()) {\n <div class=\"axp-weather-forecast-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>Loading forecast...</span>\n </div>\n }\n <!-- Scrollable forecast days display -->\n <div class=\"axp-weather-forecast-items\">\n @for (day of displayedForecast(); track day.day) {\n <div class=\"axp-weather-forecast-day\">\n <div class=\"axp-weather-forecast-day-name\">{{ day.day }}</div>\n <div class=\"axp-weather-forecast-icon\" title=\"{{ getConditionName(day.condition) }}\">\n <i [class]=\"getConditionIcon(day.condition)\" [style.color]=\"getConditionColor(day.condition)\"></i>\n </div>\n <div class=\"axp-weather-forecast-temps\">\n <span class=\"axp-weather-forecast-low\">\n {{ temperatureUnit() === '\u00B0C' ? day.minTempC : day.minTempF }}\u00B0\n </span>\n <span class=\"axp-weather-forecast-high\">\n {{ temperatureUnit() === '\u00B0C' ? day.maxTempC : day.maxTempF }}\u00B0\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Last updated timestamp -->\n <div class=\"axp-weather-last-updated\">\n <span>Last updated: {{ getLastUpdated() }}</span>\n </div>\n\n <!-- Manual refresh button -->\n <div class=\"axp-weather-refresh-action\">\n <button\n class=\"axp-weather-refresh-button\"\n (click)=\"refreshWeather()\"\n [attr.aria-label]=\"'Refresh weather data'\"\n title=\"Refresh weather data\"\n >\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>Refresh</span>\n </button>\n </div>\n </div>\n } @else if (!isLoading() && !hasError()) {\n <!-- No data state (not loading, no error) -->\n <div class=\"axp-weather-no-data-state\">\n <i class=\"fa-solid fa-cloud-sun\"></i>\n <p>No weather data available</p>\n <button class=\"axp-weather-refresh-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>Load Data</span>\n </button>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%;--primary-gradient-start: #2196f3;--primary-gradient-end: #1976d2;--shadow-color: rgba(0, 0, 0, .2);--glass-bg: rgba(255, 255, 255, .15);--glass-border: rgba(255, 255, 255, .2);--text-primary: rgba(255, 255, 255, .95);--text-secondary: rgba(255, 255, 255, .75);--transition-speed: .3s}.axp-weather-container{width:100%;height:100%;border-radius:8px;overflow:hidden;position:relative;box-shadow:0 4px 8px rgba(0,0,0,.1);color:#fff;min-height:300px;background-color:#2c3e50}.axp-weather-loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(44,62,80,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-loading-spinner{text-align:center}.axp-weather-loading-spinner i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-loading-spinner span{display:block;color:#fff;font-size:1rem}.axp-weather-error-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(189,54,47,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-error-message{text-align:center;padding:1rem}.axp-weather-error-message i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-error-message span{display:block;color:#fff;font-size:1.1rem;margin-bottom:1rem}.axp-weather-error-message .axp-weather-retry-button{color:#bd362f;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-error-message .axp-weather-retry-button:hover{transform:translateY(-1px)}.axp-weather-no-data-state{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;padding:2rem;text-align:center}.axp-weather-no-data-state i{font-size:3rem;margin-bottom:1rem;color:rgba(255,255,255,.8)}.axp-weather-no-data-state p{margin-bottom:1.5rem;font-size:1.1rem}.axp-weather-no-data-state .axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-no-data-state .axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-background-decorations{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.axp-weather-decoration{position:absolute;top:0;left:0;width:100%;height:100%;background-size:cover;background-position:center}.axp-weather-decoration.sunny{background:linear-gradient(135deg,#ff7e00,#f7d358)}.axp-weather-decoration.partlyCloudy{background:linear-gradient(135deg,#7ba2e7,#b4d2f7)}.axp-weather-decoration.cloudy{background:linear-gradient(135deg,#717e8c,#919eab)}.axp-weather-decoration.rain{background:linear-gradient(135deg,#6a8caf,#567a9e)}.axp-weather-decoration.snow{background:linear-gradient(135deg,#99b3cc,#c6d4e1)}.axp-weather-decoration.thunder{background:linear-gradient(135deg,#425777,#2c3e50)}.axp-weather-decoration.mist{background:linear-gradient(135deg,#94a3b8,#cbd5e1)}.axp-weather-gradient-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,.5))}.axp-weather-inner{position:relative;z-index:2;height:100%;padding:1.5rem;display:flex;flex-direction:column}.axp-weather-location-info{display:flex;align-items:center;margin-bottom:1.5rem}.axp-weather-location-icon{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,.2);border-radius:50%;margin-right:.75rem}.axp-weather-location-icon i{color:#fff}.axp-weather-location-name{margin:0;font-size:1.5rem;font-weight:500;text-shadow:1px 1px 3px rgba(0,0,0,.2);text-transform:capitalize}.axp-weather-current-weather{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;flex-wrap:wrap}.axp-weather-condition{display:flex;flex-direction:column;align-items:center}.axp-weather-icon-wrapper{position:relative;margin-bottom:.5rem}.axp-weather-icon{position:relative;z-index:2}.axp-weather-icon i{font-size:2.75rem;filter:drop-shadow(0 0 8px rgba(0,0,0,.3))}.axp-weather-icon-glow{position:absolute;z-index:1;top:50%;left:50%;transform:translate(-50%,-50%);width:45px;height:45px;border-radius:50%;filter:blur(15px);opacity:.75}.axp-weather-condition-name{font-size:1.1rem;text-align:center;text-shadow:1px 1px 2px rgba(0,0,0,.2)}.axp-weather-temperature{display:flex;align-items:flex-start;text-shadow:1px 1px 3px rgba(0,0,0,.3)}.axp-weather-temperature-value{font-size:3.5rem;font-weight:500;line-height:1}.axp-weather-temperature-unit{font-size:1.5rem;margin-top:.25rem}.axp-weather-details{display:flex;flex-wrap:wrap;gap:1.5rem;margin-bottom:1.5rem;padding:1rem;background-color:rgba(0,0,0,.15);border-radius:8px}.axp-weather-detail-item{display:flex;align-items:center;flex:1;min-width:120px}.axp-weather-detail-icon{width:40px;height:40px;border-radius:50%;background-color:rgba(255,255,255,.2);display:flex;align-items:center;justify-content:center;margin-right:.75rem}.axp-weather-detail-icon i{font-size:1.25rem}.axp-weather-detail-info{display:flex;flex-direction:column}.axp-weather-detail-label{font-size:.875rem;color:rgba(255,255,255,.8);margin-bottom:.25rem}.axp-weather-detail-value{font-size:1.125rem;font-weight:500}.axp-weather-forecast{margin-top:auto;margin-bottom:1rem;background-color:rgba(0,0,0,.15);border-radius:8px;padding:1rem}.axp-weather-forecast-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.axp-weather-forecast-title{margin:0;font-size:1.125rem;font-weight:500;display:flex;align-items:center}.axp-weather-forecast-title i{margin-right:.5rem;opacity:.8}.axp-weather-scroll-indicator{color:rgba(255,255,255,.6)}.axp-weather-forecast-items{display:flex;overflow-x:auto;gap:.75rem;padding-bottom:.5rem}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.3);border-radius:4px}.axp-weather-forecast-items::-webkit-scrollbar-track{background-color:rgba(0,0,0,.1);border-radius:4px}.axp-weather-forecast-day{min-width:80px;display:flex;flex-direction:column;align-items:center;padding:.75rem .5rem;background-color:rgba(255,255,255,.1);border-radius:6px;transition:all .3s ease}.axp-weather-forecast-day:hover{background-color:rgba(255,255,255,.15);transform:translateY(-2px)}.axp-weather-forecast-day-name{font-size:.875rem;margin-bottom:.5rem;font-weight:500}.axp-weather-forecast-icon{font-size:1.5rem;margin-bottom:.5rem}.axp-weather-forecast-icon i{filter:drop-shadow(0 0 5px rgba(0,0,0,.2))}.axp-weather-forecast-temps{display:flex;flex-direction:row;gap:.75rem;align-items:center;font-size:.875rem}.axp-weather-last-updated{text-align:center;font-size:.75rem;opacity:.7;margin-bottom:.5rem}.axp-weather-refresh-action{text-align:center}.axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:.875rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-refresh-button i{font-size:.875rem}@media (max-width: 576px){.axp-weather-inner{padding:.8rem;gap:.4rem}.axp-weather-location-name{font-size:1.1rem}.axp-weather-temperature{font-size:2.5rem}.axp-weather-temperature-unit{font-size:1.1rem}.axp-weather-weather-details{flex-direction:column;gap:.5rem}.axp-weather-forecast-items{flex-wrap:nowrap;overflow-x:auto;padding-bottom:.5rem;margin:0 -.4rem;scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scrollbar-width:thin;mask-image:linear-gradient(to right,#000 95%,rgba(0,0,0,0));-webkit-mask-image:linear-gradient(to right,rgb(0,0,0) 95%,rgba(0,0,0,0))}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.2);border-radius:4px}.axp-weather-forecast-day{min-width:60px;flex:0 0 auto;padding:.4rem .6rem}.axp-weather-forecast-day-name{font-size:.7rem}.axp-weather-forecast-icon{padding:.3rem;height:1.6rem}.axp-weather-forecast-temps{font-size:.7rem}.axp-weather-scroll-indicator{display:block}}:host-context(.theme-dark){--glass-bg: rgba(0, 0, 0, .3);--glass-border: rgba(255, 255, 255, .1)}\n"] }]
3297
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Weather Widget Component Template -->\n<div class=\"axp-weather-container\" #containerElement>\n <!-- Loading indicator -->\n @if (isLoading()) {\n <div class=\"axp-weather-loading-overlay\">\n <div class=\"axp-weather-loading-spinner\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n </div>\n }\n\n <!-- Error message -->\n @if (hasError()) {\n <div class=\"axp-weather-error-overlay\">\n <div class=\"axp-weather-error-message\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n <span>{{ errorMessage() | translate: { scope: 'dashboard' } | async }}</span>\n <button class=\"axp-weather-retry-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.retry' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n }\n\n <!-- Weather content - only show when we have data -->\n @if (weatherData()) {\n <!-- Background decorations based on weather condition -->\n <div class=\"axp-weather-background-decorations\">\n <div class=\"axp-weather-decoration\" [ngClass]=\"weatherData()?.current?.condition?.toLowerCase()\"></div>\n <div class=\"axp-weather-gradient-overlay\"></div>\n </div>\n\n <div class=\"axp-weather-inner\">\n <!-- Location information section -->\n <div class=\"axp-weather-location-info\">\n <div class=\"axp-weather-location-icon\">\n <i class=\"fa-solid fa-location-dot\"></i>\n </div>\n <div class=\"axp-weather-location-text\">\n <h2 class=\"axp-weather-location-name\">{{ city() }}</h2>\n </div>\n </div>\n\n <!-- Current weather conditions section -->\n <div class=\"axp-weather-current-weather\">\n <!-- Weather icon and condition name -->\n @if (showCurrentCondition()) {\n <div class=\"axp-weather-condition\">\n <div class=\"axp-weather-icon-wrapper\">\n <div class=\"axp-weather-icon\">\n <i\n [class]=\"getConditionIcon(weatherData()?.current?.condition || '')\"\n [style.color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></i>\n </div>\n <div\n class=\"axp-weather-icon-glow\"\n [style.background-color]=\"getConditionColor(weatherData()?.current?.condition || '')\"\n ></div>\n </div>\n <div class=\"axp-weather-condition-name\">\n {{ getCurrentCondition() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n }\n\n <!-- Temperature display -->\n @if (showTemperature()) {\n <div class=\"axp-weather-temperature\">\n <span class=\"axp-weather-temperature-value\">{{ getCurrentTemperature() }}</span>\n <span class=\"axp-weather-temperature-unit\">{{\n getTemperatureUnit() | translate: { scope: 'dashboard' } | async\n }}</span>\n </div>\n }\n </div>\n\n <!-- Weather details section (humidity and wind) -->\n @if (showHumidity() || showWind()) {\n <div class=\"axp-weather-details\">\n <!-- Humidity information -->\n @if (showHumidity()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-droplet\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.humidity' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">{{ getHumidity() }}%</div>\n </div>\n </div>\n }\n\n <!-- Wind speed information -->\n @if (showWind()) {\n <div class=\"axp-weather-detail-item\">\n <div class=\"axp-weather-detail-icon\">\n <i class=\"fa-solid fa-wind\"></i>\n </div>\n <div class=\"axp-weather-detail-info\">\n <div class=\"axp-weather-detail-label\">\n {{ 'weather.wind' | translate: { scope: 'dashboard' } | async }}\n </div>\n <div class=\"axp-weather-detail-value\">\n {{ getWindSpeed() }} {{ getWindSpeedUnit() | translate: { scope: 'dashboard' } | async }}\n </div>\n </div>\n </div>\n }\n </div>\n }\n\n <!-- Weather forecast section -->\n @if (showForecast() && weatherData()?.forecast) {\n <div class=\"axp-weather-forecast\">\n <div class=\"axp-weather-forecast-header\">\n <h3 class=\"axp-weather-forecast-title\">\n <i class=\"fa-solid fa-calendar-days\"></i>\n <span class=\"ax-px-1\">{{ 'weather.forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </h3>\n </div>\n <!-- Loading indicator for forecast -->\n <!-- @if (isForecastLoading()) {\n <div class=\"axp-weather-forecast-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i>\n <span>{{ 'weather.loading-forecast' | translate: { scope: 'dashboard' } | async }}</span>\n </div>\n } -->\n <!-- Scrollable forecast days display -->\n <div class=\"axp-weather-forecast-items\">\n @for (day of displayedForecast(); track day.day) {\n <div class=\"axp-weather-forecast-day\">\n <div class=\"axp-weather-forecast-day-name\">\n {{ getDayName(parseDate(day.date)) | translate: { scope: 'dashboard' } | async }}\n </div>\n <div\n class=\"axp-weather-forecast-icon\"\n [title]=\"getConditionName(day.condition) | translate: { scope: 'dashboard' } | async\"\n >\n <i [class]=\"getConditionIcon(day.condition)\" [style.color]=\"getConditionColor(day.condition)\"></i>\n </div>\n <div class=\"axp-weather-forecast-temps\">\n <span class=\"axp-weather-forecast-low\">\n {{ temperatureUnit() === '\u00B0C' ? day.minTempC : day.minTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n <span class=\"axp-weather-forecast-high\">\n {{ temperatureUnit() === '\u00B0C' ? day.maxTempC : day.maxTempF\n }}{{ getTemperatureUnit() | translate: { scope: 'dashboard' } | async }}\n </span>\n </div>\n </div>\n }\n </div>\n </div>\n }\n\n <!-- Last updated timestamp -->\n <div class=\"axp-weather-last-updated\">\n <span>{{ 'weather.last-updated' | translate: { scope: 'dashboard' } | async }}: {{ getLastUpdated() }}</span>\n </div>\n\n <!-- Manual refresh button -->\n <div class=\"axp-weather-refresh-action\">\n <button\n class=\"axp-weather-refresh-button\"\n (click)=\"refreshWeather()\"\n [attr.aria-label]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n [title]=\"'weather.refresh' | translate: { scope: 'dashboard' } | async\"\n >\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.refresh' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n </div>\n } @else if (!isLoading() && !hasError()) {\n <!-- No data state (not loading, no error) -->\n <div class=\"axp-weather-no-data-state\">\n <i class=\"fa-solid fa-cloud-sun\"></i>\n <p>{{ 'weather.no-data' | translate: { scope: 'dashboard' } | async }}</p>\n <button class=\"axp-weather-refresh-button\" (click)=\"refreshWeather()\">\n <i class=\"fa-solid fa-sync-alt\"></i>\n <span>{{ 'weather.load-data' | translate: { scope: 'dashboard' } | async }}</span>\n </button>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%;--primary-gradient-start: #2196f3;--primary-gradient-end: #1976d2;--shadow-color: rgba(0, 0, 0, .2);--glass-bg: rgba(255, 255, 255, .15);--glass-border: rgba(255, 255, 255, .2);--text-primary: rgba(255, 255, 255, .95);--text-secondary: rgba(255, 255, 255, .75);--transition-speed: .3s}.axp-weather-container{width:100%;height:100%;overflow:hidden;position:relative;box-shadow:0 4px 8px rgba(0,0,0,.1);color:#fff;min-height:300px;background-color:#2c3e50}.axp-weather-loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(44,62,80,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-loading-spinner{text-align:center}.axp-weather-loading-spinner i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-loading-spinner span{display:block;color:#fff;font-size:1rem}.axp-weather-error-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-color:rgba(189,54,47,.85);display:flex;justify-content:center;align-items:center;z-index:100}.axp-weather-error-message{text-align:center;padding:1rem}.axp-weather-error-message i{font-size:2.5rem;color:#fff;margin-bottom:.5rem}.axp-weather-error-message span{display:block;color:#fff;font-size:1.1rem;margin-bottom:1rem}.axp-weather-error-message .axp-weather-retry-button{color:#bd362f;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-error-message .axp-weather-retry-button:hover{transform:translateY(-1px)}.axp-weather-no-data-state{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;padding:2rem;text-align:center}.axp-weather-no-data-state i{font-size:3rem;margin-bottom:1rem;color:rgba(255,255,255,.8)}.axp-weather-no-data-state p{margin-bottom:1.5rem;font-size:1.1rem}.axp-weather-no-data-state .axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:1rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-no-data-state .axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-background-decorations{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.axp-weather-decoration{position:absolute;top:0;left:0;width:100%;height:100%;background-size:cover;background-position:center}.axp-weather-decoration.sunny{background:linear-gradient(135deg,#ff7e00,#f7d358)}.axp-weather-decoration.partlyCloudy{background:linear-gradient(135deg,#7ba2e7,#b4d2f7)}.axp-weather-decoration.cloudy{background:linear-gradient(135deg,#717e8c,#919eab)}.axp-weather-decoration.rain{background:linear-gradient(135deg,#6a8caf,#567a9e)}.axp-weather-decoration.snow{background:linear-gradient(135deg,#99b3cc,#c6d4e1)}.axp-weather-decoration.thunder{background:linear-gradient(135deg,#425777,#2c3e50)}.axp-weather-decoration.mist{background:linear-gradient(135deg,#94a3b8,#cbd5e1)}.axp-weather-gradient-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(rgba(0,0,0,.2),rgba(0,0,0,.5))}.axp-weather-inner{position:relative;z-index:2;height:100%;padding:1.5rem;display:flex;flex-direction:column;justify-content:space-between}.axp-weather-location-info{display:flex;align-items:center;margin-bottom:1.5rem}.axp-weather-location-icon{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background-color:rgba(255,255,255,.2);border-radius:50%;margin-right:.75rem}.axp-weather-location-icon i{color:#fff}.axp-weather-location-name{margin:0;font-size:1.5rem;font-weight:500;text-shadow:1px 1px 3px rgba(0,0,0,.2);text-transform:capitalize}.axp-weather-current-weather{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;flex-wrap:wrap}.axp-weather-condition{display:flex;flex-direction:column;align-items:center}.axp-weather-icon-wrapper{position:relative;margin-bottom:.5rem}.axp-weather-icon{position:relative;z-index:2}.axp-weather-icon i{font-size:2.75rem;filter:drop-shadow(0 0 8px rgba(0,0,0,.3))}.axp-weather-icon-glow{position:absolute;z-index:1;top:50%;left:50%;transform:translate(-50%,-50%);width:45px;height:45px;border-radius:50%;filter:blur(15px);opacity:.75}.axp-weather-condition-name{font-size:1.1rem;text-align:center;text-shadow:1px 1px 2px rgba(0,0,0,.2)}.axp-weather-temperature{display:flex;align-items:flex-start;text-shadow:1px 1px 3px rgba(0,0,0,.3)}.axp-weather-temperature-value{font-size:3.5rem;font-weight:500;line-height:1}.axp-weather-temperature-unit{font-size:1.5rem;margin-top:.25rem}.axp-weather-details{display:flex;flex-wrap:wrap;gap:1.5rem;margin-bottom:1rem;padding:1rem;background-color:rgba(0,0,0,.15);border-radius:8px}.axp-weather-detail-item{display:flex;align-items:center;flex:1;min-width:120px}.axp-weather-detail-icon{width:40px;height:40px;border-radius:50%;background-color:rgba(255,255,255,.2);display:flex;align-items:center;justify-content:center;margin-right:.75rem}.axp-weather-detail-icon i{font-size:1.25rem}.axp-weather-detail-info{display:flex;padding-inline:.25rem;flex-direction:column}.axp-weather-detail-label{font-size:.875rem;color:rgba(255,255,255,.8);margin-bottom:.25rem}.axp-weather-detail-value{font-size:1.125rem;font-weight:500}.axp-weather-forecast{margin-bottom:.5rem;background-color:rgba(0,0,0,.15);border-radius:8px;padding:1rem}.axp-weather-forecast-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.axp-weather-forecast-title{margin:0;font-size:1.125rem;font-weight:500;display:flex;align-items:center}.axp-weather-forecast-title i{margin-right:.5rem;opacity:.8}.axp-weather-scroll-indicator{color:rgba(255,255,255,.6)}.axp-weather-forecast-items{display:flex;overflow-x:auto;gap:.75rem;padding-bottom:.5rem}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.3);border-radius:4px}.axp-weather-forecast-items::-webkit-scrollbar-track{background-color:rgba(0,0,0,.1);border-radius:4px}.axp-weather-forecast-day{min-width:90px;display:flex;flex-direction:column;align-items:center;padding:.75rem .5rem;background-color:rgba(255,255,255,.1);border-radius:6px;transition:all .3s ease}.axp-weather-forecast-day:hover{background-color:rgba(255,255,255,.15);transform:translateY(-2px)}.axp-weather-forecast-day-name{font-size:.875rem;margin-bottom:.5rem;font-weight:500}.axp-weather-forecast-icon{font-size:1.5rem;margin-bottom:.5rem}.axp-weather-forecast-icon i{filter:drop-shadow(0 0 5px rgba(0,0,0,.2))}.axp-weather-forecast-temps{display:flex;flex-direction:row;gap:.75rem;align-items:center;font-size:.775rem}.axp-weather-last-updated{text-align:center;font-size:.75rem;opacity:.7;margin-bottom:.5rem}.axp-weather-refresh-action{text-align:center}.axp-weather-refresh-button{background-color:rgba(255,255,255,.2);color:#fff;border:none;border-radius:4px;padding:.5rem 1rem;font-size:.875rem;cursor:pointer;transition:all .3s ease;display:inline-flex;align-items:center;gap:.5rem}.axp-weather-refresh-button:hover{background-color:rgba(255,255,255,.3);transform:translateY(-1px)}.axp-weather-refresh-button i{font-size:.875rem}@media (max-width: 576px){.axp-weather-inner{padding:.8rem;gap:.4rem}.axp-weather-location-name{font-size:1.1rem;padding-inline:.25rem}.axp-weather-temperature{font-size:2.5rem}.axp-weather-temperature-unit{font-size:1.1rem}.axp-weather-weather-details{flex-direction:column;gap:.5rem}.axp-weather-forecast-items{flex-wrap:nowrap;overflow-x:auto;padding-bottom:.5rem;margin:0 -.4rem;scroll-behavior:smooth;-webkit-overflow-scrolling:touch;scrollbar-width:thin;mask-image:linear-gradient(to right,#000 95%,rgba(0,0,0,0));-webkit-mask-image:linear-gradient(to right,rgb(0,0,0) 95%,rgba(0,0,0,0))}.axp-weather-forecast-items::-webkit-scrollbar{height:4px}.axp-weather-forecast-items::-webkit-scrollbar-thumb{background-color:rgba(255,255,255,.2);border-radius:4px}.axp-weather-forecast-day{min-width:60px;flex:0 0 auto;padding:.4rem .6rem}.axp-weather-forecast-day-name{font-size:.7rem}.axp-weather-forecast-icon{padding:.3rem;height:1.6rem}.axp-weather-forecast-temps{font-size:.7rem}.axp-weather-scroll-indicator{display:block}}:host-context(.theme-dark){--glass-bg: rgba(0, 0, 0, .3);--glass-border: rgba(255, 255, 255, .1)}\n"] }]
3245
3298
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }] });
3246
3299
 
3247
3300
  var weatherWidget_component = /*#__PURE__*/Object.freeze({
@@ -3264,7 +3317,7 @@ const AXPWeatherWidget = {
3264
3317
  /* Location Settings */
3265
3318
  {
3266
3319
  name: 'city',
3267
- title: 'City',
3320
+ title: '@dashboard:widgets.weather.city',
3268
3321
  group: AXP_DATA_PROPERTY_GROUP,
3269
3322
  schema: {
3270
3323
  defaultValue: 'New York',
@@ -3340,7 +3393,7 @@ const AXPWeatherWidget = {
3340
3393
  // },
3341
3394
  {
3342
3395
  name: 'showHumidity',
3343
- title: 'Show Humidity',
3396
+ title: '@dashboard:widgets.weather.show-humidity',
3344
3397
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3345
3398
  schema: {
3346
3399
  defaultValue: true,
@@ -3355,7 +3408,7 @@ const AXPWeatherWidget = {
3355
3408
  },
3356
3409
  {
3357
3410
  name: 'showWind',
3358
- title: 'Show Wind Speed',
3411
+ title: '@dashboard:widgets.weather.show-wind',
3359
3412
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3360
3413
  schema: {
3361
3414
  defaultValue: true,
@@ -3370,7 +3423,7 @@ const AXPWeatherWidget = {
3370
3423
  },
3371
3424
  {
3372
3425
  name: 'showForecast',
3373
- title: 'Show Forecast',
3426
+ title: '@dashboard:widgets.weather.show-forecast',
3374
3427
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3375
3428
  schema: {
3376
3429
  defaultValue: true,
@@ -3385,7 +3438,7 @@ const AXPWeatherWidget = {
3385
3438
  },
3386
3439
  {
3387
3440
  name: 'forecastDays',
3388
- title: 'Forecast Days',
3441
+ title: '@dashboard:widgets.weather.forecast-days',
3389
3442
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3390
3443
  schema: {
3391
3444
  defaultValue: 5,
@@ -3406,7 +3459,7 @@ const AXPWeatherWidget = {
3406
3459
  /* Units Settings */
3407
3460
  {
3408
3461
  name: 'temperatureUnit',
3409
- title: 'Temperature Unit',
3462
+ title: '@dashboard:widgets.weather.temperature-unit',
3410
3463
  group: AXP_DATA_PROPERTY_GROUP,
3411
3464
  schema: {
3412
3465
  defaultValue: '°C',
@@ -3424,7 +3477,7 @@ const AXPWeatherWidget = {
3424
3477
  },
3425
3478
  {
3426
3479
  name: 'windSpeedUnit',
3427
- title: 'Wind Speed Unit',
3480
+ title: '@dashboard:widgets.weather.wind-speed-unit',
3428
3481
  group: AXP_DATA_PROPERTY_GROUP,
3429
3482
  schema: {
3430
3483
  defaultValue: 'km/h',
@@ -3443,7 +3496,7 @@ const AXPWeatherWidget = {
3443
3496
  /* Refresh Settings */
3444
3497
  {
3445
3498
  name: 'autoRefresh',
3446
- title: 'Auto Refresh',
3499
+ title: '@dashboard:widgets.weather.auto-refresh',
3447
3500
  group: AXP_BEHAVIOR_PROPERTY_GROUP,
3448
3501
  schema: {
3449
3502
  defaultValue: true,
@@ -3458,7 +3511,7 @@ const AXPWeatherWidget = {
3458
3511
  },
3459
3512
  {
3460
3513
  name: 'refreshInterval',
3461
- title: 'Refresh Interval (minutes)',
3514
+ title: '@dashboard:widgets.weather.refresh-interval',
3462
3515
  group: AXP_BEHAVIOR_PROPERTY_GROUP,
3463
3516
  schema: {
3464
3517
  defaultValue: 15,
@@ -3505,7 +3558,7 @@ class AXPDashboardShortcutWidgetViewComponent extends AXPLayoutWidgetComponent {
3505
3558
  super.ngOnInit();
3506
3559
  if (!this.color()) {
3507
3560
  this.setOptions({
3508
- color: AXPDataGenerator.color()
3561
+ color: AXPDataGenerator.color(),
3509
3562
  });
3510
3563
  }
3511
3564
  }
@@ -3531,8 +3584,8 @@ class AXPDashboardShortcutWidgetViewComponent extends AXPLayoutWidgetComponent {
3531
3584
  title: result.title,
3532
3585
  description: result.description,
3533
3586
  icon: result.icon,
3534
- command: result.command
3535
- }
3587
+ command: result.command,
3588
+ },
3536
3589
  });
3537
3590
  }
3538
3591
  }
@@ -3558,56 +3611,68 @@ class AXPDashboardShortcutWidgetViewComponent extends AXPLayoutWidgetComponent {
3558
3611
  }
3559
3612
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPDashboardShortcutWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3560
3613
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AXPDashboardShortcutWidgetViewComponent, isStandalone: true, selector: "ng-component", host: { properties: { "style": "this.__style", "class": "this.__class" } }, usesInheritance: true, ngImport: i0, template: `
3561
- @if(item()) {
3562
- <div
3614
+ @if (item()) {
3615
+ <div
3563
3616
  class="ax-group ax-flex ax-flex-col ax-items-center ax-justify-center ax-p-3 ax-w-full ax-h-full ax-relative ax-overflow-hidden "
3564
- (click)="executeCommand()">
3617
+ (click)="executeCommand()"
3618
+ >
3565
3619
  <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/10 ax-transition-opacity"></div>
3566
3620
  <i [class]="item().icon + ' ax-text-3xl'"></i>
3567
3621
  <span class="ax-text-xl ax-font-semibold">{{ item().title | translate | async }}</span>
3568
- @if(item().description) {
3569
- <span class="ax-text-sm ax-opacity-90 ax-text-center ax-px-2">{{ item().description! | translate | async }}</span>
3622
+ @if (item().description) {
3623
+ <span class="ax-text-sm ax-opacity-90 ax-text-center ax-px-2">{{
3624
+ item().description! | translate | async
3625
+ }}</span>
3570
3626
  }
3571
3627
  </div>
3572
3628
  } @else {
3573
- <div
3574
- (click)="setCommand()"
3575
- class="ax-group ax-flex ax-flex-col ax-items-center ax-justify-center ax-p-3 ax-w-full ax-h-full ax-relative ax-overflow-hidden">
3629
+ <div
3630
+ (click)="setCommand()"
3631
+ class="ax-group ax-flex ax-flex-col ax-items-center ax-justify-center ax-p-3 ax-w-full ax-h-full ax-relative ax-overflow-hidden"
3632
+ >
3576
3633
  <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/5 ax-transition-opacity"></div>
3577
3634
  <i class="fa-light fa-plus ax-text-3xl"></i>
3578
- <span class="ax-text-xl ax-font-semibold">Add Shortcut</span>
3635
+ <span class="ax-text-xl ax-font-semibold">{{
3636
+ '@dashboard:widgets.dashboard-shortcut.add-shortcut' | translate | async
3637
+ }}</span>
3579
3638
  </div>
3580
3639
  }
3581
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3640
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2$3.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3582
3641
  }
3583
3642
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXPDashboardShortcutWidgetViewComponent, decorators: [{
3584
3643
  type: Component,
3585
3644
  args: [{
3586
3645
  template: `
3587
- @if(item()) {
3588
- <div
3646
+ @if (item()) {
3647
+ <div
3589
3648
  class="ax-group ax-flex ax-flex-col ax-items-center ax-justify-center ax-p-3 ax-w-full ax-h-full ax-relative ax-overflow-hidden "
3590
- (click)="executeCommand()">
3649
+ (click)="executeCommand()"
3650
+ >
3591
3651
  <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/10 ax-transition-opacity"></div>
3592
3652
  <i [class]="item().icon + ' ax-text-3xl'"></i>
3593
3653
  <span class="ax-text-xl ax-font-semibold">{{ item().title | translate | async }}</span>
3594
- @if(item().description) {
3595
- <span class="ax-text-sm ax-opacity-90 ax-text-center ax-px-2">{{ item().description! | translate | async }}</span>
3654
+ @if (item().description) {
3655
+ <span class="ax-text-sm ax-opacity-90 ax-text-center ax-px-2">{{
3656
+ item().description! | translate | async
3657
+ }}</span>
3596
3658
  }
3597
3659
  </div>
3598
3660
  } @else {
3599
- <div
3600
- (click)="setCommand()"
3601
- class="ax-group ax-flex ax-flex-col ax-items-center ax-justify-center ax-p-3 ax-w-full ax-h-full ax-relative ax-overflow-hidden">
3661
+ <div
3662
+ (click)="setCommand()"
3663
+ class="ax-group ax-flex ax-flex-col ax-items-center ax-justify-center ax-p-3 ax-w-full ax-h-full ax-relative ax-overflow-hidden"
3664
+ >
3602
3665
  <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/5 ax-transition-opacity"></div>
3603
3666
  <i class="fa-light fa-plus ax-text-3xl"></i>
3604
- <span class="ax-text-xl ax-font-semibold">Add Shortcut</span>
3667
+ <span class="ax-text-xl ax-font-semibold">{{
3668
+ '@dashboard:widgets.dashboard-shortcut.add-shortcut' | translate | async
3669
+ }}</span>
3605
3670
  </div>
3606
3671
  }
3607
3672
  `,
3608
3673
  standalone: true,
3609
3674
  changeDetection: ChangeDetectionStrategy.OnPush,
3610
- imports: [CommonModule, AXTranslationModule]
3675
+ imports: [CommonModule, AXTranslationModule],
3611
3676
  }]
3612
3677
  }], propDecorators: { __style: [{
3613
3678
  type: HostBinding,
@@ -3623,15 +3688,18 @@ var dashboardShortcutWidgetView_component = /*#__PURE__*/Object.freeze({
3623
3688
  });
3624
3689
 
3625
3690
  const AXPDashboardShortcutWidget = {
3626
- name: "dashboard-shortcut",
3627
- title: "Shortcut",
3691
+ name: 'dashboard-shortcut',
3692
+ title: 'Shortcut',
3628
3693
  description: 'Quick access to your key features.',
3629
3694
  type: 'view',
3630
3695
  categories: [AXP_WIDGETS_UTILITY_CATEGORY],
3631
3696
  groups: [AXPWidgetGroupEnum.DashboardWidget],
3632
- icon: "fa-light fa-link",
3697
+ icon: 'fa-light fa-link',
3633
3698
  properties: [
3634
- AXP_COLOR_PROPERTY
3699
+ {
3700
+ ...AXP_COLOR_PROPERTY,
3701
+ title: '@dashboard:widgets.dashboard-shortcut.color',
3702
+ },
3635
3703
  ],
3636
3704
  meta: {
3637
3705
  dimensions: {
@@ -3647,7 +3715,7 @@ const AXPDashboardShortcutWidget = {
3647
3715
  view: {
3648
3716
  component: () => Promise.resolve().then(function () { return dashboardShortcutWidgetView_component; }).then((c) => c.AXPDashboardShortcutWidgetViewComponent),
3649
3717
  },
3650
- }
3718
+ },
3651
3719
  };
3652
3720
 
3653
3721
  class AXMMenuProvider {
@@ -3843,6 +3911,7 @@ class AXMDashboardWidgetWrapperComponent {
3843
3911
  });
3844
3912
  });
3845
3913
  this.hasConfiguration = input(true);
3914
+ this.isLocked = input(false);
3846
3915
  this.isDropdownOpen = signal(false);
3847
3916
  }
3848
3917
  #init;
@@ -3863,11 +3932,11 @@ class AXMDashboardWidgetWrapperComponent {
3863
3932
  console.log('Dropdown event:', event);
3864
3933
  }
3865
3934
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMDashboardWidgetWrapperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3866
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AXMDashboardWidgetWrapperComponent, isStandalone: true, selector: "axm-dashboard-widget-wrapper", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, hasConfiguration: { classPropertyName: "hasConfiguration", publicName: "hasConfiguration", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onDelete: "onDelete", onConfiguration: "onConfiguration", onValueChanged: "onValueChanged", onOptionsChanged: "onOptionsChanged" }, queries: [{ propertyName: "widget", first: true, predicate: AXPWidgetRendererDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<section class=\"ax-relative ax-size-full ax-flex ax-flex-col ax-group ax-overflow-hidden\">\n <!-- Action button - stays absolute -->\n <div\n class=\"ax-p-[0.6125rem] ax-absolute ax-top-0 ax-end-0 ax-z-[99] ax-invisible group-hover:ax-visible\"\n [class.!ax-visible]=\"isDropdownOpen()\"\n >\n <ax-button class=\"ax-sm\" [look]=\"'blank'\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-ellipsis-vertical\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel (onOpened)=\"isDropdownOpen.set(true)\" (onClosed)=\"isDropdownOpen.set(false)\">\n <ng-container *translate=\"let t\">\n <ax-button-item-list (onItemClick)=\"handleOnItemClick($event)\">\n @if(hasConfiguration()){\n <ax-button-item\n [data]=\"'configuration'\"\n [text]=\"(t('configuration', { scope: 'dashboard' }) | async) || 'configuration'\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-cog\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-divider></ax-divider>\n }\n <ax-button-item\n [data]=\"'delete'\"\n [text]=\"(t('delete', { scope: 'dashboard' }) | async) || 'delete'\"\n color=\"danger\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ng-container>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n\n <!-- Title section -->\n @if(title()) {\n <div class=\"ax-ps-5 ax-pe-8 ax-py-3 ax-border-b\">\n <h3 class=\"ax-text-start ax-text-lg ax-font-medium ax-truncate\">{{title()}}</h3>\n </div>\n }\n\n <!-- Content section -->\n <div class=\"ax-overflow-auto ax-h-full\">\n <ng-content></ng-content>\n </div>\n</section>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i1$2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$2.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i3$2.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i6.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3935
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.10", type: AXMDashboardWidgetWrapperComponent, isStandalone: true, selector: "axm-dashboard-widget-wrapper", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, hasConfiguration: { classPropertyName: "hasConfiguration", publicName: "hasConfiguration", isSignal: true, isRequired: false, transformFunction: null }, isLocked: { classPropertyName: "isLocked", publicName: "isLocked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onDelete: "onDelete", onConfiguration: "onConfiguration", onValueChanged: "onValueChanged", onOptionsChanged: "onOptionsChanged" }, queries: [{ propertyName: "widget", first: true, predicate: AXPWidgetRendererDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<section class=\"ax-relative ax-size-full ax-flex ax-flex-col ax-group ax-overflow-hidden\">\n <!-- Action button - stays absolute -->\n @if(!isLocked()) {\n <div\n class=\"ax-p-[0.6125rem] ax-absolute ax-top-0 ax-end-0 ax-z-[99] ax-invisible group-hover:ax-visible md:group-hover:ax-visible\"\n [class.!ax-visible]=\"isDropdownOpen()\"\n (touchstart)=\"isDropdownOpen.set(true)\"\n >\n <ax-button class=\"ax-sm ax-main-button\" [look]=\"'blank'\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-ellipsis-vertical\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel (onOpened)=\"isDropdownOpen.set(true)\" (onClosed)=\"isDropdownOpen.set(false)\">\n <ng-container *translate=\"let t\">\n <ax-button-item-list (onItemClick)=\"handleOnItemClick($event)\">\n @if(hasConfiguration()){\n <ax-button-item\n [data]=\"'configuration'\"\n [text]=\"(t('configuration', { scope: 'dashboard' }) | async) || 'configuration'\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-cog\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-divider></ax-divider>\n }\n <ax-button-item [data]=\"'delete'\" [text]=\"(t('delete') | async) || 'delete'\" color=\"danger\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ng-container>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n\n <!-- Title section -->\n @if(title()) {\n <div class=\"ax-ps-5 ax-pe-8 ax-py-3 ax-border-b\">\n <h3 class=\"ax-text-start ax-text-lg ax-font-medium ax-truncate\">{{title()}}</h3>\n </div>\n }\n\n <!-- Content section -->\n <div class=\"ax-overflow-auto ax-h-full\">\n <ng-content></ng-content>\n </div>\n</section>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i1$2.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$2.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i3$2.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i2$3.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3867
3936
  }
3868
3937
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMDashboardWidgetWrapperComponent, decorators: [{
3869
3938
  type: Component,
3870
- args: [{ selector: 'axm-dashboard-widget-wrapper', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AXButtonModule, AXDecoratorModule, AXDropdownModule, AXTranslationModule, CommonModule], standalone: true, template: "<section class=\"ax-relative ax-size-full ax-flex ax-flex-col ax-group ax-overflow-hidden\">\n <!-- Action button - stays absolute -->\n <div\n class=\"ax-p-[0.6125rem] ax-absolute ax-top-0 ax-end-0 ax-z-[99] ax-invisible group-hover:ax-visible\"\n [class.!ax-visible]=\"isDropdownOpen()\"\n >\n <ax-button class=\"ax-sm\" [look]=\"'blank'\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-ellipsis-vertical\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel (onOpened)=\"isDropdownOpen.set(true)\" (onClosed)=\"isDropdownOpen.set(false)\">\n <ng-container *translate=\"let t\">\n <ax-button-item-list (onItemClick)=\"handleOnItemClick($event)\">\n @if(hasConfiguration()){\n <ax-button-item\n [data]=\"'configuration'\"\n [text]=\"(t('configuration', { scope: 'dashboard' }) | async) || 'configuration'\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-cog\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-divider></ax-divider>\n }\n <ax-button-item\n [data]=\"'delete'\"\n [text]=\"(t('delete', { scope: 'dashboard' }) | async) || 'delete'\"\n color=\"danger\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ng-container>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n\n <!-- Title section -->\n @if(title()) {\n <div class=\"ax-ps-5 ax-pe-8 ax-py-3 ax-border-b\">\n <h3 class=\"ax-text-start ax-text-lg ax-font-medium ax-truncate\">{{title()}}</h3>\n </div>\n }\n\n <!-- Content section -->\n <div class=\"ax-overflow-auto ax-h-full\">\n <ng-content></ng-content>\n </div>\n</section>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
3939
+ args: [{ selector: 'axm-dashboard-widget-wrapper', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AXButtonModule, AXDecoratorModule, AXDropdownModule, AXTranslationModule, CommonModule], standalone: true, template: "<section class=\"ax-relative ax-size-full ax-flex ax-flex-col ax-group ax-overflow-hidden\">\n <!-- Action button - stays absolute -->\n @if(!isLocked()) {\n <div\n class=\"ax-p-[0.6125rem] ax-absolute ax-top-0 ax-end-0 ax-z-[99] ax-invisible group-hover:ax-visible md:group-hover:ax-visible\"\n [class.!ax-visible]=\"isDropdownOpen()\"\n (touchstart)=\"isDropdownOpen.set(true)\"\n >\n <ax-button class=\"ax-sm ax-main-button\" [look]=\"'blank'\">\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-ellipsis-vertical\"></ax-icon>\n </ax-prefix>\n <ax-dropdown-panel (onOpened)=\"isDropdownOpen.set(true)\" (onClosed)=\"isDropdownOpen.set(false)\">\n <ng-container *translate=\"let t\">\n <ax-button-item-list (onItemClick)=\"handleOnItemClick($event)\">\n @if(hasConfiguration()){\n <ax-button-item\n [data]=\"'configuration'\"\n [text]=\"(t('configuration', { scope: 'dashboard' }) | async) || 'configuration'\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-cog\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-divider></ax-divider>\n }\n <ax-button-item [data]=\"'delete'\" [text]=\"(t('delete') | async) || 'delete'\" color=\"danger\">\n <ax-prefix>\n <ax-icon icon=\"fa-solid fa-trash-can\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ng-container>\n </ax-dropdown-panel>\n </ax-button>\n </div>\n }\n\n <!-- Title section -->\n @if(title()) {\n <div class=\"ax-ps-5 ax-pe-8 ax-py-3 ax-border-b\">\n <h3 class=\"ax-text-start ax-text-lg ax-font-medium ax-truncate\">{{title()}}</h3>\n </div>\n }\n\n <!-- Content section -->\n <div class=\"ax-overflow-auto ax-h-full\">\n <ng-content></ng-content>\n </div>\n</section>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
3871
3940
  }] });
3872
3941
 
3873
3942
  const path = 'home:dashboard:';
@@ -3955,14 +4024,16 @@ class AXMAddDashboardPopup extends AXBasePageComponent {
3955
4024
  </ax-select-box>
3956
4025
  </div>
3957
4026
 
3958
- <div class="ax-flex ax-flex-col ax-gap-2 ax-mt-4">
3959
- <p class="ax-font-semibold">{{ 'disable' | translate: { scope } | async }}</p>
3960
- <ax-check-box [(ngModel)]="isDisabled" name="isDisabled"></ax-check-box>
3961
- </div>
4027
+ <div class="ax-grid grid-cols-2 ax-grid-flow-col ax-gap-8 ax-mt-4">
4028
+ <div class="ax-flex ax-flex-row ax-items-center ax-gap-2">
4029
+ <p class="ax-font-semibold">{{ 'disable' | translate: { scope } | async }}</p>
4030
+ <ax-switch [(ngModel)]="isDisabled" name="isDisabled"></ax-switch>
4031
+ </div>
3962
4032
 
3963
- <div class="ax-flex ax-flex-col ax-gap-2 ax-mt-4">
3964
- <p class="ax-font-semibold">{{ 'lock' | translate: { scope } | async }}</p>
3965
- <ax-check-box [(ngModel)]="isLocked" name="isLocked"></ax-check-box>
4033
+ <div class="ax-flex ax-flex-row ax-items-center ax-gap-2">
4034
+ <p class="ax-font-semibold">{{ 'lock' | translate: { scope } | async }}</p>
4035
+ <ax-switch [(ngModel)]="isLocked" name="isLocked"></ax-switch>
4036
+ </div>
3966
4037
  </div>
3967
4038
  }
3968
4039
  </div>
@@ -3982,7 +4053,7 @@ class AXMAddDashboardPopup extends AXBasePageComponent {
3982
4053
  </ax-button>
3983
4054
  </ax-suffix>
3984
4055
  </ax-footer>
3985
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i3$3.AXTextBoxComponent, selector: "ax-text-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "maxLength", "allowNull", "type", "autoComplete", "look", "mask-options", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXLabelModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "component", type: i7.AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed"] }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "component", type: i4.AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "checked", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }] }); }
4056
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$2.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i3$3.AXTextBoxComponent, selector: "ax-text-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "maxLength", "allowNull", "type", "autoComplete", "look", "mask-options", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXLabelModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$2.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2$3.AXTranslatorPipe, name: "translate" }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "component", type: i7.AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed"] }, { kind: "ngmodule", type: AXSwitchModule }, { kind: "component", type: i8.AXSwitchComponent, selector: "ax-switch", inputs: ["disabled", "readonly", "color", "tabIndex", "value", "name", "isLoading"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged", "readonlyChange", "disabledChange"] }] }); }
3986
4057
  }
3987
4058
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMAddDashboardPopup, decorators: [{
3988
4059
  type: Component,
@@ -4014,14 +4085,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
4014
4085
  </ax-select-box>
4015
4086
  </div>
4016
4087
 
4017
- <div class="ax-flex ax-flex-col ax-gap-2 ax-mt-4">
4018
- <p class="ax-font-semibold">{{ 'disable' | translate: { scope } | async }}</p>
4019
- <ax-check-box [(ngModel)]="isDisabled" name="isDisabled"></ax-check-box>
4020
- </div>
4088
+ <div class="ax-grid grid-cols-2 ax-grid-flow-col ax-gap-8 ax-mt-4">
4089
+ <div class="ax-flex ax-flex-row ax-items-center ax-gap-2">
4090
+ <p class="ax-font-semibold">{{ 'disable' | translate: { scope } | async }}</p>
4091
+ <ax-switch [(ngModel)]="isDisabled" name="isDisabled"></ax-switch>
4092
+ </div>
4021
4093
 
4022
- <div class="ax-flex ax-flex-col ax-gap-2 ax-mt-4">
4023
- <p class="ax-font-semibold">{{ 'lock' | translate: { scope } | async }}</p>
4024
- <ax-check-box [(ngModel)]="isLocked" name="isLocked"></ax-check-box>
4094
+ <div class="ax-flex ax-flex-row ax-items-center ax-gap-2">
4095
+ <p class="ax-font-semibold">{{ 'lock' | translate: { scope } | async }}</p>
4096
+ <ax-switch [(ngModel)]="isLocked" name="isLocked"></ax-switch>
4097
+ </div>
4025
4098
  </div>
4026
4099
  }
4027
4100
  </div>
@@ -4051,7 +4124,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
4051
4124
  CommonModule,
4052
4125
  AXTranslationModule,
4053
4126
  AXSelectBoxModule,
4054
- AXCheckBoxModule,
4127
+ AXSwitchModule,
4055
4128
  ],
4056
4129
  standalone: true,
4057
4130
  }]
@@ -4120,6 +4193,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
4120
4193
  class AXMDashboardPopupService {
4121
4194
  constructor() {
4122
4195
  this.popupService = inject(AXPopupService);
4196
+ this.translateService = inject(AXTranslationService);
4123
4197
  }
4124
4198
  async generateDashboardLayout(data, isAdmin) {
4125
4199
  // Add isAdmin to the data object
@@ -4129,7 +4203,7 @@ class AXMDashboardPopupService {
4129
4203
  size: 'sm',
4130
4204
  draggable: true,
4131
4205
  hasBackdrop: true,
4132
- title: 'Dashboard Info',
4206
+ title: await this.translateService.translateAsync('dashboard-info', { scope: 'dashboard' }),
4133
4207
  data: dashboardData,
4134
4208
  });
4135
4209
  if (!result.data) {
@@ -4178,7 +4252,7 @@ withState(() => {
4178
4252
  currentDashboardId: null,
4179
4253
  isAdmin: false,
4180
4254
  dashboardsOption: {
4181
- float: true,
4255
+ float: false,
4182
4256
  cellHeight: 75,
4183
4257
  gap: 5,
4184
4258
  minRow: 9,
@@ -4194,7 +4268,7 @@ withState(() => {
4194
4268
  return state;
4195
4269
  }),
4196
4270
  // Computed Properties
4197
- withComputed((state, sessionService = inject(AXPSessionService)) => ({
4271
+ withComputed((state, sessionService = inject(AXPSessionService), layoutThemeService = inject(AXPLayoutThemeService)) => ({
4198
4272
  currentDashboard: computed(() => {
4199
4273
  return state.dashboards().find((dashboard) => dashboard.id === state.currentDashboardId()) || null;
4200
4274
  }),
@@ -4211,11 +4285,20 @@ withComputed((state, sessionService = inject(AXPSessionService)) => ({
4211
4285
  if (!currentDashboard) {
4212
4286
  return baseOptions;
4213
4287
  }
4214
- // If admin, no restrictions
4215
- if (state.isAdmin()) {
4288
+ // Always disable drag and resize on mobile devices
4289
+ if (!layoutThemeService.isDesktopDevice()) {
4290
+ return {
4291
+ ...baseOptions,
4292
+ disableDrag: true,
4293
+ disableResize: true,
4294
+ };
4295
+ }
4296
+ // If the base options already have explicit disableDrag and disableResize values,
4297
+ // preserve those values (these were likely set by toggleLockDashboard)
4298
+ if (baseOptions.disableDrag !== undefined && baseOptions.disableResize !== undefined) {
4216
4299
  return baseOptions;
4217
4300
  }
4218
- // Check if dashboard is locked
4301
+ // Check if dashboard is locked - locked dashboards always have drag and resize disabled
4219
4302
  if (currentDashboard.locked === true) {
4220
4303
  return {
4221
4304
  ...baseOptions,
@@ -4223,6 +4306,10 @@ withComputed((state, sessionService = inject(AXPSessionService)) => ({
4223
4306
  disableResize: true,
4224
4307
  };
4225
4308
  }
4309
+ // If admin, no restrictions unless it's locked (which is checked above)
4310
+ if (state.isAdmin()) {
4311
+ return baseOptions;
4312
+ }
4226
4313
  // Get user role
4227
4314
  const userRole = sessionService.user ? sessionService.user['role'] : undefined;
4228
4315
  // Check if user has role in dashboard
@@ -4264,9 +4351,33 @@ withComputed((state, sessionService = inject(AXPSessionService)) => ({
4264
4351
  return widget.node?.options?.['hasConfiguration'] ?? true;
4265
4352
  };
4266
4353
  }),
4354
+ isWidgetLocked: computed(() => {
4355
+ return (widget) => {
4356
+ const currentDashboard = state.dashboards().find((dashboard) => dashboard.id === state.currentDashboardId());
4357
+ if (!currentDashboard)
4358
+ return false;
4359
+ // If dashboard is locked, widget is locked
4360
+ if (currentDashboard.locked === true) {
4361
+ return true;
4362
+ }
4363
+ // If admin, widget is not locked
4364
+ if (state.isAdmin())
4365
+ return false;
4366
+ // Get user role
4367
+ const userRole = sessionService.user ? sessionService.user['role'] : undefined;
4368
+ // Check if user has role in dashboard
4369
+ const hasRoleIds = currentDashboard.roleIds && Array.isArray(currentDashboard.roleIds) && currentDashboard.roleIds.length > 0;
4370
+ const hasUserRole = userRole && hasRoleIds && currentDashboard.roleIds?.includes(userRole);
4371
+ // If user is not admin, has role in dashboard, and dashboard has scope 'T', widget is locked
4372
+ if (hasUserRole && currentDashboard.scope === 'T') {
4373
+ return true;
4374
+ }
4375
+ return false;
4376
+ };
4377
+ }),
4267
4378
  })),
4268
4379
  // Methods for State Management
4269
- withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogService = inject(AXDialogService), translationService = inject(AXTranslationService), widgetPickerService = inject(AXPWidgetPickerService), dashboardService = inject(AXMDashboardService), settingService = inject(AXPSettingService), sessionService = inject(AXPSessionService)) => {
4380
+ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogService = inject(AXDialogService), translationService = inject(AXTranslationService), widgetPickerService = inject(AXPWidgetPickerService), dashboardService = inject(AXMDashboardService), settingService = inject(AXPSettingService), sessionService = inject(AXPSessionService), layoutThemeService = inject(AXPLayoutThemeService)) => {
4270
4381
  // Load dashboards from service - runs on init via effect
4271
4382
  effect(() => {
4272
4383
  loadDashboards();
@@ -4521,6 +4632,10 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4521
4632
  },
4522
4633
  // Handle grid layout changes
4523
4634
  async onGridChange(event) {
4635
+ // Skip any changes on mobile devices
4636
+ if (!layoutThemeService.isDesktopDevice()) {
4637
+ return;
4638
+ }
4524
4639
  if (!store.currentDashboard()) {
4525
4640
  console.warn('No current dashboard for grid change');
4526
4641
  return;
@@ -4666,37 +4781,11 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4666
4781
  console.error('Error handling widget options change:', error);
4667
4782
  }
4668
4783
  },
4669
- // Reload dashboards from service
4670
- async refreshDashboards() {
4671
- try {
4672
- patchState(store, { isLoading: true });
4673
- // Get dashboards from service using query method
4674
- const result = await dashboardService.query({ skip: 0, take: 100 });
4675
- const dashboardModels = result.items || [];
4676
- // Convert dashboard models to AXPDashboardLayout
4677
- const dashboards = dashboardModels.map(modelToDashboardLayout);
4678
- // Update allDashboards state
4679
- patchState(store, {
4680
- allDashboards: dashboards,
4681
- isLoading: false,
4682
- });
4683
- // Re-apply filtering based on current isAdmin state
4684
- // This will update the dashboards state with filtered results
4685
- const userId = sessionService.user?.id;
4686
- const userRole = sessionService.user ? sessionService.user['role'] : undefined;
4687
- if (userId) {
4688
- this.filterDashboardsByScope(store.isAdmin());
4689
- }
4690
- else {
4691
- // If no user, just show all dashboards
4692
- patchState(store, { dashboards });
4693
- }
4694
- }
4695
- catch (error) {
4696
- console.error('Error refreshing dashboards:', error);
4697
- patchState(store, { isLoading: false });
4698
- }
4784
+ // Handle setting admin state
4785
+ setIsAdmin(isAdmin) {
4786
+ patchState(store, { isAdmin });
4699
4787
  },
4788
+ // Filter dashboards by scope
4700
4789
  filterDashboardsByScope(isAdmin) {
4701
4790
  // Get all dashboards from the stored allDashboards array
4702
4791
  const allDashboards = store.allDashboards();
@@ -4737,10 +4826,6 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4737
4826
  this.setCurrentDashboard(filteredDashboards[0].id);
4738
4827
  }
4739
4828
  },
4740
- // Add method to set isAdmin state
4741
- setIsAdmin(isAdmin) {
4742
- patchState(store, { isAdmin });
4743
- },
4744
4829
  // Toggle lock state for the current dashboard
4745
4830
  async toggleLockDashboard() {
4746
4831
  const currentDashboard = store.currentDashboard();
@@ -4749,6 +4834,18 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4749
4834
  return;
4750
4835
  }
4751
4836
  try {
4837
+ // Check permission to toggle lock
4838
+ const isAdmin = store.isAdmin();
4839
+ const userId = sessionService.user?.id;
4840
+ // Determine if user can toggle lock based on the rules:
4841
+ // 1. If isAdmin is false, user can only toggle their own user-level dashboards
4842
+ // 2. If isAdmin is true, user can only toggle tenant-level dashboards
4843
+ const canToggle = (!isAdmin && currentDashboard.scope === 'U' && currentDashboard.createdBy === userId) ||
4844
+ (isAdmin && currentDashboard.scope === 'T');
4845
+ if (!canToggle) {
4846
+ console.warn('User does not have permission to toggle lock for this dashboard');
4847
+ return;
4848
+ }
4752
4849
  // Toggle the locked state
4753
4850
  const newLockedState = !currentDashboard.locked;
4754
4851
  // Create an updated dashboard with toggled lock state
@@ -4762,8 +4859,24 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4762
4859
  const updatedDashboards = store
4763
4860
  .dashboards()
4764
4861
  .map((dashboard) => (dashboard.id === updatedDashboard.id ? updatedDashboard : dashboard));
4765
- patchState(store, { dashboards: updatedDashboards });
4766
- console.log(`Dashboard ${newLockedState ? 'locked' : 'unlocked'}`);
4862
+ // IMPORTANT: Get the base options BEFORE updating the dashboards state
4863
+ // This ensures we're getting the current options without the lock state applied yet
4864
+ const baseOptions = { ...store.dashboardsOption() };
4865
+ // First update the dashboards state
4866
+ patchState(store, {
4867
+ dashboards: updatedDashboards,
4868
+ });
4869
+ // Get a fresh reference to the updated options with drag/resize explicitly set
4870
+ // This ensures the grid layout container gets a new object reference and responds immediately
4871
+ const updatedOptions = {
4872
+ ...baseOptions,
4873
+ disableDrag: newLockedState,
4874
+ disableResize: newLockedState,
4875
+ };
4876
+ // Now update the options state separately to force a refresh of the grid layout
4877
+ patchState(store, {
4878
+ dashboardsOption: updatedOptions,
4879
+ });
4767
4880
  }
4768
4881
  catch (error) {
4769
4882
  console.error('Error toggling dashboard lock state:', error);
@@ -4780,59 +4893,44 @@ withMethods((store, dashboardPopup = inject(AXMDashboardPopupService), dialogSer
4780
4893
  class AXMDashboardHomeComponent extends AXPBasePageComponent {
4781
4894
  constructor() {
4782
4895
  super(...arguments);
4783
- //#region ---------------- Services & Dependencies ----------------
4784
4896
  this.rootConfig = RootConfig;
4785
- this.popupService = inject(AXPopupService);
4897
+ this.activatedRoute = inject(ActivatedRoute);
4786
4898
  this.dialogService = inject(AXDialogService);
4787
- this.store = inject(AXMDashboardStore);
4899
+ this.popupService = inject(AXPopupService);
4788
4900
  this.router = inject(Router);
4789
- this.activatedRoute = inject(ActivatedRoute);
4790
- this.layoutService = inject(AXPLayoutThemeService);
4791
- this.sessionService = inject(AXPSessionService);
4792
- // Track if dashboards have been loaded
4793
- this.dashboardsLoaded = signal(false);
4794
- //#endregion
4795
- //#region ---------------- View Properties ----------------
4901
+ this.store = inject(AXMDashboardStore);
4902
+ this.themeService = inject(AXPLayoutThemeService);
4796
4903
  this.isEdited = signal(false);
4797
4904
  this.context = signal({});
4798
- //#endregion
4799
- //#region ---------------- Effects ----------------
4800
- // Create an effect to watch for dashboards loading
4905
+ this.dashboardsLoaded = signal(false);
4801
4906
  this.#dashboardsEffect = effect(() => {
4802
4907
  const allDashboards = this.store.allDashboards();
4803
4908
  if (allDashboards.length > 0 && !this.dashboardsLoaded()) {
4804
4909
  this.dashboardsLoaded.set(true);
4805
- // Apply dashboard filtering now that dashboards are loaded
4806
4910
  this.applyDashboardFiltering();
4911
+ this.recompute();
4807
4912
  }
4808
4913
  });
4809
4914
  this.#loadingEffect = effect(() => {
4810
- const isLoading = false; // Since store doesn't have isLoading, we'll default to false
4811
- this.layoutService.setNavigationLoading(isLoading);
4915
+ const isLoading = this.store.isLoading();
4916
+ if (isLoading === false && this.dashboardsLoaded()) {
4917
+ this.recompute;
4918
+ setTimeout(() => this.recompute(), 0);
4919
+ }
4812
4920
  });
4813
4921
  }
4814
- //#endregion
4815
- //#region ---------------- Lifecycle Methods ----------------
4816
4922
  async ngOnInit() {
4817
- // Get the child route if it exists
4818
4923
  const childRoute = this.activatedRoute.firstChild || this.activatedRoute;
4819
4924
  childRoute.data.subscribe((data) => {
4820
4925
  const isAdmin = data['isAdmin'] ?? false;
4821
- // Set isAdmin state in the store
4822
4926
  this.store.setIsAdmin(isAdmin);
4823
4927
  });
4824
4928
  }
4825
4929
  applyDashboardFiltering() {
4826
- // The store now gets user info directly from the session service
4827
4930
  this.store.filterDashboardsByScope(this.store.isAdmin());
4828
4931
  }
4829
- //#endregion
4830
- //#region ---------------- Effects ----------------
4831
- // Create an effect to watch for dashboards loading
4832
4932
  #dashboardsEffect;
4833
4933
  #loadingEffect;
4834
- //#endregion
4835
- //#region ---------------- Event Handlers ----------------
4836
4934
  toggleEdit() {
4837
4935
  this.isEdited.update((value) => !value);
4838
4936
  }
@@ -4847,7 +4945,6 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
4847
4945
  console.error('Error confirming widget deletion:', error);
4848
4946
  }
4849
4947
  }
4850
- //#endregion
4851
4948
  getPageTitle() {
4852
4949
  return this.store.currentDashboard()?.title || 'Dashboard';
4853
4950
  }
@@ -4885,6 +4982,7 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
4885
4982
  command: {
4886
4983
  name: 'new-widget',
4887
4984
  },
4985
+ disabled: this.store.dashboards().length < 1,
4888
4986
  },
4889
4987
  ],
4890
4988
  },
@@ -4894,7 +4992,7 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
4894
4992
  const scope = this.rootConfig.config.i18n;
4895
4993
  const items = [
4896
4994
  {
4897
- title: await this.translateService.translateAsync('delete-current-dashboard', { scope: 'dashboard' }),
4995
+ title: await this.translateService.translateAsync('delete'),
4898
4996
  icon: 'fa-light fa-trash-can',
4899
4997
  color: 'danger',
4900
4998
  disabled: this.store.dashboards().length < 1,
@@ -4903,10 +5001,11 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
4903
5001
  },
4904
5002
  },
4905
5003
  ];
4906
- // Only add lock toggle if not admin
4907
- if (!this.store.isAdmin()) {
5004
+ if (!this.store.isAdmin() && this.themeService.isDesktopDevice()) {
4908
5005
  items.push({
4909
- title: await this.translateService.translateAsync(this.store.isDashboardLocked() ? 'unlock-dashboard' : 'lock-dashboard', { scope: 'dashboard' }),
5006
+ title: await this.translateService.translateAsync(this.store.isDashboardLocked() ? 'unlock' : 'lock', {
5007
+ scope: 'dashboard',
5008
+ }),
4910
5009
  icon: this.store.isDashboardLocked() ? 'fa-light fa-lock-open' : 'fa-light fa-lock',
4911
5010
  color: 'accent3',
4912
5011
  disabled: this.store.dashboards().length < 1,
@@ -4941,6 +5040,10 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
4941
5040
  case 'toggle-lock':
4942
5041
  await this.store.toggleLockDashboard();
4943
5042
  this.recompute();
5043
+ // Add a short delay to ensure the grid layout updates properly
5044
+ setTimeout(() => {
5045
+ this.recompute();
5046
+ }, 50);
4944
5047
  break;
4945
5048
  }
4946
5049
  }
@@ -4953,7 +5056,7 @@ class AXMDashboardHomeComponent extends AXPBasePageComponent {
4953
5056
  provide: AXPBasePage,
4954
5057
  useExisting: AXMDashboardHomeComponent,
4955
5058
  },
4956
- ], usesInheritance: true, ngImport: i0, template: "<axp-page-layout *translate=\"let t\">\n <!-- Content Section -->\n\n <axp-page-content class=\"ax-relative\">\n @if(store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ t('loading', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container [options]=\"store.dashboardsOption()\" (onChange)=\"store.onGridChange($event)\">\n @for(widget of store.currentDashboard()?.widgets; track widget.config.id) {\n <ax-grid-layout-widget [options]=\"widget.config\">\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.currentDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!,$event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!,$event)\"\n >\n @if(widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n } @empty {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-bg-gray-50 ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-text-gray-400 ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-text-gray-700 ax-mb-2\">\n {{ t('no-widgets', { scope: 'dashboard' }) | async }}\n </h2>\n <p class=\"ax-text-gray-500 ax-text-center ax-mb-6\">\n {{ t('add-first-widget', { scope: 'dashboard' }) | async }}\n </p>\n </div>\n }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important;--ax-comp-grid-layout-stack-item-content-bg-color: var(--ax-sys-color-lightest-surface) }\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2$3.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXPLayoutBuilderModule }, { kind: "component", type: i3$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "ngmodule", type: AXGridLayoutBuilderModule }, { kind: "component", type: i4$1.AXGridLayoutContainerComponent, selector: "ax-grid-layout-container", inputs: ["options", "isEmpty"], outputs: ["onAdded", "onRemoved", "onWidgetChange", "onChange", "onRender", "isEmptyChange"] }, { kind: "component", type: i4$1.AXGridLayoutWidgetComponent, selector: "ax-grid-layout-widget", inputs: ["options"] }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer, axp-page-header, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-container, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i6.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXBreadcrumbsModule }, { kind: "component", type: AXMDashboardWidgetWrapperComponent, selector: "axm-dashboard-widget-wrapper", inputs: ["title", "hasConfiguration"], outputs: ["onDelete", "onConfiguration", "onValueChanged", "onOptionsChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
5059
+ ], usesInheritance: true, ngImport: i0, template: "<axp-page-layout *translate=\"let t\">\n <!-- Content Section -->\n\n <axp-page-content class=\"ax-relative\">\n @if(store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ t('loading', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container [options]=\"store.dashboardsOption()\" (onChange)=\"store.onGridChange($event)\">\n @if(!store.dashboards() || store.dashboards().length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-dashboards', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else if (!store.currentDashboard()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">\n {{ t('no-current-dashboard', { scope: 'dashboard' }) | async }}\n </h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('select-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else if (!store.currentDashboard()?.widgets || store.currentDashboard()?.widgets.length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-widgets', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-widget', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else { @for(widget of store.currentDashboard()?.widgets; track widget.config.id) {\n <ax-grid-layout-widget [options]=\"widget.config\">\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n [isLocked]=\"store.isWidgetLocked()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.currentDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!,$event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!,$event)\"\n >\n @if(widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n } }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important;--ax-comp-grid-layout-stack-item-content-bg-color: var(--ax-sys-color-lightest-surface) }\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2$4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXPLayoutBuilderModule }, { kind: "component", type: i3$1.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i3$1.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "ngmodule", type: AXGridLayoutBuilderModule }, { kind: "component", type: i4$1.AXGridLayoutContainerComponent, selector: "ax-grid-layout-container", inputs: ["options", "isEmpty"], outputs: ["onAdded", "onRemoved", "onWidgetChange", "onChange", "onRender", "isEmptyChange"] }, { kind: "component", type: i4$1.AXGridLayoutWidgetComponent, selector: "ax-grid-layout-widget", inputs: ["options"] }, { kind: "component", type: AXPPageLayoutComponent, selector: "axp-page-layout" }, { kind: "component", type: AXPThemeLayoutBlockComponent, selector: " axp-page-content, axp-page-footer, axp-page-header, axp-page-toolbar, axp-layout-content, axp-layout-page-content, axp-layout-sections, axp-layout-body, axp-layout-container, axp-layout-page-body, axp-layout-prefix, axp-layout-suffix, axp-layout-title-bar, axp-layout-title, axp-layout-title-actions, axp-layout-nav-button, axp-layout-description, axp-layout-breadcrumbs, axp-layout-list-action, " }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i2$3.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXBreadcrumbsModule }, { kind: "component", type: AXMDashboardWidgetWrapperComponent, selector: "axm-dashboard-widget-wrapper", inputs: ["title", "hasConfiguration", "isLocked"], outputs: ["onDelete", "onConfiguration", "onValueChanged", "onOptionsChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
4957
5060
  }
4958
5061
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: AXMDashboardHomeComponent, decorators: [{
4959
5062
  type: Component,
@@ -4979,7 +5082,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImpo
4979
5082
  provide: AXPBasePage,
4980
5083
  useExisting: AXMDashboardHomeComponent,
4981
5084
  },
4982
- ], template: "<axp-page-layout *translate=\"let t\">\n <!-- Content Section -->\n\n <axp-page-content class=\"ax-relative\">\n @if(store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ t('loading', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container [options]=\"store.dashboardsOption()\" (onChange)=\"store.onGridChange($event)\">\n @for(widget of store.currentDashboard()?.widgets; track widget.config.id) {\n <ax-grid-layout-widget [options]=\"widget.config\">\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.currentDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!,$event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!,$event)\"\n >\n @if(widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n } @empty {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-bg-gray-50 ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-text-gray-400 ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-text-gray-700 ax-mb-2\">\n {{ t('no-widgets', { scope: 'dashboard' }) | async }}\n </h2>\n <p class=\"ax-text-gray-500 ax-text-center ax-mb-6\">\n {{ t('add-first-widget', { scope: 'dashboard' }) | async }}\n </p>\n </div>\n }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important;--ax-comp-grid-layout-stack-item-content-bg-color: var(--ax-sys-color-lightest-surface) }\n"] }]
5085
+ ], template: "<axp-page-layout *translate=\"let t\">\n <!-- Content Section -->\n\n <axp-page-content class=\"ax-relative\">\n @if(store.isLoading()) {\n <div\n class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-w-full ax-absolute ax-z-10 ax-bg-white/80\"\n >\n <ax-loading></ax-loading>\n <p class=\"ax-mt-3 ax-text-gray-600\">{{ t('loading', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else {\n <axp-widgets-container [context]=\"context()\">\n <ax-grid-layout-container [options]=\"store.dashboardsOption()\" (onChange)=\"store.onGridChange($event)\">\n @if(!store.dashboards() || store.dashboards().length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-dashboards', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else if (!store.currentDashboard()) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">\n {{ t('no-current-dashboard', { scope: 'dashboard' }) | async }}\n </h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('select-dashboard', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else if (!store.currentDashboard()?.widgets || store.currentDashboard()?.widgets.length === 0) {\n <div class=\"ax-flex ax-flex-col ax-items-center ax-justify-center ax-h-full ax-p-4\">\n <ax-icon icon=\"fa-light fa-shapes\" class=\"ax-text-4xl ax-mb-4\"></ax-icon>\n <h2 class=\"ax-text-xl ax-font-semibold ax-mb-2\">{{ t('no-widgets', { scope: 'dashboard' }) | async }}</h2>\n <p class=\"ax-text-center ax-mb-6\">{{ t('add-first-widget', { scope: 'dashboard' }) | async }}</p>\n </div>\n } @else { @for(widget of store.currentDashboard()?.widgets; track widget.config.id) {\n <ax-grid-layout-widget [options]=\"widget.config\">\n <axm-dashboard-widget-wrapper\n [title]=\"widget.node?.options?.['title']\"\n [hasConfiguration]=\"store.canConfigureWidget()(widget)\"\n [isLocked]=\"store.isWidgetLocked()(widget)\"\n (onDelete)=\"confirmWidgetDelete(store.currentDashboard()?.id!, widget.config.id!)\"\n (onConfiguration)=\"store.handlePopupConfiguration(widget.node!)\"\n (onValueChanged)=\"store.handleValueChanged(widget?.node!,$event)\"\n (onOptionsChanged)=\"store.handleOptionsChanged(widget?.node!,$event)\"\n >\n @if(widget.node) {\n <ng-container axp-widget-renderer [node]=\"widget.node\" [mode]=\"'view'\"></ng-container>\n }\n </axm-dashboard-widget-wrapper>\n </ax-grid-layout-widget>\n } }\n </ax-grid-layout-container>\n </axp-widgets-container>\n }\n </axp-page-content>\n</axp-page-layout>\n", styles: ["axm-dashboard-home{background-color:rgb(var(--ax-sys-color-lighter-surface));color:rgb(var(--ax-sys-color-on-lighter-surface));border-color:rgb(var(--ax-sys-color-border-lighter-surface))}axm-dashboard-home .placeholder-content{border-radius:.5rem!important;border-width:1px!important;border-style:dashed!important;--tw-border-opacity: 1 !important;border-color:rgba(var(--ax-sys-color-primary-500),var(--tw-border-opacity, 1))!important;background-color:rgba(var(--ax-sys-color-primary-lightest-surface),.5)!important}axm-dashboard-home ax-grid-layout-widget .grid-stack-item-content{border-radius:.375rem!important;border-width:1px!important;--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05) !important;--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important;--ax-comp-grid-layout-stack-item-content-bg-color: var(--ax-sys-color-lightest-surface) }\n"] }]
4983
5086
  }] });
4984
5087
 
4985
5088
  var homeDashboard = /*#__PURE__*/Object.freeze({