@acorex/modules 19.3.1 → 19.3.3-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/common/index.d.ts +1 -0
  2. package/common/lib/common.module.d.ts +3 -1
  3. package/common/lib/features/global-search/index.d.ts +3 -0
  4. package/common/lib/features/global-search/search-popup.component.d.ts +22 -0
  5. package/common/lib/features/global-search/search-slot.component.d.ts +9 -0
  6. package/common/lib/features/global-search/search.config.d.ts +5 -0
  7. package/common/lib/features/global-search/search.module.d.ts +11 -0
  8. package/common/lib/features/global-search/search.viewmodel.d.ts +34 -0
  9. package/common/lib/features/global-search/workflows/search.workflow.d.ts +11 -0
  10. package/dashboard-management/lib/entities/dashboard/dashboard.types.d.ts +2 -2
  11. package/dashboard-management/lib/features/home-dashboard/dashboard-home/home-dashboard.d.ts +7 -7
  12. package/dashboard-management/lib/features/home-dashboard/dashboard-home/home-dashboard.store.d.ts +6 -6
  13. package/dashboard-management/lib/features/home-dashboard/dashboard-home/home-dashboard.type.d.ts +3 -3
  14. package/dashboard-management/lib/features/home-dashboard/dashboard-popups/add-dashboard-popup.d.ts +3 -3
  15. package/dashboard-management/lib/features/home-dashboard/dashboard-popups/configuration-popup.d.ts +3 -3
  16. package/dashboard-management/lib/features/home-dashboard/dashboard-popups/dashboard-popup.service.d.ts +5 -5
  17. package/dashboard-management/lib/features/home-dashboard/widget-wrapper/dashboard-widget-wrapper.d.ts +4 -3
  18. package/dashboard-management/lib/features/shared/widgets/bar-chart/bar-chart-widget.component.d.ts +9 -64
  19. package/dashboard-management/lib/features/shared/widgets/clock-calendar/clock-calendar-widget.component.d.ts +0 -1
  20. package/dashboard-management/lib/features/shared/widgets/donut-chart/donut-chart-widget.component.d.ts +9 -50
  21. package/dashboard-management/lib/features/shared/widgets/gauge-chart/gauge-chart-widget.component.d.ts +8 -67
  22. package/dashboard-management/lib/features/shared/widgets/gauge-chart/index.d.ts +0 -1
  23. package/dashboard-management/lib/features/shared/widgets/index.d.ts +0 -2
  24. package/dashboard-management/lib/features/shared/widgets/line-chart/index.d.ts +0 -1
  25. package/dashboard-management/lib/features/shared/widgets/line-chart/line-chart-widget.component.d.ts +9 -68
  26. package/document-management/lib/features/document-explorer/document-explorer.component.d.ts +1 -0
  27. package/document-management/lib/features/document-explorer/document-explorer.viewmodel.d.ts +1 -0
  28. package/document-management/lib/features/document-explorer/views/detail-panel/detail-panel.component.d.ts +1 -0
  29. package/document-management/lib/features/document-explorer/views/details/details-view.component.d.ts +1 -0
  30. package/document-management/lib/features/document-explorer/views/large-icons/large-icons-view.component.d.ts +1 -0
  31. package/document-management/lib/features/document-explorer/views/large-tiles/large-tiles-view.component.d.ts +1 -0
  32. package/document-management/lib/features/document-explorer/views/list/list-view.component.d.ts +1 -0
  33. package/document-management/lib/features/document-explorer/views/small-icons/small-icons-view.component.d.ts +1 -0
  34. package/document-management/lib/features/document-explorer/views/small-tiles/small-tiles-view.component.d.ts +1 -0
  35. package/document-management/lib/features/drive/drive.component.d.ts +1 -0
  36. package/document-management/lib/features/drive-choose/drive-choose.component.d.ts +1 -0
  37. package/document-management/lib/features/shared/components/folder-path-breadcrumbs/folder-path-breadcrumbs.component.d.ts +1 -0
  38. package/document-management/lib/features/widgets/document-attachment/document-attachment-widget-edit.component.d.ts +4 -3
  39. package/document-management/lib/permission-definition.provider.d.ts +4 -0
  40. package/document-management/lib/permission.keys.d.ts +19 -0
  41. package/fesm2022/{acorex-modules-auth-acorex-modules-auth-B1HTJdsE.mjs → acorex-modules-auth-acorex-modules-auth-DJZcD1j3.mjs} +23 -83
  42. package/fesm2022/acorex-modules-auth-acorex-modules-auth-DJZcD1j3.mjs.map +1 -0
  43. package/fesm2022/acorex-modules-auth-app-chooser.component-DlYxDGQr.mjs +65 -0
  44. package/fesm2022/acorex-modules-auth-app-chooser.component-DlYxDGQr.mjs.map +1 -0
  45. package/fesm2022/{acorex-modules-auth-login.module-TtdNj0aL.mjs → acorex-modules-auth-login.module-D-XgzifC.mjs} +4 -4
  46. package/fesm2022/{acorex-modules-auth-login.module-TtdNj0aL.mjs.map → acorex-modules-auth-login.module-D-XgzifC.mjs.map} +1 -1
  47. package/fesm2022/{acorex-modules-auth-master.layout-CtVrY1hn.mjs → acorex-modules-auth-master.layout-ZaCb3CED.mjs} +2 -2
  48. package/fesm2022/{acorex-modules-auth-master.layout-CtVrY1hn.mjs.map → acorex-modules-auth-master.layout-ZaCb3CED.mjs.map} +1 -1
  49. package/fesm2022/{acorex-modules-auth-password.component-Dmj9zZSI.mjs → acorex-modules-auth-password.component-C-xRIhrM.mjs} +2 -2
  50. package/fesm2022/{acorex-modules-auth-password.component-Dmj9zZSI.mjs.map → acorex-modules-auth-password.component-C-xRIhrM.mjs.map} +1 -1
  51. package/fesm2022/{acorex-modules-auth-password.component-BXm2NAaN.mjs → acorex-modules-auth-password.component-CLTZoufP.mjs} +2 -2
  52. package/fesm2022/{acorex-modules-auth-password.component-BXm2NAaN.mjs.map → acorex-modules-auth-password.component-CLTZoufP.mjs.map} +1 -1
  53. package/fesm2022/{acorex-modules-auth-routes-DkgsKi3a.mjs → acorex-modules-auth-routes-4T5jq7su.mjs} +2 -2
  54. package/fesm2022/{acorex-modules-auth-routes-DkgsKi3a.mjs.map → acorex-modules-auth-routes-4T5jq7su.mjs.map} +1 -1
  55. package/fesm2022/acorex-modules-auth-tenant-chooser.component-Ow7QtAWc.mjs +98 -0
  56. package/fesm2022/acorex-modules-auth-tenant-chooser.component-Ow7QtAWc.mjs.map +1 -0
  57. package/fesm2022/{acorex-modules-auth-two-factor.module-DDOSqjYs.mjs → acorex-modules-auth-two-factor.module-D72KIpvA.mjs} +2 -2
  58. package/fesm2022/{acorex-modules-auth-two-factor.module-DDOSqjYs.mjs.map → acorex-modules-auth-two-factor.module-D72KIpvA.mjs.map} +1 -1
  59. package/fesm2022/{acorex-modules-auth-user-sessions.component-B3i44VC5.mjs → acorex-modules-auth-user-sessions.component-Btnu_Oeq.mjs} +2 -2
  60. package/fesm2022/{acorex-modules-auth-user-sessions.component-B3i44VC5.mjs.map → acorex-modules-auth-user-sessions.component-Btnu_Oeq.mjs.map} +1 -1
  61. package/fesm2022/acorex-modules-auth.mjs +1 -1
  62. package/fesm2022/acorex-modules-common-search-popup.component-C3XUb6pF.mjs +128 -0
  63. package/fesm2022/acorex-modules-common-search-popup.component-C3XUb6pF.mjs.map +1 -0
  64. package/fesm2022/acorex-modules-common.mjs +289 -9
  65. package/fesm2022/acorex-modules-common.mjs.map +1 -1
  66. package/fesm2022/{acorex-modules-dashboard-management-acorex-modules-dashboard-management-CReOsVhq.mjs → acorex-modules-dashboard-management-acorex-modules-dashboard-management-Ccj2AaJ1.mjs} +848 -2176
  67. package/fesm2022/acorex-modules-dashboard-management-acorex-modules-dashboard-management-Ccj2AaJ1.mjs.map +1 -0
  68. package/fesm2022/{acorex-modules-dashboard-management-home-dashboard-CHXDeuSF.mjs → acorex-modules-dashboard-management-home-dashboard-BXD0g_tp.mjs} +49 -48
  69. package/fesm2022/acorex-modules-dashboard-management-home-dashboard-BXD0g_tp.mjs.map +1 -0
  70. package/fesm2022/acorex-modules-dashboard-management.mjs +1 -1
  71. package/fesm2022/{acorex-modules-document-management-acorex-modules-document-management-vYaqbxKs.mjs → acorex-modules-document-management-acorex-modules-document-management-Dw7YKb_h.mjs} +59 -41
  72. package/fesm2022/acorex-modules-document-management-acorex-modules-document-management-Dw7YKb_h.mjs.map +1 -0
  73. package/fesm2022/{acorex-modules-document-management-create-folder-dialog.component-Bc_IX3gT.mjs → acorex-modules-document-management-create-folder-dialog.component-Ty5V60Tu.mjs} +2 -2
  74. package/fesm2022/{acorex-modules-document-management-create-folder-dialog.component-Bc_IX3gT.mjs.map → acorex-modules-document-management-create-folder-dialog.component-Ty5V60Tu.mjs.map} +1 -1
  75. package/fesm2022/{acorex-modules-document-management-details-view.component-_9f5TQJi.mjs → acorex-modules-document-management-details-view.component-BuUJq8WU.mjs} +2 -2
  76. package/fesm2022/{acorex-modules-document-management-details-view.component-_9f5TQJi.mjs.map → acorex-modules-document-management-details-view.component-BuUJq8WU.mjs.map} +1 -1
  77. package/fesm2022/{acorex-modules-document-management-drive-choose.component-CFOb0_MF.mjs → acorex-modules-document-management-drive-choose.component-DSCIj1X_.mjs} +2 -2
  78. package/fesm2022/{acorex-modules-document-management-drive-choose.component-CFOb0_MF.mjs.map → acorex-modules-document-management-drive-choose.component-DSCIj1X_.mjs.map} +1 -1
  79. package/fesm2022/{acorex-modules-document-management-large-icons-view.component-D9es4CBl.mjs → acorex-modules-document-management-large-icons-view.component-DvrdSkIZ.mjs} +2 -2
  80. package/fesm2022/{acorex-modules-document-management-large-icons-view.component-D9es4CBl.mjs.map → acorex-modules-document-management-large-icons-view.component-DvrdSkIZ.mjs.map} +1 -1
  81. package/fesm2022/{acorex-modules-document-management-large-tiles-view.component-Q1Sjg47F.mjs → acorex-modules-document-management-large-tiles-view.component-rIxsD8sE.mjs} +2 -2
  82. package/fesm2022/{acorex-modules-document-management-large-tiles-view.component-Q1Sjg47F.mjs.map → acorex-modules-document-management-large-tiles-view.component-rIxsD8sE.mjs.map} +1 -1
  83. package/fesm2022/{acorex-modules-document-management-list-view.component-BUu5vrul.mjs → acorex-modules-document-management-list-view.component-BrutZLAU.mjs} +2 -2
  84. package/fesm2022/{acorex-modules-document-management-list-view.component-BUu5vrul.mjs.map → acorex-modules-document-management-list-view.component-BrutZLAU.mjs.map} +1 -1
  85. package/fesm2022/acorex-modules-document-management-permission-definition.provider-CQOLEctF.mjs +31 -0
  86. package/fesm2022/acorex-modules-document-management-permission-definition.provider-CQOLEctF.mjs.map +1 -0
  87. package/fesm2022/{acorex-modules-document-management-rename-node-dialog.component-BMRmdslE.mjs → acorex-modules-document-management-rename-node-dialog.component-zSY0PShA.mjs} +2 -2
  88. package/fesm2022/{acorex-modules-document-management-rename-node-dialog.component-BMRmdslE.mjs.map → acorex-modules-document-management-rename-node-dialog.component-zSY0PShA.mjs.map} +1 -1
  89. package/fesm2022/{acorex-modules-document-management-small-icons-view.component-ChSS7z9z.mjs → acorex-modules-document-management-small-icons-view.component-CFB6g5r6.mjs} +2 -2
  90. package/fesm2022/{acorex-modules-document-management-small-icons-view.component-ChSS7z9z.mjs.map → acorex-modules-document-management-small-icons-view.component-CFB6g5r6.mjs.map} +1 -1
  91. package/fesm2022/{acorex-modules-document-management-small-tiles-view.component-Ci33qbBY.mjs → acorex-modules-document-management-small-tiles-view.component-Dp2Lnb3c.mjs} +2 -2
  92. package/fesm2022/{acorex-modules-document-management-small-tiles-view.component-Ci33qbBY.mjs.map → acorex-modules-document-management-small-tiles-view.component-Dp2Lnb3c.mjs.map} +1 -1
  93. package/fesm2022/acorex-modules-document-management.mjs +1 -1
  94. package/fesm2022/{acorex-modules-form-template-management-acorex-modules-form-template-management-Cv92x_9Z.mjs → acorex-modules-form-template-management-acorex-modules-form-template-management-CJ2Qoott.mjs} +33 -15
  95. package/fesm2022/acorex-modules-form-template-management-acorex-modules-form-template-management-CJ2Qoott.mjs.map +1 -0
  96. package/fesm2022/{acorex-modules-form-template-management-category.entity-DPVwQW4X.mjs → acorex-modules-form-template-management-category.entity-BjNsUAZq.mjs} +2 -2
  97. package/fesm2022/{acorex-modules-form-template-management-category.entity-DPVwQW4X.mjs.map → acorex-modules-form-template-management-category.entity-BjNsUAZq.mjs.map} +1 -1
  98. package/fesm2022/{acorex-modules-form-template-management-permission-definition.provider-BrWbwKTK.mjs → acorex-modules-form-template-management-permission-definition.provider-CqZ8ytjA.mjs} +2 -21
  99. package/fesm2022/acorex-modules-form-template-management-permission-definition.provider-CqZ8ytjA.mjs.map +1 -0
  100. package/fesm2022/{acorex-modules-form-template-management-settings.provider-iwOUp0iw.mjs → acorex-modules-form-template-management-settings.provider-LrzsYkiL.mjs} +2 -2
  101. package/fesm2022/{acorex-modules-form-template-management-settings.provider-iwOUp0iw.mjs.map → acorex-modules-form-template-management-settings.provider-LrzsYkiL.mjs.map} +1 -1
  102. package/fesm2022/{acorex-modules-form-template-management-template-widget-edit.component-BkR3x74p.mjs → acorex-modules-form-template-management-template-widget-edit.component-BP75i9zU.mjs} +2 -2
  103. package/fesm2022/{acorex-modules-form-template-management-template-widget-edit.component-BkR3x74p.mjs.map → acorex-modules-form-template-management-template-widget-edit.component-BP75i9zU.mjs.map} +1 -1
  104. package/fesm2022/{acorex-modules-form-template-management-template.entity-NgmH7r8R.mjs → acorex-modules-form-template-management-template.entity-CCaHPkWq.mjs} +2 -2
  105. package/fesm2022/{acorex-modules-form-template-management-template.entity-NgmH7r8R.mjs.map → acorex-modules-form-template-management-template.entity-CCaHPkWq.mjs.map} +1 -1
  106. package/fesm2022/{acorex-modules-form-template-management-viewer-popup.component-Cq33xA62.mjs → acorex-modules-form-template-management-viewer-popup.component-CUOsh6e5.mjs} +2 -2
  107. package/fesm2022/{acorex-modules-form-template-management-viewer-popup.component-Cq33xA62.mjs.map → acorex-modules-form-template-management-viewer-popup.component-CUOsh6e5.mjs.map} +1 -1
  108. package/fesm2022/acorex-modules-form-template-management.mjs +1 -1
  109. package/fesm2022/{acorex-modules-issue-management-acorex-modules-issue-management-Q47ZZSSE.mjs → acorex-modules-issue-management-acorex-modules-issue-management-DcmAnBue.mjs} +42 -43
  110. package/fesm2022/{acorex-modules-issue-management-acorex-modules-issue-management-Q47ZZSSE.mjs.map → acorex-modules-issue-management-acorex-modules-issue-management-DcmAnBue.mjs.map} +1 -1
  111. package/fesm2022/{acorex-modules-issue-management-capture-screen.component-Dns1Wrkd.mjs → acorex-modules-issue-management-capture-screen.component-BMpafdHr.mjs} +2 -2
  112. package/fesm2022/{acorex-modules-issue-management-capture-screen.component-Dns1Wrkd.mjs.map → acorex-modules-issue-management-capture-screen.component-BMpafdHr.mjs.map} +1 -1
  113. package/fesm2022/acorex-modules-issue-management.mjs +1 -1
  114. package/fesm2022/acorex-modules-log-management.mjs +3 -8
  115. package/fesm2022/acorex-modules-log-management.mjs.map +1 -1
  116. package/fesm2022/acorex-modules-notification-management.mjs +621 -52
  117. package/fesm2022/acorex-modules-notification-management.mjs.map +1 -1
  118. package/fesm2022/{acorex-modules-organization-management-add-item.component-DW0TneoX.mjs → acorex-modules-organization-management-add-item.component-DE0Ek0dk.mjs} +3 -3
  119. package/fesm2022/{acorex-modules-organization-management-add-item.component-DW0TneoX.mjs.map → acorex-modules-organization-management-add-item.component-DE0Ek0dk.mjs.map} +1 -1
  120. package/fesm2022/acorex-modules-organization-management-org-chart-configuration.page-RuvkSheN.mjs +124 -0
  121. package/fesm2022/acorex-modules-organization-management-org-chart-configuration.page-RuvkSheN.mjs.map +1 -0
  122. package/fesm2022/{acorex-modules-organization-management-org-chart.page-DnRbGIWN.mjs → acorex-modules-organization-management-org-chart.page-C2qYJxpY.mjs} +59 -19
  123. package/fesm2022/acorex-modules-organization-management-org-chart.page-C2qYJxpY.mjs.map +1 -0
  124. package/fesm2022/acorex-modules-organization-management.mjs +7 -7
  125. package/fesm2022/acorex-modules-organization-management.mjs.map +1 -1
  126. package/fesm2022/{acorex-modules-platform-management-acorex-modules-platform-management-DIsYLKbA.mjs → acorex-modules-platform-management-acorex-modules-platform-management-BaYlXX3M.mjs} +46 -53
  127. package/fesm2022/acorex-modules-platform-management-acorex-modules-platform-management-BaYlXX3M.mjs.map +1 -0
  128. package/fesm2022/{acorex-modules-platform-management-list-version.component-D83yTFAm.mjs → acorex-modules-platform-management-list-version.component-DB8pe9so.mjs} +2 -2
  129. package/fesm2022/{acorex-modules-platform-management-list-version.component-D83yTFAm.mjs.map → acorex-modules-platform-management-list-version.component-DB8pe9so.mjs.map} +1 -1
  130. package/fesm2022/{acorex-modules-platform-management-settings.provider-DKkXCwrd.mjs → acorex-modules-platform-management-settings.provider-BQzM-lyt.mjs} +2 -2
  131. package/fesm2022/{acorex-modules-platform-management-settings.provider-DKkXCwrd.mjs.map → acorex-modules-platform-management-settings.provider-BQzM-lyt.mjs.map} +1 -1
  132. package/fesm2022/acorex-modules-platform-management.mjs +1 -1
  133. package/fesm2022/acorex-modules-project-management.mjs +218 -155
  134. package/fesm2022/acorex-modules-project-management.mjs.map +1 -1
  135. package/fesm2022/acorex-modules-security-management.mjs +472 -787
  136. package/fesm2022/acorex-modules-security-management.mjs.map +1 -1
  137. package/fesm2022/acorex-modules-settings-management-setting-page.component-XDFtTqft.mjs +219 -0
  138. package/fesm2022/acorex-modules-settings-management-setting-page.component-XDFtTqft.mjs.map +1 -0
  139. package/fesm2022/acorex-modules-settings-management-setting-view.component-B_6RIU9e.mjs +103 -0
  140. package/fesm2022/acorex-modules-settings-management-setting-view.component-B_6RIU9e.mjs.map +1 -0
  141. package/fesm2022/acorex-modules-settings-management.mjs +442 -0
  142. package/fesm2022/acorex-modules-settings-management.mjs.map +1 -0
  143. package/fesm2022/acorex-modules-training-management.mjs +5572 -0
  144. package/fesm2022/acorex-modules-training-management.mjs.map +1 -0
  145. package/notification-management/index.d.ts +1 -0
  146. package/notification-management/lib/entities/notification/notification.service.d.ts +6 -6
  147. package/notification-management/lib/features/components/admin-notification-panel/admin-notification-panel.component.d.ts +13 -7
  148. package/{dashboard-management/lib/features/shared/widgets/notification → notification-management/lib/features/dashboard/widgets/my-notification}/index.d.ts +0 -1
  149. package/{dashboard-management/lib/features/shared/widgets/notification → notification-management/lib/features/dashboard/widgets/my-notification}/notification-widget.component.d.ts +37 -9
  150. package/notification-management/lib/features/dashboard/widgets/my-notification/notification-widget.config.d.ts +5 -0
  151. package/notification-management/lib/features/shared/notification-connector.service.d.ts +57 -0
  152. package/notification-management/lib/notification-management.module.d.ts +2 -1
  153. package/notification-management/lib/notification-management.type.d.ts +3 -0
  154. package/organization-management/lib/features/organization-chart/org-chart-configuration.page.d.ts +7 -61
  155. package/organization-management/lib/features/organization-chart/org-chart.page.d.ts +8 -61
  156. package/package.json +9 -1
  157. package/platform-management/lib/const.d.ts +2 -6
  158. package/platform-management/lib/features/app-terms/pages/list/list-terms.component.d.ts +11 -13
  159. package/security-management/lib/entities/index.d.ts +1 -2
  160. package/security-management/lib/entities/profile/index.d.ts +0 -1
  161. package/security-management/lib/entities/users/users.service.d.ts +2 -2
  162. package/security-management/lib/entities/users/users.types.d.ts +2 -2
  163. package/security-management/lib/user-avatar.provider.d.ts +5 -0
  164. package/settings-management/README.md +3 -0
  165. package/settings-management/index.d.ts +2 -0
  166. package/settings-management/lib/features/settings/convert-setting-data.d.ts +2 -0
  167. package/settings-management/lib/features/settings/search-definition.provider.d.ts +4 -0
  168. package/settings-management/lib/features/settings/search.provider.d.ts +9 -0
  169. package/settings-management/lib/features/settings/setting-page/setting-page.component.d.ts +65 -0
  170. package/settings-management/lib/features/settings/setting-view/setting-view.component.d.ts +135 -0
  171. package/settings-management/lib/features/settings/settings.viewmodel.d.ts +46 -0
  172. package/settings-management/lib/settings-management.module.d.ts +9 -0
  173. package/training-management/README.md +3 -0
  174. package/training-management/index.d.ts +7 -0
  175. package/training-management/lib/const.d.ts +85 -0
  176. package/training-management/lib/entities/certificate/certificate.entity.d.ts +3 -0
  177. package/training-management/lib/entities/certificate/certificate.service.d.ts +10 -0
  178. package/training-management/lib/entities/certificate/certificate.types.d.ts +12 -0
  179. package/training-management/lib/entities/certificate/index.d.ts +3 -0
  180. package/training-management/lib/entities/course/course.entity.d.ts +3 -0
  181. package/training-management/lib/entities/course/course.service.d.ts +10 -0
  182. package/training-management/lib/entities/course/course.types.d.ts +8 -0
  183. package/training-management/lib/entities/course/index.d.ts +3 -0
  184. package/training-management/lib/entities/course-location/course-location.entity.d.ts +3 -0
  185. package/training-management/lib/entities/course-location/course-location.service.d.ts +10 -0
  186. package/training-management/lib/entities/course-location/course-location.types.d.ts +6 -0
  187. package/training-management/lib/entities/course-location/index.d.ts +3 -0
  188. package/training-management/lib/entities/course-period/course-period.entity.d.ts +3 -0
  189. package/training-management/lib/entities/course-period/course-period.service.d.ts +10 -0
  190. package/training-management/lib/entities/course-period/course-period.types.d.ts +6 -0
  191. package/training-management/lib/entities/course-period/index.d.ts +3 -0
  192. package/training-management/lib/entities/course-type/course-type.entity.d.ts +3 -0
  193. package/training-management/lib/entities/course-type/course-type.service.d.ts +10 -0
  194. package/training-management/lib/entities/course-type/course-type.types.d.ts +5 -0
  195. package/training-management/lib/entities/course-type/index.d.ts +3 -0
  196. package/training-management/lib/entities/facilitator-type/facilitator-type.entity.d.ts +3 -0
  197. package/training-management/lib/entities/facilitator-type/facilitator-type.service.d.ts +10 -0
  198. package/training-management/lib/entities/facilitator-type/facilitator-type.types.d.ts +6 -0
  199. package/training-management/lib/entities/facilitator-type/index.d.ts +3 -0
  200. package/training-management/lib/entities/index.d.ts +12 -0
  201. package/training-management/lib/entities/location/index.d.ts +3 -0
  202. package/training-management/lib/entities/location/location.entity.d.ts +3 -0
  203. package/training-management/lib/entities/location/location.service.d.ts +10 -0
  204. package/training-management/lib/entities/location/location.types.d.ts +7 -0
  205. package/training-management/lib/entities/period/index.d.ts +3 -0
  206. package/training-management/lib/entities/period/period.entity.d.ts +3 -0
  207. package/training-management/lib/entities/period/period.service.d.ts +10 -0
  208. package/training-management/lib/entities/period/period.types.d.ts +6 -0
  209. package/training-management/lib/entities/training/index.d.ts +3 -0
  210. package/training-management/lib/entities/training/training.entity.d.ts +3 -0
  211. package/training-management/lib/entities/training/training.service.d.ts +10 -0
  212. package/training-management/lib/entities/training/training.types.d.ts +13 -0
  213. package/training-management/lib/entities/training-facilitator/index.d.ts +3 -0
  214. package/training-management/lib/entities/training-facilitator/training-facilitator.entity.d.ts +3 -0
  215. package/training-management/lib/entities/training-facilitator/training-facilitator.service.d.ts +10 -0
  216. package/training-management/lib/entities/training-facilitator/training-facilitator.types.d.ts +7 -0
  217. package/training-management/lib/entities/training-participant/index.d.ts +3 -0
  218. package/training-management/lib/entities/training-participant/training-participant.entity.d.ts +3 -0
  219. package/training-management/lib/entities/training-participant/training-participant.service.d.ts +10 -0
  220. package/training-management/lib/entities/training-participant/training-participant.types.d.ts +7 -0
  221. package/training-management/lib/entities/training-type/index.d.ts +3 -0
  222. package/training-management/lib/entities/training-type/training-type.entity.d.ts +3 -0
  223. package/training-management/lib/entities/training-type/training-type.service.d.ts +10 -0
  224. package/training-management/lib/entities/training-type/training-type.types.d.ts +7 -0
  225. package/training-management/lib/entity.provider.d.ts +10 -0
  226. package/training-management/lib/menu.provider.d.ts +5 -0
  227. package/training-management/lib/permission-definition.provider.d.ts +4 -0
  228. package/training-management/lib/search-command.provider.d.ts +4 -0
  229. package/training-management/lib/setting.provider.d.ts +4 -0
  230. package/training-management/lib/training-management.module.d.ts +6 -0
  231. package/auth/lib/pages/account/avatar/avatar.component.d.ts +0 -20
  232. package/dashboard-management/lib/features/shared/widgets/bar-chart/bar-chart.type.d.ts +0 -34
  233. package/dashboard-management/lib/features/shared/widgets/donut-chart/donut-chart.type.d.ts +0 -67
  234. package/dashboard-management/lib/features/shared/widgets/gauge-chart/gauge-chart.type.d.ts +0 -29
  235. package/dashboard-management/lib/features/shared/widgets/line-chart/line-chart.type.d.ts +0 -41
  236. package/dashboard-management/lib/features/shared/widgets/notification/notification-widget.config.d.ts +0 -10
  237. package/dashboard-management/lib/features/shared/widgets/notification/notification.type.d.ts +0 -47
  238. package/dashboard-management/lib/features/shared/widgets/shared/chart-base.component.d.ts +0 -44
  239. package/dashboard-management/lib/features/shared/widgets/shared/chart-base.type.d.ts +0 -37
  240. package/dashboard-management/lib/features/shared/widgets/shared/components/chart-tooltip/chart-tooltip.component.d.ts +0 -28
  241. package/dashboard-management/lib/features/shared/widgets/shared/components/chart-tooltip/index.d.ts +0 -1
  242. package/dashboard-management/lib/features/shared/widgets/shared/index.d.ts +0 -3
  243. package/fesm2022/acorex-modules-auth-acorex-modules-auth-B1HTJdsE.mjs.map +0 -1
  244. package/fesm2022/acorex-modules-auth-app-chooser.component-Ct-vco0y.mjs +0 -64
  245. package/fesm2022/acorex-modules-auth-app-chooser.component-Ct-vco0y.mjs.map +0 -1
  246. package/fesm2022/acorex-modules-auth-tenant-chooser.component-D9C6LCjn.mjs +0 -97
  247. package/fesm2022/acorex-modules-auth-tenant-chooser.component-D9C6LCjn.mjs.map +0 -1
  248. package/fesm2022/acorex-modules-dashboard-management-acorex-modules-dashboard-management-CReOsVhq.mjs.map +0 -1
  249. package/fesm2022/acorex-modules-dashboard-management-home-dashboard-CHXDeuSF.mjs.map +0 -1
  250. package/fesm2022/acorex-modules-document-management-acorex-modules-document-management-vYaqbxKs.mjs.map +0 -1
  251. package/fesm2022/acorex-modules-form-template-management-acorex-modules-form-template-management-Cv92x_9Z.mjs.map +0 -1
  252. package/fesm2022/acorex-modules-form-template-management-permission-definition.provider-BrWbwKTK.mjs.map +0 -1
  253. package/fesm2022/acorex-modules-organization-management-org-chart-configuration.page-DFqOS0So.mjs +0 -92
  254. package/fesm2022/acorex-modules-organization-management-org-chart-configuration.page-DFqOS0So.mjs.map +0 -1
  255. package/fesm2022/acorex-modules-organization-management-org-chart.page-DnRbGIWN.mjs.map +0 -1
  256. package/fesm2022/acorex-modules-platform-management-acorex-modules-platform-management-DIsYLKbA.mjs.map +0 -1
  257. package/security-management/lib/entities/profile/profile.service.d.ts +0 -13
@@ -1,47 +1,48 @@
1
+ import { AXPSessionService, AXPAuthGuard } from '@acorex/platform/auth';
1
2
  import { createAllQueryView, AXPEntityCommandScope, AXPEntityQueryType, AXP_HOME_PAGES, AXP_MENU_PROVIDER, AXP_HOME_PAGE_DEFAULT_KEY } from '@acorex/platform/common';
3
+ import * as i3$1 from '@acorex/platform/layout/builder';
4
+ import { AXPWidgetsCatalog, AXPValueWidgetComponent, cloneProperty, AXPWidgetGroupEnum, AXPLayoutWidgetComponent, AXPLayoutBuilderModule } from '@acorex/platform/layout/builder';
2
5
  import { AXMEntityCrudServiceImpl, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER } from '@acorex/platform/layout/entity';
6
+ import { AXP_APPEARANCE_PROPERTY_GROUP, AXP_STYLING_PROPERTY_GROUP, AXP_NAME_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_BEHAVIOR_PROPERTY_GROUP, AXP_BG_COLOR_PROPERTY, plainTextDefaultProperty, AXP_DATA_PROPERTY_GROUP, AXP_COLOR_PROPERTY, AXPWidgetsModule } from '@acorex/platform/widgets';
3
7
  import * as i0 from '@angular/core';
4
- import { inject, Injector, Injectable, computed, HostBinding, ChangeDetectionStrategy, Component, signal, runInInjectionContext, effect, Directive, input, output, viewChild, ChangeDetectorRef, ElementRef, HostListener, InjectionToken, NgModule } from '@angular/core';
5
- import { AXPSessionService, AXPAuthGuard } from '@acorex/platform/auth';
6
- import { firstValueFrom, interval, map, Observable, catchError, throwError, switchMap } from 'rxjs';
7
- import { AXP_COLOR_PROPERTY, AXP_STYLING_PROPERTY_GROUP, AXP_APPEARANCE_PROPERTY_GROUP, AXP_BEHAVIOR_PROPERTY_GROUP, AXP_DATA_PATH_PROPERTY, AXP_BG_COLOR_PROPERTY, plainTextDefaultProperty, AXP_DATA_PROPERTY_GROUP, AXPWidgetsModule } from '@acorex/platform/widgets';
8
- import * as i3 from '@acorex/platform/layout/builder';
9
- import { AXPWidgetsCatalog, AXPLayoutWidgetComponent, AXPWidgetGroupEnum, AXPValueWidgetComponent, cloneProperty, AXPLayoutBuilderModule } from '@acorex/platform/layout/builder';
10
- import { AXPopupService } from '@acorex/components/popup';
11
- import * as i2 from '@acorex/core/translation';
12
- import { AXTranslationModule } from '@acorex/core/translation';
13
- import { AXPDataGenerator } from '@acorex/platform/core';
14
- import { AXP_GLOBAL_SEARCH_CONFIG_TOKEN } from '@acorex/platform/layout/search';
15
- import { AXPWorkflowService } from '@acorex/platform/workflow';
16
- import * as i1 from '@angular/common';
17
- import { CommonModule, DatePipe } from '@angular/common';
18
- import * as i2$3 from '@acorex/components/decorators';
8
+ import { Injectable, inject, Injector, computed, ChangeDetectionStrategy, Component, ChangeDetectorRef, signal, viewChild, ElementRef, HostListener, output, InjectionToken, effect, HostBinding, NgModule } from '@angular/core';
9
+ import { AXBarChartComponent } from '@acorex/charts/bar-chart';
10
+ import * as i2$2 from '@acorex/components/decorators';
19
11
  import { AXDecoratorModule } from '@acorex/components/decorators';
20
12
  import { AXTagModule } from '@acorex/components/tag';
21
13
  import { AXDateTimeModule } from '@acorex/core/date-time';
22
- import * as i2$1 from '@acorex/core/format';
14
+ import * as i2 from '@acorex/core/format';
23
15
  import { AXFormatModule } from '@acorex/core/format';
24
- import * as i5 from '@acorex/components/avatar';
25
- import { AXAvatarModule } from '@acorex/components/avatar';
26
- import * as i4 from '@acorex/components/badge';
27
- import { AXBadgeModule } from '@acorex/components/badge';
28
- import { AXButtonModule } from '@acorex/components/button';
29
- import * as i6 from '@acorex/components/image';
30
- import { AXImageModule } from '@acorex/components/image';
31
- import * as i2$2 from '@acorex/components/tabs';
32
- import { AXTabsModule } from '@acorex/components/tabs';
16
+ import * as i1 from '@angular/common';
17
+ import { CommonModule, DatePipe } from '@angular/common';
18
+ import { interval, map, Observable, catchError, throwError, switchMap, firstValueFrom } from 'rxjs';
19
+ import { AXDonutChartComponent } from '@acorex/charts/donut-chart';
20
+ import { AXGaugeChartComponent } from '@acorex/charts/gauge-chart';
21
+ import { AXLineChartComponent } from '@acorex/charts/line-chart';
33
22
  import { AXColorBoxModule } from '@acorex/components/color-box';
34
23
  import { AXGridLayoutWidgetComponent } from '@acorex/components/grid-layout-builder';
35
24
  import { AXPopoverModule } from '@acorex/components/popover';
36
25
  import { AXToolBarModule } from '@acorex/components/toolbar';
37
26
  import * as i1$1 from '@acorex/components/wysiwyg';
38
27
  import { AXWysiwygModule } from '@acorex/components/wysiwyg';
39
- import * as i2$4 from '@angular/forms';
28
+ import * as i2$1 from '@angular/forms';
40
29
  import { FormsModule } from '@angular/forms';
41
- import * as i4$1 from '@acorex/components/check-box';
30
+ import { AXAvatarModule } from '@acorex/components/avatar';
31
+ import * as i3 from '@acorex/components/badge';
32
+ import { AXBadgeModule } from '@acorex/components/badge';
33
+ import { AXButtonModule } from '@acorex/components/button';
34
+ import * as i4 from '@acorex/components/check-box';
42
35
  import { AXCheckBoxModule } from '@acorex/components/check-box';
36
+ import { AXImageModule } from '@acorex/components/image';
43
37
  import { AXLabelModule } from '@acorex/components/label';
38
+ import { AXTabsModule } from '@acorex/components/tabs';
39
+ import * as i5 from '@acorex/core/translation';
40
+ import { AXTranslationModule } from '@acorex/core/translation';
44
41
  import { HttpClient, HttpClientModule } from '@angular/common/http';
42
+ import { AXPopupService } from '@acorex/components/popup';
43
+ import { AXP_GLOBAL_SEARCH_CONFIG_TOKEN } from '@acorex/modules/common';
44
+ import { AXPDataGenerator } from '@acorex/platform/core';
45
+ import { AXPWorkflowService } from '@acorex/platform/workflow';
45
46
 
46
47
  const config = {
47
48
  i18n: 'common',
@@ -64,48 +65,6 @@ const RootConfig = {
64
65
  },
65
66
  };
66
67
 
67
- class AXMEntityProvider {
68
- constructor() {
69
- this.injector = inject(Injector);
70
- }
71
- preload() {
72
- const module = RootConfig.module.name;
73
- return Array.from(Object.values(RootConfig.entities)).map((entity) => ({
74
- module: module,
75
- entity: entity.name,
76
- }));
77
- }
78
- async get(moduleName, entityName) {
79
- if (moduleName == RootConfig.module.name) {
80
- switch (entityName) {
81
- case RootConfig.entities.dashboard.name:
82
- return (await Promise.resolve().then(function () { return dashboard_entity; })).dashboardFactory(this.injector);
83
- }
84
- }
85
- return null;
86
- }
87
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMEntityProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
88
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMEntityProvider }); }
89
- }
90
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMEntityProvider, decorators: [{
91
- type: Injectable
92
- }] });
93
-
94
- class AXMMenuProvider {
95
- constructor() {
96
- this.sessionService = inject(AXPSessionService);
97
- }
98
- async provide(context) {
99
- const scope = RootConfig.config.i18n;
100
- const module = RootConfig.module;
101
- const appName = this.sessionService.application?.name;
102
- const isAuthorized = await firstValueFrom(this.sessionService.isAuthorized$);
103
- if (!isAuthorized) {
104
- return;
105
- }
106
- }
107
- }
108
-
109
68
  class AXMDashboardService extends AXMEntityCrudServiceImpl {
110
69
  }
111
70
  class AXMDashboardServiceImpl extends AXMDashboardService {
@@ -439,134 +398,57 @@ var dashboard_entity = /*#__PURE__*/Object.freeze({
439
398
  dashboardFactory: dashboardFactory
440
399
  });
441
400
 
442
- class AXPDashboardShortcutWidgetViewComponent extends AXPLayoutWidgetComponent {
401
+ class AXMEntityProvider {
443
402
  constructor() {
444
- super(...arguments);
445
- this.popupService = inject(AXPopupService);
446
- this.workflow = inject(AXPWorkflowService);
447
- this.searchConfig = inject(AXP_GLOBAL_SEARCH_CONFIG_TOKEN);
448
- this.item = computed(() => this.options()['item']);
449
- this.color = computed(() => this.options()['color']);
450
- }
451
- ngOnInit() {
452
- super.ngOnInit();
453
- if (!this.color()) {
454
- this.setOptions({
455
- color: AXPDataGenerator.color()
456
- });
457
- }
403
+ this.injector = inject(Injector);
458
404
  }
459
- async executeCommand() {
460
- if (this.item()?.command) {
461
- await this.workflow.execute(this.item().command.name, this.item().command.options);
462
- }
405
+ preload() {
406
+ const module = RootConfig.module.name;
407
+ return Array.from(Object.values(RootConfig.entities)).map((entity) => ({
408
+ module: module,
409
+ entity: entity.name,
410
+ }));
463
411
  }
464
- async setCommand() {
465
- const component = await this.searchConfig.window();
466
- const popup = await this.popupService.open(component, {
467
- title: 'Choose command...',
468
- size: 'fit',
469
- closeOnBackdropClick: true,
470
- header: false,
471
- });
472
- if (popup.data) {
473
- const result = popup.data;
474
- if (result && result.command) {
475
- this.setOptions({
476
- item: {
477
- name: result.name,
478
- title: result.title,
479
- description: result.description,
480
- icon: result.icon,
481
- command: result.command
482
- }
483
- });
412
+ async get(moduleName, entityName) {
413
+ if (moduleName == RootConfig.module.name) {
414
+ switch (entityName) {
415
+ case RootConfig.entities.dashboard.name:
416
+ return (await Promise.resolve().then(function () { return dashboard_entity; })).dashboardFactory(this.injector);
484
417
  }
485
418
  }
419
+ return null;
486
420
  }
487
- get __style() {
488
- const cls = {};
489
- cls[`background-color`] = this.color();
490
- return cls;
491
- }
492
- get __class() {
493
- const cls = {};
494
- cls[`ax-flex`] = true;
495
- cls[`ax-flex-col`] = true;
496
- cls[`ax-items-center`] = true;
497
- cls[`ax-justify-center`] = true;
498
- cls[`ax-w-full`] = true;
499
- cls[`ax-h-full`] = true;
500
- cls[`ax-text-center`] = true;
501
- cls[`ax-overflow-hidden`] = true;
502
- cls[`ax-cursor-pointer`] = true;
503
- cls[`ax-text-white`] = true;
504
- return cls;
421
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMEntityProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
422
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMEntityProvider }); }
423
+ }
424
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMEntityProvider, decorators: [{
425
+ type: Injectable
426
+ }] });
427
+
428
+ /**
429
+ * Bar Chart Widget Component
430
+ * Renders data as vertical bars with interactive hover effects and animations
431
+ */
432
+ class AXPBarChartWidgetViewComponent extends AXPValueWidgetComponent {
433
+ constructor() {
434
+ super(...arguments);
435
+ this.barChartData = computed(() => this.getValue());
436
+ this.barChartOptions = computed(() => this.options());
505
437
  }
506
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPDashboardShortcutWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
507
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXPDashboardShortcutWidgetViewComponent, isStandalone: true, selector: "ng-component", host: { properties: { "style": "this.__style", "class": "this.__class" } }, usesInheritance: true, ngImport: i0, template: `
508
- @if(item()) {
509
- <div
510
- 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 "
511
- (click)="executeCommand()">
512
- <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/10 ax-transition-opacity"></div>
513
- <i [class]="item().icon + ' ax-text-3xl'"></i>
514
- <span class="ax-text-xl ax-font-semibold">{{ item().title | translate | async }}</span>
515
- @if(item().description) {
516
- <span class="ax-text-sm ax-opacity-90 ax-text-center ax-px-2">{{ item().description! | translate | async }}</span>
517
- }
518
- </div>
519
- } @else {
520
- <div
521
- (click)="setCommand()"
522
- 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">
523
- <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/5 ax-transition-opacity"></div>
524
- <i class="fa-light fa-plus ax-text-3xl"></i>
525
- <span class="ax-text-xl ax-font-semibold">Add Shortcut</span>
526
- </div>
438
+ handleBarClick(event) {
439
+ //console.log(event);
527
440
  }
528
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
441
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPBarChartWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
442
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: AXPBarChartWidgetViewComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<ax-bar-chart [data]=\"barChartData()\" [options]=\"barChartOptions()\" (barClick)=\"handleBarClick($event)\"></ax-bar-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "component", type: AXBarChartComponent, selector: "ax-bar-chart", inputs: ["data", "options"], outputs: ["barClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
529
443
  }
530
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPDashboardShortcutWidgetViewComponent, decorators: [{
444
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPBarChartWidgetViewComponent, decorators: [{
531
445
  type: Component,
532
- args: [{
533
- template: `
534
- @if(item()) {
535
- <div
536
- 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 "
537
- (click)="executeCommand()">
538
- <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/10 ax-transition-opacity"></div>
539
- <i [class]="item().icon + ' ax-text-3xl'"></i>
540
- <span class="ax-text-xl ax-font-semibold">{{ item().title | translate | async }}</span>
541
- @if(item().description) {
542
- <span class="ax-text-sm ax-opacity-90 ax-text-center ax-px-2">{{ item().description! | translate | async }}</span>
543
- }
544
- </div>
545
- } @else {
546
- <div
547
- (click)="setCommand()"
548
- 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">
549
- <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/5 ax-transition-opacity"></div>
550
- <i class="fa-light fa-plus ax-text-3xl"></i>
551
- <span class="ax-text-xl ax-font-semibold">Add Shortcut</span>
552
- </div>
553
- }
554
- `,
555
- standalone: true,
556
- changeDetection: ChangeDetectionStrategy.OnPush,
557
- imports: [CommonModule, AXTranslationModule]
558
- }]
559
- }], propDecorators: { __style: [{
560
- type: HostBinding,
561
- args: ['style']
562
- }], __class: [{
563
- type: HostBinding,
564
- args: ['class']
565
- }] } });
446
+ args: [{ imports: [AXBarChartComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ax-bar-chart [data]=\"barChartData()\" [options]=\"barChartOptions()\" (barClick)=\"handleBarClick($event)\"></ax-bar-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
447
+ }] });
566
448
 
567
- var dashboardShortcutWidgetView_component = /*#__PURE__*/Object.freeze({
449
+ var barChartWidget_component = /*#__PURE__*/Object.freeze({
568
450
  __proto__: null,
569
- AXPDashboardShortcutWidgetViewComponent: AXPDashboardShortcutWidgetViewComponent
451
+ AXPBarChartWidgetViewComponent: AXPBarChartWidgetViewComponent
570
452
  });
571
453
 
572
454
  const AXP_WIDGETS_CHART_CATEGORY = {
@@ -580,537 +462,75 @@ const AXP_WIDGETS_UTILITY_CATEGORY = {
580
462
  title: 'Utilities',
581
463
  };
582
464
 
583
- const AXPDashboardShortcutWidget = {
584
- name: "dashboard-shortcut",
585
- title: "Shortcut",
586
- description: 'Quick access to your key features.',
587
- type: 'view',
588
- categories: [AXP_WIDGETS_UTILITY_CATEGORY],
465
+ const AXPBarChartWidget = {
466
+ name: 'bar-chart',
467
+ title: 'Bar Chart Widget',
468
+ categories: [AXP_WIDGETS_CHART_CATEGORY],
589
469
  groups: [AXPWidgetGroupEnum.DashboardWidget],
590
- icon: "fa-light fa-link",
470
+ type: 'dashboard',
471
+ icon: 'fa-light fa-chart-bar',
591
472
  properties: [
592
- AXP_COLOR_PROPERTY
593
- ],
594
- meta: {
595
- dimensions: {
596
- width: 2,
597
- height: 2,
598
- minWidth: 1,
599
- minHeight: 1,
600
- maxWidth: 3,
601
- maxHeight: 2,
602
- },
603
- },
604
- components: {
605
- view: {
606
- component: () => Promise.resolve().then(function () { return dashboardShortcutWidgetView_component; }).then((c) => c.AXPDashboardShortcutWidgetViewComponent),
473
+ cloneProperty(AXP_NAME_PROPERTY, { visible: false }),
474
+ cloneProperty(AXP_DATA_PATH_PROPERTY, { visible: false }),
475
+ // ====== Chart Title ======
476
+ {
477
+ name: 'title',
478
+ title: 'Chart Title',
479
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
480
+ schema: {
481
+ defaultValue: '',
482
+ dataType: 'string',
483
+ interface: {
484
+ name: 'title',
485
+ path: 'options.title',
486
+ type: AXPWidgetsCatalog.text,
487
+ options: {
488
+ placeholder: 'Enter chart title',
489
+ },
490
+ },
491
+ },
492
+ visible: true,
607
493
  },
608
- }
609
- };
610
-
611
- /**
612
- * Common base types and utilities for all chart components
613
- */
614
- /**
615
- * Color utility functions for charts
616
- */
617
- const AXPChartColors = {
618
- // Modern color palette suitable for data visualization
619
- defaultColors: [
620
- '#4361ee', // Blue
621
- '#3a0ca3', // Purple
622
- '#7209b7', // Violet
623
- '#f72585', // Pink
624
- '#4cc9f0', // Light Blue
625
- '#4895ef', // Sky Blue
626
- '#560bad', // Deep Purple
627
- '#f15bb5', // Light Pink
628
- '#00bbf9', // Cyan
629
- '#00f5d4', // Teal
630
- ],
631
- // Get a color from the palette by index with wraparound
632
- getColor: (index, customPalette) => {
633
- const palette = customPalette || AXPChartColors.defaultColors;
634
- return palette[index % palette.length];
635
- },
636
- // Generate a continuous color palette from a base color
637
- generatePalette: (baseColor, count) => {
638
- // Simple implementation - in real usage you might want a more sophisticated algorithm
639
- const colors = [];
640
- for (let i = 0; i < count; i++) {
641
- // This is simplistic - a real implementation would use HSL or other color manipulation
642
- const opacity = 0.4 + (0.6 * i) / count;
643
- colors.push(`${baseColor}${Math.floor(opacity * 255)
644
- .toString(16)
645
- .padStart(2, '0')}`);
646
- }
647
- return colors;
648
- },
649
- };
650
- /**
651
- * Shared utility for loading D3.js dynamically
652
- */
653
- async function loadD3() {
654
- try {
655
- // Dynamic import of d3 without relying on d3 being imported at the top
656
- return await import('d3');
657
- }
658
- catch (error) {
659
- console.error('Failed to load D3.js:', error);
660
- throw error;
661
- }
662
- }
663
-
664
- /**
665
- * Base component class for all chart components with common chart functionality
666
- */
667
- class AXPChartBaseComponent extends AXPValueWidgetComponent {
668
- // Constructor with protected change detector
669
- constructor(cdr) {
670
- super();
671
- this.cdr = cdr;
672
- // Get injector for running effects
673
- this.injector = inject(Injector);
674
- // Track component lifecycle
675
- this.isInitialized = signal(false);
676
- this.isRendered = signal(false);
677
- // Internal chart data storage with fallback logic
678
- this._internalData = signal(null);
679
- // Accessor for chart data with fallback to getValue() or defaultValue
680
- this.chartData = computed(() => {
681
- if (this._internalData()) {
682
- return this._internalData();
683
- }
684
- return this.getValue() || this.defaultValue;
685
- });
686
- // Options tracker for detecting changes
687
- this._lastOptionsSnapshot = '';
688
- // Store the effect cleanup function
689
- this.effectRef = null;
690
- }
691
- ngOnInit() {
692
- super.ngOnInit();
693
- this.loadD3();
694
- }
695
- ngAfterViewInit() {
696
- this.isRendered.set(true);
697
- this.setupEffects();
698
- }
699
- ngOnDestroy() {
700
- // Clean up effect if it exists
701
- if (this.effectRef) {
702
- this.effectRef.destroy();
703
- }
704
- this.cleanupChart();
705
- }
706
- /**
707
- * Load D3.js library asynchronously
708
- */
709
- async loadD3() {
710
- try {
711
- this.d3 = await loadD3();
712
- this.isInitialized.set(true);
713
- // Initialize chart data once D3 is loaded
714
- const initialData = this.getValue() || this.defaultValue;
715
- if (initialData) {
716
- this._internalData.set(initialData);
717
- }
718
- // Create chart once D3 is loaded and if we're already rendered
719
- if (this.isRendered()) {
720
- this.createChart();
721
- }
722
- }
723
- catch (error) {
724
- console.error('Error loading D3.js:', error);
725
- }
726
- }
727
- /**
728
- * Set up reactive effects to track data and option changes
729
- */
730
- setupEffects() {
731
- // Run effect in injection context to avoid NG0203 error
732
- this.effectRef = runInInjectionContext(this.injector, () => {
733
- return effect(() => {
734
- // Only update if D3 is loaded and component is rendered
735
- if (!this.isInitialized() || !this.isRendered())
736
- return;
737
- // Track dependencies explicitly
738
- const data = this.getValue();
739
- const options = this.options();
740
- // Store current options snapshot for comparison
741
- const currentOptions = JSON.stringify(options);
742
- const optionsChanged = currentOptions !== this._lastOptionsSnapshot;
743
- this._lastOptionsSnapshot = currentOptions;
744
- // Check if data changed
745
- const dataChanged = data && JSON.stringify(data) !== JSON.stringify(this._internalData());
746
- // Update internal data if it changed
747
- if (dataChanged && data) {
748
- this._internalData.set(data);
749
- }
750
- // Update chart if either data or options changed
751
- if (dataChanged || optionsChanged) {
752
- this.updateChart();
753
- }
754
- });
755
- });
756
- }
757
- /**
758
- * Get dimensions of the container element
759
- */
760
- getContainerDimensions(containerElement) {
761
- if (!containerElement?.nativeElement) {
762
- return { width: 300, height: 300 }; // Default fallback
763
- }
764
- const { clientWidth, clientHeight } = containerElement.nativeElement;
765
- return {
766
- width: clientWidth || 300,
767
- height: clientHeight || 300,
768
- };
769
- }
770
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPChartBaseComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
771
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.3", type: AXPChartBaseComponent, isStandalone: true, usesInheritance: true, ngImport: i0 }); }
772
- }
773
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPChartBaseComponent, decorators: [{
774
- type: Directive
775
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }] });
776
-
777
- class AXPChartTooltipComponent {
778
- constructor() {
779
- this.data = input(null);
780
- this.position = input({ x: 0, y: 0 });
781
- this.visible = input(false);
782
- /**
783
- * Whether to show the tooltip's percentage badge
784
- */
785
- this.showPercentage = input(true);
786
- /**
787
- * Optional custom styling for the tooltip
788
- */
789
- this.style = input({});
790
- }
791
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPChartTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
792
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXPChartTooltipComponent, isStandalone: true, selector: "ax-chart-tooltip", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, showPercentage: { classPropertyName: "showPercentage", publicName: "showPercentage", isSignal: true, isRequired: false, transformFunction: null }, style: { classPropertyName: "style", publicName: "style", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (visible() && data()) {\n<div class=\"chart-tooltip\" [style.left.px]=\"position().x\" [style.top.px]=\"position().y\" [ngStyle]=\"style()\">\n <div class=\"chart-tooltip-title\">{{ data()!.title }}</div>\n <div class=\"chart-tooltip-content\">\n @if (data()!.color) {\n <div class=\"chart-tooltip-color\" [style.background-color]=\"data()!.color\"></div>\n }\n <div class=\"chart-tooltip-value\">{{ data()!.value }}</div>\n @if (showPercentage() && data()!.percentage) {\n <div class=\"chart-tooltip-percentage\">{{ data()!.percentage }}</div>\n }\n </div>\n</div>\n}\n", styles: [".chart-tooltip{position:absolute;pointer-events:none;background-color:rgba(33,33,33,.9);color:#fff;padding:.5rem .75rem;border-radius:.375rem;font-size:.8rem;z-index:10;box-shadow:0 4px 12px rgba(0,0,0,.15);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.1);transform:translate(10px,-50%);max-width:200px;font-family:var(--ax-font-family, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);transition:opacity .15s ease,transform .15s ease}.chart-tooltip-title{font-weight:600;padding-bottom:.5rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chart-tooltip-content{display:flex;justify-content:space-between;align-items:center;gap:.5rem}.chart-tooltip-color{width:10px;height:10px;border-radius:2px;flex-shrink:0;box-shadow:0 1px 2px rgba(0,0,0,.2)}.chart-tooltip-value{font-weight:500;flex-grow:1}.chart-tooltip-percentage{background-color:rgba(255,255,255,.2);padding:.125rem .375rem;border-radius:1rem;font-size:.7rem;font-weight:500;flex-shrink:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
793
- }
794
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPChartTooltipComponent, decorators: [{
795
- type: Component,
796
- args: [{ selector: 'ax-chart-tooltip', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (visible() && data()) {\n<div class=\"chart-tooltip\" [style.left.px]=\"position().x\" [style.top.px]=\"position().y\" [ngStyle]=\"style()\">\n <div class=\"chart-tooltip-title\">{{ data()!.title }}</div>\n <div class=\"chart-tooltip-content\">\n @if (data()!.color) {\n <div class=\"chart-tooltip-color\" [style.background-color]=\"data()!.color\"></div>\n }\n <div class=\"chart-tooltip-value\">{{ data()!.value }}</div>\n @if (showPercentage() && data()!.percentage) {\n <div class=\"chart-tooltip-percentage\">{{ data()!.percentage }}</div>\n }\n </div>\n</div>\n}\n", styles: [".chart-tooltip{position:absolute;pointer-events:none;background-color:rgba(33,33,33,.9);color:#fff;padding:.5rem .75rem;border-radius:.375rem;font-size:.8rem;z-index:10;box-shadow:0 4px 12px rgba(0,0,0,.15);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border:1px solid rgba(255,255,255,.1);transform:translate(10px,-50%);max-width:200px;font-family:var(--ax-font-family, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif);transition:opacity .15s ease,transform .15s ease}.chart-tooltip-title{font-weight:600;padding-bottom:.5rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chart-tooltip-content{display:flex;justify-content:space-between;align-items:center;gap:.5rem}.chart-tooltip-color{width:10px;height:10px;border-radius:2px;flex-shrink:0;box-shadow:0 1px 2px rgba(0,0,0,.2)}.chart-tooltip-value{font-weight:500;flex-grow:1}.chart-tooltip-percentage{background-color:rgba(255,255,255,.2);padding:.125rem .375rem;border-radius:1rem;font-size:.7rem;font-weight:500;flex-shrink:0}\n"] }]
797
- }] });
798
-
799
- /**
800
- * Bar Chart Widget Component
801
- * Renders data as vertical bars with interactive hover effects and animations
802
- */
803
- class AXPBarChartWidgetViewComponent extends AXPChartBaseComponent {
804
- constructor() {
805
- super(...arguments);
806
- this.barClick = output();
807
- // Chart container reference
808
- this.chartContainerEl = viewChild.required('chartContainer');
809
- this.margin = { top: 20, right: 20, bottom: 30, left: 40 };
810
- // Tooltip state
811
- this._tooltipVisible = signal(false);
812
- this._tooltipPosition = signal({ x: 0, y: 0 });
813
- this._tooltipData = signal({
814
- title: '',
815
- value: '0',
816
- percentage: '0%',
817
- color: '',
818
- });
819
- // Tooltip accessors
820
- this.tooltipVisible = computed(() => this._tooltipVisible());
821
- this.tooltipPosition = computed(() => this._tooltipPosition());
822
- this.tooltipData = computed(() => this._tooltipData());
823
- // Bar appearance options
824
- this.barWidth = computed(() => this.options()['barWidth'] ?? 80);
825
- this.cornerRadius = computed(() => this.options()['cornerRadius'] ?? 4);
826
- }
827
- // Chart lifecycle methods
828
- /**
829
- * Creates the bar chart SVG and renders all elements
830
- */
831
- createChart() {
832
- if (!this.d3 || !this.chartContainerEl()?.nativeElement)
833
- return;
834
- const containerElement = this.chartContainerEl().nativeElement;
835
- const data = this.chartData() || [];
836
- // Clear existing chart
837
- this.d3.select(containerElement).selectAll('svg').remove();
838
- // Early return if no data
839
- if (!data.length) {
840
- this.showNoDataMessage(containerElement);
841
- return;
842
- }
843
- // Get options and setup dimensions
844
- const options = this.options();
845
- this.setupDimensions(containerElement, options);
846
- // No need to create SVG here as it's now done in setupDimensions
847
- // Create scales and axes
848
- this.setupScales(data);
849
- this.createAxes(options);
850
- // Render the bars
851
- this.renderBars(data);
852
- }
853
- updateChart() {
854
- this.createChart();
855
- }
856
- cleanupChart() {
857
- if (this.svg) {
858
- this.d3.select(this.chartContainerEl()?.nativeElement).selectAll('svg').remove();
859
- this.svg = null;
860
- this.chart = null;
861
- }
862
- this._tooltipVisible.set(false);
863
- }
864
- // Private chart creation methods
865
- /**
866
- * Sets up chart dimensions and creates SVG with responsive attributes
867
- */
868
- setupDimensions(containerElement, options) {
869
- // Get container dimensions
870
- const containerWidth = containerElement.clientWidth;
871
- const containerHeight = containerElement.clientHeight;
872
- // If options specify width and height, use those, otherwise default to container size
873
- const minDim = Math.min(200, containerWidth, containerHeight); // Ensure reasonable minimum
874
- if (options.width && options.height) {
875
- // Explicit dimensions provided
876
- this.width = options.width - this.margin.left - this.margin.right;
877
- this.height = options.height - this.margin.top - this.margin.bottom;
878
- }
879
- else {
880
- // Responsive dimensions
881
- this.width = Math.max(containerWidth, minDim) - this.margin.left - this.margin.right;
882
- this.height = Math.max(containerHeight, minDim) - this.margin.top - this.margin.bottom;
883
- }
884
- // Create responsive SVG that scales with its container
885
- const svg = this.d3
886
- .select(containerElement)
887
- .append('svg')
888
- .attr('width', '100%')
889
- .attr('height', '100%')
890
- .attr('viewBox', `0 0 ${this.width + this.margin.left + this.margin.right} ${this.height + this.margin.top + this.margin.bottom}`)
891
- .attr('preserveAspectRatio', 'xMidYMid meet');
892
- this.svg = svg;
893
- // Create chart group with margins
894
- this.chart = this.svg.append('g').attr('transform', `translate(${this.margin.left},${this.margin.top})`);
895
- }
896
- /**
897
- * Creates x and y scales for the chart
898
- */
899
- setupScales(data) {
900
- // Get the bar width percentage (default 80%)
901
- const barWidthPercent = this.barWidth() / 100;
902
- // Calculate padding based on barWidth (inverse relationship)
903
- const padding = Math.max(0.1, 1 - barWidthPercent);
904
- // Create x scale (band scale for categorical data)
905
- this.xScale = this.d3
906
- .scaleBand()
907
- .domain(data.map((d) => d.label))
908
- .range([0, this.width])
909
- .padding(padding);
910
- // Create y scale (linear scale for values)
911
- this.yScale = this.d3
912
- .scaleLinear()
913
- .domain([0, this.d3.max(data, (d) => d.value) || 0])
914
- .nice()
915
- .range([this.height, 0]);
916
- }
917
- /**
918
- * Creates x and y axes with grid lines
919
- */
920
- createAxes(options) {
921
- // Only create axes if they are enabled in options
922
- const showXAxis = options.showXAxis !== false;
923
- const showYAxis = options.showYAxis !== false;
924
- const showGrid = options.showGrid !== false;
925
- if (showXAxis) {
926
- // Create X axis
927
- this.xAxis = this.chart
928
- .append('g')
929
- .attr('class', 'axp-bar-chart-axis-x')
930
- .attr('transform', `translate(0,${this.height})`)
931
- .call(this.d3.axisBottom(this.xScale));
932
- }
933
- if (showYAxis) {
934
- // Create Y axis
935
- this.yAxis = this.chart.append('g').attr('class', 'axp-bar-chart-axis-y').call(this.d3.axisLeft(this.yScale));
936
- }
937
- if (showGrid) {
938
- // Add horizontal grid lines
939
- this.chart
940
- .append('g')
941
- .attr('class', 'axp-bar-chart-grid')
942
- .call(this.d3
943
- .axisLeft(this.yScale)
944
- .tickSize(-this.width)
945
- .tickFormat(() => ''))
946
- .selectAll('.tick')
947
- .style('color', 'rgb(153 153 153 / 30%)'); // Add gray color to ticks
948
- }
949
- }
950
- /**
951
- * Renders the bars with animations
952
- */
953
- renderBars(data) {
954
- // Get corner radius from options
955
- const radius = this.cornerRadius();
956
- // Add bars with modern colors
957
- const bars = this.chart
958
- .selectAll('.axp-bar-chart-bar')
959
- .data(data)
960
- .enter()
961
- .append('rect')
962
- .attr('class', 'axp-bar-chart-bar')
963
- .attr('x', (d) => this.xScale(d.label))
964
- .attr('width', this.xScale.bandwidth())
965
- .attr('y', this.height) // Start from bottom for animation
966
- .attr('height', 0) // Start with height 0 for animation
967
- .attr('rx', radius) // Rounded corners
968
- .attr('ry', radius) // Rounded corners
969
- .attr('fill', (d, i) => d.color || AXPChartColors.getColor(i))
970
- .on('mouseenter', (event, d) => this.handleBarHover(event, d))
971
- .on('mousemove', (event) => this.updateTooltipPosition(event))
972
- .on('mouseleave', () => this._tooltipVisible.set(false))
973
- .on('click', (event, d) => this.handleBarClick(event, d));
974
- // Add animation
975
- bars
976
- .transition()
977
- .duration(800)
978
- .delay((d, i) => i * 50) // Stagger each bar animation
979
- .attr('y', (d) => this.yScale(d.value))
980
- .attr('height', (d) => this.height - this.yScale(d.value))
981
- .ease(this.d3.easeQuadOut); // Simple quadratic ease-out animation
982
- }
983
- // Event handlers
984
- /**
985
- * Handles bar hover event and shows tooltip
986
- */
987
- handleBarHover(event, datum) {
988
- if (this.options().showTooltip !== false) {
989
- const index = this.chartData().findIndex((item) => item.id === datum.id);
990
- const color = datum.color || AXPChartColors.getColor(index);
991
- // Calculate percentage of total
992
- const total = this.chartData().reduce((sum, item) => sum + item.value, 0);
993
- const percentage = total > 0 ? ((datum.value / total) * 100).toFixed(1) : '0';
994
- this._tooltipData.set({
995
- title: datum.label,
996
- value: datum.value.toString(),
997
- percentage: `${percentage}%`,
998
- color: color,
999
- });
1000
- this.updateTooltipPosition(event);
1001
- this._tooltipVisible.set(true);
1002
- }
1003
- }
1004
- /**
1005
- * Updates tooltip position based on mouse coordinates
1006
- */
1007
- updateTooltipPosition(event) {
1008
- const container = this.chartContainerEl().nativeElement.getBoundingClientRect();
1009
- const x = event.clientX - container.left;
1010
- const y = event.clientY - container.top;
1011
- this._tooltipPosition.set({
1012
- x: x,
1013
- y: y,
1014
- });
1015
- }
1016
- /**
1017
- * Handles bar click event
1018
- */
1019
- handleBarClick(event, datum) {
1020
- this.barClick.emit(datum);
1021
- }
1022
- /**
1023
- * Shows a message when no data is available
1024
- */
1025
- showNoDataMessage(containerElement) {
1026
- const messageContainer = this.d3
1027
- .select(containerElement)
1028
- .append('div')
1029
- .attr('class', 'axp-bar-chart-no-data-message')
1030
- .style('width', '100%')
1031
- .style('height', '100%')
1032
- .style('display', 'flex')
1033
- .style('flex-direction', 'column')
1034
- .style('align-items', 'center')
1035
- .style('justify-content', 'center')
1036
- .style('text-align', 'center');
1037
- // Add an icon
1038
- messageContainer
1039
- .append('div')
1040
- .attr('class', 'axp-bar-chart-no-data-icon')
1041
- .style('margin-bottom', '10px')
1042
- .style('color', 'var(--ax-text-muted, #999)')
1043
- .html('<i class="fa-light fa-chart-bar fa-2x"></i>');
1044
- // Add text message
1045
- messageContainer
1046
- .append('div')
1047
- .attr('class', 'axp-bar-chart-no-data-text')
1048
- .style('font-size', '16px')
1049
- .style('font-weight', '600')
1050
- .style('color', 'var(--ax-text-color, #333)')
1051
- .text('No data available');
1052
- }
1053
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPBarChartWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1054
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.0.3", type: AXPBarChartWidgetViewComponent, isStandalone: true, selector: "ng-component", outputs: { barClick: "barClick" }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"axp-bar-chart\" #chartContainer>\n <!-- Shared tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: [":host{display:block;width:100%;height:100%;min-height:200px}.axp-bar-chart{width:100%;height:100%;position:relative;display:flex;align-items:center;justify-content:center;border-radius:.5rem;overflow:hidden}.axp-bar-chart svg{width:100%;height:100%;max-width:100%;max-height:100%;overflow:visible}.axp-bar-chart-bar{transition:all .3s cubic-bezier(.4,0,.2,1);cursor:pointer}.axp-bar-chart-bar:hover{filter:brightness(.9);transform:translateY(-3px)}.axp-bar-chart-axis-x path,.axp-bar-chart-axis-y path{stroke:var(--ax-border-color, #e0e0e0)}.axp-bar-chart-axis-x line,.axp-bar-chart-axis-y line,.axp-bar-chart-grid line{stroke:var(--ax-border-color, #e0e0e0);stroke-dasharray:2,2;stroke-opacity:.5}.axp-bar-chart-grid path{stroke-width:0}.axp-bar-chart-axis-x text,.axp-bar-chart-axis-y text{fill:var(--ax-text-muted, #666);font-size:clamp(8px,2vmin,12px)}.axp-bar-chart-no-data-message{font-family:var(--ax-font-family, system-ui, sans-serif);display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:1rem;width:100%;height:100%}.axp-bar-chart-no-data-icon{margin-bottom:.75rem;color:var(--ax-text-muted, #999)}.axp-bar-chart-no-data-text{font-weight:600;color:var(--ax-text-color, #333)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXPChartTooltipComponent, selector: "ax-chart-tooltip", inputs: ["data", "position", "visible", "showPercentage", "style"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1055
- }
1056
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPBarChartWidgetViewComponent, decorators: [{
1057
- type: Component,
1058
- args: [{ standalone: true, imports: [CommonModule, AXPChartTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"axp-bar-chart\" #chartContainer>\n <!-- Shared tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: [":host{display:block;width:100%;height:100%;min-height:200px}.axp-bar-chart{width:100%;height:100%;position:relative;display:flex;align-items:center;justify-content:center;border-radius:.5rem;overflow:hidden}.axp-bar-chart svg{width:100%;height:100%;max-width:100%;max-height:100%;overflow:visible}.axp-bar-chart-bar{transition:all .3s cubic-bezier(.4,0,.2,1);cursor:pointer}.axp-bar-chart-bar:hover{filter:brightness(.9);transform:translateY(-3px)}.axp-bar-chart-axis-x path,.axp-bar-chart-axis-y path{stroke:var(--ax-border-color, #e0e0e0)}.axp-bar-chart-axis-x line,.axp-bar-chart-axis-y line,.axp-bar-chart-grid line{stroke:var(--ax-border-color, #e0e0e0);stroke-dasharray:2,2;stroke-opacity:.5}.axp-bar-chart-grid path{stroke-width:0}.axp-bar-chart-axis-x text,.axp-bar-chart-axis-y text{fill:var(--ax-text-muted, #666);font-size:clamp(8px,2vmin,12px)}.axp-bar-chart-no-data-message{font-family:var(--ax-font-family, system-ui, sans-serif);display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:1rem;width:100%;height:100%}.axp-bar-chart-no-data-icon{margin-bottom:.75rem;color:var(--ax-text-muted, #999)}.axp-bar-chart-no-data-text{font-weight:600;color:var(--ax-text-color, #333)}\n"] }]
1059
- }] });
1060
-
1061
- var barChartWidget_component = /*#__PURE__*/Object.freeze({
1062
- __proto__: null,
1063
- AXPBarChartWidgetViewComponent: AXPBarChartWidgetViewComponent
1064
- });
1065
-
1066
- const AXPBarChartWidget = {
1067
- name: 'bar-chart',
1068
- title: 'Bar Chart Widget',
1069
- categories: [AXP_WIDGETS_CHART_CATEGORY],
1070
- groups: [AXPWidgetGroupEnum.DashboardWidget],
1071
- type: 'dashboard',
1072
- icon: 'fa-light fa-chart-bar',
1073
- properties: [
1074
494
  // ====== Layout & Dimensions ======
1075
495
  {
1076
- name: 'height',
1077
- title: 'Height',
496
+ name: 'width',
497
+ title: 'Width',
1078
498
  group: AXP_STYLING_PROPERTY_GROUP,
1079
499
  schema: {
1080
- defaultValue: 300,
500
+ defaultValue: null,
1081
501
  dataType: 'number',
1082
502
  interface: {
1083
- name: 'height',
1084
- path: 'options.height',
503
+ name: 'width',
504
+ path: 'options.width',
1085
505
  type: AXPWidgetsCatalog.number,
1086
506
  options: {
1087
507
  minValue: 0,
1088
- maxValue: 800,
508
+ maxValue: 1200,
1089
509
  },
1090
510
  },
1091
511
  },
1092
512
  visible: true,
1093
513
  },
1094
514
  {
1095
- name: 'width',
1096
- title: 'Width',
515
+ name: 'height',
516
+ title: 'Height',
1097
517
  group: AXP_STYLING_PROPERTY_GROUP,
1098
518
  schema: {
1099
- defaultValue: null,
519
+ defaultValue: 300,
1100
520
  dataType: 'number',
1101
521
  interface: {
1102
- name: 'width',
1103
- path: 'options.width',
522
+ name: 'height',
523
+ path: 'options.height',
1104
524
  type: AXPWidgetsCatalog.number,
1105
525
  options: {
1106
526
  minValue: 0,
1107
- maxValue: 1200,
527
+ maxValue: 800,
1108
528
  },
1109
529
  },
1110
530
  },
1111
531
  visible: true,
1112
532
  },
1113
- // ====== Axis Settings ======
533
+ // ====== X Axis Settings ======
1114
534
  {
1115
535
  name: 'showXAxis',
1116
536
  title: 'Show X Axis',
@@ -1126,6 +546,22 @@ const AXPBarChartWidget = {
1126
546
  },
1127
547
  visible: true,
1128
548
  },
549
+ {
550
+ name: 'xAxisLabel',
551
+ title: 'X Axis Label',
552
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
553
+ schema: {
554
+ defaultValue: '',
555
+ dataType: 'string',
556
+ interface: {
557
+ name: 'xAxisLabel',
558
+ path: 'options.xAxisLabel',
559
+ type: AXPWidgetsCatalog.text,
560
+ },
561
+ },
562
+ visible: true,
563
+ },
564
+ // ====== Y Axis Settings ======
1129
565
  {
1130
566
  name: 'showYAxis',
1131
567
  title: 'Show Y Axis',
@@ -1141,6 +577,63 @@ const AXPBarChartWidget = {
1141
577
  },
1142
578
  visible: true,
1143
579
  },
580
+ {
581
+ name: 'yAxisLabel',
582
+ title: 'Y Axis Label',
583
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
584
+ schema: {
585
+ defaultValue: '',
586
+ dataType: 'string',
587
+ interface: {
588
+ name: 'yAxisLabel',
589
+ path: 'options.yAxisLabel',
590
+ type: AXPWidgetsCatalog.text,
591
+ },
592
+ },
593
+ visible: true,
594
+ },
595
+ // ====== Bar Appearance ======
596
+ {
597
+ name: 'barWidth',
598
+ title: 'Bar Width',
599
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
600
+ schema: {
601
+ defaultValue: 80,
602
+ dataType: 'number',
603
+ interface: {
604
+ name: 'barWidth',
605
+ path: 'options.barWidth',
606
+ type: AXPWidgetsCatalog.number,
607
+ options: {
608
+ placeholder: '1-100',
609
+ minValue: 1,
610
+ maxValue: 100,
611
+ },
612
+ },
613
+ },
614
+ visible: true,
615
+ },
616
+ {
617
+ name: 'cornerRadius',
618
+ title: 'Corner Radius',
619
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
620
+ schema: {
621
+ defaultValue: 4,
622
+ dataType: 'number',
623
+ interface: {
624
+ name: 'cornerRadius',
625
+ path: 'options.cornerRadius',
626
+ type: AXPWidgetsCatalog.number,
627
+ options: {
628
+ placeholder: '0-20',
629
+ minValue: 0,
630
+ maxValue: 20,
631
+ },
632
+ },
633
+ },
634
+ visible: true,
635
+ },
636
+ // ====== Grid Settings ======
1144
637
  {
1145
638
  name: 'showGrid',
1146
639
  title: 'Show Grid Lines',
@@ -1172,42 +665,52 @@ const AXPBarChartWidget = {
1172
665
  },
1173
666
  visible: true,
1174
667
  },
1175
- // ====== Bar Appearance ======
668
+ // ====== Animation Settings ======
1176
669
  {
1177
- name: 'barWidth',
1178
- title: 'Bar Width',
670
+ name: 'animationEasing',
671
+ title: 'Animation Easing',
1179
672
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1180
673
  schema: {
1181
- defaultValue: 80,
1182
- dataType: 'number',
674
+ defaultValue: 'cubic-out',
675
+ dataType: 'string',
1183
676
  interface: {
1184
- name: 'barWidth',
1185
- path: 'options.barWidth',
1186
- type: AXPWidgetsCatalog.number,
677
+ name: 'animationEasing',
678
+ path: 'options.animationEasing',
679
+ type: AXPWidgetsCatalog.select,
1187
680
  options: {
1188
- placeholder: '1-100',
1189
- minValue: 1,
1190
- maxValue: 100,
681
+ dataSource: [
682
+ { value: 'linear', text: 'Linear' },
683
+ { value: 'ease', text: 'Ease' },
684
+ { value: 'ease-in', text: 'Ease In' },
685
+ { value: 'ease-out', text: 'Ease Out' },
686
+ { value: 'ease-in-out', text: 'Ease In Out' },
687
+ { value: 'cubic', text: 'Cubic' },
688
+ { value: 'cubic-in', text: 'Cubic In' },
689
+ { value: 'cubic-out', text: 'Cubic Out' },
690
+ { value: 'cubic-in-out', text: 'Cubic In Out' },
691
+ ],
692
+ textField: 'text',
693
+ valueField: 'value',
1191
694
  },
1192
695
  },
1193
696
  },
1194
697
  visible: true,
1195
698
  },
1196
699
  {
1197
- name: 'cornerRadius',
1198
- title: 'Corner Radius',
700
+ name: 'animationDuration',
701
+ title: 'Animation Duration',
1199
702
  group: AXP_APPEARANCE_PROPERTY_GROUP,
1200
703
  schema: {
1201
- defaultValue: 4,
704
+ defaultValue: 800,
1202
705
  dataType: 'number',
1203
706
  interface: {
1204
- name: 'cornerRadius',
1205
- path: 'options.cornerRadius',
707
+ name: 'animationDuration',
708
+ path: 'options.animationDuration',
1206
709
  type: AXPWidgetsCatalog.number,
1207
710
  options: {
1208
- placeholder: '0-20',
711
+ placeholder: '0-2000',
1209
712
  minValue: 0,
1210
- maxValue: 20,
713
+ maxValue: 2000,
1211
714
  },
1212
715
  },
1213
716
  },
@@ -1266,7 +769,7 @@ class AXPClockCalendarWidgetViewComponent extends AXPValueWidgetComponent {
1266
769
  this.showSeconds = computed(() => this.options()?.showSeconds !== false);
1267
770
  this.dateFormat = computed(() => this.options()?.dateFormat?.id ?? 'dd MMM yyyy');
1268
771
  this.timezone = computed(() => this.options()?.timezone?.id ?? 'local');
1269
- this.showTimezoneIndicator = computed(() => this.timezone() !== 'local');
772
+ // protected readonly showTimezoneIndicator: Signal<boolean> = computed(() => this.timezone() !== 'local');
1270
773
  this.displayTimezone = computed(() => {
1271
774
  const tz = this.timezone();
1272
775
  if (tz === 'local')
@@ -1354,11 +857,11 @@ class AXPClockCalendarWidgetViewComponent extends AXPValueWidgetComponent {
1354
857
  return days[this.currentDate.getDay()];
1355
858
  }
1356
859
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPClockCalendarWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1357
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", 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$1.AXFormatPipe, name: "format" }, { kind: "ngmodule", type: AXTagModule }, { kind: "ngmodule", type: AXDecoratorModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
860
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", 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 }); }
1358
861
  }
1359
862
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPClockCalendarWidgetViewComponent, decorators: [{
1360
863
  type: Component,
1361
- 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"] }]
864
+ 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"] }]
1362
865
  }] });
1363
866
 
1364
867
  var clockCalendarWidget_component = /*#__PURE__*/Object.freeze({
@@ -1407,6 +910,25 @@ const AXPClockCalendarWidget = {
1407
910
  type: 'dashboard',
1408
911
  icon: 'fa-light fa-clock',
1409
912
  properties: [
913
+ // ====== Title ======
914
+ {
915
+ name: 'title',
916
+ title: 'Chart Title',
917
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
918
+ schema: {
919
+ defaultValue: '',
920
+ dataType: 'string',
921
+ interface: {
922
+ name: 'title',
923
+ path: 'options.title',
924
+ type: AXPWidgetsCatalog.text,
925
+ options: {
926
+ placeholder: 'Enter chart title',
927
+ },
928
+ },
929
+ },
930
+ visible: true,
931
+ },
1410
932
  // ====== Display Settings ======
1411
933
  {
1412
934
  name: 'displayLayout',
@@ -1564,407 +1086,21 @@ const AXPClockCalendarWidget = {
1564
1086
  * Donut Chart Widget Component
1565
1087
  * Displays data in a circular donut chart with interactive segments
1566
1088
  */
1567
- class AXPDonutChartWidgetViewComponent extends AXPChartBaseComponent {
1089
+ class AXPDonutChartWidgetViewComponent extends AXPValueWidgetComponent {
1568
1090
  constructor() {
1569
1091
  super(...arguments);
1570
- this.segmentClick = output();
1571
- // Chart reference and D3 related properties
1572
- this.cdr = inject(ChangeDetectorRef);
1573
- this.chartContainerEl = viewChild.required('chartContainer');
1574
- this.pieData = [];
1575
- // State management
1576
- this.hiddenSegments = new Set();
1577
- // Tooltip state
1578
- this._tooltipVisible = signal(false);
1579
- this._tooltipPosition = signal({ x: 0, y: 0 });
1580
- this._tooltipData = signal({
1581
- title: '',
1582
- value: 0,
1583
- percentage: '0%',
1584
- color: '',
1585
- });
1586
- // Public computed properties for the template
1587
- this.tooltipVisible = computed(() => this._tooltipVisible());
1588
- this.tooltipPosition = computed(() => this._tooltipPosition());
1589
- this.tooltipData = computed(() => this._tooltipData());
1590
- // Computed configuration options
1591
- this.showLegend = computed(() => this.options()['showLegend'] !== false);
1592
- this.showTooltip = computed(() => this.options()['showTooltip'] !== false);
1593
- this.legendPosition = computed(() => this.options()['legendPosition']?.id || 'right');
1594
- this.donutWidth = computed(() => this.options()['donutWidth'] ?? 35);
1595
- this.cornerRadius = computed(() => this.options()['cornerRadius'] ?? 4);
1596
- // Data accessor for handling different incoming data formats
1597
- this.chartDataArray = computed(() => {
1598
- const data = this.chartData();
1599
- if (data === null || data === undefined) {
1600
- return [];
1601
- }
1602
- // Handle both array format and object format with data property
1603
- return Array.isArray(data) ? data : data.data || [];
1604
- });
1605
- }
1606
- getColor(index) {
1607
- return AXPChartColors.getColor(index);
1608
- }
1609
- isSegmentHidden(id) {
1610
- return this.hiddenSegments.has(id);
1611
- }
1612
- // Event handlers
1613
- onSegmentClick(item) {
1614
- this.toggleSegment(item);
1615
- this.segmentClick.emit(item);
1616
- }
1617
- onLegendMouseEnter(item) {
1618
- if (!this.svg)
1619
- return;
1620
- // Highlight the target segment
1621
- this.svg
1622
- .selectAll('path')
1623
- .filter((d) => d?.data?.id === item.id)
1624
- .classed('axp-donut-chart-highlighted', true)
1625
- .attr('transform', 'scale(1.02)');
1626
- // Dim other segments
1627
- this.svg
1628
- .selectAll('path')
1629
- .filter((d) => d?.data?.id !== item.id)
1630
- .classed('axp-donut-chart-dimmed', true);
1631
- }
1632
- onLegendMouseLeave() {
1633
- if (!this.svg)
1634
- return;
1635
- // Reset all segments
1636
- this.svg
1637
- .selectAll('path')
1638
- .classed('axp-donut-chart-highlighted', false)
1639
- .classed('axp-donut-chart-dimmed', false)
1640
- .attr('transform', 'scale(1)');
1641
- }
1642
- // Chart lifecycle methods (implementation of base class abstract methods)
1643
- createChart() {
1644
- if (!this.d3 || !this.chartContainerEl()?.nativeElement)
1645
- return;
1646
- try {
1647
- const containerElement = this.chartContainerEl().nativeElement;
1648
- const chartElement = containerElement.querySelector('div');
1649
- this.clearChart(chartElement);
1650
- const data = this.chartDataArray();
1651
- if (!data || data.length === 0) {
1652
- this.showNoDataMessage(chartElement);
1653
- return;
1654
- }
1655
- const options = this.options();
1656
- const { width, height } = this.setupDimensions(containerElement, options);
1657
- this.renderDonutChart(chartElement, width, height);
1658
- }
1659
- catch (error) {
1660
- console.error('Error creating donut chart:', error);
1661
- this.handleChartError();
1662
- }
1663
- }
1664
- updateChart() {
1665
- this.createChart();
1666
- }
1667
- cleanupChart() {
1668
- if (this.svg) {
1669
- this.d3.select(this.chartContainerEl()?.nativeElement).selectAll('svg').remove();
1670
- this.svg = null;
1671
- this.pieData = [];
1672
- }
1673
- this.hiddenSegments.clear();
1674
- this._tooltipVisible.set(false);
1675
- }
1676
- // Private helper methods
1677
- clearChart(element) {
1678
- this.d3.select(element).selectAll('*').remove();
1679
- }
1680
- handleChartError() {
1681
- try {
1682
- const containerElement = this.chartContainerEl()?.nativeElement;
1683
- if (containerElement) {
1684
- const chartElement = containerElement.querySelector('div');
1685
- if (chartElement) {
1686
- this.showNoDataMessage(chartElement);
1687
- }
1688
- }
1689
- }
1690
- catch (e) {
1691
- console.error('Failed to show no data message:', e);
1692
- }
1693
- }
1694
- setupDimensions(containerElement, options) {
1695
- const containerWidth = containerElement.clientWidth;
1696
- const containerHeight = containerElement.clientHeight;
1697
- // Ensure minimum dimensions for the chart
1698
- const minDim = 200;
1699
- const width = Math.max(options['width'] || containerWidth, minDim);
1700
- const height = Math.max(options['height'] || containerHeight, minDim);
1701
- return { width, height };
1702
- }
1703
- renderDonutChart(chartElement, width, height) {
1704
- const data = this.chartDataArray();
1705
- // Filter out hidden segments
1706
- const visibleData = data.filter((item) => !this.hiddenSegments.has(item.id));
1707
- // If all segments are hidden, show no data message and return
1708
- if (visibleData.length === 0) {
1709
- this.showAllSegmentsHiddenMessage(chartElement);
1710
- return;
1711
- }
1712
- const total = this.calculateTotal();
1713
- // Calculate chart dimensions based on legend position
1714
- const { chartWidth, chartHeight, translateX, translateY } = this.calculateChartLayout(width, height);
1715
- // Create SVG container with filters
1716
- const svg = this.createSvgWithFilters(chartElement, width, height);
1717
- // Create main chart group
1718
- this.svg = svg.append('g').attr('transform', `translate(${translateX}, ${translateY})`);
1719
- // Create donut segments
1720
- this.createDonutSegments(chartWidth, chartHeight, visibleData, total);
1721
- // Add total in center
1722
- this.addTotalDisplay(total);
1723
- }
1724
- calculateChartLayout(width, height) {
1725
- const legendPosition = this.legendPosition();
1726
- let chartWidth = width;
1727
- let chartHeight = height;
1728
- let translateX = width / 2;
1729
- let translateY = height / 2;
1730
- if (this.showLegend()) {
1731
- if (legendPosition === 'right') {
1732
- // Reserve space for right legend
1733
- const legendWidth = Math.min(width * 0.3, 150);
1734
- chartWidth = width - legendWidth - 20;
1735
- translateX = (width - chartWidth) / 3 + chartWidth / 2;
1736
- }
1737
- else if (legendPosition === 'bottom') {
1738
- // Reserve space for bottom legend
1739
- const legendHeight = Math.min(height * 0.2, 80);
1740
- chartHeight = height - legendHeight - 20;
1741
- translateY = (height - chartHeight) / 3 + chartHeight / 2;
1742
- }
1743
- }
1744
- return { chartWidth, chartHeight, translateX, translateY };
1745
- }
1746
- createSvgWithFilters(chartElement, width, height) {
1747
- const svg = this.d3
1748
- .select(chartElement)
1749
- .append('svg')
1750
- .attr('width', width)
1751
- .attr('height', height)
1752
- .attr('viewBox', `0 0 ${width} ${height}`)
1753
- .attr('preserveAspectRatio', 'xMidYMid meet');
1754
- // Add drop shadow filter
1755
- const defs = svg.append('defs');
1756
- const filter = defs.append('filter').attr('id', 'axp-donut-chart-segment-shadow').attr('height', '130%');
1757
- filter.append('feGaussianBlur').attr('in', 'SourceAlpha').attr('stdDeviation', 2).attr('result', 'blur');
1758
- filter.append('feOffset').attr('in', 'blur').attr('dx', 1).attr('dy', 1).attr('result', 'offsetBlur');
1759
- const feComponentTransfer = filter
1760
- .append('feComponentTransfer')
1761
- .attr('in', 'offsetBlur')
1762
- .attr('result', 'offsetBlur');
1763
- feComponentTransfer.append('feFuncA').attr('type', 'linear').attr('slope', 0.3);
1764
- const feMerge = filter.append('feMerge');
1765
- feMerge.append('feMergeNode').attr('in', 'offsetBlur');
1766
- feMerge.append('feMergeNode').attr('in', 'SourceGraphic');
1767
- return svg;
1768
- }
1769
- createDonutSegments(chartWidth, chartHeight, data, total) {
1770
- // Create pie layout
1771
- const pie = this.d3
1772
- .pie()
1773
- .value((d) => d.value)
1774
- .sort(null)
1775
- .padAngle(0.02);
1776
- // Calculate the radius of the donut chart
1777
- const radius = (Math.min(chartWidth, chartHeight) / 2) * 0.85;
1778
- // Calculate inner radius based on donutWidth percentage
1779
- const donutWidthPercent = this.donutWidth() / 100;
1780
- const innerRadius = radius * (1 - donutWidthPercent);
1781
- // Create arc generator with the configured radius and corner radius
1782
- const arc = this.d3
1783
- .arc()
1784
- .innerRadius(innerRadius)
1785
- .outerRadius(radius * 0.95)
1786
- .cornerRadius(this.cornerRadius());
1787
- // Generate pie data
1788
- this.pieData = pie(data);
1789
- // Create color scale
1790
- const colorScale = this.setupColorScale(this.chartDataArray());
1791
- // Add segments with animation
1792
- this.addSegmentsWithAnimation(arc, colorScale, total);
1793
- }
1794
- setupColorScale(data) {
1795
- return this.d3
1796
- .scaleOrdinal()
1797
- .domain(data.map((_, i) => i.toString()))
1798
- .range(data.map((_, i) => this.getColor(i)));
1799
- }
1800
- addSegmentsWithAnimation(arc, colorScale, total) {
1801
- // Add segments
1802
- const segments = this.svg
1803
- .selectAll('path')
1804
- .data(this.pieData)
1805
- .enter()
1806
- .append('path')
1807
- .attr('class', 'axp-donut-chart-segment')
1808
- .attr('fill', (d, i) => colorScale(i.toString()))
1809
- .style('opacity', 0)
1810
- .on('click', (event, d) => this.onSegmentClick(d.data))
1811
- .on('mousemove', (event, d) => this.handleSegmentHover(event, d, total))
1812
- .on('mouseleave', () => this._tooltipVisible.set(false));
1813
- // Animate segments
1814
- segments
1815
- .transition()
1816
- .duration(800)
1817
- .ease(this.d3.easeCubicOut)
1818
- .delay((d, i) => i * 50)
1819
- .style('opacity', 1)
1820
- .attrTween('d', (d) => {
1821
- const interpolate = this.d3.interpolate({ startAngle: d.startAngle, endAngle: d.startAngle }, d);
1822
- return (t) => arc(interpolate(t));
1823
- });
1824
- }
1825
- handleSegmentHover(event, datum, total) {
1826
- if (!this.showTooltip())
1827
- return;
1828
- const percentage = ((datum.data.value / total) * 100).toFixed(1);
1829
- const segmentColor = this.getColor(this.chartDataArray().findIndex((item) => item.id === datum.data.id));
1830
- this._tooltipData.set({
1831
- title: datum.data.name,
1832
- value: datum.data.value,
1833
- percentage: `${percentage}%`,
1834
- color: segmentColor,
1835
- });
1836
- this.updateTooltipPosition(event);
1837
- this._tooltipVisible.set(true);
1838
- }
1839
- updateTooltipPosition(event) {
1840
- const container = this.chartContainerEl().nativeElement.getBoundingClientRect();
1841
- const x = event.clientX - container.left;
1842
- const y = event.clientY - container.top;
1843
- this._tooltipPosition.set({
1844
- x: x,
1845
- y: y,
1846
- });
1847
- }
1848
- toggleSegment(item) {
1849
- if (this.hiddenSegments.has(item.id)) {
1850
- this.hiddenSegments.delete(item.id);
1851
- }
1852
- else {
1853
- this.hiddenSegments.add(item.id);
1854
- }
1855
- // Hide tooltip when toggling segments
1856
- this._tooltipVisible.set(false);
1857
- this.updateChart();
1858
- }
1859
- calculateTotal() {
1860
- return this.chartDataArray()
1861
- .filter((item) => !this.hiddenSegments.has(item.id))
1862
- .reduce((sum, item) => sum + item.value, 0);
1092
+ this.donutChartData = computed(() => this.getValue());
1093
+ this.donutChartOptions = computed(() => this.options());
1863
1094
  }
1864
- showNoDataMessage(containerElement) {
1865
- const messageContainer = this.d3
1866
- .select(containerElement)
1867
- .append('div')
1868
- .attr('class', 'axp-donut-chart-no-data-message')
1869
- .style('width', 'auto')
1870
- .style('text-align', 'center');
1871
- // Add an icon
1872
- messageContainer
1873
- .append('div')
1874
- .attr('class', 'axp-donut-chart-no-data-icon')
1875
- .html('<i class="fa-light fa-chart-pie-simple fa-2x"></i>');
1876
- // Add text message and help text
1877
- messageContainer.append('div').attr('class', 'axp-donut-chart-no-data-text').text('No data available');
1878
- messageContainer
1879
- .append('div')
1880
- .attr('class', 'axp-donut-chart-no-data-help')
1881
- .text('Please provide data in the correct format');
1882
- // Position in center
1883
- const container = containerElement.getBoundingClientRect();
1884
- messageContainer.style('left', `${container.width / 2}px`).style('top', `${container.height / 2}px`);
1885
- }
1886
- // Add method to show message when all segments are hidden
1887
- showAllSegmentsHiddenMessage(containerElement) {
1888
- this.clearChart(containerElement);
1889
- // Add a simple div to ensure proper positioning
1890
- const wrapper = this.d3
1891
- .select(containerElement)
1892
- .append('div')
1893
- .style('position', 'relative')
1894
- .style('width', '100%')
1895
- .style('height', '100%');
1896
- const messageContainer = wrapper
1897
- .append('div')
1898
- .attr('class', 'axp-donut-chart-no-data-message')
1899
- .style('position', 'absolute')
1900
- .style('left', '50%')
1901
- .style('top', '50%')
1902
- .style('transform', 'translate(-50%, -50%)')
1903
- .style('text-align', 'center')
1904
- .style('z-index', '10')
1905
- .style('background-color', 'rgba(255, 255, 255, 0.95)')
1906
- .style('padding', '1.5rem')
1907
- .style('border-radius', '0.5rem')
1908
- .style('box-shadow', '0 2px 12px rgba(0, 0, 0, 0.08)')
1909
- .style('width', '80%')
1910
- .style('max-width', '300px');
1911
- // Add an icon
1912
- messageContainer
1913
- .append('div')
1914
- .attr('class', 'axp-donut-chart-no-data-icon')
1915
- .style('color', 'var(--ax-text-muted, #999)')
1916
- .style('margin-bottom', '0.75rem')
1917
- .html('<i class="fa-light fa-eye-slash fa-2x"></i>');
1918
- // Add text message and help text
1919
- messageContainer
1920
- .append('div')
1921
- .attr('class', 'axp-donut-chart-no-data-text')
1922
- .style('font-size', '1rem')
1923
- .style('font-weight', '600')
1924
- .style('color', 'var(--ax-text-color, #333)')
1925
- .style('margin-bottom', '0.5rem')
1926
- .text('All segments are hidden');
1927
- messageContainer
1928
- .append('div')
1929
- .attr('class', 'axp-donut-chart-no-data-help')
1930
- .style('font-size', '0.8rem')
1931
- .style('color', 'var(--ax-text-muted, #999)')
1932
- .text('Click on a legend item to show data');
1933
- }
1934
- addTotalDisplay(total) {
1935
- if (!this.svg)
1936
- return;
1937
- // Remove any existing total display
1938
- this.svg.selectAll('.axp-donut-chart-total-display').remove();
1939
- // Create group for the total display
1940
- const totalDisplay = this.svg
1941
- .append('g')
1942
- .attr('class', 'axp-donut-chart-total-display')
1943
- .attr('text-anchor', 'middle');
1944
- // Add total value
1945
- totalDisplay
1946
- .append('text')
1947
- .attr('class', 'axp-donut-chart-total-value')
1948
- .style('font-size', '1.8rem')
1949
- .style('font-weight', '600')
1950
- .style('fill', 'currentColor')
1951
- .text(total.toLocaleString());
1952
- // Add "Total" label
1953
- totalDisplay
1954
- .append('text')
1955
- .attr('class', 'axp-donut-chart-total-label')
1956
- .attr('dy', '1.4em')
1957
- .style('font-size', '0.9rem')
1958
- .style('fill', 'currentColor')
1959
- .style('fill-opacity', '0.8')
1960
- .text('Total');
1095
+ handleDonutChartSegmentClick(event) {
1096
+ //console.log(event);
1961
1097
  }
1962
1098
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPDonutChartWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1963
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXPDonutChartWidgetViewComponent, isStandalone: true, selector: "ng-component", outputs: { segmentClick: "segmentClick" }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"axp-donut-chart-container\" #chartContainer>\n <!-- Chart visualization area -->\n <div class=\"axp-donut-chart-content\"></div>\n\n <!-- Legend with conditional positioning -->\n @if (showLegend()) {\n <div\n class=\"axp-donut-chart-legend-container\"\n [class.axp-donut-chart-legend-right]=\"legendPosition() === 'right'\"\n [class.axp-donut-chart-legend-bottom]=\"legendPosition() === 'bottom'\"\n >\n @for (item of chartDataArray(); track item.id) {\n <div\n class=\"axp-donut-chart-legend-item\"\n (mouseenter)=\"onLegendMouseEnter(item)\"\n (mouseleave)=\"onLegendMouseLeave()\"\n (click)=\"onSegmentClick(item)\"\n [class.axp-donut-chart-hidden]=\"isSegmentHidden(item.id)\"\n >\n <div class=\"axp-donut-chart-legend-color\" [style.background-color]=\"getColor($index)\"></div>\n <span class=\"axp-donut-chart-legend-name\">{{ item.name }}</span>\n <span class=\"axp-donut-chart-legend-value\">{{ item.value }}</span>\n </div>\n }\n </div>\n }\n\n <!-- Shared tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.axp-donut-chart-container{position:relative;height:100%;width:100%;padding:1rem;border-radius:.5rem;box-shadow:var(--ax-card-shadow, 0 2px 8px rgba(0, 0, 0, .05));box-sizing:border-box;display:flex;flex-direction:column;overflow:hidden}.axp-donut-chart-content{flex:1;width:100%;display:flex;align-items:center;justify-content:center;position:relative;min-height:0}.axp-donut-chart-legend-container{display:flex;gap:.75rem;padding:.75rem;flex-wrap:wrap;justify-content:center;font-family:var(--ax-font-family, system-ui, sans-serif);z-index:5}.axp-donut-chart-legend-right{flex-direction:column;position:absolute;right:.75rem;top:0;bottom:0;margin:auto;height:fit-content;max-height:80%;overflow-y:auto;overflow-x:hidden;padding:.75rem;background-color:rgba(255,255,255,.9);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border-radius:.375rem;box-shadow:0 2px 8px rgba(0,0,0,.05);max-width:30%}.axp-donut-chart-legend-bottom{position:absolute;bottom:.5rem;left:0;right:0;margin:0 auto;width:auto;max-width:98%;flex-direction:row;flex-wrap:wrap;justify-content:center;padding:.75rem;background-color:rgba(255,255,255,.9);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border-radius:.375rem;box-shadow:0 2px 8px rgba(0,0,0,.05)}.axp-donut-chart-legend-item{display:flex;align-items:center;gap:.375rem;padding:.25rem .5rem;border-radius:.375rem;cursor:pointer;transition:all .2s ease;white-space:nowrap;font-size:.875rem}.axp-donut-chart-legend-item:hover{background-color:var(--ax-hover-bg, rgba(0, 0, 0, .05));transform:translateY(-1px)}.axp-donut-chart-legend-item.axp-donut-chart-hidden{opacity:.5}.axp-donut-chart-legend-color{min-width:10px;min-height:10px;width:10px;height:10px;border-radius:2px;box-shadow:0 1px 3px rgba(0,0,0,.1)}.axp-donut-chart-legend-name{font-size:.875rem;font-weight:500;color:var(--ax-text-color, #333)}.axp-donut-chart-legend-value{font-size:.875rem;opacity:.7;margin-left:4px;font-weight:400;color:var(--ax-text-muted, #666)}.axp-donut-chart-no-data-message{position:absolute;text-align:center;transform:translate(-50%,-50%);font-family:var(--ax-font-family, system-ui, sans-serif);background-color:rgba(255,255,255,.9);padding:1.5rem;border-radius:.5rem;box-shadow:0 2px 12px rgba(0,0,0,.08);width:80%;max-width:300px}.axp-donut-chart-no-data-message .axp-donut-chart-no-data-icon{color:var(--ax-text-muted, #999);margin-bottom:.75rem}.axp-donut-chart-no-data-message .axp-donut-chart-no-data-text{font-size:1rem;font-weight:600;color:var(--ax-text-color, #333);margin-bottom:.5rem}.axp-donut-chart-no-data-message .axp-donut-chart-no-data-help{font-size:.8rem;color:var(--ax-text-muted, #999)}.axp-donut-chart-segment{cursor:pointer;transition:all .3s cubic-bezier(.25,.8,.25,1);stroke:#fff;stroke-width:1.5px;filter:drop-shadow(0px 1px 2px rgba(0,0,0,.1))}.axp-donut-chart-segment:hover{opacity:.92;filter:drop-shadow(0px 3px 5px rgba(0,0,0,.15));transform:scale(1.01)}.axp-donut-chart-highlighted{opacity:1;filter:brightness(1.05) drop-shadow(0px 3px 5px rgba(0,0,0,.15));transform:scale(1.02)}.axp-donut-chart-dimmed{opacity:.4}.axp-donut-chart-total-display{pointer-events:none}.axp-donut-chart-total-value{fill:currentColor}.axp-donut-chart-total-label{fill:currentColor;opacity:.8}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXPChartTooltipComponent, selector: "ax-chart-tooltip", inputs: ["data", "position", "visible", "showPercentage", "style"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1099
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: AXPDonutChartWidgetViewComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<ax-donut-chart\n [data]=\"donutChartData()\"\n [options]=\"donutChartOptions()\"\n (segmentClick)=\"handleDonutChartSegmentClick($event)\"\n></ax-donut-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "component", type: AXDonutChartComponent, selector: "ax-donut-chart", inputs: ["data", "options"], outputs: ["segmentClick", "segmentHover"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1964
1100
  }
1965
1101
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPDonutChartWidgetViewComponent, decorators: [{
1966
1102
  type: Component,
1967
- args: [{ standalone: true, imports: [CommonModule, AXPChartTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"axp-donut-chart-container\" #chartContainer>\n <!-- Chart visualization area -->\n <div class=\"axp-donut-chart-content\"></div>\n\n <!-- Legend with conditional positioning -->\n @if (showLegend()) {\n <div\n class=\"axp-donut-chart-legend-container\"\n [class.axp-donut-chart-legend-right]=\"legendPosition() === 'right'\"\n [class.axp-donut-chart-legend-bottom]=\"legendPosition() === 'bottom'\"\n >\n @for (item of chartDataArray(); track item.id) {\n <div\n class=\"axp-donut-chart-legend-item\"\n (mouseenter)=\"onLegendMouseEnter(item)\"\n (mouseleave)=\"onLegendMouseLeave()\"\n (click)=\"onSegmentClick(item)\"\n [class.axp-donut-chart-hidden]=\"isSegmentHidden(item.id)\"\n >\n <div class=\"axp-donut-chart-legend-color\" [style.background-color]=\"getColor($index)\"></div>\n <span class=\"axp-donut-chart-legend-name\">{{ item.name }}</span>\n <span class=\"axp-donut-chart-legend-value\">{{ item.value }}</span>\n </div>\n }\n </div>\n }\n\n <!-- Shared tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"true\"\n ></ax-chart-tooltip>\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.axp-donut-chart-container{position:relative;height:100%;width:100%;padding:1rem;border-radius:.5rem;box-shadow:var(--ax-card-shadow, 0 2px 8px rgba(0, 0, 0, .05));box-sizing:border-box;display:flex;flex-direction:column;overflow:hidden}.axp-donut-chart-content{flex:1;width:100%;display:flex;align-items:center;justify-content:center;position:relative;min-height:0}.axp-donut-chart-legend-container{display:flex;gap:.75rem;padding:.75rem;flex-wrap:wrap;justify-content:center;font-family:var(--ax-font-family, system-ui, sans-serif);z-index:5}.axp-donut-chart-legend-right{flex-direction:column;position:absolute;right:.75rem;top:0;bottom:0;margin:auto;height:fit-content;max-height:80%;overflow-y:auto;overflow-x:hidden;padding:.75rem;background-color:rgba(255,255,255,.9);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border-radius:.375rem;box-shadow:0 2px 8px rgba(0,0,0,.05);max-width:30%}.axp-donut-chart-legend-bottom{position:absolute;bottom:.5rem;left:0;right:0;margin:0 auto;width:auto;max-width:98%;flex-direction:row;flex-wrap:wrap;justify-content:center;padding:.75rem;background-color:rgba(255,255,255,.9);-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);border-radius:.375rem;box-shadow:0 2px 8px rgba(0,0,0,.05)}.axp-donut-chart-legend-item{display:flex;align-items:center;gap:.375rem;padding:.25rem .5rem;border-radius:.375rem;cursor:pointer;transition:all .2s ease;white-space:nowrap;font-size:.875rem}.axp-donut-chart-legend-item:hover{background-color:var(--ax-hover-bg, rgba(0, 0, 0, .05));transform:translateY(-1px)}.axp-donut-chart-legend-item.axp-donut-chart-hidden{opacity:.5}.axp-donut-chart-legend-color{min-width:10px;min-height:10px;width:10px;height:10px;border-radius:2px;box-shadow:0 1px 3px rgba(0,0,0,.1)}.axp-donut-chart-legend-name{font-size:.875rem;font-weight:500;color:var(--ax-text-color, #333)}.axp-donut-chart-legend-value{font-size:.875rem;opacity:.7;margin-left:4px;font-weight:400;color:var(--ax-text-muted, #666)}.axp-donut-chart-no-data-message{position:absolute;text-align:center;transform:translate(-50%,-50%);font-family:var(--ax-font-family, system-ui, sans-serif);background-color:rgba(255,255,255,.9);padding:1.5rem;border-radius:.5rem;box-shadow:0 2px 12px rgba(0,0,0,.08);width:80%;max-width:300px}.axp-donut-chart-no-data-message .axp-donut-chart-no-data-icon{color:var(--ax-text-muted, #999);margin-bottom:.75rem}.axp-donut-chart-no-data-message .axp-donut-chart-no-data-text{font-size:1rem;font-weight:600;color:var(--ax-text-color, #333);margin-bottom:.5rem}.axp-donut-chart-no-data-message .axp-donut-chart-no-data-help{font-size:.8rem;color:var(--ax-text-muted, #999)}.axp-donut-chart-segment{cursor:pointer;transition:all .3s cubic-bezier(.25,.8,.25,1);stroke:#fff;stroke-width:1.5px;filter:drop-shadow(0px 1px 2px rgba(0,0,0,.1))}.axp-donut-chart-segment:hover{opacity:.92;filter:drop-shadow(0px 3px 5px rgba(0,0,0,.15));transform:scale(1.01)}.axp-donut-chart-highlighted{opacity:1;filter:brightness(1.05) drop-shadow(0px 3px 5px rgba(0,0,0,.15));transform:scale(1.02)}.axp-donut-chart-dimmed{opacity:.4}.axp-donut-chart-total-display{pointer-events:none}.axp-donut-chart-total-value{fill:currentColor}.axp-donut-chart-total-label{fill:currentColor;opacity:.8}\n"] }]
1103
+ args: [{ imports: [AXDonutChartComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ax-donut-chart\n [data]=\"donutChartData()\"\n [options]=\"donutChartOptions()\"\n (segmentClick)=\"handleDonutChartSegmentClick($event)\"\n></ax-donut-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
1968
1104
  }] });
1969
1105
 
1970
1106
  var donutChartWidget_component = /*#__PURE__*/Object.freeze({
@@ -1980,79 +1116,141 @@ const AXPDonutChartWidget = {
1980
1116
  type: 'dashboard',
1981
1117
  icon: 'fa-light fa-donut',
1982
1118
  properties: [
1119
+ cloneProperty(AXP_NAME_PROPERTY, { visible: false }),
1120
+ cloneProperty(AXP_DATA_PATH_PROPERTY, { visible: false }),
1121
+ // ====== Chart Title ======
1122
+ {
1123
+ name: 'title',
1124
+ title: 'Chart Title',
1125
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1126
+ schema: {
1127
+ defaultValue: '',
1128
+ dataType: 'string',
1129
+ interface: {
1130
+ name: 'title',
1131
+ path: 'options.title',
1132
+ type: AXPWidgetsCatalog.text,
1133
+ options: {
1134
+ placeholder: 'Enter chart title',
1135
+ },
1136
+ },
1137
+ },
1138
+ visible: true,
1139
+ },
1983
1140
  // ====== Size & Layout ======
1984
1141
  {
1985
- name: 'height',
1986
- title: 'Height',
1142
+ name: 'width',
1143
+ title: 'Width',
1987
1144
  group: AXP_STYLING_PROPERTY_GROUP,
1988
1145
  schema: {
1989
1146
  defaultValue: 300,
1990
1147
  dataType: 'number',
1991
1148
  interface: {
1992
- name: 'height',
1993
- path: 'options.height',
1149
+ name: 'width',
1150
+ path: 'options.width',
1994
1151
  type: AXPWidgetsCatalog.number,
1995
1152
  options: {
1996
1153
  minValue: 200,
1997
- maxValue: 800,
1154
+ maxValue: 1200,
1998
1155
  },
1999
1156
  },
2000
1157
  },
2001
1158
  visible: true,
2002
1159
  },
2003
1160
  {
2004
- name: 'width',
2005
- title: 'Width',
1161
+ name: 'height',
1162
+ title: 'Height',
2006
1163
  group: AXP_STYLING_PROPERTY_GROUP,
2007
1164
  schema: {
2008
1165
  defaultValue: 300,
2009
1166
  dataType: 'number',
2010
1167
  interface: {
2011
- name: 'width',
2012
- path: 'options.width',
1168
+ name: 'height',
1169
+ path: 'options.height',
2013
1170
  type: AXPWidgetsCatalog.number,
2014
1171
  options: {
2015
1172
  minValue: 200,
2016
- maxValue: 1200,
1173
+ maxValue: 800,
2017
1174
  },
2018
1175
  },
2019
1176
  },
2020
1177
  visible: true,
2021
1178
  },
2022
- // ====== Legend ======
1179
+ // ====== Donut Appearance ======
2023
1180
  {
2024
- name: 'showLegend',
2025
- title: 'Show Legend',
1181
+ name: 'donutWidth',
1182
+ title: 'Donut Width',
2026
1183
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2027
1184
  schema: {
2028
- defaultValue: true,
2029
- dataType: 'boolean',
1185
+ defaultValue: 35,
1186
+ dataType: 'number',
2030
1187
  interface: {
2031
- name: 'showLegend',
2032
- path: 'options.showLegend',
2033
- type: AXPWidgetsCatalog.toggle,
1188
+ name: 'donutWidth',
1189
+ path: 'options.donutWidth',
1190
+ type: AXPWidgetsCatalog.number,
1191
+ options: {
1192
+ placeholder: '10-80',
1193
+ minValue: 10,
1194
+ maxValue: 80,
1195
+ },
2034
1196
  },
2035
1197
  },
2036
1198
  visible: true,
2037
1199
  },
2038
1200
  {
2039
- name: 'legendPosition',
2040
- title: 'Legend Position',
1201
+ name: 'cornerRadius',
1202
+ title: 'Corner Radius',
2041
1203
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2042
1204
  schema: {
2043
- defaultValue: 'right',
2044
- dataType: 'string',
1205
+ defaultValue: 4,
1206
+ dataType: 'number',
2045
1207
  interface: {
2046
- name: 'legendPosition',
2047
- path: 'options.legendPosition',
2048
- type: AXPWidgetsCatalog.select,
1208
+ name: 'cornerRadius',
1209
+ path: 'options.cornerRadius',
1210
+ type: AXPWidgetsCatalog.number,
2049
1211
  options: {
2050
- dataSource: ['right', 'bottom'],
1212
+ placeholder: '0-20',
1213
+ minValue: 0,
1214
+ maxValue: 20,
2051
1215
  },
2052
1216
  },
2053
1217
  },
2054
1218
  visible: true,
2055
1219
  },
1220
+ // ====== Legend ======
1221
+ // {
1222
+ // name: 'showLegend',
1223
+ // title: 'Show Legend',
1224
+ // group: AXP_APPEARANCE_PROPERTY_GROUP,
1225
+ // schema: {
1226
+ // defaultValue: true,
1227
+ // dataType: 'boolean',
1228
+ // interface: {
1229
+ // name: 'showLegend',
1230
+ // path: 'options.showLegend',
1231
+ // type: AXPWidgetsCatalog.toggle,
1232
+ // },
1233
+ // },
1234
+ // visible: true,
1235
+ // },
1236
+ // {
1237
+ // name: 'legendPosition',
1238
+ // title: 'Legend Position',
1239
+ // group: AXP_APPEARANCE_PROPERTY_GROUP,
1240
+ // schema: {
1241
+ // defaultValue: 'right',
1242
+ // dataType: 'string',
1243
+ // interface: {
1244
+ // name: 'legendPosition',
1245
+ // path: 'options.legendPosition',
1246
+ // type: AXPWidgetsCatalog.select,
1247
+ // options: {
1248
+ // dataSource: ['right', 'bottom'],
1249
+ // },
1250
+ // },
1251
+ // },
1252
+ // visible: true,
1253
+ // },
2056
1254
  // ====== Tooltip ======
2057
1255
  {
2058
1256
  name: 'showTooltip',
@@ -2069,42 +1267,52 @@ const AXPDonutChartWidget = {
2069
1267
  },
2070
1268
  visible: true,
2071
1269
  },
2072
- // ====== Donut Appearance ======
1270
+ // ====== Animation Settings ======
2073
1271
  {
2074
- name: 'donutWidth',
2075
- title: 'Donut Width',
1272
+ name: 'animationEasing',
1273
+ title: 'Animation Easing',
2076
1274
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2077
1275
  schema: {
2078
- defaultValue: 35,
2079
- dataType: 'number',
1276
+ defaultValue: 'cubic-out',
1277
+ dataType: 'string',
2080
1278
  interface: {
2081
- name: 'donutWidth',
2082
- path: 'options.donutWidth',
2083
- type: AXPWidgetsCatalog.number,
1279
+ name: 'animationEasing',
1280
+ path: 'options.animationEasing',
1281
+ type: AXPWidgetsCatalog.select,
2084
1282
  options: {
2085
- placeholder: '10-80',
2086
- minValue: 10,
2087
- maxValue: 80,
1283
+ dataSource: [
1284
+ { value: 'linear', text: 'Linear' },
1285
+ { value: 'ease', text: 'Ease' },
1286
+ { value: 'ease-in', text: 'Ease In' },
1287
+ { value: 'ease-out', text: 'Ease Out' },
1288
+ { value: 'ease-in-out', text: 'Ease In Out' },
1289
+ { value: 'cubic', text: 'Cubic' },
1290
+ { value: 'cubic-in', text: 'Cubic In' },
1291
+ { value: 'cubic-out', text: 'Cubic Out' },
1292
+ { value: 'cubic-in-out', text: 'Cubic In Out' },
1293
+ ],
1294
+ textField: 'text',
1295
+ valueField: 'value',
2088
1296
  },
2089
1297
  },
2090
1298
  },
2091
1299
  visible: true,
2092
1300
  },
2093
1301
  {
2094
- name: 'cornerRadius',
2095
- title: 'Corner Radius',
1302
+ name: 'animationDuration',
1303
+ title: 'Animation Duration',
2096
1304
  group: AXP_APPEARANCE_PROPERTY_GROUP,
2097
1305
  schema: {
2098
- defaultValue: 4,
1306
+ defaultValue: 800,
2099
1307
  dataType: 'number',
2100
1308
  interface: {
2101
- name: 'cornerRadius',
2102
- path: 'options.cornerRadius',
1309
+ name: 'animationDuration',
1310
+ path: 'options.animationDuration',
2103
1311
  type: AXPWidgetsCatalog.number,
2104
1312
  options: {
2105
- placeholder: '0-20',
1313
+ placeholder: '0-2000',
2106
1314
  minValue: 0,
2107
- maxValue: 20,
1315
+ maxValue: 2000,
2108
1316
  },
2109
1317
  },
2110
1318
  },
@@ -2132,370 +1340,18 @@ const AXPDonutChartWidget = {
2132
1340
  * Gauge Chart Widget Component
2133
1341
  * Renders a semi-circular gauge chart with animated needle and thresholds
2134
1342
  */
2135
- class AXPGaugeChartWidgetViewComponent extends AXPChartBaseComponent {
1343
+ class AXPGaugeChartWidgetViewComponent extends AXPValueWidgetComponent {
2136
1344
  constructor() {
2137
1345
  super(...arguments);
2138
- this.cdr = inject(ChangeDetectorRef);
2139
- this.chartContainerEl = viewChild.required('chartContainer');
2140
- this.chartEl = viewChild.required('chart');
2141
- // Default values
2142
- this.backgroundColor = 'transparent';
2143
- this.baseColor = '#e2e8f0';
2144
- this.labelFontSize = 16;
2145
- this.showValue = true;
2146
- this.valueColor = '#6366f1';
2147
- this.valueFontSize = 24;
2148
- // Default values as computed properties
2149
- this.minValue = computed(() => this.options()['minValue'] ?? 0);
2150
- this.maxValue = computed(() => this.options()['maxValue'] ?? 100);
2151
- this.thresholds = computed(() => this.options()['thresholds'] ?? []);
2152
- this.label = computed(() => this.options()['label'] ?? '');
2153
- this.width = computed(() => this.options()['width'] ?? 300);
2154
- this.height = computed(() => this.options()['height'] ?? 300);
2155
- this.gaugeWidth = computed(() => this.options()['gaugeWidth'] ?? 22);
2156
- this.cornerRadius = computed(() => this.options()['cornerRadius'] ?? 5);
2157
- }
2158
- /**
2159
- * Creates the gauge chart with all elements
2160
- */
2161
- createChart() {
2162
- // Clear any existing chart
2163
- this.d3.select(this.chartEl().nativeElement).selectAll('*').remove();
2164
- // Calculate responsive dimensions
2165
- const containerElement = this.chartContainerEl().nativeElement;
2166
- const containerWidth = containerElement.clientWidth;
2167
- const containerHeight = containerElement.clientHeight;
2168
- // Determine size based on explicit dimensions or container size
2169
- const options = this.options();
2170
- let size;
2171
- if (options.width && options.height) {
2172
- // Use explicit dimensions if provided
2173
- size = Math.min(options.width, options.height * 2);
2174
- }
2175
- else {
2176
- // Use container dimensions with minimum constraints
2177
- const minDim = Math.max(200, Math.min(containerWidth, containerHeight));
2178
- size = Math.min(containerWidth, containerHeight * 2, minDim * 2);
2179
- }
2180
- const margin = size * 0.1;
2181
- // Set up SVG with responsive viewBox
2182
- const svg = this.d3
2183
- .select(this.chartEl().nativeElement)
2184
- .attr('width', '100%')
2185
- .attr('height', '100%')
2186
- .attr('viewBox', `0 0 ${size} ${size / 2}`)
2187
- .attr('preserveAspectRatio', 'xMidYMid meet');
2188
- // Create a group for the chart with margin and move it to show only the top half
2189
- const chartGroup = svg.append('g').attr('transform', `translate(${size / 2}, ${size / 2 - margin})`);
2190
- // Define gauge parameters
2191
- const radius = size / 2 - margin;
2192
- const innerRadius = radius - this.gaugeWidth();
2193
- const outerRadius = radius;
2194
- // Create gradient definitions
2195
- this.createGradients(svg, this.thresholds());
2196
- // Draw the background arc
2197
- this.drawBackgroundArc(chartGroup, innerRadius, outerRadius, this.cornerRadius());
2198
- // Draw the threshold arcs if thresholds exist
2199
- if (this.thresholds().length > 0) {
2200
- this.drawThresholds(chartGroup, innerRadius, outerRadius, this.minValue(), this.maxValue(), this.thresholds(), this.cornerRadius());
2201
- }
2202
- // Draw tick marks
2203
- this.drawTicks(chartGroup, outerRadius, this.minValue(), this.maxValue());
2204
- // Draw the dial/needle with animation
2205
- this.drawDial(chartGroup, radius, this.chartData() ?? 0, this.minValue(), this.maxValue());
2206
- // Draw the value display (after the dial so it's on top)
2207
- if (this.showValue) {
2208
- this.drawValueDisplay(chartGroup, this.chartData() ?? 0, this.label(), radius);
2209
- }
2210
- }
2211
- updateChart() {
2212
- this.createChart();
2213
- }
2214
- cleanupChart() {
2215
- if (this.chartEl()?.nativeElement) {
2216
- this.d3.select(this.chartEl().nativeElement).selectAll('*').remove();
2217
- }
2218
- }
2219
- /**
2220
- * Creates gradient definitions for thresholds
2221
- */
2222
- createGradients(svg, thresholds) {
2223
- const defs = svg.append('defs');
2224
- // Create a radial gradient for the background
2225
- const bgGradient = defs
2226
- .append('radialGradient')
2227
- .attr('id', 'gauge-bg-gradient')
2228
- .attr('cx', '50%')
2229
- .attr('cy', '50%')
2230
- .attr('r', '50%')
2231
- .attr('gradientUnits', 'userSpaceOnUse');
2232
- if (thresholds.length === 0) {
2233
- // Default gradient when no thresholds are provided
2234
- bgGradient
2235
- .append('stop')
2236
- .attr('offset', '0%')
2237
- .attr('stop-color', this.d3.color(this.valueColor)?.brighter(0.5).toString() || this.valueColor);
2238
- bgGradient.append('stop').attr('offset', '100%').attr('stop-color', this.valueColor);
2239
- }
2240
- else {
2241
- bgGradient
2242
- .append('stop')
2243
- .attr('offset', '0%')
2244
- .attr('stop-color', this.d3.color(this.baseColor)?.brighter(0.5).toString() || this.baseColor);
2245
- bgGradient.append('stop').attr('offset', '100%').attr('stop-color', this.baseColor);
2246
- // Create gradients for each threshold
2247
- thresholds.forEach((threshold, i) => {
2248
- const gradient = defs
2249
- .append('linearGradient')
2250
- .attr('id', `threshold-gradient-${i}`)
2251
- .attr('gradientUnits', 'userSpaceOnUse')
2252
- .attr('x1', '-1')
2253
- .attr('y1', '0')
2254
- .attr('x2', '1')
2255
- .attr('y2', '0');
2256
- gradient
2257
- .append('stop')
2258
- .attr('offset', '0%')
2259
- .attr('stop-color', this.d3.color(threshold.color)?.brighter(0.5).toString() || threshold.color);
2260
- gradient.append('stop').attr('offset', '100%').attr('stop-color', threshold.color);
2261
- });
2262
- }
2263
- }
2264
- /**
2265
- * Draws the background arc
2266
- */
2267
- drawBackgroundArc(chartGroup, innerRadius, outerRadius, cornerRadius) {
2268
- const backgroundArc = this.d3
2269
- .arc()
2270
- .innerRadius(innerRadius)
2271
- .outerRadius(outerRadius)
2272
- .startAngle(-Math.PI / 2) // Start from bottom (-90 degrees)
2273
- .endAngle(Math.PI / 2) // End at top (90 degrees)
2274
- .cornerRadius(cornerRadius);
2275
- chartGroup
2276
- .append('path')
2277
- .attr('d', backgroundArc({
2278
- innerRadius,
2279
- outerRadius,
2280
- startAngle: -Math.PI / 2,
2281
- endAngle: Math.PI / 2,
2282
- }))
2283
- .attr('fill', this.backgroundColor === 'transparent' ? 'url(#gauge-bg-gradient)' : this.backgroundColor)
2284
- .attr('filter', 'drop-shadow(0px 2px 3px rgba(0,0,0,0.1))');
2285
- }
2286
- /**
2287
- * Draws the threshold arcs with colors
2288
- */
2289
- drawThresholds(chartGroup, innerRadius, outerRadius, minValue, maxValue, thresholds, cornerRadius) {
2290
- const arc = this.d3
2291
- .arc()
2292
- .innerRadius(innerRadius)
2293
- .outerRadius(outerRadius * 0.98)
2294
- .cornerRadius(cornerRadius);
2295
- // Sort thresholds by value in ascending order
2296
- const sortedThresholds = [...thresholds].sort((a, b) => a.value - b.value);
2297
- // Calculate all angles first using the color angle calculation
2298
- const angles = sortedThresholds.map((t) => this.scaleValueToColorAngle(t.value, minValue, maxValue));
2299
- // Start from the minimum value angle
2300
- let previousEndAngle = this.scaleValueToColorAngle(minValue, minValue, maxValue);
2301
- sortedThresholds.forEach((threshold, i) => {
2302
- const endAngle = angles[i];
2303
- chartGroup
2304
- .append('path')
2305
- .attr('d', arc({
2306
- innerRadius,
2307
- outerRadius,
2308
- startAngle: previousEndAngle,
2309
- endAngle,
2310
- }))
2311
- .attr('fill', `url(#threshold-gradient-${i})`)
2312
- .attr('stroke', 'rgba(255,255,255,0.3)')
2313
- .attr('stroke-width', 1);
2314
- previousEndAngle = endAngle;
2315
- });
2316
- // Fill the remaining space to maxValue if needed
2317
- const lastEndAngle = this.scaleValueToColorAngle(maxValue, minValue, maxValue);
2318
- if (previousEndAngle < lastEndAngle) {
2319
- chartGroup
2320
- .append('path')
2321
- .attr('d', arc({
2322
- innerRadius,
2323
- outerRadius,
2324
- startAngle: previousEndAngle,
2325
- endAngle: lastEndAngle,
2326
- }))
2327
- .attr('fill', `url(#threshold-gradient-${sortedThresholds.length - 1})`)
2328
- .attr('stroke', 'rgba(255,255,255,0.3)')
2329
- .attr('stroke-width', 1);
2330
- }
2331
- }
2332
- /**
2333
- * Draws tick marks around the gauge
2334
- */
2335
- drawTicks(chartGroup, radius, minValue, maxValue) {
2336
- const tickCount = 10;
2337
- const minorTickCount = 40;
2338
- // Draw minor ticks
2339
- for (let i = 0; i <= minorTickCount; i++) {
2340
- const value = minValue + (i / minorTickCount) * (maxValue - minValue);
2341
- const angle = this.scaleValueToAngle(value, minValue, maxValue);
2342
- const outerPoint = {
2343
- x: radius * 0.9 * Math.cos(angle),
2344
- y: radius * 0.9 * Math.sin(angle),
2345
- };
2346
- const innerPoint = {
2347
- x: radius * 0.87 * Math.cos(angle),
2348
- y: radius * 0.87 * Math.sin(angle),
2349
- };
2350
- chartGroup
2351
- .append('line')
2352
- .attr('x1', innerPoint.x)
2353
- .attr('y1', innerPoint.y)
2354
- .attr('x2', outerPoint.x)
2355
- .attr('y2', outerPoint.y)
2356
- .attr('stroke', '#adb5bd')
2357
- .attr('stroke-width', 0.5);
2358
- }
2359
- // Draw major ticks and labels
2360
- for (let i = 0; i <= tickCount; i++) {
2361
- const value = minValue + (i / tickCount) * (maxValue - minValue);
2362
- const angle = this.scaleValueToAngle(value, minValue, maxValue);
2363
- const outerPoint = {
2364
- x: radius * 0.92 * Math.cos(angle),
2365
- y: radius * 0.92 * Math.sin(angle),
2366
- };
2367
- const innerPoint = {
2368
- x: radius * 0.85 * Math.cos(angle),
2369
- y: radius * 0.85 * Math.sin(angle),
2370
- };
2371
- // Major tick line
2372
- chartGroup
2373
- .append('line')
2374
- .attr('x1', innerPoint.x)
2375
- .attr('y1', innerPoint.y)
2376
- .attr('x2', outerPoint.x)
2377
- .attr('y2', outerPoint.y)
2378
- .attr('stroke', '#adb5bd')
2379
- .attr('stroke-width', 2);
2380
- // Label position with offset
2381
- const labelRadius = radius * 1.15;
2382
- const labelX = labelRadius * Math.cos(angle);
2383
- const labelY = labelRadius * Math.sin(angle);
2384
- // Add tick value label
2385
- chartGroup
2386
- .append('text')
2387
- .attr('x', labelX)
2388
- .attr('y', labelY)
2389
- .attr('text-anchor', 'middle')
2390
- .style('font-size', `${radius * 0.1}px`)
2391
- .style('font-weight', '500')
2392
- .style('fill', 'currentColor')
2393
- .text(value.toFixed(0));
2394
- }
2395
- }
2396
- /**
2397
- * Draws the value display in the center
2398
- */
2399
- drawValueDisplay(chartGroup, value, label, radius) {
2400
- // Value text - positioned below the needle pivot
2401
- chartGroup
2402
- .append('text')
2403
- .attr('class', 'gauge-value')
2404
- .attr('x', 0)
2405
- .attr('y', radius * 0.25) // Moved up from 0.3
2406
- .attr('text-anchor', 'middle')
2407
- .attr('dominant-baseline', 'central')
2408
- .style('font-size', `${this.valueFontSize}px`)
2409
- .style('font-weight', 'bold')
2410
- .style('fill', 'currentColor')
2411
- .text(value.toFixed(1));
2412
- // Label text
2413
- chartGroup
2414
- .append('text')
2415
- .attr('class', 'gauge-label')
2416
- .attr('x', 0)
2417
- .attr('y', radius * 0.45) // Keeping this position to create more space
2418
- .attr('text-anchor', 'middle')
2419
- .attr('dominant-baseline', 'central')
2420
- .style('font-size', `${this.labelFontSize}px`)
2421
- .style('fill', '#6c757d')
2422
- .text(label);
2423
- }
2424
- /**
2425
- * Draws the dial/needle with animation
2426
- */
2427
- drawDial(chartGroup, radius, value, minValue, maxValue) {
2428
- const needleGroup = chartGroup.append('g');
2429
- const valueAngle = this.scaleValueToAngle(value, minValue, maxValue); // Use regular angle for needle
2430
- // Draw needle base (circle)
2431
- needleGroup
2432
- .append('circle')
2433
- .attr('cx', 0)
2434
- .attr('cy', 0)
2435
- .attr('r', radius * 0.08)
2436
- .attr('fill', 'url(#gauge-bg-gradient)')
2437
- .attr('stroke', '#6c757d')
2438
- .attr('stroke-width', 1);
2439
- // Inner circle
2440
- needleGroup
2441
- .append('circle')
2442
- .attr('cx', 0)
2443
- .attr('cy', 0)
2444
- .attr('r', radius * 0.04)
2445
- .attr('fill', '#495057');
2446
- // Create needle
2447
- const needlePath = needleGroup
2448
- .append('path')
2449
- .attr('d', this.createNeedlePath(radius))
2450
- .attr('fill', '#dc3545')
2451
- .attr('transform', `rotate(${this.radiansToDegrees(-Math.PI)})`) // Start at left (-180 degrees)
2452
- .attr('filter', 'drop-shadow(0px 1px 2px rgba(0,0,0,0.3))');
2453
- // Animate the needle
2454
- needlePath
2455
- .transition()
2456
- .duration(800)
2457
- .ease(this.d3.easeCubicOut)
2458
- .attrTween('transform', () => {
2459
- const interpolate = this.d3.interpolate(-Math.PI, valueAngle);
2460
- return (t) => `rotate(${this.radiansToDegrees(interpolate(t))})`;
2461
- });
2462
- }
2463
- /**
2464
- * Creates a path for the needle
2465
- */
2466
- createNeedlePath(radius) {
2467
- const needleLength = radius * 0.75;
2468
- const needleBaseWidth = radius * 0.04;
2469
- return `M 0 -${needleBaseWidth} L ${needleLength} 0 L 0 ${needleBaseWidth} Z`;
2470
- }
2471
- /**
2472
- * Scales a value to an angle for needle positioning
2473
- */
2474
- scaleValueToAngle(value, min, max) {
2475
- const scaledValue = (value - min) / (max - min);
2476
- // Map from -180 to 0 degrees in radians, starting from the left
2477
- return -Math.PI + scaledValue * Math.PI;
2478
- }
2479
- /**
2480
- * Scales a value to an angle for threshold colors
2481
- */
2482
- scaleValueToColorAngle(value, min, max) {
2483
- const scaledValue = (value - min) / (max - min);
2484
- // Map from -90 to 90 degrees in radians (-π/2 to π/2), starting from the bottom
2485
- return -Math.PI / 2 + scaledValue * Math.PI;
2486
- }
2487
- /**
2488
- * Converts radians to degrees
2489
- */
2490
- radiansToDegrees(radians) {
2491
- return radians * (180 / Math.PI);
1346
+ this.gaugeChartValue = computed(() => this.getValue());
1347
+ this.gaugeChartOptions = computed(() => this.options());
2492
1348
  }
2493
1349
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPGaugeChartWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
2494
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.0.3", type: AXPGaugeChartWidgetViewComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }, { propertyName: "chartEl", first: true, predicate: ["chart"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-flex ax-justify-center ax-items-center ax-w-full ax-h-full\" #chartContainer>\n <svg #chart class=\"ax-w-full ax-h-full\"></svg>\n</div>\n", styles: [":host{display:block;width:100%;height:100%;min-height:200px}div.ax-flex{position:relative;width:100%;height:100%;overflow:visible}svg{display:block;width:100%;height:100%;max-width:100%;max-height:100%;overflow:visible}.gauge-arc{transition:stroke-dashoffset 1s ease}.gauge-label{font-family:var(--ax-font-family, system-ui, sans-serif);font-weight:600}.gauge-value{font-family:var(--ax-font-family, system-ui, sans-serif);font-weight:700}.gauge-min-max{font-family:var(--ax-font-family, system-ui, sans-serif);opacity:.7}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1350
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: AXPGaugeChartWidgetViewComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<ax-gauge-chart [value]=\"gaugeChartValue()\" [options]=\"gaugeChartOptions()\"></ax-gauge-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "component", type: AXGaugeChartComponent, selector: "ax-gauge-chart", inputs: ["value", "options"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2495
1351
  }
2496
1352
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPGaugeChartWidgetViewComponent, decorators: [{
2497
1353
  type: Component,
2498
- args: [{ standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-flex ax-justify-center ax-items-center ax-w-full ax-h-full\" #chartContainer>\n <svg #chart class=\"ax-w-full ax-h-full\"></svg>\n</div>\n", styles: [":host{display:block;width:100%;height:100%;min-height:200px}div.ax-flex{position:relative;width:100%;height:100%;overflow:visible}svg{display:block;width:100%;height:100%;max-width:100%;max-height:100%;overflow:visible}.gauge-arc{transition:stroke-dashoffset 1s ease}.gauge-label{font-family:var(--ax-font-family, system-ui, sans-serif);font-weight:600}.gauge-value{font-family:var(--ax-font-family, system-ui, sans-serif);font-weight:700}.gauge-min-max{font-family:var(--ax-font-family, system-ui, sans-serif);opacity:.7}\n"] }]
1354
+ args: [{ imports: [AXGaugeChartComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ax-gauge-chart [value]=\"gaugeChartValue()\" [options]=\"gaugeChartOptions()\"></ax-gauge-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
2499
1355
  }] });
2500
1356
 
2501
1357
  var gaugeChartWidget_component = /*#__PURE__*/Object.freeze({
@@ -2510,27 +1366,28 @@ const AXPGaugeChartWidget = {
2510
1366
  type: 'dashboard',
2511
1367
  icon: 'fa-light fa-gauge',
2512
1368
  properties: [
2513
- // ====== Layout & Dimensions ======
1369
+ cloneProperty(AXP_NAME_PROPERTY, { visible: false }),
1370
+ cloneProperty(AXP_DATA_PATH_PROPERTY, { visible: false }),
1371
+ // ====== Chart Title ======
2514
1372
  {
2515
- name: 'height',
2516
- title: 'Height',
2517
- group: AXP_STYLING_PROPERTY_GROUP,
1373
+ name: 'title',
1374
+ title: 'Chart Title',
1375
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2518
1376
  schema: {
2519
- defaultValue: 300,
2520
- dataType: 'number',
1377
+ defaultValue: '',
1378
+ dataType: 'string',
2521
1379
  interface: {
2522
- name: 'height',
2523
- path: 'options.height',
2524
- type: AXPWidgetsCatalog.number,
1380
+ name: 'title',
1381
+ path: 'options.title',
1382
+ type: AXPWidgetsCatalog.text,
2525
1383
  options: {
2526
- placeholder: '1-800',
2527
- minValue: 1,
2528
- maxValue: 800,
1384
+ placeholder: 'Enter chart title',
2529
1385
  },
2530
1386
  },
2531
1387
  },
2532
1388
  visible: true,
2533
1389
  },
1390
+ // ====== Layout & Dimensions ======
2534
1391
  {
2535
1392
  name: 'width',
2536
1393
  title: 'Width',
@@ -2551,6 +1408,26 @@ const AXPGaugeChartWidget = {
2551
1408
  },
2552
1409
  visible: true,
2553
1410
  },
1411
+ {
1412
+ name: 'height',
1413
+ title: 'Height',
1414
+ group: AXP_STYLING_PROPERTY_GROUP,
1415
+ schema: {
1416
+ defaultValue: 300,
1417
+ dataType: 'number',
1418
+ interface: {
1419
+ name: 'height',
1420
+ path: 'options.height',
1421
+ type: AXPWidgetsCatalog.number,
1422
+ options: {
1423
+ placeholder: '1-800',
1424
+ minValue: 1,
1425
+ maxValue: 800,
1426
+ },
1427
+ },
1428
+ },
1429
+ visible: true,
1430
+ },
2554
1431
  // ====== Gauge Configuration ======
2555
1432
  {
2556
1433
  name: 'minValue',
@@ -2639,13 +1516,64 @@ const AXPGaugeChartWidget = {
2639
1516
  },
2640
1517
  visible: true,
2641
1518
  },
2642
- ],
2643
- components: {
2644
- view: {
2645
- component: () => Promise.resolve().then(function () { return gaugeChartWidget_component; }).then((c) => c.AXPGaugeChartWidgetViewComponent),
2646
- },
2647
- },
2648
- meta: {
1519
+ // ====== Animation Settings ======
1520
+ {
1521
+ name: 'animationEasing',
1522
+ title: 'Animation Easing',
1523
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1524
+ schema: {
1525
+ defaultValue: 'cubic-out',
1526
+ dataType: 'string',
1527
+ interface: {
1528
+ name: 'animationEasing',
1529
+ path: 'options.animationEasing',
1530
+ type: AXPWidgetsCatalog.select,
1531
+ options: {
1532
+ dataSource: [
1533
+ { value: 'linear', text: 'Linear' },
1534
+ { value: 'ease', text: 'Ease' },
1535
+ { value: 'ease-in', text: 'Ease In' },
1536
+ { value: 'ease-out', text: 'Ease Out' },
1537
+ { value: 'ease-in-out', text: 'Ease In Out' },
1538
+ { value: 'cubic', text: 'Cubic' },
1539
+ { value: 'cubic-in', text: 'Cubic In' },
1540
+ { value: 'cubic-out', text: 'Cubic Out' },
1541
+ { value: 'cubic-in-out', text: 'Cubic In Out' },
1542
+ ],
1543
+ textField: 'text',
1544
+ valueField: 'value',
1545
+ },
1546
+ },
1547
+ },
1548
+ visible: true,
1549
+ },
1550
+ {
1551
+ name: 'animationDuration',
1552
+ title: 'Animation Duration',
1553
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1554
+ schema: {
1555
+ defaultValue: 800,
1556
+ dataType: 'number',
1557
+ interface: {
1558
+ name: 'animationDuration',
1559
+ path: 'options.animationDuration',
1560
+ type: AXPWidgetsCatalog.number,
1561
+ options: {
1562
+ placeholder: '0-2000',
1563
+ minValue: 0,
1564
+ maxValue: 2000,
1565
+ },
1566
+ },
1567
+ },
1568
+ visible: true,
1569
+ },
1570
+ ],
1571
+ components: {
1572
+ view: {
1573
+ component: () => Promise.resolve().then(function () { return gaugeChartWidget_component; }).then((c) => c.AXPGaugeChartWidgetViewComponent),
1574
+ },
1575
+ },
1576
+ meta: {
2649
1577
  dimensions: {
2650
1578
  width: 3,
2651
1579
  height: 4,
@@ -2661,399 +1589,21 @@ const AXPGaugeChartWidget = {
2661
1589
  * Line Chart Widget Component
2662
1590
  * Renders data as lines with interactive hover effects and animations
2663
1591
  */
2664
- class AXPLineChartWidgetViewComponent extends AXPChartBaseComponent {
1592
+ class AXPLineChartWidgetViewComponent extends AXPValueWidgetComponent {
2665
1593
  constructor() {
2666
1594
  super(...arguments);
2667
- this.pointClick = output();
2668
- // Chart container reference
2669
- this.chartContainerEl = viewChild.required('chartContainer');
2670
- this.margin = { top: 20, right: 20, bottom: 30, left: 40 };
2671
- // Tooltip state
2672
- this._tooltipVisible = signal(false);
2673
- this._tooltipPosition = signal({ x: 0, y: 0 });
2674
- this._tooltipData = signal({
2675
- title: '',
2676
- value: '0',
2677
- percentage: '0%',
2678
- color: '',
2679
- });
2680
- // Tooltip accessors
2681
- this.tooltipVisible = computed(() => this._tooltipVisible());
2682
- this.tooltipPosition = computed(() => this._tooltipPosition());
2683
- this.tooltipData = computed(() => this._tooltipData());
2684
- // Line appearance options
2685
- this.lineWidth = computed(() => this.options()['lineWidth'] ?? 2);
2686
- this.showPoints = computed(() => this.options()['showPoints'] !== false);
2687
- this.pointRadius = computed(() => this.options()['pointRadius'] ?? 4);
2688
- this.smoothLine = computed(() => this.options()['smoothLine'] !== false);
2689
- this.fillArea = computed(() => this.options()['fillArea'] === true);
2690
- this.fillOpacity = computed(() => (this.options()['fillOpacity'] ?? 20) / 100);
1595
+ this.lineChartData = computed(() => this.getValue());
1596
+ this.lineChartOptions = computed(() => this.options());
2691
1597
  }
2692
- // Chart lifecycle methods
2693
- /**
2694
- * Creates the line chart SVG and renders all elements
2695
- */
2696
- createChart() {
2697
- if (!this.d3 || !this.chartContainerEl()?.nativeElement)
2698
- return;
2699
- const containerElement = this.chartContainerEl().nativeElement;
2700
- let data = this.chartData() || [];
2701
- // Clear existing chart
2702
- this.d3.select(containerElement).selectAll('svg').remove();
2703
- // Normalize data structure to array of arrays (multi-series format)
2704
- let normalizedData = [];
2705
- // Handle both flat array and array of arrays formats
2706
- if (data.length > 0) {
2707
- if (Array.isArray(data[0])) {
2708
- // Already in multi-series format
2709
- normalizedData = data;
2710
- }
2711
- else {
2712
- // Single series or flat array with seriesName
2713
- const dataPoints = data;
2714
- // Check if this is multi-series data (has seriesName property)
2715
- const hasSeriesNames = dataPoints.some((d) => d.seriesName !== undefined);
2716
- if (hasSeriesNames) {
2717
- // Organize by series name
2718
- const seriesMap = new Map();
2719
- dataPoints.forEach((d) => {
2720
- const seriesName = d.seriesName || 'default';
2721
- if (!seriesMap.has(seriesName)) {
2722
- seriesMap.set(seriesName, []);
2723
- }
2724
- seriesMap.get(seriesName).push(d);
2725
- });
2726
- // Convert to array of arrays
2727
- normalizedData = Array.from(seriesMap.values());
2728
- }
2729
- else {
2730
- // Single series, wrap it in an array
2731
- normalizedData = [dataPoints];
2732
- }
2733
- }
2734
- }
2735
- // Early return if no data
2736
- if (normalizedData.length === 0 || normalizedData.flat().length === 0) {
2737
- this.showNoDataMessage(containerElement);
2738
- return;
2739
- }
2740
- // Get options and setup dimensions
2741
- const options = this.options();
2742
- this.setupDimensions(containerElement, options);
2743
- // Flatten data for scale calculation
2744
- const flatData = normalizedData.flat();
2745
- // Create scales with the flattened data
2746
- this.setupScales(flatData);
2747
- this.createAxes(options);
2748
- // Render the lines using the structured data (array of arrays)
2749
- this.renderLines(normalizedData);
2750
- }
2751
- updateChart() {
2752
- this.createChart();
2753
- }
2754
- cleanupChart() {
2755
- if (this.svg) {
2756
- this.d3.select(this.chartContainerEl()?.nativeElement).selectAll('svg').remove();
2757
- this.svg = null;
2758
- this.chart = null;
2759
- }
2760
- this._tooltipVisible.set(false);
2761
- }
2762
- // Private chart creation methods
2763
- /**
2764
- * Sets up chart dimensions and creates SVG with responsive attributes
2765
- */
2766
- setupDimensions(containerElement, options) {
2767
- // Get container dimensions
2768
- const containerWidth = containerElement.clientWidth;
2769
- const containerHeight = containerElement.clientHeight;
2770
- // If options specify width and height, use those, otherwise default to container size
2771
- const minDim = Math.min(200, containerWidth, containerHeight); // Ensure reasonable minimum
2772
- if (options.width && options.height) {
2773
- // Explicit dimensions provided
2774
- this.width = options.width - this.margin.left - this.margin.right;
2775
- this.height = options.height - this.margin.top - this.margin.bottom;
2776
- }
2777
- else {
2778
- // Responsive dimensions
2779
- this.width = Math.max(containerWidth, minDim) - this.margin.left - this.margin.right;
2780
- this.height = Math.max(containerHeight, minDim) - this.margin.top - this.margin.bottom;
2781
- }
2782
- // Create responsive SVG that scales with its container
2783
- const svg = this.d3
2784
- .select(containerElement)
2785
- .append('svg')
2786
- .attr('width', '100%')
2787
- .attr('height', '100%')
2788
- .attr('viewBox', `0 0 ${this.width + this.margin.left + this.margin.right} ${this.height + this.margin.top + this.margin.bottom}`)
2789
- .attr('preserveAspectRatio', 'xMidYMid meet');
2790
- this.svg = svg;
2791
- // Create chart group with margins
2792
- this.chart = this.svg.append('g').attr('transform', `translate(${this.margin.left},${this.margin.top})`);
2793
- }
2794
- /**
2795
- * Creates x and y scales for the chart
2796
- */
2797
- setupScales(data) {
2798
- // Determine x-axis type based on data
2799
- const allNumericX = data.every((d) => typeof d.xValue === 'number');
2800
- const allDates = data.every((d) => !isNaN(new Date(d.xValue).getTime()));
2801
- // Create appropriate x scale based on data type
2802
- if (allNumericX) {
2803
- // Numeric x-axis
2804
- this.xScale = this.d3
2805
- .scaleLinear()
2806
- .domain([
2807
- this.d3.min(data, (d) => d.xValue) || 0,
2808
- this.d3.max(data, (d) => d.xValue) || 0,
2809
- ])
2810
- .range([0, this.width]);
2811
- }
2812
- else if (allDates) {
2813
- // Date x-axis
2814
- this.xScale = this.d3
2815
- .scaleTime()
2816
- .domain([
2817
- this.d3.min(data, (d) => new Date(d.xValue)) || new Date(),
2818
- this.d3.max(data, (d) => new Date(d.xValue)) || new Date(),
2819
- ])
2820
- .range([0, this.width]);
2821
- }
2822
- else {
2823
- // Categorical x-axis
2824
- this.xScale = this.d3
2825
- .scaleBand()
2826
- .domain(data.map((d) => d.xValue.toString()))
2827
- .range([0, this.width])
2828
- .padding(0.1);
2829
- }
2830
- // Create y scale (linear scale for values)
2831
- this.yScale = this.d3
2832
- .scaleLinear()
2833
- .domain([0, this.d3.max(data, (d) => d.value) || 0])
2834
- .nice()
2835
- .range([this.height, 0]);
2836
- }
2837
- /**
2838
- * Creates x and y axes with grid lines
2839
- */
2840
- createAxes(options) {
2841
- // Only create axes if they are enabled in options
2842
- const showXAxis = options.showXAxis !== false;
2843
- const showYAxis = options.showYAxis !== false;
2844
- const showGrid = options.showGrid !== false;
2845
- if (showXAxis) {
2846
- // Create X axis
2847
- this.xAxis = this.chart
2848
- .append('g')
2849
- .attr('class', 'axp-line-chart-axis-x')
2850
- .attr('transform', `translate(0,${this.height})`)
2851
- .call(this.d3.axisBottom(this.xScale));
2852
- }
2853
- if (showYAxis) {
2854
- // Create Y axis
2855
- this.yAxis = this.chart.append('g').attr('class', 'axp-line-chart-axis-y').call(this.d3.axisLeft(this.yScale));
2856
- }
2857
- if (showGrid) {
2858
- // Add horizontal grid lines
2859
- this.chart
2860
- .append('g')
2861
- .attr('class', 'axp-line-chart-grid')
2862
- .call(this.d3
2863
- .axisLeft(this.yScale)
2864
- .tickSize(-this.width)
2865
- .tickFormat(() => ''))
2866
- .selectAll('.tick')
2867
- .style('color', 'rgb(153 153 153 / 30%)'); // Add gray color to ticks
2868
- }
2869
- }
2870
- /**
2871
- * Renders the lines with animations
2872
- */
2873
- renderLines(data) {
2874
- // Get line options
2875
- const lineWidth = this.lineWidth();
2876
- const useSmooth = this.smoothLine();
2877
- const shouldFill = this.fillArea();
2878
- const fillOpacity = this.fillOpacity();
2879
- // Create line generator
2880
- const getX = (d) => {
2881
- // Handle different x scale types
2882
- if (this.xScale.bandwidth) {
2883
- // band scale for categorical
2884
- return this.xScale(d.xValue.toString()) + this.xScale.bandwidth() / 2;
2885
- }
2886
- else {
2887
- // linear or time scale
2888
- return this.xScale(d.xValue);
2889
- }
2890
- };
2891
- // Define line generator function
2892
- const lineGenerator = useSmooth
2893
- ? this.d3
2894
- .line()
2895
- .x(getX)
2896
- .y((d) => this.yScale(d.value))
2897
- .curve(this.d3.curveMonotoneX) // Smooth curve
2898
- : this.d3
2899
- .line()
2900
- .x(getX)
2901
- .y((d) => this.yScale(d.value))
2902
- .curve(this.d3.curveLinear); // Straight lines
2903
- // Define area generator if we should fill
2904
- const areaGenerator = useSmooth
2905
- ? this.d3
2906
- .area()
2907
- .x(getX)
2908
- .y0(this.height)
2909
- .y1((d) => this.yScale(d.value))
2910
- .curve(this.d3.curveMonotoneX)
2911
- : this.d3
2912
- .area()
2913
- .x(getX)
2914
- .y0(this.height)
2915
- .y1((d) => this.yScale(d.value))
2916
- .curve(this.d3.curveLinear);
2917
- // Render each series
2918
- data.forEach((seriesData, seriesIndex) => {
2919
- // Skip empty series
2920
- if (!seriesData.length)
2921
- return;
2922
- // Sort data within series by x value
2923
- seriesData.sort((a, b) => {
2924
- if (typeof a.xValue === 'number' && typeof b.xValue === 'number') {
2925
- return a.xValue - b.xValue;
2926
- }
2927
- else {
2928
- return a.xValue.toString().localeCompare(b.xValue.toString());
2929
- }
2930
- });
2931
- // Get series name and color
2932
- const seriesName = seriesData[0].seriesName || `Series ${seriesIndex + 1}`;
2933
- // Get color for this series - prefer the color from data point, otherwise use palette
2934
- const seriesColor = seriesData[0]?.color || AXPChartColors.getColor(seriesIndex);
2935
- // Draw the area if fill is enabled
2936
- if (shouldFill) {
2937
- this.chart
2938
- .append('path')
2939
- .datum(seriesData)
2940
- .attr('class', 'axp-line-chart-area')
2941
- .attr('fill', seriesColor)
2942
- .attr('fill-opacity', fillOpacity)
2943
- .attr('d', areaGenerator);
2944
- }
2945
- // Draw the line with animation
2946
- const path = this.chart
2947
- .append('path')
2948
- .datum(seriesData)
2949
- .attr('class', 'axp-line-chart-line')
2950
- .attr('stroke', seriesColor)
2951
- .attr('stroke-width', lineWidth)
2952
- .attr('fill', 'none') // Ensure no fill on the line
2953
- .attr('d', lineGenerator);
2954
- // Animate the line drawing
2955
- const pathLength = path.node().getTotalLength();
2956
- path
2957
- .attr('stroke-dasharray', pathLength)
2958
- .attr('stroke-dashoffset', pathLength)
2959
- .transition()
2960
- .duration(1000)
2961
- .attr('stroke-dashoffset', 0)
2962
- .ease(this.d3.easeQuadOut);
2963
- // Add data points if enabled
2964
- if (this.showPoints()) {
2965
- this.chart
2966
- .selectAll(`.axp-line-chart-point-${seriesIndex}`)
2967
- .data(seriesData)
2968
- .enter()
2969
- .append('circle')
2970
- .attr('class', `axp-line-chart-point axp-line-chart-point-${seriesIndex}`)
2971
- .attr('cx', (d) => getX(d))
2972
- .attr('cy', (d) => this.yScale(d.value))
2973
- .attr('r', 0) // Start with radius 0 for animation
2974
- .attr('fill', seriesColor)
2975
- .attr('stroke', 'white')
2976
- .attr('stroke-width', 1)
2977
- .on('mouseenter', (event, d) => this.handlePointHover(event, d, seriesName))
2978
- .on('mousemove', (event) => this.updateTooltipPosition(event))
2979
- .on('mouseleave', () => this._tooltipVisible.set(false))
2980
- .on('click', (event, d) => this.handlePointClick(event, d))
2981
- .transition()
2982
- .delay((d, i) => i * 50 + 300) // Stagger with delay after line animation
2983
- .duration(300)
2984
- .attr('r', this.pointRadius())
2985
- .ease(this.d3.easeBackOut); // Bouncy animation
2986
- }
2987
- });
2988
- }
2989
- // Event handlers
2990
- /**
2991
- * Handles point hover event and shows tooltip
2992
- */
2993
- handlePointHover(event, datum, seriesName) {
2994
- if (this.options().showTooltip !== false) {
2995
- const data = this.chartData();
2996
- let index = 0;
2997
- // Find index based on data structure
2998
- if (Array.isArray(data)) {
2999
- if (Array.isArray(data[0])) {
3000
- // Multi-series data (array of arrays)
3001
- const flatData = data.flat();
3002
- index = flatData.findIndex((item) => item.id === datum.id);
3003
- }
3004
- else {
3005
- // Single series (array of data points)
3006
- index = data.findIndex((item) => item.id === datum.id);
3007
- }
3008
- }
3009
- const color = datum.color || AXPChartColors.getColor(index);
3010
- // Update tooltip data
3011
- this._tooltipData.set({
3012
- title: datum.label || seriesName,
3013
- value: datum.value.toString(),
3014
- percentage: '', // Not showing percentage for line charts
3015
- color,
3016
- });
3017
- // Position tooltip near the point
3018
- this.updateTooltipPosition(event);
3019
- this._tooltipVisible.set(true);
3020
- }
3021
- }
3022
- /**
3023
- * Updates tooltip position based on mouse coordinates
3024
- */
3025
- updateTooltipPosition(event) {
3026
- const rect = event.target.getBoundingClientRect();
3027
- const containerRect = this.chartContainerEl().nativeElement.getBoundingClientRect();
3028
- // Position relative to the container
3029
- const x = event.clientX - containerRect.left;
3030
- const y = event.clientY - containerRect.top;
3031
- this._tooltipPosition.set({ x, y });
3032
- }
3033
- /**
3034
- * Handles point click event
3035
- */
3036
- handlePointClick(event, datum) {
3037
- // Emit click event with the data point
3038
- this.pointClick.emit(datum);
3039
- }
3040
- /**
3041
- * Shows a message when no data is available
3042
- */
3043
- showNoDataMessage(containerElement) {
3044
- const noDataDiv = this.d3.select(containerElement).append('div').attr('class', 'axp-line-chart-no-data-message');
3045
- noDataDiv
3046
- .append('div')
3047
- .attr('class', 'axp-line-chart-no-data-icon')
3048
- .html('<i class="fa-light fa-chart-line fa-3x"></i>');
3049
- noDataDiv.append('div').attr('class', 'axp-line-chart-no-data-text').text('No data available');
1598
+ handleLineChartPointClick(event) {
1599
+ //console.log(event);
3050
1600
  }
3051
1601
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPLineChartWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3052
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.0.3", type: AXPLineChartWidgetViewComponent, isStandalone: true, selector: "ng-component", outputs: { pointClick: "pointClick" }, viewQueries: [{ propertyName: "chartContainerEl", first: true, predicate: ["chartContainer"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"axp-line-chart\" #chartContainer>\n <!-- Shared tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"false\"\n ></ax-chart-tooltip>\n</div>\n", styles: [":host{display:block;width:100%;height:100%;min-height:200px}.axp-line-chart{width:100%;height:100%;position:relative;display:flex;align-items:center;justify-content:center;border-radius:.5rem;overflow:hidden}.axp-line-chart svg{width:100%;height:100%;max-width:100%;max-height:100%;overflow:visible}.axp-line-chart-line{fill:none;stroke-width:2px;stroke-linejoin:round;stroke-linecap:round;transition:stroke-width .3s ease}.axp-line-chart-line:hover{stroke-width:3px}.axp-line-chart-area{opacity:.2;transition:opacity .3s ease}.axp-line-chart-area:hover{opacity:.3}.axp-line-chart-point{cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.axp-line-chart-point:hover{r:6;stroke-width:2;stroke:var(--ax-background-color, #fff)}.axp-line-chart-axis-x path,.axp-line-chart-axis-y path{stroke:var(--ax-border-color, #e0e0e0)}.axp-line-chart-axis-x line,.axp-line-chart-axis-y line,.axp-line-chart-grid line{stroke:var(--ax-border-color, #e0e0e0);stroke-dasharray:2,2;stroke-opacity:.5}.axp-line-chart-grid path{stroke-width:0}.axp-line-chart-axis-x text,.axp-line-chart-axis-y text{fill:var(--ax-text-muted, #666);font-size:clamp(8px,2vmin,12px)}.axp-line-chart-no-data-message{font-family:var(--ax-font-family, system-ui, sans-serif);display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:1rem;width:100%;height:100%}.axp-line-chart-no-data-icon{margin-bottom:.75rem;color:var(--ax-text-muted, #999)}.axp-line-chart-no-data-text{font-weight:600;color:var(--ax-text-color, #333)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXPChartTooltipComponent, selector: "ax-chart-tooltip", inputs: ["data", "position", "visible", "showPercentage", "style"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1602
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: AXPLineChartWidgetViewComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: "<ax-line-chart\n (pointClick)=\"handleLineChartPointClick($event)\"\n [data]=\"lineChartData()\"\n [options]=\"lineChartOptions()\"\n></ax-line-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"], dependencies: [{ kind: "component", type: AXLineChartComponent, selector: "ax-line-chart", inputs: ["data", "options"], outputs: ["pointClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3053
1603
  }
3054
1604
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPLineChartWidgetViewComponent, decorators: [{
3055
1605
  type: Component,
3056
- args: [{ standalone: true, imports: [CommonModule, AXPChartTooltipComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"axp-line-chart\" #chartContainer>\n <!-- Shared tooltip component -->\n <ax-chart-tooltip\n [visible]=\"tooltipVisible()\"\n [position]=\"tooltipPosition()\"\n [data]=\"tooltipData()\"\n [showPercentage]=\"false\"\n ></ax-chart-tooltip>\n</div>\n", styles: [":host{display:block;width:100%;height:100%;min-height:200px}.axp-line-chart{width:100%;height:100%;position:relative;display:flex;align-items:center;justify-content:center;border-radius:.5rem;overflow:hidden}.axp-line-chart svg{width:100%;height:100%;max-width:100%;max-height:100%;overflow:visible}.axp-line-chart-line{fill:none;stroke-width:2px;stroke-linejoin:round;stroke-linecap:round;transition:stroke-width .3s ease}.axp-line-chart-line:hover{stroke-width:3px}.axp-line-chart-area{opacity:.2;transition:opacity .3s ease}.axp-line-chart-area:hover{opacity:.3}.axp-line-chart-point{cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1)}.axp-line-chart-point:hover{r:6;stroke-width:2;stroke:var(--ax-background-color, #fff)}.axp-line-chart-axis-x path,.axp-line-chart-axis-y path{stroke:var(--ax-border-color, #e0e0e0)}.axp-line-chart-axis-x line,.axp-line-chart-axis-y line,.axp-line-chart-grid line{stroke:var(--ax-border-color, #e0e0e0);stroke-dasharray:2,2;stroke-opacity:.5}.axp-line-chart-grid path{stroke-width:0}.axp-line-chart-axis-x text,.axp-line-chart-axis-y text{fill:var(--ax-text-muted, #666);font-size:clamp(8px,2vmin,12px)}.axp-line-chart-no-data-message{font-family:var(--ax-font-family, system-ui, sans-serif);display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:1rem;width:100%;height:100%}.axp-line-chart-no-data-icon{margin-bottom:.75rem;color:var(--ax-text-muted, #999)}.axp-line-chart-no-data-text{font-weight:600;color:var(--ax-text-color, #333)}\n"] }]
1606
+ args: [{ standalone: true, imports: [AXLineChartComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ax-line-chart\n (pointClick)=\"handleLineChartPointClick($event)\"\n [data]=\"lineChartData()\"\n [options]=\"lineChartOptions()\"\n></ax-line-chart>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
3057
1607
  }] });
3058
1608
 
3059
1609
  var lineChartWidget_component = /*#__PURE__*/Object.freeze({
@@ -3069,26 +1619,28 @@ const AXPLineChartWidget = {
3069
1619
  type: 'dashboard',
3070
1620
  icon: 'fa-light fa-chart-line',
3071
1621
  properties: [
3072
- // ====== Layout & Dimensions ======
1622
+ cloneProperty(AXP_NAME_PROPERTY, { visible: false }),
1623
+ cloneProperty(AXP_DATA_PATH_PROPERTY, { visible: false }),
1624
+ // ====== Chart Title ======
3073
1625
  {
3074
- name: 'height',
3075
- title: 'Height',
3076
- group: AXP_STYLING_PROPERTY_GROUP,
1626
+ name: 'title',
1627
+ title: 'Chart Title',
1628
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
3077
1629
  schema: {
3078
- defaultValue: 300,
3079
- dataType: 'number',
1630
+ defaultValue: '',
1631
+ dataType: 'string',
3080
1632
  interface: {
3081
- name: 'height',
3082
- path: 'options.height',
3083
- type: AXPWidgetsCatalog.number,
1633
+ name: 'title',
1634
+ path: 'options.title',
1635
+ type: AXPWidgetsCatalog.text,
3084
1636
  options: {
3085
- minValue: 0,
3086
- maxValue: 800,
1637
+ placeholder: 'Enter chart title',
3087
1638
  },
3088
1639
  },
3089
1640
  },
3090
1641
  visible: true,
3091
1642
  },
1643
+ // ====== Layout & Dimensions ======
3092
1644
  {
3093
1645
  name: 'width',
3094
1646
  title: 'Width',
@@ -3108,6 +1660,25 @@ const AXPLineChartWidget = {
3108
1660
  },
3109
1661
  visible: true,
3110
1662
  },
1663
+ {
1664
+ name: 'height',
1665
+ title: 'Height',
1666
+ group: AXP_STYLING_PROPERTY_GROUP,
1667
+ schema: {
1668
+ defaultValue: 300,
1669
+ dataType: 'number',
1670
+ interface: {
1671
+ name: 'height',
1672
+ path: 'options.height',
1673
+ type: AXPWidgetsCatalog.number,
1674
+ options: {
1675
+ minValue: 0,
1676
+ maxValue: 800,
1677
+ },
1678
+ },
1679
+ },
1680
+ visible: true,
1681
+ },
3111
1682
  // ====== Axis Settings ======
3112
1683
  {
3113
1684
  name: 'showXAxis',
@@ -3124,6 +1695,21 @@ const AXPLineChartWidget = {
3124
1695
  },
3125
1696
  visible: true,
3126
1697
  },
1698
+ {
1699
+ name: 'xAxisLabel',
1700
+ title: 'X Axis Label',
1701
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1702
+ schema: {
1703
+ defaultValue: '',
1704
+ dataType: 'string',
1705
+ interface: {
1706
+ name: 'xAxisLabel',
1707
+ path: 'options.xAxisLabel',
1708
+ type: AXPWidgetsCatalog.text,
1709
+ },
1710
+ },
1711
+ visible: true,
1712
+ },
3127
1713
  {
3128
1714
  name: 'showYAxis',
3129
1715
  title: 'Show Y Axis',
@@ -3140,82 +1726,95 @@ const AXPLineChartWidget = {
3140
1726
  visible: true,
3141
1727
  },
3142
1728
  {
3143
- name: 'showGrid',
3144
- title: 'Show Grid Lines',
1729
+ name: 'yAxisLabel',
1730
+ title: 'Y Axis Label',
3145
1731
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3146
1732
  schema: {
3147
- defaultValue: true,
3148
- dataType: 'boolean',
1733
+ defaultValue: '',
1734
+ dataType: 'string',
3149
1735
  interface: {
3150
- name: 'showGrid',
3151
- path: 'options.showGrid',
3152
- type: AXPWidgetsCatalog.toggle,
1736
+ name: 'yAxisLabel',
1737
+ path: 'options.yAxisLabel',
1738
+ type: AXPWidgetsCatalog.text,
3153
1739
  },
3154
1740
  },
3155
1741
  visible: true,
3156
1742
  },
3157
- // ====== Tooltip Settings ======
3158
1743
  {
3159
- name: 'showTooltip',
3160
- title: 'Show Tooltip',
1744
+ name: 'yAxisStartsAtZero',
1745
+ title: 'Y Axis Starts At Zero',
3161
1746
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3162
1747
  schema: {
3163
1748
  defaultValue: true,
3164
1749
  dataType: 'boolean',
3165
1750
  interface: {
3166
- name: 'showTooltip',
3167
- path: 'options.showTooltip',
1751
+ name: 'yAxisStartsAtZero',
1752
+ path: 'options.yAxisStartsAtZero',
3168
1753
  type: AXPWidgetsCatalog.toggle,
3169
1754
  },
3170
1755
  },
3171
1756
  visible: true,
3172
1757
  },
3173
- // ====== Line Appearance ======
3174
1758
  {
3175
- name: 'lineWidth',
3176
- title: 'Line Width',
1759
+ name: 'axisPadding',
1760
+ title: 'Axis Padding',
3177
1761
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3178
1762
  schema: {
3179
- defaultValue: 2,
1763
+ defaultValue: 5,
3180
1764
  dataType: 'number',
3181
1765
  interface: {
3182
- name: 'lineWidth',
3183
- path: 'options.lineWidth',
1766
+ name: 'axisPadding',
1767
+ path: 'options.axisPadding',
3184
1768
  type: AXPWidgetsCatalog.number,
3185
1769
  options: {
3186
- placeholder: '1-10',
3187
- minValue: 1,
3188
- maxValue: 10,
1770
+ minValue: 0,
1771
+ maxValue: 50,
3189
1772
  },
3190
1773
  },
3191
1774
  },
3192
1775
  visible: true,
3193
1776
  },
3194
1777
  {
3195
- name: 'showPoints',
3196
- title: 'Show Points',
1778
+ name: 'showGrid',
1779
+ title: 'Show Grid Lines',
3197
1780
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3198
1781
  schema: {
3199
1782
  defaultValue: true,
3200
1783
  dataType: 'boolean',
3201
1784
  interface: {
3202
- name: 'showPoints',
3203
- path: 'options.showPoints',
1785
+ name: 'showGrid',
1786
+ path: 'options.showGrid',
3204
1787
  type: AXPWidgetsCatalog.toggle,
3205
1788
  },
3206
1789
  },
3207
1790
  visible: true,
3208
1791
  },
3209
1792
  {
3210
- name: 'pointRadius',
3211
- title: 'Point Size',
1793
+ name: 'showVerticalGrid',
1794
+ title: 'Show Vertical Grid',
3212
1795
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3213
1796
  schema: {
3214
- defaultValue: 4,
1797
+ defaultValue: true,
1798
+ dataType: 'boolean',
1799
+ interface: {
1800
+ name: 'showVerticalGrid',
1801
+ path: 'options.showVerticalGrid',
1802
+ type: AXPWidgetsCatalog.toggle,
1803
+ },
1804
+ },
1805
+ visible: true,
1806
+ },
1807
+ // ====== Line Appearance ======
1808
+ {
1809
+ name: 'lineWidth',
1810
+ title: 'Line Width',
1811
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1812
+ schema: {
1813
+ defaultValue: 2,
3215
1814
  dataType: 'number',
3216
1815
  interface: {
3217
- name: 'pointRadius',
3218
- path: 'options.pointRadius',
1816
+ name: 'lineWidth',
1817
+ path: 'options.lineWidth',
3219
1818
  type: AXPWidgetsCatalog.number,
3220
1819
  options: {
3221
1820
  placeholder: '1-10',
@@ -3242,287 +1841,170 @@ const AXPLineChartWidget = {
3242
1841
  visible: true,
3243
1842
  },
3244
1843
  {
3245
- name: 'fillArea',
3246
- title: 'Fill Area',
1844
+ name: 'showPoints',
1845
+ title: 'Show Points',
3247
1846
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3248
1847
  schema: {
3249
- defaultValue: false,
1848
+ defaultValue: true,
3250
1849
  dataType: 'boolean',
3251
1850
  interface: {
3252
- name: 'fillArea',
3253
- path: 'options.fillArea',
1851
+ name: 'showPoints',
1852
+ path: 'options.showPoints',
3254
1853
  type: AXPWidgetsCatalog.toggle,
3255
1854
  },
3256
1855
  },
3257
1856
  visible: true,
3258
1857
  },
3259
1858
  {
3260
- name: 'fillOpacity',
3261
- title: 'Fill Opacity',
1859
+ name: 'pointRadius',
1860
+ title: 'Point Size',
3262
1861
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3263
1862
  schema: {
3264
- defaultValue: 10,
1863
+ defaultValue: 4,
3265
1864
  dataType: 'number',
3266
1865
  interface: {
3267
- name: 'fillOpacity',
3268
- path: 'options.fillOpacity',
1866
+ name: 'pointRadius',
1867
+ path: 'options.pointRadius',
3269
1868
  type: AXPWidgetsCatalog.number,
3270
1869
  options: {
3271
- placeholder: '0-100',
3272
- minValue: 0,
3273
- maxValue: 100,
1870
+ placeholder: '1-10',
1871
+ minValue: 1,
1872
+ maxValue: 10,
3274
1873
  },
3275
1874
  },
3276
1875
  },
3277
1876
  visible: true,
3278
1877
  },
3279
- ],
3280
- components: {
3281
- view: {
3282
- component: () => Promise.resolve().then(function () { return lineChartWidget_component; }).then((c) => c.AXPLineChartWidgetViewComponent),
3283
- },
3284
- },
3285
- meta: {
3286
- dimensions: {
3287
- width: 5,
3288
- height: 6,
3289
- minWidth: 2,
3290
- minHeight: 2,
3291
- maxWidth: 6,
3292
- maxHeight: 7,
3293
- },
3294
- },
3295
- };
3296
-
3297
- /**
3298
- * Notification Widget Component
3299
- * Displays notifications in a card with tabs
3300
- */
3301
- class AXPNotificationWidgetViewComponent extends AXPValueWidgetComponent {
3302
- constructor() {
3303
- super(...arguments);
3304
- // Outputs
3305
- this.notificationClick = output();
3306
- this.markAsRead = output();
3307
- // Dependencies
3308
- this.cdr = inject(ChangeDetectorRef);
3309
- this.datePipe = inject(DatePipe);
3310
- // State
3311
- this.activeTab = signal('new');
3312
- // Configuration
3313
- this.maxItems = computed(() => this.options()?.maxItems ?? 10);
3314
- this.showAvatar = computed(() => this.options()?.showAvatar ?? true);
3315
- this.showDate = computed(() => this.options()?.showDate ?? true);
3316
- // Computed data
3317
- this.notificationItems = computed(() => {
3318
- const value = this.getValue();
3319
- if (!value?.data?.length)
3320
- return [];
3321
- // Filter by active tab
3322
- const filtered = this.activeTab() === 'new' ? value.data.filter((n) => !n.readAt) : value.data;
3323
- return filtered.slice(0, this.maxItems());
3324
- });
3325
- }
3326
- /**
3327
- * Get the count of new messages for the badge
3328
- */
3329
- getNewMessageCount() {
3330
- const value = this.getValue();
3331
- if (!value?.data?.length)
3332
- return 0;
3333
- return value.data.filter((n) => !n.readAt).length;
3334
- }
3335
- /**
3336
- * Handle tab change event from ax-tabs component
3337
- * @param index The index of the tab that was activated
3338
- */
3339
- handleTabChange(data) {
3340
- const index = data.index;
3341
- // Map index to tab name: 0 = 'new', 1 = 'all'
3342
- const tabName = index === 0 ? 'new' : 'all';
3343
- this.onTabChange(tabName);
3344
- }
3345
- /**
3346
- * Mark all notifications as read
3347
- */
3348
- markAllAsRead() {
3349
- const value = this.getValue();
3350
- if (!value?.data?.length)
3351
- return;
3352
- const now = new Date();
3353
- const updatedNotifications = value.data.map((n) => {
3354
- if (n.readAt)
3355
- return n;
3356
- return { ...n, readAt: now };
3357
- });
3358
- this.setValue({
3359
- ...value,
3360
- data: updatedNotifications,
3361
- });
3362
- this.cdr.detectChanges();
3363
- }
3364
- /**
3365
- * Change the active tab
3366
- */
3367
- onTabChange(tabName) {
3368
- this.activeTab.set(tabName);
3369
- this.cdr.detectChanges();
3370
- }
3371
- /**
3372
- * Handle notification click event
3373
- */
3374
- onNotificationClick(notification) {
3375
- this.markAsReadIfNeeded(notification);
3376
- this.notificationClick.emit(notification);
3377
- }
3378
- /**
3379
- * Format the timestamp in a user-friendly way
3380
- */
3381
- formatTime(date) {
3382
- if (!date)
3383
- return '';
3384
- const dateObj = typeof date === 'string' ? new Date(date) : date;
3385
- const diffDays = this.getDaysDifference(dateObj);
3386
- // Format based on how recent the date is
3387
- if (diffDays === 0)
3388
- return this.datePipe.transform(dateObj, 'h:mm a') || ''; // Today
3389
- if (diffDays === 1)
3390
- return 'Yesterday';
3391
- if (diffDays < 7)
3392
- return this.datePipe.transform(dateObj, 'EEE') || ''; // Day of week
3393
- return this.datePipe.transform(dateObj, 'MM/dd/yyyy') || ''; // Older date
3394
- }
3395
- /**
3396
- * Mark notification as read if needed
3397
- */
3398
- markAsReadIfNeeded(notification) {
3399
- // Only mark as read if not already read
3400
- if (notification.readAt)
3401
- return;
3402
- const updatedNotification = {
3403
- ...notification,
3404
- readAt: new Date(),
3405
- };
3406
- // Update the model
3407
- const value = this.getValue();
3408
- if (!value?.data)
3409
- return;
3410
- const updatedNotifications = value.data.map((n) => (n.id === notification.id ? updatedNotification : n));
3411
- this.setValue({
3412
- ...value,
3413
- data: updatedNotifications,
3414
- });
3415
- // Notify about the change
3416
- this.markAsRead.emit(updatedNotification);
3417
- }
3418
- /**
3419
- * Calculate days difference from now
3420
- */
3421
- getDaysDifference(date) {
3422
- const now = new Date();
3423
- const diffMs = now.getTime() - date.getTime();
3424
- return Math.floor(diffMs / (1000 * 60 * 60 * 24));
3425
- }
3426
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPNotificationWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3427
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXPNotificationWidgetViewComponent, isStandalone: true, selector: "ng-component", outputs: { notificationClick: "notificationClick", markAsRead: "markAsRead" }, providers: [DatePipe], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-p-4 ax-size-full\">\n <ax-tabs\n class=\"ax-bg-light-start ax-border-b ax-border-default\"\n [fitParent]=\"true\"\n location=\"bottom\"\n (onActiveTabChanged)=\"handleTabChange($event)\"\n >\n <ax-tab-item [text]=\"('widget.notification.new' | translate | async) ?? 'New'\" class=\"ax-font-medium\">\n <ax-suffix>\n @if (getNewMessageCount() > 0) {\n <ax-badge color=\"primary\" [text]=\"getNewMessageCount().toString()\" size=\"sm\" class=\"ax-ml-1\"></ax-badge>\n }\n </ax-suffix>\n </ax-tab-item>\n <ax-tab-item [text]=\"('widget.notification.all' | translate | async) ?? 'All'\" class=\"ax-font-medium\"></ax-tab-item>\n </ax-tabs>\n <div class=\"ax-space-y-4 ax-mt-4 ax-px-2\">\n @for (item of notificationItems(); track item.id) {\n <ng-container [ngTemplateOutlet]=\"chatItemTemplateRef\" [ngTemplateOutletContext]=\"{ $implicit: item }\">\n </ng-container>\n } @empty {\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-bell-slash\"></i>\n </ax-icon>\n <p class=\"ax-text-center\">{{ 'widget.notification.noNotifications' | translate | async }}</p>\n </div>\n }\n </div>\n</div>\n\n<ng-template #chatItemTemplateRef let-data>\n <div class=\"ax-flex ax-gap-3\">\n @if(showAvatar()){\n <div class=\"ax-rounded-full ax-size-10\">\n <ax-avatar shape=\"rounded\" class=\"ax-shrink-0\" [size]=\"40\">\n @if(data.user?.image){\n <ax-image\n [src]=\"data.user.image\"\n [alt]=\"data.user?.name || ('widget.notification.user' | translate | async)\"\n ></ax-image>\n } @else {\n <ax-icon>\n <i class=\"fa-light fa-user\"></i>\n </ax-icon>\n }\n </ax-avatar>\n </div>\n }\n <div class=\"ax-overflow-hidden ax-grow ax-text-start\">\n <h6 class=\"ax-pb-2 ax-font-semibold ax-truncate\">{{ data.user?.name || data.title }}</h6>\n <p class=\"ax-text-xs ax-truncate\">{{ data.body }}</p>\n </div>\n @if(showDate()){\n <div class=\"ax-text-xs ax-shrink-0\">\n <span>\n {{ formatTime(data.createdAt) }}\n </span>\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;width:100%;height:100%}\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: "component", type: i2$2.AXTabsComponent, selector: "ax-tabs", inputs: ["look", "location", "fitParent", "minWidth", "content"], outputs: ["onActiveTabChanged"] }, { kind: "component", type: i2$2.AXTabItemComponent, selector: "ax-tab-item", inputs: ["disabled", "text", "key", "headerTemplate", "active"], outputs: ["disabledChange", "onClick", "onBlur", "onFocus", "activeChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$3.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: AXButtonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "component", type: i5.AXAvatarComponent, selector: "ax-avatar", inputs: ["color", "size", "shape", "look"], outputs: ["sizeChange"] }, { kind: "ngmodule", type: AXImageModule }, { kind: "component", type: i6.AXImageComponent, selector: "ax-image", inputs: ["width", "height", "overlayMode", "src", "alt", "priority", "lazy"], outputs: ["onLoad", "onError"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3428
- }
3429
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPNotificationWidgetViewComponent, decorators: [{
3430
- type: Component,
3431
- args: [{ standalone: true, imports: [
3432
- CommonModule,
3433
- AXTabsModule,
3434
- AXDecoratorModule,
3435
- AXButtonModule,
3436
- AXBadgeModule,
3437
- AXAvatarModule,
3438
- AXImageModule,
3439
- AXTranslationModule,
3440
- ], providers: [DatePipe], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ax-p-4 ax-size-full\">\n <ax-tabs\n class=\"ax-bg-light-start ax-border-b ax-border-default\"\n [fitParent]=\"true\"\n location=\"bottom\"\n (onActiveTabChanged)=\"handleTabChange($event)\"\n >\n <ax-tab-item [text]=\"('widget.notification.new' | translate | async) ?? 'New'\" class=\"ax-font-medium\">\n <ax-suffix>\n @if (getNewMessageCount() > 0) {\n <ax-badge color=\"primary\" [text]=\"getNewMessageCount().toString()\" size=\"sm\" class=\"ax-ml-1\"></ax-badge>\n }\n </ax-suffix>\n </ax-tab-item>\n <ax-tab-item [text]=\"('widget.notification.all' | translate | async) ?? 'All'\" class=\"ax-font-medium\"></ax-tab-item>\n </ax-tabs>\n <div class=\"ax-space-y-4 ax-mt-4 ax-px-2\">\n @for (item of notificationItems(); track item.id) {\n <ng-container [ngTemplateOutlet]=\"chatItemTemplateRef\" [ngTemplateOutletContext]=\"{ $implicit: item }\">\n </ng-container>\n } @empty {\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-bell-slash\"></i>\n </ax-icon>\n <p class=\"ax-text-center\">{{ 'widget.notification.noNotifications' | translate | async }}</p>\n </div>\n }\n </div>\n</div>\n\n<ng-template #chatItemTemplateRef let-data>\n <div class=\"ax-flex ax-gap-3\">\n @if(showAvatar()){\n <div class=\"ax-rounded-full ax-size-10\">\n <ax-avatar shape=\"rounded\" class=\"ax-shrink-0\" [size]=\"40\">\n @if(data.user?.image){\n <ax-image\n [src]=\"data.user.image\"\n [alt]=\"data.user?.name || ('widget.notification.user' | translate | async)\"\n ></ax-image>\n } @else {\n <ax-icon>\n <i class=\"fa-light fa-user\"></i>\n </ax-icon>\n }\n </ax-avatar>\n </div>\n }\n <div class=\"ax-overflow-hidden ax-grow ax-text-start\">\n <h6 class=\"ax-pb-2 ax-font-semibold ax-truncate\">{{ data.user?.name || data.title }}</h6>\n <p class=\"ax-text-xs ax-truncate\">{{ data.body }}</p>\n </div>\n @if(showDate()){\n <div class=\"ax-text-xs ax-shrink-0\">\n <span>\n {{ formatTime(data.createdAt) }}\n </span>\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;width:100%;height:100%}\n"] }]
3441
- }] });
3442
-
3443
- var notificationWidget_component = /*#__PURE__*/Object.freeze({
3444
- __proto__: null,
3445
- AXPNotificationWidgetViewComponent: AXPNotificationWidgetViewComponent
3446
- });
3447
-
3448
- /**
3449
- * Configuration for the Notification Widget
3450
- */
3451
- const AXPNotificationWidget = {
3452
- name: 'notification',
3453
- title: 'Notification Widget',
3454
- categories: [AXP_WIDGETS_UTILITY_CATEGORY],
3455
- groups: [AXPWidgetGroupEnum.DashboardWidget],
3456
- type: 'dashboard',
3457
- description: 'Displays notifications in a widget format',
3458
- icon: 'fa-regular fa-bell',
3459
- properties: [
3460
- cloneProperty(AXP_DATA_PATH_PROPERTY, { visible: false }),
3461
1878
  {
3462
- name: 'maxItems',
3463
- title: 'Max Items',
3464
- description: 'Maximum number of notification items to display',
3465
- group: AXP_STYLING_PROPERTY_GROUP,
1879
+ name: 'fillArea',
1880
+ title: 'Fill Area',
1881
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1882
+ schema: {
1883
+ defaultValue: false,
1884
+ dataType: 'boolean',
1885
+ interface: {
1886
+ name: 'fillArea',
1887
+ path: 'options.fillArea',
1888
+ type: AXPWidgetsCatalog.toggle,
1889
+ },
1890
+ },
1891
+ visible: true,
1892
+ },
1893
+ {
1894
+ name: 'fillOpacity',
1895
+ title: 'Fill Opacity',
1896
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
3466
1897
  schema: {
3467
1898
  defaultValue: 10,
3468
1899
  dataType: 'number',
3469
1900
  interface: {
3470
- name: 'maxItems',
3471
- path: 'options.maxItems',
1901
+ name: 'fillOpacity',
1902
+ path: 'options.fillOpacity',
3472
1903
  type: AXPWidgetsCatalog.number,
3473
1904
  options: {
3474
- minValue: 1,
1905
+ placeholder: '0-100',
1906
+ minValue: 0,
3475
1907
  maxValue: 100,
3476
1908
  },
3477
1909
  },
3478
1910
  },
3479
1911
  visible: true,
3480
1912
  },
1913
+ // ====== Tooltip Settings ======
3481
1914
  {
3482
- name: 'showAvatar',
3483
- title: 'Show Avatar',
3484
- description: 'Whether to show avatars in notifications',
1915
+ name: 'showTooltip',
1916
+ title: 'Show Tooltip',
3485
1917
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3486
1918
  schema: {
3487
1919
  defaultValue: true,
3488
1920
  dataType: 'boolean',
3489
1921
  interface: {
3490
- name: 'showAvatar',
3491
- path: 'options.showAvatar',
1922
+ name: 'showTooltip',
1923
+ path: 'options.showTooltip',
3492
1924
  type: AXPWidgetsCatalog.toggle,
3493
1925
  },
3494
1926
  },
3495
1927
  visible: true,
3496
1928
  },
3497
1929
  {
3498
- name: 'showDate',
3499
- title: 'Show Date',
3500
- description: 'Whether to show date in notifications',
1930
+ name: 'showCrosshair',
1931
+ title: 'Show Crosshair',
3501
1932
  group: AXP_APPEARANCE_PROPERTY_GROUP,
3502
1933
  schema: {
3503
- defaultValue: true,
1934
+ defaultValue: false,
3504
1935
  dataType: 'boolean',
3505
1936
  interface: {
3506
- name: 'showDate',
3507
- path: 'options.showDate',
1937
+ name: 'showCrosshair',
1938
+ path: 'options.showCrosshair',
3508
1939
  type: AXPWidgetsCatalog.toggle,
3509
1940
  },
3510
1941
  },
3511
1942
  visible: true,
3512
1943
  },
1944
+ // ====== Animation Settings ======
1945
+ {
1946
+ name: 'animationEasing',
1947
+ title: 'Animation Easing',
1948
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1949
+ schema: {
1950
+ defaultValue: 'cubic-out',
1951
+ dataType: 'string',
1952
+ interface: {
1953
+ name: 'animationEasing',
1954
+ path: 'options.animationEasing',
1955
+ type: AXPWidgetsCatalog.select,
1956
+ options: {
1957
+ dataSource: [
1958
+ { value: 'linear', text: 'Linear' },
1959
+ { value: 'ease', text: 'Ease' },
1960
+ { value: 'ease-in', text: 'Ease In' },
1961
+ { value: 'ease-out', text: 'Ease Out' },
1962
+ { value: 'ease-in-out', text: 'Ease In Out' },
1963
+ { value: 'cubic', text: 'Cubic' },
1964
+ { value: 'cubic-in', text: 'Cubic In' },
1965
+ { value: 'cubic-out', text: 'Cubic Out' },
1966
+ { value: 'cubic-in-out', text: 'Cubic In Out' },
1967
+ ],
1968
+ textField: 'text',
1969
+ valueField: 'value',
1970
+ },
1971
+ },
1972
+ },
1973
+ visible: true,
1974
+ },
1975
+ {
1976
+ name: 'animationDuration',
1977
+ title: 'Animation Duration',
1978
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
1979
+ schema: {
1980
+ defaultValue: 800,
1981
+ dataType: 'number',
1982
+ interface: {
1983
+ name: 'animationDuration',
1984
+ path: 'options.animationDuration',
1985
+ type: AXPWidgetsCatalog.number,
1986
+ options: {
1987
+ placeholder: '0-2000',
1988
+ minValue: 0,
1989
+ maxValue: 2000,
1990
+ },
1991
+ },
1992
+ },
1993
+ visible: true,
1994
+ },
3513
1995
  ],
3514
1996
  components: {
3515
1997
  view: {
3516
- component: () => Promise.resolve().then(function () { return notificationWidget_component; }).then((c) => c.AXPNotificationWidgetViewComponent),
1998
+ component: () => Promise.resolve().then(function () { return lineChartWidget_component; }).then((c) => c.AXPLineChartWidgetViewComponent),
3517
1999
  },
3518
2000
  },
3519
2001
  meta: {
3520
2002
  dimensions: {
3521
- width: 3,
3522
- height: 5,
2003
+ width: 5,
2004
+ height: 6,
3523
2005
  minWidth: 2,
3524
- minHeight: 4,
3525
- maxWidth: 4,
2006
+ minHeight: 2,
2007
+ maxWidth: 6,
3526
2008
  maxHeight: 7,
3527
2009
  },
3528
2010
  },
@@ -3583,7 +2065,7 @@ class AXPStickyNoteWidgetViewComponent extends AXPValueWidgetComponent {
3583
2065
  provide: AXGridLayoutWidgetComponent,
3584
2066
  useExisting: AXPStickyNoteWidgetViewComponent,
3585
2067
  },
3586
- ], viewQueries: [{ propertyName: "wysiwyg", first: true, predicate: ["wysiwyg"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div\n class=\"sticky-note-container ax-size-full ax-rounded-lg ax-flex ax-flex-col ax-p-4 ax-shadow-md ax-transition-all ax-duration-300 hover:ax-shadow-lg\"\n [style.background-color]=\"bgColor()\"\n [style.color]=\"color()\"\n [class.ax-shadow-lg]=\"isEditing()\"\n [class.ax-scale-[1.02]]=\"isEditing()\"\n (dblclick)=\"activateEdit()\"\n>\n <!-- Header with timestamp -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-3\">\n <div class=\"ax-text-xs ax-opacity-70 ax-font-medium ax-flex ax-items-center ax-gap-1\">\n <i class=\"fa-regular fa-clock ax-text-[0.65rem]\"></i>\n {{ date() | format : 'datetime' : 'dd MMM, YY HH:mm' | async }}\n </div>\n </div>\n\n <!-- Content area -->\n <div class=\"ax-flex-1 ax-overflow-auto\">\n <ax-wysiwyg-container\n #wysiwyg\n [class]=\"isEditing() ? 'ax-pointer-events-auto ax-cursor-text' : 'ax-pointer-events-none !ax-cursor-pointer'\"\n class=\"ax-h-full\"\n placeHolder=\"start writing with double click...\"\n look=\"none\"\n (onValueChanged)=\"valueChange($event)\"\n [ngModel]=\"value()\"\n >\n <ax-wysiwyg-view class=\"!ax-size-full ax-border-b-0\"></ax-wysiwyg-view>\n </ax-wysiwyg-container>\n </div>\n\n <!-- Footer with color selector and save button -->\n @if (isEditing()) {\n <div class=\"ax-absolute ax-bottom-2 ax-left-2 ax-right-2 ax-flex ax-flex-wrap ax-gap-1 ax-text-xs\">\n <!-- Color selection bar when in edit mode -->\n <div class=\"ax-flex ax-w-full ax-mt-2 ax-border ax-border-gray-200 ax-overflow-hidden ax-rounded-md\">\n @for (preset of colorPresets; track preset) {\n <div\n class=\"ax-h-6 ax-flex-1 ax-cursor-pointer ax-transition-all ax-duration-200 ax-border-r ax-border-gray-200 last:ax-border-r-0 hover:ax-brightness-95\"\n [style.background-color]=\"preset\"\n [class.ax-ring-inset]=\"bgColor() === preset\"\n [class.ax-ring-2]=\"bgColor() === preset\"\n [class.ax-ring-primary]=\"bgColor() === preset\"\n (click)=\"setColor(preset)\"\n ></div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}:host ::ng-deep ax-wysiwyg-view{color:#2e2e2e!important}\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1$1.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "placeHolder"], outputs: ["onValueChanged"] }, { kind: "component", type: i1$1.AXWysiwygViewComponent, selector: "ax-wysiwyg-view", inputs: ["class"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXToolBarModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "pipe", type: i2$1.AXFormatPipe, name: "format" }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXColorBoxModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2068
+ ], viewQueries: [{ propertyName: "wysiwyg", first: true, predicate: ["wysiwyg"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div\n class=\"sticky-note-container ax-size-full ax-rounded-lg ax-flex ax-flex-col ax-p-4 ax-shadow-md ax-transition-all ax-duration-300 hover:ax-shadow-lg\"\n [style.background-color]=\"bgColor()\"\n [style.color]=\"color()\"\n [class.ax-shadow-lg]=\"isEditing()\"\n [class.ax-scale-[1.02]]=\"isEditing()\"\n (dblclick)=\"activateEdit()\"\n>\n <!-- Header with timestamp -->\n <div class=\"ax-flex ax-justify-between ax-items-center ax-mb-3\">\n <div class=\"ax-text-xs ax-opacity-70 ax-font-medium ax-flex ax-items-center ax-gap-1\">\n <i class=\"fa-regular fa-clock ax-text-[0.65rem]\"></i>\n {{ date() | format : 'datetime' : 'dd MMM, YY HH:mm' | async }}\n </div>\n </div>\n\n <!-- Content area -->\n <div class=\"ax-flex-1 ax-overflow-auto\">\n <ax-wysiwyg-container\n #wysiwyg\n [class]=\"isEditing() ? 'ax-pointer-events-auto ax-cursor-text' : 'ax-pointer-events-none !ax-cursor-pointer'\"\n class=\"ax-h-full\"\n placeHolder=\"start writing with double click...\"\n look=\"none\"\n (onValueChanged)=\"valueChange($event)\"\n [ngModel]=\"value()\"\n >\n <ax-wysiwyg-view class=\"!ax-size-full ax-border-b-0\"></ax-wysiwyg-view>\n </ax-wysiwyg-container>\n </div>\n\n <!-- Footer with color selector and save button -->\n @if (isEditing()) {\n <div class=\"ax-absolute ax-bottom-2 ax-left-2 ax-right-2 ax-flex ax-flex-wrap ax-gap-1 ax-text-xs\">\n <!-- Color selection bar when in edit mode -->\n <div class=\"ax-flex ax-w-full ax-mt-2 ax-border ax-border-gray-200 ax-overflow-hidden ax-rounded-md\">\n @for (preset of colorPresets; track preset) {\n <div\n class=\"ax-h-6 ax-flex-1 ax-cursor-pointer ax-transition-all ax-duration-200 ax-border-r ax-border-gray-200 last:ax-border-r-0 hover:ax-brightness-95\"\n [style.background-color]=\"preset\"\n [class.ax-ring-inset]=\"bgColor() === preset\"\n [class.ax-ring-2]=\"bgColor() === preset\"\n [class.ax-ring-primary]=\"bgColor() === preset\"\n (click)=\"setColor(preset)\"\n ></div>\n }\n </div>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}:host ::ng-deep ax-wysiwyg-view{color:#2e2e2e!important}\n"], dependencies: [{ kind: "ngmodule", type: AXWysiwygModule }, { kind: "component", type: i1$1.AXWysiwygContainerComponent, selector: "ax-wysiwyg-container", inputs: ["look", "placeHolder"], outputs: ["onValueChanged"] }, { kind: "component", type: i1$1.AXWysiwygViewComponent, selector: "ax-wysiwyg-view", inputs: ["class"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXToolBarModule }, { 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: AXDateTimeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "pipe", type: i2.AXFormatPipe, name: "format" }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXColorBoxModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3587
2069
  }
3588
2070
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPStickyNoteWidgetViewComponent, decorators: [{
3589
2071
  type: Component,
@@ -3762,7 +2244,7 @@ class AXPTaskListWidgetViewComponent extends AXPValueWidgetComponent {
3762
2244
  return Math.floor(diffMs / (1000 * 60 * 60 * 24));
3763
2245
  }
3764
2246
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPTaskListWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3765
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", 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$3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "component", type: i4.AXBadgeComponent, selector: "ax-badge", inputs: ["color", "look", "text"] }, { kind: "ngmodule", type: AXAvatarModule }, { kind: "ngmodule", type: AXImageModule }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "component", type: i4$1.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.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2247
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", 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: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3766
2248
  }
3767
2249
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPTaskListWidgetViewComponent, decorators: [{
3768
2250
  type: Component,
@@ -3794,6 +2276,25 @@ const AXPTaskListWidget = {
3794
2276
  icon: 'fa-light fa-clipboard-list-check',
3795
2277
  properties: [
3796
2278
  cloneProperty(AXP_DATA_PATH_PROPERTY, { visible: false }),
2279
+ // ====== Title ======
2280
+ {
2281
+ name: 'title',
2282
+ title: 'Chart Title',
2283
+ group: AXP_APPEARANCE_PROPERTY_GROUP,
2284
+ schema: {
2285
+ defaultValue: '',
2286
+ dataType: 'string',
2287
+ interface: {
2288
+ name: 'title',
2289
+ path: 'options.title',
2290
+ type: AXPWidgetsCatalog.text,
2291
+ options: {
2292
+ placeholder: 'Enter chart title',
2293
+ },
2294
+ },
2295
+ },
2296
+ visible: true,
2297
+ },
3797
2298
  // Display options
3798
2299
  {
3799
2300
  name: 'maxItems',
@@ -4944,6 +3445,179 @@ const AXPWeatherWidget = {
4944
3445
  },
4945
3446
  };
4946
3447
 
3448
+ class AXPDashboardShortcutWidgetViewComponent extends AXPLayoutWidgetComponent {
3449
+ constructor() {
3450
+ super(...arguments);
3451
+ this.popupService = inject(AXPopupService);
3452
+ this.workflow = inject(AXPWorkflowService);
3453
+ this.searchConfig = inject(AXP_GLOBAL_SEARCH_CONFIG_TOKEN);
3454
+ this.item = computed(() => this.options()['item']);
3455
+ this.color = computed(() => this.options()['color']);
3456
+ }
3457
+ ngOnInit() {
3458
+ super.ngOnInit();
3459
+ if (!this.color()) {
3460
+ this.setOptions({
3461
+ color: AXPDataGenerator.color()
3462
+ });
3463
+ }
3464
+ }
3465
+ async executeCommand() {
3466
+ if (this.item()?.command) {
3467
+ await this.workflow.execute(this.item().command.name, this.item().command.options);
3468
+ }
3469
+ }
3470
+ async setCommand() {
3471
+ const component = await this.searchConfig.window();
3472
+ const popup = await this.popupService.open(component, {
3473
+ title: 'Choose command...',
3474
+ size: 'fit',
3475
+ closeOnBackdropClick: true,
3476
+ header: false,
3477
+ });
3478
+ if (popup.data) {
3479
+ const result = popup.data;
3480
+ if (result && result.command) {
3481
+ this.setOptions({
3482
+ item: {
3483
+ name: result.name,
3484
+ title: result.title,
3485
+ description: result.description,
3486
+ icon: result.icon,
3487
+ command: result.command
3488
+ }
3489
+ });
3490
+ }
3491
+ }
3492
+ }
3493
+ get __style() {
3494
+ const cls = {};
3495
+ cls[`background-color`] = this.color();
3496
+ return cls;
3497
+ }
3498
+ get __class() {
3499
+ const cls = {};
3500
+ cls[`ax-flex`] = true;
3501
+ cls[`ax-flex-col`] = true;
3502
+ cls[`ax-items-center`] = true;
3503
+ cls[`ax-justify-center`] = true;
3504
+ cls[`ax-w-full`] = true;
3505
+ cls[`ax-h-full`] = true;
3506
+ cls[`ax-text-center`] = true;
3507
+ cls[`ax-overflow-hidden`] = true;
3508
+ cls[`ax-cursor-pointer`] = true;
3509
+ cls[`ax-text-white`] = true;
3510
+ return cls;
3511
+ }
3512
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPDashboardShortcutWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3513
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.3", type: AXPDashboardShortcutWidgetViewComponent, isStandalone: true, selector: "ng-component", host: { properties: { "style": "this.__style", "class": "this.__class" } }, usesInheritance: true, ngImport: i0, template: `
3514
+ @if(item()) {
3515
+ <div
3516
+ 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 "
3517
+ (click)="executeCommand()">
3518
+ <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/10 ax-transition-opacity"></div>
3519
+ <i [class]="item().icon + ' ax-text-3xl'"></i>
3520
+ <span class="ax-text-xl ax-font-semibold">{{ item().title | translate | async }}</span>
3521
+ @if(item().description) {
3522
+ <span class="ax-text-sm ax-opacity-90 ax-text-center ax-px-2">{{ item().description! | translate | async }}</span>
3523
+ }
3524
+ </div>
3525
+ } @else {
3526
+ <div
3527
+ (click)="setCommand()"
3528
+ 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">
3529
+ <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/5 ax-transition-opacity"></div>
3530
+ <i class="fa-light fa-plus ax-text-3xl"></i>
3531
+ <span class="ax-text-xl ax-font-semibold">Add Shortcut</span>
3532
+ </div>
3533
+ }
3534
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3535
+ }
3536
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXPDashboardShortcutWidgetViewComponent, decorators: [{
3537
+ type: Component,
3538
+ args: [{
3539
+ template: `
3540
+ @if(item()) {
3541
+ <div
3542
+ 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 "
3543
+ (click)="executeCommand()">
3544
+ <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/10 ax-transition-opacity"></div>
3545
+ <i [class]="item().icon + ' ax-text-3xl'"></i>
3546
+ <span class="ax-text-xl ax-font-semibold">{{ item().title | translate | async }}</span>
3547
+ @if(item().description) {
3548
+ <span class="ax-text-sm ax-opacity-90 ax-text-center ax-px-2">{{ item().description! | translate | async }}</span>
3549
+ }
3550
+ </div>
3551
+ } @else {
3552
+ <div
3553
+ (click)="setCommand()"
3554
+ 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">
3555
+ <div class="ax-absolute ax-inset-0 ax-bg-black/0 hover:ax-bg-black/5 ax-transition-opacity"></div>
3556
+ <i class="fa-light fa-plus ax-text-3xl"></i>
3557
+ <span class="ax-text-xl ax-font-semibold">Add Shortcut</span>
3558
+ </div>
3559
+ }
3560
+ `,
3561
+ standalone: true,
3562
+ changeDetection: ChangeDetectionStrategy.OnPush,
3563
+ imports: [CommonModule, AXTranslationModule]
3564
+ }]
3565
+ }], propDecorators: { __style: [{
3566
+ type: HostBinding,
3567
+ args: ['style']
3568
+ }], __class: [{
3569
+ type: HostBinding,
3570
+ args: ['class']
3571
+ }] } });
3572
+
3573
+ var dashboardShortcutWidgetView_component = /*#__PURE__*/Object.freeze({
3574
+ __proto__: null,
3575
+ AXPDashboardShortcutWidgetViewComponent: AXPDashboardShortcutWidgetViewComponent
3576
+ });
3577
+
3578
+ const AXPDashboardShortcutWidget = {
3579
+ name: "dashboard-shortcut",
3580
+ title: "Shortcut",
3581
+ description: 'Quick access to your key features.',
3582
+ type: 'view',
3583
+ categories: [AXP_WIDGETS_UTILITY_CATEGORY],
3584
+ groups: [AXPWidgetGroupEnum.DashboardWidget],
3585
+ icon: "fa-light fa-link",
3586
+ properties: [
3587
+ AXP_COLOR_PROPERTY
3588
+ ],
3589
+ meta: {
3590
+ dimensions: {
3591
+ width: 2,
3592
+ height: 2,
3593
+ minWidth: 1,
3594
+ minHeight: 1,
3595
+ maxWidth: 3,
3596
+ maxHeight: 2,
3597
+ },
3598
+ },
3599
+ components: {
3600
+ view: {
3601
+ component: () => Promise.resolve().then(function () { return dashboardShortcutWidgetView_component; }).then((c) => c.AXPDashboardShortcutWidgetViewComponent),
3602
+ },
3603
+ }
3604
+ };
3605
+
3606
+ class AXMMenuProvider {
3607
+ constructor() {
3608
+ this.sessionService = inject(AXPSessionService);
3609
+ }
3610
+ async provide(context) {
3611
+ const scope = RootConfig.config.i18n;
3612
+ const module = RootConfig.module;
3613
+ const appName = this.sessionService.application?.name;
3614
+ const isAuthorized = await firstValueFrom(this.sessionService.isAuthorized$);
3615
+ if (!isAuthorized) {
3616
+ return;
3617
+ }
3618
+ }
3619
+ }
3620
+
4947
3621
  function routesFactory() {
4948
3622
  const config = inject(AXP_ENTITY_CONFIG_TOKEN);
4949
3623
  return {
@@ -4955,14 +3629,14 @@ function routesFactory() {
4955
3629
  children: [
4956
3630
  {
4957
3631
  path: 'dashboard',
4958
- loadComponent: () => import('./acorex-modules-dashboard-management-home-dashboard-CHXDeuSF.mjs').then((c) => c.AXPDashboardHomeComponent),
3632
+ loadComponent: () => import('./acorex-modules-dashboard-management-home-dashboard-BXD0g_tp.mjs').then((c) => c.AXMDashboardHomeComponent),
4959
3633
  },
4960
3634
  ],
4961
3635
  };
4962
3636
  }
4963
3637
  class AXMDashboardManagementModule {
4964
3638
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMDashboardManagementModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
4965
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.3", ngImport: i0, type: AXMDashboardManagementModule, imports: [i3.AXPLayoutBuilderModule] }); }
3639
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.3", ngImport: i0, type: AXMDashboardManagementModule, imports: [i3$1.AXPLayoutBuilderModule] }); }
4966
3640
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: AXMDashboardManagementModule, providers: [
4967
3641
  {
4968
3642
  provide: AXMDashboardService,
@@ -4975,8 +3649,8 @@ class AXMDashboardManagementModule {
4975
3649
  {
4976
3650
  key: 'dashboard',
4977
3651
  title: 'Dashboard',
4978
- route: routesFactory()
4979
- }
3652
+ route: routesFactory(),
3653
+ },
4980
3654
  ],
4981
3655
  },
4982
3656
  AXPWidgetsModule,
@@ -5009,7 +3683,6 @@ class AXMDashboardManagementModule {
5009
3683
  AXPStickyNoteWidget,
5010
3684
  AXPClockCalendarWidget,
5011
3685
  AXPWeatherWidget,
5012
- AXPNotificationWidget,
5013
3686
  AXPTaskListWidget,
5014
3687
  ],
5015
3688
  })] }); }
@@ -5029,7 +3702,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
5029
3702
  AXPStickyNoteWidget,
5030
3703
  AXPClockCalendarWidget,
5031
3704
  AXPWeatherWidget,
5032
- AXPNotificationWidget,
5033
3705
  AXPTaskListWidget,
5034
3706
  ],
5035
3707
  }),
@@ -5048,8 +3720,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
5048
3720
  {
5049
3721
  key: 'dashboard',
5050
3722
  title: 'Dashboard',
5051
- route: routesFactory()
5052
- }
3723
+ route: routesFactory(),
3724
+ },
5053
3725
  ],
5054
3726
  },
5055
3727
  AXPWidgetsModule,
@@ -5079,5 +3751,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImpor
5079
3751
  * Generated bundle index. Do not edit.
5080
3752
  */
5081
3753
 
5082
- export { AXMDashboardService as A, AXPWeatherApiMockService as B, AXPWeatherApiService as C, AXPWeatherWidgetViewComponent as D, AXPWeatherWidget as E, RootConfig as R, AXMDashboardManagementModule as a, AXPBarChartWidgetViewComponent as b, AXPBarChartWidget as c, AXP_WIDGETS_CHART_CATEGORY as d, AXP_WIDGETS_UTILITY_CATEGORY as e, AXPClockCalendarWidgetViewComponent as f, AXPClockCalendarWidget as g, AXP_TIMEZONE_OPTIONS as h, AXP_DATE_FORMAT_OPTIONS as i, AXPDonutChartWidgetViewComponent as j, AXPDonutChartWidget as k, AXPGaugeChartWidgetViewComponent as l, AXPGaugeChartWidget as m, AXPLineChartWidgetViewComponent as n, AXPLineChartWidget as o, AXPNotificationWidgetViewComponent as p, AXPNotificationWidget as q, AXPChartBaseComponent as r, AXPChartColors as s, loadD3 as t, AXPChartTooltipComponent as u, AXPStickyNoteWidgetViewComponent as v, AXPStickyNoteWidget as w, AXPTaskListWidgetViewComponent as x, AXPTaskListWidget as y, AXPWeatherApiAbstract as z };
5083
- //# sourceMappingURL=acorex-modules-dashboard-management-acorex-modules-dashboard-management-CReOsVhq.mjs.map
3754
+ export { AXMDashboardService as A, RootConfig as R, AXMDashboardManagementModule as a, AXPBarChartWidgetViewComponent as b, AXPBarChartWidget as c, AXP_WIDGETS_CHART_CATEGORY as d, AXP_WIDGETS_UTILITY_CATEGORY as e, AXPClockCalendarWidgetViewComponent as f, AXPClockCalendarWidget as g, AXP_TIMEZONE_OPTIONS as h, AXP_DATE_FORMAT_OPTIONS as i, AXPDonutChartWidgetViewComponent as j, AXPDonutChartWidget as k, AXPGaugeChartWidgetViewComponent as l, AXPGaugeChartWidget as m, AXPLineChartWidgetViewComponent as n, AXPLineChartWidget as o, AXPStickyNoteWidgetViewComponent as p, AXPStickyNoteWidget as q, AXPTaskListWidgetViewComponent as r, AXPTaskListWidget as s, AXPWeatherApiAbstract as t, AXPWeatherApiMockService as u, AXPWeatherApiService as v, AXPWeatherWidgetViewComponent as w, AXPWeatherWidget as x };
3755
+ //# sourceMappingURL=acorex-modules-dashboard-management-acorex-modules-dashboard-management-Ccj2AaJ1.mjs.map