@sdcorejs/angular 20.0.0 → 21.0.0-rc.2

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 (195) hide show
  1. package/fesm2022/sdcorejs-angular-components-anchor.mjs +28 -28
  2. package/fesm2022/sdcorejs-angular-components-anchor.mjs.map +1 -1
  3. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs +34 -34
  4. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs.map +1 -1
  5. package/fesm2022/sdcorejs-angular-components-avatar.mjs +9 -9
  6. package/fesm2022/sdcorejs-angular-components-avatar.mjs.map +1 -1
  7. package/fesm2022/sdcorejs-angular-components-badge.mjs +25 -33
  8. package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
  9. package/fesm2022/sdcorejs-angular-components-base.mjs +3 -3
  10. package/fesm2022/sdcorejs-angular-components-button.mjs +19 -29
  11. package/fesm2022/sdcorejs-angular-components-button.mjs.map +1 -1
  12. package/fesm2022/sdcorejs-angular-components-chart.mjs +28 -28
  13. package/fesm2022/sdcorejs-angular-components-chart.mjs.map +1 -1
  14. package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs +4 -4
  15. package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs.map +1 -1
  16. package/fesm2022/sdcorejs-angular-components-code-editor.mjs +11 -11
  17. package/fesm2022/sdcorejs-angular-components-code-editor.mjs.map +1 -1
  18. package/fesm2022/sdcorejs-angular-components-document-builder.mjs +6 -6
  19. package/fesm2022/sdcorejs-angular-components-editor.mjs +36 -48
  20. package/fesm2022/sdcorejs-angular-components-editor.mjs.map +1 -1
  21. package/fesm2022/sdcorejs-angular-components-form-generic.mjs +212 -212
  22. package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
  23. package/fesm2022/sdcorejs-angular-components-history.mjs +8 -8
  24. package/fesm2022/sdcorejs-angular-components-history.mjs.map +1 -1
  25. package/fesm2022/sdcorejs-angular-components-import-excel.mjs +10 -10
  26. package/fesm2022/sdcorejs-angular-components-inform.mjs +35 -39
  27. package/fesm2022/sdcorejs-angular-components-inform.mjs.map +1 -1
  28. package/fesm2022/sdcorejs-angular-components-mini-editor.mjs +3 -3
  29. package/fesm2022/sdcorejs-angular-components-modal.mjs +20 -20
  30. package/fesm2022/sdcorejs-angular-components-modal.mjs.map +1 -1
  31. package/fesm2022/sdcorejs-angular-components-operator.mjs +11 -11
  32. package/fesm2022/sdcorejs-angular-components-operator.mjs.map +1 -1
  33. package/fesm2022/sdcorejs-angular-components-preview.mjs +119 -119
  34. package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
  35. package/fesm2022/sdcorejs-angular-components-query-bar.mjs +132 -141
  36. package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
  37. package/fesm2022/sdcorejs-angular-components-query-builder.mjs +3 -3
  38. package/fesm2022/sdcorejs-angular-components-quick-action.mjs +4 -4
  39. package/fesm2022/sdcorejs-angular-components-quick-action.mjs.map +1 -1
  40. package/fesm2022/sdcorejs-angular-components-section.mjs +18 -22
  41. package/fesm2022/sdcorejs-angular-components-section.mjs.map +1 -1
  42. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +14 -14
  43. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
  44. package/fesm2022/sdcorejs-angular-components-splitter.mjs +36 -38
  45. package/fesm2022/sdcorejs-angular-components-splitter.mjs.map +1 -1
  46. package/fesm2022/sdcorejs-angular-components-stepper.mjs +24 -24
  47. package/fesm2022/sdcorejs-angular-components-stepper.mjs.map +1 -1
  48. package/fesm2022/sdcorejs-angular-components-tab-router.mjs +23 -23
  49. package/fesm2022/sdcorejs-angular-components-tab-router.mjs.map +1 -1
  50. package/fesm2022/sdcorejs-angular-components-tab.mjs +23 -23
  51. package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
  52. package/fesm2022/sdcorejs-angular-components-table.mjs +225 -225
  53. package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
  54. package/fesm2022/sdcorejs-angular-components-upload-file.mjs +70 -106
  55. package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
  56. package/fesm2022/sdcorejs-angular-components-view.mjs +14 -14
  57. package/fesm2022/sdcorejs-angular-components-view.mjs.map +1 -1
  58. package/fesm2022/sdcorejs-angular-directives.mjs +30 -30
  59. package/fesm2022/sdcorejs-angular-directives.mjs.map +1 -1
  60. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +61 -76
  61. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
  62. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +26 -49
  63. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
  64. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +48 -83
  65. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
  66. package/fesm2022/sdcorejs-angular-forms-chip.mjs +47 -82
  67. package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
  68. package/fesm2022/sdcorejs-angular-forms-date-range.mjs +46 -61
  69. package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
  70. package/fesm2022/sdcorejs-angular-forms-date.mjs +53 -68
  71. package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
  72. package/fesm2022/sdcorejs-angular-forms-datetime.mjs +74 -89
  73. package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
  74. package/fesm2022/sdcorejs-angular-forms-directives.mjs +12 -12
  75. package/fesm2022/sdcorejs-angular-forms-input-color.mjs +19 -19
  76. package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
  77. package/fesm2022/sdcorejs-angular-forms-input-number.mjs +56 -71
  78. package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
  79. package/fesm2022/sdcorejs-angular-forms-input.mjs +58 -73
  80. package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
  81. package/fesm2022/sdcorejs-angular-forms-label.mjs +3 -3
  82. package/fesm2022/sdcorejs-angular-forms-models.mjs +2 -2
  83. package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
  84. package/fesm2022/sdcorejs-angular-forms-radio.mjs +39 -70
  85. package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
  86. package/fesm2022/sdcorejs-angular-forms-select.mjs +69 -86
  87. package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
  88. package/fesm2022/sdcorejs-angular-forms-switch.mjs +28 -49
  89. package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
  90. package/fesm2022/sdcorejs-angular-forms-textarea.mjs +50 -77
  91. package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
  92. package/fesm2022/sdcorejs-angular-forms.mjs +4 -4
  93. package/fesm2022/sdcorejs-angular-handlers.mjs +3 -3
  94. package/fesm2022/sdcorejs-angular-i18n.mjs +9 -9
  95. package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
  96. package/fesm2022/sdcorejs-angular-interceptors.mjs +6 -6
  97. package/fesm2022/sdcorejs-angular-modules-auth.mjs +10 -10
  98. package/fesm2022/sdcorejs-angular-modules-auth.mjs.map +1 -1
  99. package/fesm2022/sdcorejs-angular-modules-authom.mjs +10 -10
  100. package/fesm2022/sdcorejs-angular-modules-authom.mjs.map +1 -1
  101. package/fesm2022/sdcorejs-angular-modules-keycloak.mjs +7 -7
  102. package/fesm2022/sdcorejs-angular-modules-layout.mjs +131 -131
  103. package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
  104. package/fesm2022/sdcorejs-angular-modules-permission.mjs +11 -11
  105. package/fesm2022/sdcorejs-angular-modules-permission.mjs.map +1 -1
  106. package/fesm2022/sdcorejs-angular-pipes.mjs +14 -14
  107. package/fesm2022/sdcorejs-angular-services-api.mjs +10 -10
  108. package/fesm2022/sdcorejs-angular-services-cache.mjs +3 -3
  109. package/fesm2022/sdcorejs-angular-services-confirm.mjs +6 -6
  110. package/fesm2022/sdcorejs-angular-services-docx.mjs +3 -3
  111. package/fesm2022/sdcorejs-angular-services-excel.mjs +3 -3
  112. package/fesm2022/sdcorejs-angular-services-license.mjs +3 -3
  113. package/fesm2022/sdcorejs-angular-services-loading.mjs +3 -3
  114. package/fesm2022/sdcorejs-angular-services-notify.mjs +12 -12
  115. package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
  116. package/fesm2022/sdcorejs-angular-services-storage.mjs +3 -3
  117. package/package.json +82 -81
  118. package/{forms/select/index.d.ts → types/sdcorejs-angular-forms-select.d.ts} +3 -3
  119. /package/{components/anchor/index.d.ts → types/sdcorejs-angular-components-anchor.d.ts} +0 -0
  120. /package/{components/autoid-inspector/index.d.ts → types/sdcorejs-angular-components-autoid-inspector.d.ts} +0 -0
  121. /package/{components/avatar/index.d.ts → types/sdcorejs-angular-components-avatar.d.ts} +0 -0
  122. /package/{components/badge/index.d.ts → types/sdcorejs-angular-components-badge.d.ts} +0 -0
  123. /package/{components/base/index.d.ts → types/sdcorejs-angular-components-base.d.ts} +0 -0
  124. /package/{components/button/index.d.ts → types/sdcorejs-angular-components-button.d.ts} +0 -0
  125. /package/{components/chart/index.d.ts → types/sdcorejs-angular-components-chart.d.ts} +0 -0
  126. /package/{components/ckeditor-styles/index.d.ts → types/sdcorejs-angular-components-ckeditor-styles.d.ts} +0 -0
  127. /package/{components/code-editor/index.d.ts → types/sdcorejs-angular-components-code-editor.d.ts} +0 -0
  128. /package/{components/document-builder/index.d.ts → types/sdcorejs-angular-components-document-builder.d.ts} +0 -0
  129. /package/{components/editor/index.d.ts → types/sdcorejs-angular-components-editor.d.ts} +0 -0
  130. /package/{components/form-generic/index.d.ts → types/sdcorejs-angular-components-form-generic.d.ts} +0 -0
  131. /package/{components/history/index.d.ts → types/sdcorejs-angular-components-history.d.ts} +0 -0
  132. /package/{components/import-excel/index.d.ts → types/sdcorejs-angular-components-import-excel.d.ts} +0 -0
  133. /package/{components/inform/index.d.ts → types/sdcorejs-angular-components-inform.d.ts} +0 -0
  134. /package/{components/mini-editor/index.d.ts → types/sdcorejs-angular-components-mini-editor.d.ts} +0 -0
  135. /package/{components/modal/index.d.ts → types/sdcorejs-angular-components-modal.d.ts} +0 -0
  136. /package/{components/operator/index.d.ts → types/sdcorejs-angular-components-operator.d.ts} +0 -0
  137. /package/{components/preview/index.d.ts → types/sdcorejs-angular-components-preview.d.ts} +0 -0
  138. /package/{components/query-bar/index.d.ts → types/sdcorejs-angular-components-query-bar.d.ts} +0 -0
  139. /package/{components/query-builder/index.d.ts → types/sdcorejs-angular-components-query-builder.d.ts} +0 -0
  140. /package/{components/quick-action/index.d.ts → types/sdcorejs-angular-components-quick-action.d.ts} +0 -0
  141. /package/{components/section/index.d.ts → types/sdcorejs-angular-components-section.d.ts} +0 -0
  142. /package/{components/side-drawer/index.d.ts → types/sdcorejs-angular-components-side-drawer.d.ts} +0 -0
  143. /package/{components/splitter/index.d.ts → types/sdcorejs-angular-components-splitter.d.ts} +0 -0
  144. /package/{components/stepper/index.d.ts → types/sdcorejs-angular-components-stepper.d.ts} +0 -0
  145. /package/{components/tab-router/index.d.ts → types/sdcorejs-angular-components-tab-router.d.ts} +0 -0
  146. /package/{components/tab/index.d.ts → types/sdcorejs-angular-components-tab.d.ts} +0 -0
  147. /package/{components/table/index.d.ts → types/sdcorejs-angular-components-table.d.ts} +0 -0
  148. /package/{components/upload-file/index.d.ts → types/sdcorejs-angular-components-upload-file.d.ts} +0 -0
  149. /package/{components/view/index.d.ts → types/sdcorejs-angular-components-view.d.ts} +0 -0
  150. /package/{components/index.d.ts → types/sdcorejs-angular-components.d.ts} +0 -0
  151. /package/{configurations/index.d.ts → types/sdcorejs-angular-configurations.d.ts} +0 -0
  152. /package/{directives/index.d.ts → types/sdcorejs-angular-directives.d.ts} +0 -0
  153. /package/{forms/autocomplete/index.d.ts → types/sdcorejs-angular-forms-autocomplete.d.ts} +0 -0
  154. /package/{forms/checkbox/index.d.ts → types/sdcorejs-angular-forms-checkbox.d.ts} +0 -0
  155. /package/{forms/chip-calendar/index.d.ts → types/sdcorejs-angular-forms-chip-calendar.d.ts} +0 -0
  156. /package/{forms/chip/index.d.ts → types/sdcorejs-angular-forms-chip.d.ts} +0 -0
  157. /package/{forms/date-range/index.d.ts → types/sdcorejs-angular-forms-date-range.d.ts} +0 -0
  158. /package/{forms/date/index.d.ts → types/sdcorejs-angular-forms-date.d.ts} +0 -0
  159. /package/{forms/datetime/index.d.ts → types/sdcorejs-angular-forms-datetime.d.ts} +0 -0
  160. /package/{forms/directives/index.d.ts → types/sdcorejs-angular-forms-directives.d.ts} +0 -0
  161. /package/{forms/input-color/index.d.ts → types/sdcorejs-angular-forms-input-color.d.ts} +0 -0
  162. /package/{forms/input-number/index.d.ts → types/sdcorejs-angular-forms-input-number.d.ts} +0 -0
  163. /package/{forms/input/index.d.ts → types/sdcorejs-angular-forms-input.d.ts} +0 -0
  164. /package/{forms/label/index.d.ts → types/sdcorejs-angular-forms-label.d.ts} +0 -0
  165. /package/{forms/models/index.d.ts → types/sdcorejs-angular-forms-models.d.ts} +0 -0
  166. /package/{forms/radio/index.d.ts → types/sdcorejs-angular-forms-radio.d.ts} +0 -0
  167. /package/{forms/switch/index.d.ts → types/sdcorejs-angular-forms-switch.d.ts} +0 -0
  168. /package/{forms/textarea/index.d.ts → types/sdcorejs-angular-forms-textarea.d.ts} +0 -0
  169. /package/{forms/index.d.ts → types/sdcorejs-angular-forms.d.ts} +0 -0
  170. /package/{handlers/index.d.ts → types/sdcorejs-angular-handlers.d.ts} +0 -0
  171. /package/{i18n/index.d.ts → types/sdcorejs-angular-i18n.d.ts} +0 -0
  172. /package/{interceptors/index.d.ts → types/sdcorejs-angular-interceptors.d.ts} +0 -0
  173. /package/{models/index.d.ts → types/sdcorejs-angular-models.d.ts} +0 -0
  174. /package/{modules/auth/index.d.ts → types/sdcorejs-angular-modules-auth.d.ts} +0 -0
  175. /package/{modules/authom/index.d.ts → types/sdcorejs-angular-modules-authom.d.ts} +0 -0
  176. /package/{modules/keycloak/index.d.ts → types/sdcorejs-angular-modules-keycloak.d.ts} +0 -0
  177. /package/{modules/layout/index.d.ts → types/sdcorejs-angular-modules-layout.d.ts} +0 -0
  178. /package/{modules/permission/index.d.ts → types/sdcorejs-angular-modules-permission.d.ts} +0 -0
  179. /package/{modules/index.d.ts → types/sdcorejs-angular-modules.d.ts} +0 -0
  180. /package/{pipes/index.d.ts → types/sdcorejs-angular-pipes.d.ts} +0 -0
  181. /package/{services/api/index.d.ts → types/sdcorejs-angular-services-api.d.ts} +0 -0
  182. /package/{services/cache/index.d.ts → types/sdcorejs-angular-services-cache.d.ts} +0 -0
  183. /package/{services/confirm/index.d.ts → types/sdcorejs-angular-services-confirm.d.ts} +0 -0
  184. /package/{services/docx/index.d.ts → types/sdcorejs-angular-services-docx.d.ts} +0 -0
  185. /package/{services/excel/index.d.ts → types/sdcorejs-angular-services-excel.d.ts} +0 -0
  186. /package/{services/license/index.d.ts → types/sdcorejs-angular-services-license.d.ts} +0 -0
  187. /package/{services/loading/index.d.ts → types/sdcorejs-angular-services-loading.d.ts} +0 -0
  188. /package/{services/notify/index.d.ts → types/sdcorejs-angular-services-notify.d.ts} +0 -0
  189. /package/{services/storage/index.d.ts → types/sdcorejs-angular-services-storage.d.ts} +0 -0
  190. /package/{services/index.d.ts → types/sdcorejs-angular-services.d.ts} +0 -0
  191. /package/{utilities/data-state/index.d.ts → types/sdcorejs-angular-utilities-data-state.d.ts} +0 -0
  192. /package/{utilities/extensions/index.d.ts → types/sdcorejs-angular-utilities-extensions.d.ts} +0 -0
  193. /package/{utilities/models/index.d.ts → types/sdcorejs-angular-utilities-models.d.ts} +0 -0
  194. /package/{utilities/index.d.ts → types/sdcorejs-angular-utilities.d.ts} +0 -0
  195. /package/{index.d.ts → types/sdcorejs-angular.d.ts} +0 -0
@@ -33,9 +33,9 @@ import { MatMenuModule } from '@angular/material/menu';
33
33
 
34
34
  class SdPageComponent {
35
35
  el = inject(ElementRef);
36
- title = input('', ...(ngDevMode ? [{ debugName: "title", alias: 'title' }] : [{ alias: 'title' }]));
37
- description = input('', ...(ngDevMode ? [{ debugName: "description", alias: 'description' }] : [{ alias: 'description' }]));
38
- noHeader = input(false, ...(ngDevMode ? [{ debugName: "noHeader", transform: booleanAttribute, alias: 'noHeader' }] : [{ transform: booleanAttribute, alias: 'noHeader' }]));
36
+ title = input('', { ...(ngDevMode ? { debugName: "title" } : /* istanbul ignore next */ {}), alias: 'title' });
37
+ description = input('', { ...(ngDevMode ? { debugName: "description" } : /* istanbul ignore next */ {}), alias: 'description' });
38
+ noHeader = input(false, { ...(ngDevMode ? { debugName: "noHeader" } : /* istanbul ignore next */ {}), transform: booleanAttribute, alias: 'noHeader' });
39
39
  constructor() {
40
40
  effect(() => {
41
41
  if (this.title()) {
@@ -43,10 +43,10 @@ class SdPageComponent {
43
43
  }
44
44
  });
45
45
  }
46
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
47
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.23", type: SdPageComponent, isStandalone: true, selector: "sd-page", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, noHeader: { classPropertyName: "noHeader", publicName: "noHeader", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (!noHeader()) {\n <div class=\"c-page-header bg-white\">\n <div class=\"p-16 d-flex align-items-center w-full justify-content-between\">\n <div class=\"d-flex\">\n <ng-content select=\"[headerLeft]\">\n <div class=\"d-flex flex-column\">\n <div class=\"T20M\">{{ title() }}</div>\n @if (description()) {\n <div class=\"T14R text-secondary mt-4\">{{ description() }}</div>\n }\n </div>\n </ng-content>\n </div>\n <ng-content select=\"[headerRight]\"></ng-content>\n </div>\n </div>\n}\n\n<div class=\"c-page-wrapper px-0\">\n <div class=\"c-page-content\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{height:100%;display:flex;flex-direction:column;background-color:#f9f9f9}.c-page-header{box-shadow:0 1px 2px #2f31361a;z-index:1;position:relative}.c-page-wrapper{flex:1;display:flex;flex-direction:row;width:100%;overflow-y:auto;max-height:100vh}.c-page-wrapper .c-page-content{flex:1;height:100%;width:100%}.c-page-wrapper .c-page-right{position:-webkit-sticky;position:sticky;top:0;height:100%;overflow-y:auto}\n"] });
46
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
47
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SdPageComponent, isStandalone: true, selector: "sd-page", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, noHeader: { classPropertyName: "noHeader", publicName: "noHeader", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (!noHeader()) {\n <div class=\"c-page-header bg-white\">\n <div class=\"p-16 d-flex align-items-center w-full justify-content-between\">\n <div class=\"d-flex\">\n <ng-content select=\"[headerLeft]\">\n <div class=\"d-flex flex-column\">\n <div class=\"T20M\">{{ title() }}</div>\n @if (description()) {\n <div class=\"T14R text-secondary mt-4\">{{ description() }}</div>\n }\n </div>\n </ng-content>\n </div>\n <ng-content select=\"[headerRight]\"></ng-content>\n </div>\n </div>\n}\n\n<div class=\"c-page-wrapper px-0\">\n <div class=\"c-page-content\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{height:100%;display:flex;flex-direction:column;background-color:#f9f9f9}.c-page-header{box-shadow:0 1px 2px #2f31361a;z-index:1;position:relative}.c-page-wrapper{flex:1;display:flex;flex-direction:row;width:100%;overflow-y:auto;max-height:100vh}.c-page-wrapper .c-page-content{flex:1;height:100%;width:100%}.c-page-wrapper .c-page-right{position:-webkit-sticky;position:sticky;top:0;height:100%;overflow-y:auto}\n"] });
48
48
  }
49
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdPageComponent, decorators: [{
49
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdPageComponent, decorators: [{
50
50
  type: Component,
51
51
  args: [{ selector: 'sd-page', template: "@if (!noHeader()) {\n <div class=\"c-page-header bg-white\">\n <div class=\"p-16 d-flex align-items-center w-full justify-content-between\">\n <div class=\"d-flex\">\n <ng-content select=\"[headerLeft]\">\n <div class=\"d-flex flex-column\">\n <div class=\"T20M\">{{ title() }}</div>\n @if (description()) {\n <div class=\"T14R text-secondary mt-4\">{{ description() }}</div>\n }\n </div>\n </ng-content>\n </div>\n <ng-content select=\"[headerRight]\"></ng-content>\n </div>\n </div>\n}\n\n<div class=\"c-page-wrapper px-0\">\n <div class=\"c-page-content\">\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{height:100%;display:flex;flex-direction:column;background-color:#f9f9f9}.c-page-header{box-shadow:0 1px 2px #2f31361a;z-index:1;position:relative}.c-page-wrapper{flex:1;display:flex;flex-direction:row;width:100%;overflow-y:auto;max-height:100vh}.c-page-wrapper .c-page-content{flex:1;height:100%;width:100%}.c-page-wrapper .c-page-right{position:-webkit-sticky;position:sticky;top:0;height:100%;overflow-y:auto}\n"] }]
52
52
  }], ctorParameters: () => [], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], noHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "noHeader", required: false }] }] } });
@@ -68,10 +68,10 @@ class SdLayoutStorageService {
68
68
  this.pinnedMenuGroup = this.sdStorageService.create('e81da122-5dab-4250-b309-64197fb19d44');
69
69
  // End
70
70
  }
71
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutStorageService, deps: [{ token: i1.SdStorageService }], target: i0.ɵɵFactoryTarget.Injectable });
72
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutStorageService, providedIn: 'root' });
71
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutStorageService, deps: [{ token: i1.SdStorageService }], target: i0.ɵɵFactoryTarget.Injectable });
72
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutStorageService, providedIn: 'root' });
73
73
  }
74
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutStorageService, decorators: [{
74
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutStorageService, decorators: [{
75
75
  type: Injectable,
76
76
  args: [{
77
77
  providedIn: 'root',
@@ -91,8 +91,8 @@ class SdLayoutService {
91
91
  // ==========================================
92
92
  // SHARED SIGNALS (STATE)
93
93
  // ==========================================
94
- userInfo = signal(undefined, ...(ngDevMode ? [{ debugName: "userInfo" }] : []));
95
- sidebar = signal(undefined, ...(ngDevMode ? [{ debugName: "sidebar" }] : []));
94
+ userInfo = signal(undefined, ...(ngDevMode ? [{ debugName: "userInfo" }] : /* istanbul ignore next */ []));
95
+ sidebar = signal(undefined, ...(ngDevMode ? [{ debugName: "sidebar" }] : /* istanbul ignore next */ []));
96
96
  constructor() {
97
97
  if (!this.#layoutConfiguration) {
98
98
  // WHY: cho phép layout module chạy không cần config (use case demo / khởi tạo nhanh).
@@ -144,11 +144,11 @@ class SdLayoutService {
144
144
  defaultTitle: 'Back Office',
145
145
  };
146
146
  }
147
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
148
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutService, providedIn: 'root' // Có thể đổi thành 'any' hoặc khai báo trong mảng providers của LayoutModule tùy kiến trúc của bạn
147
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
148
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutService, providedIn: 'root' // Có thể đổi thành 'any' hoặc khai báo trong mảng providers của LayoutModule tùy kiến trúc của bạn
149
149
  });
150
150
  }
151
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutService, decorators: [{
151
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutService, decorators: [{
152
152
  type: Injectable,
153
153
  args: [{
154
154
  providedIn: 'root' // Có thể đổi thành 'any' hoặc khai báo trong mảng providers của LayoutModule tùy kiến trúc của bạn
@@ -234,11 +234,11 @@ class MenuPipe {
234
234
  }, {});
235
235
  return Object.keys(hashData).length > 0 ? Utilities.hash(hashData) : uuid.v4();
236
236
  };
237
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: MenuPipe, deps: [{ token: i1$1.SdPermissionService }], target: i0.ɵɵFactoryTarget.Pipe });
238
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.23", ngImport: i0, type: MenuPipe, isStandalone: true, name: "menu" });
239
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: MenuPipe, providedIn: 'root' });
237
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MenuPipe, deps: [{ token: i1$1.SdPermissionService }], target: i0.ɵɵFactoryTarget.Pipe });
238
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: MenuPipe, isStandalone: true, name: "menu" });
239
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MenuPipe, providedIn: 'root' });
240
240
  }
241
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: MenuPipe, decorators: [{
241
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MenuPipe, decorators: [{
242
242
  type: Pipe,
243
243
  args: [{
244
244
  name: 'menu',
@@ -275,11 +275,11 @@ class MenuFocusPipe {
275
275
  #normalizePath = (p) => {
276
276
  return p.endsWith('/') ? p : p + '/';
277
277
  };
278
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: MenuFocusPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
279
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.23", ngImport: i0, type: MenuFocusPipe, isStandalone: true, name: "menuFocus" });
280
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: MenuFocusPipe, providedIn: 'root' });
278
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MenuFocusPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
279
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: MenuFocusPipe, isStandalone: true, name: "menuFocus" });
280
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MenuFocusPipe, providedIn: 'root' });
281
281
  }
282
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: MenuFocusPipe, decorators: [{
282
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: MenuFocusPipe, decorators: [{
283
283
  type: Pipe,
284
284
  args: [{
285
285
  name: 'menuFocus',
@@ -318,10 +318,10 @@ class HighlightSearchPipe {
318
318
  str = str.trim();
319
319
  return str;
320
320
  };
321
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HighlightSearchPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
322
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.23", ngImport: i0, type: HighlightSearchPipe, isStandalone: true, name: "highLightSearch" });
321
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HighlightSearchPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
322
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: HighlightSearchPipe, isStandalone: true, name: "highLightSearch" });
323
323
  }
324
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HighlightSearchPipe, decorators: [{
324
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HighlightSearchPipe, decorators: [{
325
325
  type: Pipe,
326
326
  args: [{
327
327
  name: 'highLightSearch',
@@ -336,10 +336,10 @@ let LayoutUserComponent$1 = class LayoutUserComponent {
336
336
  // ==========================================
337
337
  // SIGNAL INPUTS & OUTPUTS
338
338
  // ==========================================
339
- isMobileOrTablet = input(false, ...(ngDevMode ? [{ debugName: "isMobileOrTablet" }] : []));
340
- isMenuLock = input(false, ...(ngDevMode ? [{ debugName: "isMenuLock" }] : []));
341
- isShowSidebar = input(false, ...(ngDevMode ? [{ debugName: "isShowSidebar" }] : []));
342
- userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : []));
339
+ isMobileOrTablet = input(false, ...(ngDevMode ? [{ debugName: "isMobileOrTablet" }] : /* istanbul ignore next */ []));
340
+ isMenuLock = input(false, ...(ngDevMode ? [{ debugName: "isMenuLock" }] : /* istanbul ignore next */ []));
341
+ isShowSidebar = input(false, ...(ngDevMode ? [{ debugName: "isShowSidebar" }] : /* istanbul ignore next */ []));
342
+ userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : /* istanbul ignore next */ []));
343
343
  // Chuyển thành void vì các hàm emit hiện tại không truyền data
344
344
  menuClosed = output();
345
345
  menuOpened = output();
@@ -369,10 +369,10 @@ let LayoutUserComponent$1 = class LayoutUserComponent {
369
369
  onToggleMenuLock = (event) => {
370
370
  this.toggleMenuLock.emit(event);
371
371
  };
372
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: LayoutUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
373
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.23", type: LayoutUserComponent, isStandalone: true, selector: "lib-layout-user", inputs: { isMobileOrTablet: { classPropertyName: "isMobileOrTablet", publicName: "isMobileOrTablet", isSignal: true, isRequired: false, transformFunction: null }, isMenuLock: { classPropertyName: "isMenuLock", publicName: "isMenuLock", isSignal: true, isRequired: false, transformFunction: null }, isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { menuClosed: "menuClosed", menuOpened: "menuOpened", toggleMenuLock: "toggleMenuLock" }, ngImport: i0, template: "@let _userInfo = userInfo();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n<div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n @if (!isMobileOrTablet()) {\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\n <mat-icon style=\"color: #8c8c8c\">\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\n </mat-icon>\n </div>\n }\n</div>\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo.fullName || _userInfo.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\n</mat-menu>", styles: ["::ng-deep .c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0+* .cdk-overlay-pane{transform:translate(277px,83px)}.c-layout-user-wrapper{display:flex;flex-direction:column;align-items:center;width:60px;height:80px}.c-layout-user-wrapper .c-layout-user-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;cursor:pointer}.c-layout-user-wrapper .c-layout-icon-toggle{background-color:transparent;border-top:1px solid #f0f0f0;box-shadow:none;margin-top:10px;width:32px;height:40px;display:flex;justify-content:center;align-items:center;cursor:pointer}.c-user-menu-wrapper .c-user-info-wrapper{width:250px;padding:16px;display:flex;flex-direction:column;align-items:center;gap:8px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-avatar{width:40px;height:40px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-name{font-size:16px;font-weight:700;text-align:center}.c-user-menu-wrapper .c-user-info-wrapper .c-user-email{font-size:14px;color:#7a7a7a;text-align:center}.c-user-menu-wrapper .c-sign-button-wrapper{text-align:center;padding:16px 16px 8px;width:100%;border-top:1px solid #dee2e6}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options{all:unset;cursor:pointer;font-size:14px;display:flex;align-items:center;gap:8px}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.c-user-menu-wrapper .c-sign-button-wrapper .c-sign-button{width:100%;color:#000;padding:16px;font-weight:700;background-color:#eef0f2}.c-avatar{max-width:100%;object-fit:cover}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i1$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: SdAvatar, selector: "sd-avatar", inputs: ["src", "size"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
372
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: LayoutUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
373
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: LayoutUserComponent, isStandalone: true, selector: "lib-layout-user", inputs: { isMobileOrTablet: { classPropertyName: "isMobileOrTablet", publicName: "isMobileOrTablet", isSignal: true, isRequired: false, transformFunction: null }, isMenuLock: { classPropertyName: "isMenuLock", publicName: "isMenuLock", isSignal: true, isRequired: false, transformFunction: null }, isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { menuClosed: "menuClosed", menuOpened: "menuOpened", toggleMenuLock: "toggleMenuLock" }, ngImport: i0, template: "@let _userInfo = userInfo();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n<div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n @if (!isMobileOrTablet()) {\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\n <mat-icon style=\"color: #8c8c8c\">\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\n </mat-icon>\n </div>\n }\n</div>\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo.fullName || _userInfo.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\n</mat-menu>", styles: ["::ng-deep .c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0+* .cdk-overlay-pane{transform:translate(277px,83px)}.c-layout-user-wrapper{display:flex;flex-direction:column;align-items:center;width:60px;height:80px}.c-layout-user-wrapper .c-layout-user-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;cursor:pointer}.c-layout-user-wrapper .c-layout-icon-toggle{background-color:transparent;border-top:1px solid #f0f0f0;box-shadow:none;margin-top:10px;width:32px;height:40px;display:flex;justify-content:center;align-items:center;cursor:pointer}.c-user-menu-wrapper .c-user-info-wrapper{width:250px;padding:16px;display:flex;flex-direction:column;align-items:center;gap:8px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-avatar{width:40px;height:40px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-name{font-size:16px;font-weight:700;text-align:center}.c-user-menu-wrapper .c-user-info-wrapper .c-user-email{font-size:14px;color:#7a7a7a;text-align:center}.c-user-menu-wrapper .c-sign-button-wrapper{text-align:center;padding:16px 16px 8px;width:100%;border-top:1px solid #dee2e6}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options{all:unset;cursor:pointer;font-size:14px;display:flex;align-items:center;gap:8px}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.c-user-menu-wrapper .c-sign-button-wrapper .c-sign-button{width:100%;color:#000;padding:16px;font-weight:700;background-color:#eef0f2}.c-avatar{max-width:100%;object-fit:cover}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i1$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: SdAvatar, selector: "sd-avatar", inputs: ["src", "size"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
374
374
  };
375
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: LayoutUserComponent$1, decorators: [{
375
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: LayoutUserComponent$1, decorators: [{
376
376
  type: Component,
377
377
  args: [{ selector: 'lib-layout-user', imports: [MatMenuModule, MatButtonModule, MatIconModule, MatTooltipModule, SdAvatar, TranslatePipe], standalone: true, template: "@let _userInfo = userInfo();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n<div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n @if (!isMobileOrTablet()) {\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\n <mat-icon style=\"color: #8c8c8c\">\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\n </mat-icon>\n </div>\n }\n</div>\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo.fullName || _userInfo.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\n</mat-menu>", styles: ["::ng-deep .c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0+* .cdk-overlay-pane{transform:translate(277px,83px)}.c-layout-user-wrapper{display:flex;flex-direction:column;align-items:center;width:60px;height:80px}.c-layout-user-wrapper .c-layout-user-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;cursor:pointer}.c-layout-user-wrapper .c-layout-icon-toggle{background-color:transparent;border-top:1px solid #f0f0f0;box-shadow:none;margin-top:10px;width:32px;height:40px;display:flex;justify-content:center;align-items:center;cursor:pointer}.c-user-menu-wrapper .c-user-info-wrapper{width:250px;padding:16px;display:flex;flex-direction:column;align-items:center;gap:8px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-avatar{width:40px;height:40px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-name{font-size:16px;font-weight:700;text-align:center}.c-user-menu-wrapper .c-user-info-wrapper .c-user-email{font-size:14px;color:#7a7a7a;text-align:center}.c-user-menu-wrapper .c-sign-button-wrapper{text-align:center;padding:16px 16px 8px;width:100%;border-top:1px solid #dee2e6}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options{all:unset;cursor:pointer;font-size:14px;display:flex;align-items:center;gap:8px}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.c-user-menu-wrapper .c-sign-button-wrapper .c-sign-button{width:100%;color:#000;padding:16px;font-weight:700;background-color:#eef0f2}.c-avatar{max-width:100%;object-fit:cover}\n"] }]
378
378
  }], propDecorators: { isMobileOrTablet: [{ type: i0.Input, args: [{ isSignal: true, alias: "isMobileOrTablet", required: false }] }], isMenuLock: [{ type: i0.Input, args: [{ isSignal: true, alias: "isMenuLock", required: false }] }], isShowSidebar: [{ type: i0.Input, args: [{ isSignal: true, alias: "isShowSidebar", required: false }] }], userInfo: [{ type: i0.Input, args: [{ isSignal: true, alias: "userInfo", required: true }] }], menuClosed: [{ type: i0.Output, args: ["menuClosed"] }], menuOpened: [{ type: i0.Output, args: ["menuOpened"] }], toggleMenuLock: [{ type: i0.Output, args: ["toggleMenuLock"] }] } });
@@ -388,10 +388,10 @@ class SidebarComponent {
388
388
  // ==========================================
389
389
  // SIGNAL INPUTS & OUTPUTS
390
390
  // ==========================================
391
- isShowSidebar = input.required(...(ngDevMode ? [{ debugName: "isShowSidebar" }] : []));
392
- menus = input.required(...(ngDevMode ? [{ debugName: "menus" }] : []));
393
- userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : []));
394
- sidebar = input.required(...(ngDevMode ? [{ debugName: "sidebar" }] : []));
391
+ isShowSidebar = input.required(...(ngDevMode ? [{ debugName: "isShowSidebar" }] : /* istanbul ignore next */ []));
392
+ menus = input.required(...(ngDevMode ? [{ debugName: "menus" }] : /* istanbul ignore next */ []));
393
+ userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : /* istanbul ignore next */ []));
394
+ sidebar = input.required(...(ngDevMode ? [{ debugName: "sidebar" }] : /* istanbul ignore next */ []));
395
395
  expandSideBar = output();
396
396
  popupUserMenuClosed = output();
397
397
  popupUserMenuOpened = output();
@@ -401,30 +401,30 @@ class SidebarComponent {
401
401
  // ==========================================
402
402
  screenHeight = window.innerHeight;
403
403
  isMobileOrTablet = BrowserUtilities.isMobile();
404
- isMenuLock = signal(this.#layoutStorageService.menuLockStatus?.get() ?? true, ...(ngDevMode ? [{ debugName: "isMenuLock" }] : []));
405
- currentPath = signal(window.location.pathname, ...(ngDevMode ? [{ debugName: "currentPath" }] : []));
406
- searchText = signal('', ...(ngDevMode ? [{ debugName: "searchText" }] : []));
407
- titleMenuGroup = signal('', ...(ngDevMode ? [{ debugName: "titleMenuGroup" }] : []));
408
- idMenuGroupActive = signal('', ...(ngDevMode ? [{ debugName: "idMenuGroupActive" }] : []));
409
- menusByGroup = signal([], ...(ngDevMode ? [{ debugName: "menusByGroup" }] : []));
410
- #hoveredMenuNodeKey = signal(null, ...(ngDevMode ? [{ debugName: "#hoveredMenuNodeKey" }] : []));
411
- #pinIconHoverTimerId = signal(null, ...(ngDevMode ? [{ debugName: "#pinIconHoverTimerId" }] : []));
404
+ isMenuLock = signal(this.#layoutStorageService.menuLockStatus?.get() ?? true, ...(ngDevMode ? [{ debugName: "isMenuLock" }] : /* istanbul ignore next */ []));
405
+ currentPath = signal(window.location.pathname, ...(ngDevMode ? [{ debugName: "currentPath" }] : /* istanbul ignore next */ []));
406
+ searchText = signal('', ...(ngDevMode ? [{ debugName: "searchText" }] : /* istanbul ignore next */ []));
407
+ titleMenuGroup = signal('', ...(ngDevMode ? [{ debugName: "titleMenuGroup" }] : /* istanbul ignore next */ []));
408
+ idMenuGroupActive = signal('', ...(ngDevMode ? [{ debugName: "idMenuGroupActive" }] : /* istanbul ignore next */ []));
409
+ menusByGroup = signal([], ...(ngDevMode ? [{ debugName: "menusByGroup" }] : /* istanbul ignore next */ []));
410
+ #hoveredMenuNodeKey = signal(null, ...(ngDevMode ? [{ debugName: "#hoveredMenuNodeKey" }] : /* istanbul ignore next */ []));
411
+ #pinIconHoverTimerId = signal(null, ...(ngDevMode ? [{ debugName: "#pinIconHoverTimerId" }] : /* istanbul ignore next */ []));
412
412
  pinnedMenuGroup = signal(this.#layoutStorageService.pinnedMenuGroup.get() ?? {
413
413
  id: 'pinned-menu-group',
414
414
  title: 'Đã ghim',
415
415
  children: [],
416
- }, ...(ngDevMode ? [{ debugName: "pinnedMenuGroup" }] : []));
416
+ }, ...(ngDevMode ? [{ debugName: "pinnedMenuGroup" }] : /* istanbul ignore next */ []));
417
417
  // ==========================================
418
418
  // COMPUTED STATE
419
419
  // ==========================================
420
- totalMenuInMenusByGroup = computed(() => this.#getTotalMenus(this.menusByGroup()), ...(ngDevMode ? [{ debugName: "totalMenuInMenusByGroup" }] : []));
421
- pinnedNodeKeys = computed(() => new Set(this.pinnedMenuGroup().children?.map(m => this.#getMenuNodeKey(m)) ?? []), ...(ngDevMode ? [{ debugName: "pinnedNodeKeys" }] : []));
422
- isPinnedMenuGroupActive = computed(() => this.idMenuGroupActive() === this.pinnedMenuGroup().id, ...(ngDevMode ? [{ debugName: "isPinnedMenuGroupActive" }] : []));
420
+ totalMenuInMenusByGroup = computed(() => this.#getTotalMenus(this.menusByGroup()), ...(ngDevMode ? [{ debugName: "totalMenuInMenusByGroup" }] : /* istanbul ignore next */ []));
421
+ pinnedNodeKeys = computed(() => new Set(this.pinnedMenuGroup().children?.map(m => this.#getMenuNodeKey(m)) ?? []), ...(ngDevMode ? [{ debugName: "pinnedNodeKeys" }] : /* istanbul ignore next */ []));
422
+ isPinnedMenuGroupActive = computed(() => this.idMenuGroupActive() === this.pinnedMenuGroup().id, ...(ngDevMode ? [{ debugName: "isPinnedMenuGroupActive" }] : /* istanbul ignore next */ []));
423
423
  // ==========================================
424
424
  // DATA STRUCTURES
425
425
  // ==========================================
426
426
  #pinIconHoverTimerDelay = 300;
427
- #isFirstBindingMenu = signal(true, ...(ngDevMode ? [{ debugName: "#isFirstBindingMenu" }] : []));
427
+ #isFirstBindingMenu = signal(true, ...(ngDevMode ? [{ debugName: "#isFirstBindingMenu" }] : /* istanbul ignore next */ []));
428
428
  dataSource = new MatTreeNestedDataSource();
429
429
  treeControl = new NestedTreeControl(node => ('children' in node && node.children?.length ? node.children : []));
430
430
  constructor() {
@@ -892,10 +892,10 @@ class SidebarComponent {
892
892
  }
893
893
  return count;
894
894
  };
895
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
896
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.23", type: SidebarComponent, isStandalone: true, selector: "sidebar", inputs: { isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: true, transformFunction: null }, menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: true, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { expandSideBar: "expandSideBar", popupUserMenuClosed: "popupUserMenuClosed", popupUserMenuOpened: "popupUserMenuOpened", showSideBar: "showSideBar" }, ngImport: i0, template: "@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div class=\"wrapper\" [style.height]=\"isMobileOrTablet ? screenHeight + 'px' : '100%'\">\n <div class=\"c-header\">\n @if (_sidebar.logoUrl) {\n <div class=\"c-logo\">\n <a href=\"javascript:;\" (click)=\"openHomePage()\">\n <img alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n </a>\n </div>\n }\n <div class=\"c-title-menu-group\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && pinnedMenuGroup().children?.length) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, pinnedMenuGroup())\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, pinnedMenuGroup())\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'\u0110\u00E3 ghim'\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <mat-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive() ? _sidebar.brandColor || '#2962FF' : '#8C8C8C',\n backgroundColor: isPinnedMenuGroupActive() ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n push_pin\n </mat-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <mat-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandColor || '#2962FF' : '#8C8C8C',\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n {{ nodeMenuGroup.icon || 'widgets' }}\n </mat-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\">\n @if (totalMenuInMenusByGroup() >= 10) {\n <div style=\"padding: 0px 4px\" class=\"c-menu-tree-search\">\n <sd-input size=\"sm\" [placeholder]=\"'core.module.layout.sidebar.search' | translate\" [model]=\"searchText()\" (sdChange)=\"onFilterSearchText($event)\">\n <ng-template sdSuffixDef>\n @if (searchText()) {\n <mat-icon class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\">cancel</mat-icon>\n } @else {\n <mat-icon class=\"c-search-prefix-icon search\">search</mat-icon>\n }\n </ng-template>\n </sd-input>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <li\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor: (currentPath() | menuFocus: node) ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n <div aria-hidden=\"true\" class=\"c-menu-node-description\" (click)=\"navigate(node)\" [class.d-none]=\"!isShowSidebar()\">\n <div\n class=\"c-menu-node-description-content\"\n [ngStyle]=\"{\n color: (currentPath() | menuFocus: node) ? _sidebar.brandColor || '#2962FF' : '#1F1F1F',\n }\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n\n @if (_sidebar?.pin?.enabled) {\n <mat-icon\n class=\"c-menu-node-description-icon-pin\"\n [fontSet]=\"isPinnedNode(node) ? 'material-icons' : 'material-icons-outlined'\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"isPinnedNode(node) || isHoveredNode(node) ? sidebar().brandColor || '#2962FF' : null\"\n (click)=\"onTogglePin($event, node)\"\n >push_pin\n </mat-icon>\n }\n </div>\n </li>\n </mat-nested-tree-node>\n\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n aria-hidden=\"true\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: currentPath() | menuFocus: node }\">\n <li>\n <div\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <div [class.d-none]=\"!isShowSidebar()\" class=\"c-menu-node-description\" (click)=\"onToggleMenuNode(node)\">\n <div\n class=\"c-menu-node-description-content\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n <mat-icon class=\"c-menu-node-description-icon-expand\">\n {{ treeControl.isExpanded(node) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </div>\n </div>\n </div>\n <ul class=\"p-0\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </ul>\n </li>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobileOrTablet\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </lib-layout-user>\n </div>\n\n <div class=\"c-vertical\"></div>\n </div>\n}\n", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host ::ng-deep .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:16px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:32px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:48px!important}ul,li{margin-top:0;margin-bottom:0;list-style-type:none}.wrapper{display:flex;flex-direction:column;width:290px;background-color:#fff}.wrapper .c-header{display:flex;align-items:center;height:52px;padding:3px;gap:16px}.wrapper .c-header .c-logo{display:flex;justify-content:center;align-items:center;width:52px;height:52px}.wrapper .c-header .c-logo img{width:32px;height:32px;object-fit:cover}.wrapper .c-header .c-title-menu-group{display:flex;align-items:center;font-size:18px;font-weight:500;flex:1}.wrapper .c-body{flex:1;overflow-y:hidden}.wrapper .c-body .c-menu{height:100%;display:flex}.wrapper .c-body .c-menu .c-menu-group{display:flex;flex-direction:column;align-items:center;width:60px;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon{display:flex;justify-content:center;align-items:center;min-height:50px;width:52px;border-radius:8px;transition:all .15s}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon img{height:24px;width:24px;object-fit:contain}.wrapper .c-body .c-menu .c-menu-tree{flex:1;display:flex;flex-direction:column;padding:3px 4px 3px 3px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon{cursor:pointer;color:#757575;padding:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.search{width:20px;height:20px;font-size:18px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.cancel{width:16px;height:16px;font-size:16px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container{flex:1;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node{width:100%;display:flex;cursor:pointer;min-height:44px;padding:8px;border-radius:8px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-icon{display:flex;justify-content:center;align-items:center;height:100%}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description{flex:1;display:flex;align-items:center}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-content{flex:1;display:flex;align-items:center;flex-wrap:wrap;white-space:pre-wrap;font-size:15px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-expand{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:20px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:18px;opacity:0}.wrapper .c-footer{height:80px}.wrapper .c-vertical{position:fixed;height:100vh;left:58px;width:2px;background-color:#f8f9fa;pointer-events:none}\n"], dependencies: [{ kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTreeModule }, { kind: "directive", type: i3.MatNestedTreeNode, selector: "mat-nested-tree-node", inputs: ["matNestedTreeNode", "disabled", "tabIndex"], outputs: ["activation", "expandedChange"], exportAs: ["matNestedTreeNode"] }, { kind: "directive", type: i3.MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "component", type: i3.MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: i3.MatTreeNodeOutlet, selector: "[matTreeNodeOutlet]" }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: SdSuffixDefDirective, selector: "[sdSuffixDef]" }, { kind: "component", type: LayoutUserComponent$1, selector: "lib-layout-user", inputs: ["isMobileOrTablet", "isMenuLock", "isShowSidebar", "userInfo"], outputs: ["menuClosed", "menuOpened", "toggleMenuLock"] }, { kind: "pipe", type: SdSafeHtmlPipe, name: "sdSafeHtml" }, { kind: "pipe", type: MenuFocusPipe, name: "menuFocus" }, { kind: "pipe", type: HighlightSearchPipe, name: "highLightSearch" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
895
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
896
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SidebarComponent, isStandalone: true, selector: "sidebar", inputs: { isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: true, transformFunction: null }, menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: true, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { expandSideBar: "expandSideBar", popupUserMenuClosed: "popupUserMenuClosed", popupUserMenuOpened: "popupUserMenuOpened", showSideBar: "showSideBar" }, ngImport: i0, template: "@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div class=\"wrapper\" [style.height]=\"isMobileOrTablet ? screenHeight + 'px' : '100%'\">\n <div class=\"c-header\">\n @if (_sidebar.logoUrl) {\n <div class=\"c-logo\">\n <a href=\"javascript:;\" (click)=\"openHomePage()\">\n <img alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n </a>\n </div>\n }\n <div class=\"c-title-menu-group\">\n <span>{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n </div>\n <div class=\"c-body\">\n <div class=\"c-menu\">\n <div class=\"c-menu-group\">\n @if (_sidebar?.pin?.enabled && pinnedMenuGroup().children?.length) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, pinnedMenuGroup())\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, pinnedMenuGroup())\"\n (click)=\"expandPinnedGroup()\"\n [matTooltip]=\"'\u0110\u00E3 ghim'\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n <mat-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: isPinnedMenuGroupActive() ? _sidebar.brandColor || '#2962FF' : '#8C8C8C',\n backgroundColor: isPinnedMenuGroupActive() ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n push_pin\n </mat-icon>\n </button>\n }\n @for (nodeMenuGroup of menus(); track nodeMenuGroup.id) {\n <button\n (mouseenter)=\"onMouseOverMenuGroupNode($event, nodeMenuGroup)\"\n (mouseleave)=\"onMouseLeaveMenuGroupNode($event, nodeMenuGroup)\"\n (click)=\"expandMenuGroup(nodeMenuGroup)\"\n [matTooltip]=\"nodeMenuGroup.tooltipTitle || nodeMenuGroup.title\"\n [matTooltipClass]=\"'c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140'\"\n [matTooltipPosition]=\"'right'\"\n style=\"padding: 0; margin: 0; border: none; background-color: transparent\">\n @if (nodeMenuGroup.iconUrl) {\n <span\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n <img width=\"24px\" height=\"24px\" [src]=\"nodeMenuGroup.iconUrl\" [alt]=\"nodeMenuGroup.title\" />\n </span>\n } @else {\n <mat-icon\n class=\"c-menu-group-icon\"\n [ngStyle]=\"{\n color: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandColor || '#2962FF' : '#8C8C8C',\n backgroundColor: idMenuGroupActive() === nodeMenuGroup?.id ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n {{ nodeMenuGroup.icon || 'widgets' }}\n </mat-icon>\n }\n </button>\n }\n </div>\n <div class=\"c-menu-tree\">\n @if (totalMenuInMenusByGroup() >= 10) {\n <div style=\"padding: 0px 4px\" class=\"c-menu-tree-search\">\n <sd-input size=\"sm\" [placeholder]=\"'core.module.layout.sidebar.search' | translate\" [model]=\"searchText()\" (sdChange)=\"onFilterSearchText($event)\">\n <ng-template sdSuffixDef>\n @if (searchText()) {\n <mat-icon class=\"c-search-prefix-icon cancel\" (click)=\"onClearSearchText()\">cancel</mat-icon>\n } @else {\n <mat-icon class=\"c-search-prefix-icon search\">search</mat-icon>\n }\n </ng-template>\n </sd-input>\n </div>\n }\n <div class=\"c-menu-tree-container\">\n <mat-tree [dataSource]=\"dataSource\" [treeControl]=\"treeControl\" [style.backgroundColor]=\"'transparent'\">\n <mat-nested-tree-node *matTreeNodeDef=\"let node; when: !hasChild\">\n <li\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\"\n [ngStyle]=\"{\n backgroundColor: (currentPath() | menuFocus: node) ? _sidebar.brandLightColor || '#F8F9FA' : 'transparent',\n }\">\n <div aria-hidden=\"true\" class=\"c-menu-node-description\" (click)=\"navigate(node)\" [class.d-none]=\"!isShowSidebar()\">\n <div\n class=\"c-menu-node-description-content\"\n [ngStyle]=\"{\n color: (currentPath() | menuFocus: node) ? _sidebar.brandColor || '#2962FF' : '#1F1F1F',\n }\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n\n @if (_sidebar?.pin?.enabled) {\n <mat-icon\n class=\"c-menu-node-description-icon-pin\"\n [fontSet]=\"isPinnedNode(node) ? 'material-icons' : 'material-icons-outlined'\"\n [style.opacity]=\"isPinnedNode(node) || isHoveredNode(node) ? '1' : null\"\n [style.color]=\"isPinnedNode(node) || isHoveredNode(node) ? sidebar().brandColor || '#2962FF' : null\"\n (click)=\"onTogglePin($event, node)\"\n >push_pin\n </mat-icon>\n }\n </div>\n </li>\n </mat-nested-tree-node>\n\n <mat-nested-tree-node\n *matTreeNodeDef=\"let node; when: hasChild\"\n aria-hidden=\"true\"\n [class]=\"{ expanded: treeControl.isExpanded(node), isfocus: currentPath() | menuFocus: node }\">\n <li>\n <div\n class=\"c-menu-node\"\n (mouseenter)=\"onMouseOverMenuNode($event, node)\"\n (mouseleave)=\"onMouseLeaveMenuNode($event, node)\">\n <div class=\"d-flex align-items-center\" style=\"gap: 10px; width: 100%\">\n <div [class.d-none]=\"!isShowSidebar()\" class=\"c-menu-node-description\" (click)=\"onToggleMenuNode(node)\">\n <div\n class=\"c-menu-node-description-content\"\n [innerHTML]=\"node.title | highLightSearch: searchText() | sdSafeHtml\"></div>\n <mat-icon class=\"c-menu-node-description-icon-expand\">\n {{ treeControl.isExpanded(node) ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </div>\n </div>\n </div>\n <ul class=\"p-0\" [class.d-none]=\"!treeControl.isExpanded(node)\">\n <ng-container matTreeNodeOutlet></ng-container>\n </ul>\n </li>\n </mat-nested-tree-node>\n </mat-tree>\n </div>\n </div>\n </div>\n </div>\n\n <div class=\"c-footer\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"isMobileOrTablet\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (toggleMenuLock)=\"toggleMenuLock($event)\">\n </lib-layout-user>\n </div>\n\n <div class=\"c-vertical\"></div>\n </div>\n}\n", styles: ["::ng-deep .mat-mdc-tooltip-panel:has(.c-tooltip-menu-group-7a22ab15-0083-4d4c-9c0c-00a30bc8c140){pointer-events:none}:host ::ng-deep .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:16px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:32px!important}:host ::ng-deep .mat-nested-tree-node ul .mat-nested-tree-node ul .mat-nested-tree-node ul .c-menu-node-description-content{margin-left:48px!important}ul,li{margin-top:0;margin-bottom:0;list-style-type:none}.wrapper{display:flex;flex-direction:column;width:290px;background-color:#fff}.wrapper .c-header{display:flex;align-items:center;height:52px;padding:3px;gap:16px}.wrapper .c-header .c-logo{display:flex;justify-content:center;align-items:center;width:52px;height:52px}.wrapper .c-header .c-logo img{width:32px;height:32px;object-fit:cover}.wrapper .c-header .c-title-menu-group{display:flex;align-items:center;font-size:18px;font-weight:500;flex:1}.wrapper .c-body{flex:1;overflow-y:hidden}.wrapper .c-body .c-menu{height:100%;display:flex}.wrapper .c-body .c-menu .c-menu-group{display:flex;flex-direction:column;align-items:center;width:60px;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon{display:flex;justify-content:center;align-items:center;min-height:50px;width:52px;border-radius:8px;transition:all .15s}.wrapper .c-body .c-menu .c-menu-group .c-menu-group-icon img{height:24px;width:24px;object-fit:contain}.wrapper .c-body .c-menu .c-menu-tree{flex:1;display:flex;flex-direction:column;padding:3px 4px 3px 3px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon{cursor:pointer;color:#757575;padding:0}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.search{width:20px;height:20px;font-size:18px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-search .c-search-prefix-icon.cancel{width:16px;height:16px;font-size:16px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container{flex:1;overflow-y:scroll;scrollbar-width:none}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node{width:100%;display:flex;cursor:pointer;min-height:44px;padding:8px;border-radius:8px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-icon{display:flex;justify-content:center;align-items:center;height:100%}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description{flex:1;display:flex;align-items:center}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-content{flex:1;display:flex;align-items:center;flex-wrap:wrap;white-space:pre-wrap;font-size:15px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-expand{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:20px}.wrapper .c-body .c-menu .c-menu-tree .c-menu-tree-container .c-menu-node .c-menu-node-description .c-menu-node-description-icon-pin{display:flex;align-items:center;justify-content:start;background-color:transparent;border:none;font-size:18px;opacity:0}.wrapper .c-footer{height:80px}.wrapper .c-vertical{position:fixed;height:100vh;left:58px;width:2px;background-color:#f8f9fa;pointer-events:none}\n"], dependencies: [{ kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "cleared", "sdFocusForceBlur"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTreeModule }, { kind: "directive", type: i3.MatNestedTreeNode, selector: "mat-nested-tree-node", inputs: ["matNestedTreeNode", "disabled", "tabIndex"], outputs: ["activation", "expandedChange"], exportAs: ["matNestedTreeNode"] }, { kind: "directive", type: i3.MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "component", type: i3.MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: i3.MatTreeNodeOutlet, selector: "[matTreeNodeOutlet]" }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: SdSuffixDefDirective, selector: "[sdSuffixDef]" }, { kind: "component", type: LayoutUserComponent$1, selector: "lib-layout-user", inputs: ["isMobileOrTablet", "isMenuLock", "isShowSidebar", "userInfo"], outputs: ["menuClosed", "menuOpened", "toggleMenuLock"] }, { kind: "pipe", type: SdSafeHtmlPipe, name: "sdSafeHtml" }, { kind: "pipe", type: MenuFocusPipe, name: "menuFocus" }, { kind: "pipe", type: HighlightSearchPipe, name: "highLightSearch" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
897
897
  }
898
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SidebarComponent, decorators: [{
898
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SidebarComponent, decorators: [{
899
899
  type: Component,
900
900
  args: [{ selector: 'sidebar', standalone: true, imports: [
901
901
  SdInput,
@@ -924,18 +924,18 @@ class SidebarV1Component {
924
924
  // VIEW CHILD & INPUTS
925
925
  // ==========================================
926
926
  sidenav = viewChild.required('sidenav');
927
- menus = input([], ...(ngDevMode ? [{ debugName: "menus" }] : []));
928
- userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : []));
929
- sidebar = input.required(...(ngDevMode ? [{ debugName: "sidebar" }] : []));
927
+ menus = input([], ...(ngDevMode ? [{ debugName: "menus" }] : /* istanbul ignore next */ []));
928
+ userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : /* istanbul ignore next */ []));
929
+ sidebar = input.required(...(ngDevMode ? [{ debugName: "sidebar" }] : /* istanbul ignore next */ []));
930
930
  // ==========================================
931
931
  // STATE SIGNALS
932
932
  // ==========================================
933
- isMobileOrTablet = signal(BrowserUtilities.isMobile(), ...(ngDevMode ? [{ debugName: "isMobileOrTablet" }] : []));
933
+ isMobileOrTablet = signal(BrowserUtilities.isMobile(), ...(ngDevMode ? [{ debugName: "isMobileOrTablet" }] : /* istanbul ignore next */ []));
934
934
  // Trạng thái khóa menu (luôn mở rộng hay không)
935
- isMenuLock = signal(this.#layoutStorageService.menuLockStatus?.get() ?? true, ...(ngDevMode ? [{ debugName: "isMenuLock" }] : []));
935
+ isMenuLock = signal(this.#layoutStorageService.menuLockStatus?.get() ?? true, ...(ngDevMode ? [{ debugName: "isMenuLock" }] : /* istanbul ignore next */ []));
936
936
  // Trạng thái hiển thị (mở/đóng) của Sidenav
937
- isShowSidebar = signal(BrowserUtilities.isMobile() ? false : (this.#layoutStorageService.menuLockStatus?.get() ?? true), ...(ngDevMode ? [{ debugName: "isShowSidebar" }] : []));
938
- onhover = signal(false, ...(ngDevMode ? [{ debugName: "onhover" }] : []));
937
+ isShowSidebar = signal(BrowserUtilities.isMobile() ? false : (this.#layoutStorageService.menuLockStatus?.get() ?? true), ...(ngDevMode ? [{ debugName: "isShowSidebar" }] : /* istanbul ignore next */ []));
938
+ onhover = signal(false, ...(ngDevMode ? [{ debugName: "onhover" }] : /* istanbul ignore next */ []));
939
939
  // ==========================================
940
940
  // PRIVATE TIMERS
941
941
  // ==========================================
@@ -1027,10 +1027,10 @@ class SidebarV1Component {
1027
1027
  }
1028
1028
  }
1029
1029
  };
1030
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SidebarV1Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
1031
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.23", type: SidebarV1Component, isStandalone: true, selector: "sidebar-v1", inputs: { menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "sidenav", first: true, predicate: ["sidenav"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-sidenav-container class=\"c-layout-wrapper\">\n <mat-sidenav\n #sidenav\n [opened]=\"isShowSidebar()\"\n (openedChange)=\"isShowSidebar.set($event)\"\n class=\"c-layout-sidebar\"\n (click)=\"openSidebar()\"\n (mouseleave)=\"onMouseleaveSideBar()\"\n [mode]=\"isMobileOrTablet() ? 'over' : 'side'\"\n [fixedInViewport]=\"isMobileOrTablet()\">\n <sidebar\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\">\n </sidebar>\n </mat-sidenav>\n\n <mat-sidenav-content class=\"c-layout-content\" [class.isShowSidebar]=\"isMenuLock()\">\n <mat-drawer-container class=\"c-mat-drawer-container\">\n <mat-drawer-content>\n <ng-content></ng-content>\n </mat-drawer-content>\n </mat-drawer-container>\n </mat-sidenav-content>\n</mat-sidenav-container>", styles: [":host ::ng-deep .c-layout-wrapper{width:100%}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar{margin-top:0;width:60px;height:100vh!important;transform:none!important;overflow:hidden!important;visibility:visible!important;transition:width .15s!important;box-shadow:0 0 6px #0003!important}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar .mat-drawer-inner-container{position:relative;overflow:visible;display:block!important}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar.mat-drawer-opened{width:290px;transition:width .15s}:host ::ng-deep .c-layout-wrapper .c-layout-content{background-color:#fff;box-sizing:border-box;height:100vh!important;margin-left:60px!important}:host ::ng-deep .c-layout-wrapper .c-layout-content.isShowSidebar{margin-left:290px!important}:host ::ng-deep .c-layout-wrapper .c-layout-content .c-mat-drawer-container{height:100%}\n"], dependencies: [{ kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1$5.MatDrawerContainer, selector: "mat-drawer-container", inputs: ["autosize", "hasBackdrop"], outputs: ["backdropClick"], exportAs: ["matDrawerContainer"] }, { kind: "component", type: i1$5.MatDrawerContent, selector: "mat-drawer-content" }, { kind: "component", type: i1$5.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1$5.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1$5.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: SidebarComponent, selector: "sidebar", inputs: ["isShowSidebar", "menus", "userInfo", "sidebar"], outputs: ["expandSideBar", "popupUserMenuClosed", "popupUserMenuOpened", "showSideBar"] }] });
1030
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SidebarV1Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
1031
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.15", type: SidebarV1Component, isStandalone: true, selector: "sidebar-v1", inputs: { menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "sidenav", first: true, predicate: ["sidenav"], descendants: true, isSignal: true }], ngImport: i0, template: "<mat-sidenav-container class=\"c-layout-wrapper\">\n <mat-sidenav\n #sidenav\n [opened]=\"isShowSidebar()\"\n (openedChange)=\"isShowSidebar.set($event)\"\n class=\"c-layout-sidebar\"\n (click)=\"openSidebar()\"\n (mouseleave)=\"onMouseleaveSideBar()\"\n [mode]=\"isMobileOrTablet() ? 'over' : 'side'\"\n [fixedInViewport]=\"isMobileOrTablet()\">\n <sidebar\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\">\n </sidebar>\n </mat-sidenav>\n\n <mat-sidenav-content class=\"c-layout-content\" [class.isShowSidebar]=\"isMenuLock()\">\n <mat-drawer-container class=\"c-mat-drawer-container\">\n <mat-drawer-content>\n <ng-content></ng-content>\n </mat-drawer-content>\n </mat-drawer-container>\n </mat-sidenav-content>\n</mat-sidenav-container>", styles: [":host ::ng-deep .c-layout-wrapper{width:100%}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar{margin-top:0;width:60px;height:100vh!important;transform:none!important;overflow:hidden!important;visibility:visible!important;transition:width .15s!important;box-shadow:0 0 6px #0003!important}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar .mat-drawer-inner-container{position:relative;overflow:visible;display:block!important}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar.mat-drawer-opened{width:290px;transition:width .15s}:host ::ng-deep .c-layout-wrapper .c-layout-content{background-color:#fff;box-sizing:border-box;height:100vh!important;margin-left:60px!important}:host ::ng-deep .c-layout-wrapper .c-layout-content.isShowSidebar{margin-left:290px!important}:host ::ng-deep .c-layout-wrapper .c-layout-content .c-mat-drawer-container{height:100%}\n"], dependencies: [{ kind: "ngmodule", type: MatSidenavModule }, { kind: "component", type: i1$5.MatDrawerContainer, selector: "mat-drawer-container", inputs: ["autosize", "hasBackdrop"], outputs: ["backdropClick"], exportAs: ["matDrawerContainer"] }, { kind: "component", type: i1$5.MatDrawerContent, selector: "mat-drawer-content" }, { kind: "component", type: i1$5.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i1$5.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i1$5.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: SidebarComponent, selector: "sidebar", inputs: ["isShowSidebar", "menus", "userInfo", "sidebar"], outputs: ["expandSideBar", "popupUserMenuClosed", "popupUserMenuOpened", "showSideBar"] }] });
1032
1032
  }
1033
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SidebarV1Component, decorators: [{
1033
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SidebarV1Component, decorators: [{
1034
1034
  type: Component,
1035
1035
  args: [{ selector: 'sidebar-v1', imports: [MatSidenavModule, CommonModule, SidebarComponent], standalone: true, template: "<mat-sidenav-container class=\"c-layout-wrapper\">\n <mat-sidenav\n #sidenav\n [opened]=\"isShowSidebar()\"\n (openedChange)=\"isShowSidebar.set($event)\"\n class=\"c-layout-sidebar\"\n (click)=\"openSidebar()\"\n (mouseleave)=\"onMouseleaveSideBar()\"\n [mode]=\"isMobileOrTablet() ? 'over' : 'side'\"\n [fixedInViewport]=\"isMobileOrTablet()\">\n <sidebar\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\">\n </sidebar>\n </mat-sidenav>\n\n <mat-sidenav-content class=\"c-layout-content\" [class.isShowSidebar]=\"isMenuLock()\">\n <mat-drawer-container class=\"c-mat-drawer-container\">\n <mat-drawer-content>\n <ng-content></ng-content>\n </mat-drawer-content>\n </mat-drawer-container>\n </mat-sidenav-content>\n</mat-sidenav-container>", styles: [":host ::ng-deep .c-layout-wrapper{width:100%}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar{margin-top:0;width:60px;height:100vh!important;transform:none!important;overflow:hidden!important;visibility:visible!important;transition:width .15s!important;box-shadow:0 0 6px #0003!important}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar .mat-drawer-inner-container{position:relative;overflow:visible;display:block!important}:host ::ng-deep .c-layout-wrapper .c-layout-sidebar.mat-drawer-opened{width:290px;transition:width .15s}:host ::ng-deep .c-layout-wrapper .c-layout-content{background-color:#fff;box-sizing:border-box;height:100vh!important;margin-left:60px!important}:host ::ng-deep .c-layout-wrapper .c-layout-content.isShowSidebar{margin-left:290px!important}:host ::ng-deep .c-layout-wrapper .c-layout-content .c-mat-drawer-container{height:100%}\n"] }]
1036
1036
  }], ctorParameters: () => [], propDecorators: { sidenav: [{ type: i0.ViewChild, args: ['sidenav', { isSignal: true }] }], menus: [{ type: i0.Input, args: [{ isSignal: true, alias: "menus", required: false }] }], userInfo: [{ type: i0.Input, args: [{ isSignal: true, alias: "userInfo", required: true }] }], sidebar: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebar", required: true }] }] } });
@@ -1043,10 +1043,10 @@ class LayoutUserComponent {
1043
1043
  // ==========================================
1044
1044
  // SIGNAL INPUTS & OUTPUTS
1045
1045
  // ==========================================
1046
- isMobileOrTablet = input(false, ...(ngDevMode ? [{ debugName: "isMobileOrTablet" }] : []));
1047
- isMenuLock = input(false, ...(ngDevMode ? [{ debugName: "isMenuLock" }] : []));
1048
- isShowSidebar = input(false, ...(ngDevMode ? [{ debugName: "isShowSidebar" }] : []));
1049
- userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : []));
1046
+ isMobileOrTablet = input(false, ...(ngDevMode ? [{ debugName: "isMobileOrTablet" }] : /* istanbul ignore next */ []));
1047
+ isMenuLock = input(false, ...(ngDevMode ? [{ debugName: "isMenuLock" }] : /* istanbul ignore next */ []));
1048
+ isShowSidebar = input(false, ...(ngDevMode ? [{ debugName: "isShowSidebar" }] : /* istanbul ignore next */ []));
1049
+ userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : /* istanbul ignore next */ []));
1050
1050
  menuClosed = output();
1051
1051
  menuOpened = output();
1052
1052
  toggleMenuLock = output();
@@ -1054,7 +1054,7 @@ class LayoutUserComponent {
1054
1054
  singoutLayoutConfig = this.#layoutConfiguration.signout;
1055
1055
  changePasswordLayoutConfig = this.#layoutConfiguration?.changePassword;
1056
1056
  // Accordion state for mobile inline expand
1057
- isExpanded = signal(false, ...(ngDevMode ? [{ debugName: "isExpanded" }] : []));
1057
+ isExpanded = signal(false, ...(ngDevMode ? [{ debugName: "isExpanded" }] : /* istanbul ignore next */ []));
1058
1058
  // ==========================================
1059
1059
  // EVENT HANDLERS
1060
1060
  // ==========================================
@@ -1085,10 +1085,10 @@ class LayoutUserComponent {
1085
1085
  onToggleMenuLock = (event) => {
1086
1086
  this.toggleMenuLock.emit(event);
1087
1087
  };
1088
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: LayoutUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1089
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.23", type: LayoutUserComponent, isStandalone: true, selector: "lib-layout-user", inputs: { isMobileOrTablet: { classPropertyName: "isMobileOrTablet", publicName: "isMobileOrTablet", isSignal: true, isRequired: false, transformFunction: null }, isMenuLock: { classPropertyName: "isMenuLock", publicName: "isMenuLock", isSignal: true, isRequired: false, transformFunction: null }, isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { menuClosed: "menuClosed", menuOpened: "menuOpened", toggleMenuLock: "toggleMenuLock" }, ngImport: i0, template: "@let _userInfo = userInfo();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n@if (isMobileOrTablet()) {\n <!-- Mobile: accordion inline expand -->\n <div class=\"m-user-card\">\n <button class=\"m-user-row\" (click)=\"toggleExpanded()\">\n <sd-avatar [src]=\"avatar\" [size]=\"44\"></sd-avatar>\n <div class=\"m-user-info\">\n <span class=\"m-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\n @if (_userInfo?.email) {\n <span class=\"m-user-email\">{{ _userInfo?.email }}</span>\n }\n </div>\n <mat-icon class=\"m-expand-icon\" [class.m-expand-icon--open]=\"isExpanded()\">\n keyboard_arrow_down\n </mat-icon>\n </button>\n\n @if (isExpanded()) {\n <div class=\"m-user-body\">\n @if (changePasswordLayoutConfig) {\n <button class=\"m-user-action\" (click)=\"changePassword()\">\n <mat-icon>lock_outline</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n }\n <button class=\"m-user-action m-user-action--logout\" (click)=\"logout()\">\n <mat-icon>logout</mat-icon>\n <span>{{ 'core.module.layout.user.logout' | translate }}</span>\n </button>\n </div>\n }\n </div>\n} @else {\n <!-- Desktop: ch\u1EC9 hi\u1EC3n th\u1ECB avatar + n\u00FAt toggle -->\n <div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\n <mat-icon style=\"color: #8c8c8c\">\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\n </mat-icon>\n </div>\n </div>\n}\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo?.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\n</mat-menu>\n", styles: ["@media(min-width:1024px){::ng-deep .c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0+* .cdk-overlay-pane{transform:translate(277px,83px)}}.m-user-card{width:100%}.m-user-row{display:flex;align-items:center;gap:12px;width:100%;padding:0;border:none;background:transparent;cursor:pointer;text-align:left;-webkit-tap-highlight-color:transparent}.m-user-info{flex:1;display:flex;flex-direction:column;gap:2px;overflow:hidden}.m-user-name{font-size:15px;font-weight:600;color:#1f1f1f;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.m-user-email{font-size:13px;color:#8c8c8c;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.m-expand-icon{color:#8c8c8c;flex-shrink:0;transition:transform .2s ease}.m-expand-icon--open{transform:rotate(180deg)}.m-user-body{margin-top:8px;border-top:1px solid #EBEBEB;padding-top:4px;display:flex;flex-direction:column}.m-user-action{display:flex;align-items:center;gap:12px;width:100%;padding:12px 4px;border:none;background:transparent;cursor:pointer;font-size:15px;color:#1f1f1f;-webkit-tap-highlight-color:transparent}.m-user-action mat-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}.m-user-action:active{background-color:#f5f5f5}.m-user-action--logout{color:#e53935}.m-user-action--logout mat-icon{color:#e53935}.c-layout-user-wrapper{display:flex;flex-direction:column;align-items:center;width:60px;height:80px}.c-layout-user-wrapper .c-layout-user-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;cursor:pointer}.c-layout-user-wrapper .c-layout-icon-toggle{background-color:transparent;border-top:1px solid #f0f0f0;box-shadow:none;margin-top:10px;width:32px;height:40px;display:flex;justify-content:center;align-items:center;cursor:pointer}.c-user-menu-wrapper .c-user-info-wrapper{width:250px;padding:16px;display:flex;flex-direction:column;align-items:center;gap:8px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-avatar{width:40px;height:40px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-name{font-size:16px;font-weight:700;text-align:center}.c-user-menu-wrapper .c-user-info-wrapper .c-user-email{font-size:14px;color:#7a7a7a;text-align:center}.c-user-menu-wrapper .c-sign-button-wrapper{text-align:center;padding:16px 16px 8px;width:100%;border-top:1px solid #dee2e6}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options{all:unset;cursor:pointer;font-size:14px;display:flex;align-items:center;gap:8px}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.c-user-menu-wrapper .c-sign-button-wrapper .c-sign-button{width:100%;color:#000;padding:16px;font-weight:700;background-color:#eef0f2}.c-avatar{max-width:100%;object-fit:cover}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i1$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: SdAvatar, selector: "sd-avatar", inputs: ["src", "size"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1088
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: LayoutUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1089
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: LayoutUserComponent, isStandalone: true, selector: "lib-layout-user", inputs: { isMobileOrTablet: { classPropertyName: "isMobileOrTablet", publicName: "isMobileOrTablet", isSignal: true, isRequired: false, transformFunction: null }, isMenuLock: { classPropertyName: "isMenuLock", publicName: "isMenuLock", isSignal: true, isRequired: false, transformFunction: null }, isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { menuClosed: "menuClosed", menuOpened: "menuOpened", toggleMenuLock: "toggleMenuLock" }, ngImport: i0, template: "@let _userInfo = userInfo();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n@if (isMobileOrTablet()) {\n <!-- Mobile: accordion inline expand -->\n <div class=\"m-user-card\">\n <button class=\"m-user-row\" (click)=\"toggleExpanded()\">\n <sd-avatar [src]=\"avatar\" [size]=\"44\"></sd-avatar>\n <div class=\"m-user-info\">\n <span class=\"m-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\n @if (_userInfo?.email) {\n <span class=\"m-user-email\">{{ _userInfo?.email }}</span>\n }\n </div>\n <mat-icon class=\"m-expand-icon\" [class.m-expand-icon--open]=\"isExpanded()\">\n keyboard_arrow_down\n </mat-icon>\n </button>\n\n @if (isExpanded()) {\n <div class=\"m-user-body\">\n @if (changePasswordLayoutConfig) {\n <button class=\"m-user-action\" (click)=\"changePassword()\">\n <mat-icon>lock_outline</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n }\n <button class=\"m-user-action m-user-action--logout\" (click)=\"logout()\">\n <mat-icon>logout</mat-icon>\n <span>{{ 'core.module.layout.user.logout' | translate }}</span>\n </button>\n </div>\n }\n </div>\n} @else {\n <!-- Desktop: ch\u1EC9 hi\u1EC3n th\u1ECB avatar + n\u00FAt toggle -->\n <div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\n <mat-icon style=\"color: #8c8c8c\">\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\n </mat-icon>\n </div>\n </div>\n}\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo?.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\n</mat-menu>\n", styles: ["@media(min-width:1024px){::ng-deep .c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0+* .cdk-overlay-pane{transform:translate(277px,83px)}}.m-user-card{width:100%}.m-user-row{display:flex;align-items:center;gap:12px;width:100%;padding:0;border:none;background:transparent;cursor:pointer;text-align:left;-webkit-tap-highlight-color:transparent}.m-user-info{flex:1;display:flex;flex-direction:column;gap:2px;overflow:hidden}.m-user-name{font-size:15px;font-weight:600;color:#1f1f1f;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.m-user-email{font-size:13px;color:#8c8c8c;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.m-expand-icon{color:#8c8c8c;flex-shrink:0;transition:transform .2s ease}.m-expand-icon--open{transform:rotate(180deg)}.m-user-body{margin-top:8px;border-top:1px solid #EBEBEB;padding-top:4px;display:flex;flex-direction:column}.m-user-action{display:flex;align-items:center;gap:12px;width:100%;padding:12px 4px;border:none;background:transparent;cursor:pointer;font-size:15px;color:#1f1f1f;-webkit-tap-highlight-color:transparent}.m-user-action mat-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}.m-user-action:active{background-color:#f5f5f5}.m-user-action--logout{color:#e53935}.m-user-action--logout mat-icon{color:#e53935}.c-layout-user-wrapper{display:flex;flex-direction:column;align-items:center;width:60px;height:80px}.c-layout-user-wrapper .c-layout-user-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;cursor:pointer}.c-layout-user-wrapper .c-layout-icon-toggle{background-color:transparent;border-top:1px solid #f0f0f0;box-shadow:none;margin-top:10px;width:32px;height:40px;display:flex;justify-content:center;align-items:center;cursor:pointer}.c-user-menu-wrapper .c-user-info-wrapper{width:250px;padding:16px;display:flex;flex-direction:column;align-items:center;gap:8px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-avatar{width:40px;height:40px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-name{font-size:16px;font-weight:700;text-align:center}.c-user-menu-wrapper .c-user-info-wrapper .c-user-email{font-size:14px;color:#7a7a7a;text-align:center}.c-user-menu-wrapper .c-sign-button-wrapper{text-align:center;padding:16px 16px 8px;width:100%;border-top:1px solid #dee2e6}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options{all:unset;cursor:pointer;font-size:14px;display:flex;align-items:center;gap:8px}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.c-user-menu-wrapper .c-sign-button-wrapper .c-sign-button{width:100%;color:#000;padding:16px;font-weight:700;background-color:#eef0f2}.c-avatar{max-width:100%;object-fit:cover}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$2.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: i1$2.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "component", type: SdAvatar, selector: "sd-avatar", inputs: ["src", "size"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1090
1090
  }
1091
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: LayoutUserComponent, decorators: [{
1091
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: LayoutUserComponent, decorators: [{
1092
1092
  type: Component,
1093
1093
  args: [{ selector: 'lib-layout-user', imports: [MatMenuModule, MatButtonModule, MatIconModule, MatTooltipModule, SdAvatar, TranslatePipe], standalone: true, template: "@let _userInfo = userInfo();\n@let avatar = _userInfo?.avatar || _userInfo?.fullName || _userInfo?.username || _userInfo?.email;\n\n@if (isMobileOrTablet()) {\n <!-- Mobile: accordion inline expand -->\n <div class=\"m-user-card\">\n <button class=\"m-user-row\" (click)=\"toggleExpanded()\">\n <sd-avatar [src]=\"avatar\" [size]=\"44\"></sd-avatar>\n <div class=\"m-user-info\">\n <span class=\"m-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\n @if (_userInfo?.email) {\n <span class=\"m-user-email\">{{ _userInfo?.email }}</span>\n }\n </div>\n <mat-icon class=\"m-expand-icon\" [class.m-expand-icon--open]=\"isExpanded()\">\n keyboard_arrow_down\n </mat-icon>\n </button>\n\n @if (isExpanded()) {\n <div class=\"m-user-body\">\n @if (changePasswordLayoutConfig) {\n <button class=\"m-user-action\" (click)=\"changePassword()\">\n <mat-icon>lock_outline</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n }\n <button class=\"m-user-action m-user-action--logout\" (click)=\"logout()\">\n <mat-icon>logout</mat-icon>\n <span>{{ 'core.module.layout.user.logout' | translate }}</span>\n </button>\n </div>\n }\n </div>\n} @else {\n <!-- Desktop: ch\u1EC9 hi\u1EC3n th\u1ECB avatar + n\u00FAt toggle -->\n <div class=\"c-layout-user-wrapper\">\n <div class=\"c-layout-user-avatar\" [matMenuTriggerFor]=\"userMenu\" (menuClosed)=\"onMenuClosed()\" (menuOpened)=\"onMenuOpened()\">\n <sd-avatar [src]=\"avatar\" [size]=\"32\"></sd-avatar>\n </div>\n\n <div aria-hidden=\"true\" mat-mini-fab class=\"c-layout-icon-toggle\" (click)=\"onToggleMenuLock($event)\">\n <mat-icon style=\"color: #8c8c8c\">\n {{ isShowSidebar() ? 'keyboard_arrow_right' : 'keyboard_arrow_left' }}\n </mat-icon>\n </div>\n </div>\n}\n\n<mat-menu #userMenu=\"matMenu\" xPosition=\"before\" backdropClass=\"c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0\">\n <div aria-hidden=\"true\" class=\"c-user-menu-wrapper\" (click)=\"keepOpenWhenClickInsideMenu($event)\">\n <div class=\"c-user-info-wrapper\">\n <div class=\"c-user-avatar\">\n <sd-avatar [src]=\"avatar\" [size]=\"40\"></sd-avatar>\n </div>\n <span class=\"c-user-name\">{{ _userInfo?.fullName || _userInfo?.username }}</span>\n <span class=\"c-user-email\">{{ _userInfo?.email }}</span>\n </div>\n\n @if (changePasswordLayoutConfig) {\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-account-options\" (click)=\"changePassword()\">\n <mat-icon fontSet=\"material-icons-outlined\">lock</mat-icon>\n <span>{{ 'core.module.layout.user.change-password' | translate }}</span>\n </button>\n </div>\n }\n\n <div class=\"c-sign-button-wrapper\">\n <button class=\"c-sign-button\" mat-flat-button (click)=\"logout()\">{{ 'core.module.layout.user.logout' | translate }}</button>\n </div>\n </div>\n</mat-menu>\n", styles: ["@media(min-width:1024px){::ng-deep .c-user-menu-backdrop-f90ce131-fa4c-4f71-a49b-ab7fa374fdd0+* .cdk-overlay-pane{transform:translate(277px,83px)}}.m-user-card{width:100%}.m-user-row{display:flex;align-items:center;gap:12px;width:100%;padding:0;border:none;background:transparent;cursor:pointer;text-align:left;-webkit-tap-highlight-color:transparent}.m-user-info{flex:1;display:flex;flex-direction:column;gap:2px;overflow:hidden}.m-user-name{font-size:15px;font-weight:600;color:#1f1f1f;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.m-user-email{font-size:13px;color:#8c8c8c;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.m-expand-icon{color:#8c8c8c;flex-shrink:0;transition:transform .2s ease}.m-expand-icon--open{transform:rotate(180deg)}.m-user-body{margin-top:8px;border-top:1px solid #EBEBEB;padding-top:4px;display:flex;flex-direction:column}.m-user-action{display:flex;align-items:center;gap:12px;width:100%;padding:12px 4px;border:none;background:transparent;cursor:pointer;font-size:15px;color:#1f1f1f;-webkit-tap-highlight-color:transparent}.m-user-action mat-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}.m-user-action:active{background-color:#f5f5f5}.m-user-action--logout{color:#e53935}.m-user-action--logout mat-icon{color:#e53935}.c-layout-user-wrapper{display:flex;flex-direction:column;align-items:center;width:60px;height:80px}.c-layout-user-wrapper .c-layout-user-avatar{width:32px;height:32px;display:flex;align-items:center;justify-content:center;cursor:pointer}.c-layout-user-wrapper .c-layout-icon-toggle{background-color:transparent;border-top:1px solid #f0f0f0;box-shadow:none;margin-top:10px;width:32px;height:40px;display:flex;justify-content:center;align-items:center;cursor:pointer}.c-user-menu-wrapper .c-user-info-wrapper{width:250px;padding:16px;display:flex;flex-direction:column;align-items:center;gap:8px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-avatar{width:40px;height:40px}.c-user-menu-wrapper .c-user-info-wrapper .c-user-name{font-size:16px;font-weight:700;text-align:center}.c-user-menu-wrapper .c-user-info-wrapper .c-user-email{font-size:14px;color:#7a7a7a;text-align:center}.c-user-menu-wrapper .c-sign-button-wrapper{text-align:center;padding:16px 16px 8px;width:100%;border-top:1px solid #dee2e6}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options{all:unset;cursor:pointer;font-size:14px;display:flex;align-items:center;gap:8px}.c-user-menu-wrapper .c-sign-button-wrapper .c-account-options mat-icon{font-size:21px;width:21px;height:21px;color:#8c8c8c}.c-user-menu-wrapper .c-sign-button-wrapper .c-sign-button{width:100%;color:#000;padding:16px;font-weight:700;background-color:#eef0f2}.c-avatar{max-width:100%;object-fit:cover}\n"] }]
1094
1094
  }], propDecorators: { isMobileOrTablet: [{ type: i0.Input, args: [{ isSignal: true, alias: "isMobileOrTablet", required: false }] }], isMenuLock: [{ type: i0.Input, args: [{ isSignal: true, alias: "isMenuLock", required: false }] }], isShowSidebar: [{ type: i0.Input, args: [{ isSignal: true, alias: "isShowSidebar", required: false }] }], userInfo: [{ type: i0.Input, args: [{ isSignal: true, alias: "userInfo", required: true }] }], menuClosed: [{ type: i0.Output, args: ["menuClosed"] }], menuOpened: [{ type: i0.Output, args: ["menuOpened"] }], toggleMenuLock: [{ type: i0.Output, args: ["toggleMenuLock"] }] } });
@@ -1100,10 +1100,10 @@ class SidebarMobileOverlayComponent {
1100
1100
  // ==========================================
1101
1101
  // INPUTS & OUTPUTS
1102
1102
  // ==========================================
1103
- isShowSidebar = input(false, ...(ngDevMode ? [{ debugName: "isShowSidebar" }] : []));
1104
- menus = input.required(...(ngDevMode ? [{ debugName: "menus" }] : []));
1105
- userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : []));
1106
- sidebar = input.required(...(ngDevMode ? [{ debugName: "sidebar" }] : []));
1103
+ isShowSidebar = input(false, ...(ngDevMode ? [{ debugName: "isShowSidebar" }] : /* istanbul ignore next */ []));
1104
+ menus = input.required(...(ngDevMode ? [{ debugName: "menus" }] : /* istanbul ignore next */ []));
1105
+ userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : /* istanbul ignore next */ []));
1106
+ sidebar = input.required(...(ngDevMode ? [{ debugName: "sidebar" }] : /* istanbul ignore next */ []));
1107
1107
  // showSideBar(null) = đóng sidebar (tương thích với onToggle của main component)
1108
1108
  showSideBar = output();
1109
1109
  expandSideBar = output();
@@ -1113,10 +1113,10 @@ class SidebarMobileOverlayComponent {
1113
1113
  // ==========================================
1114
1114
  // STATE SIGNALS
1115
1115
  // ==========================================
1116
- titleMenuGroup = signal('', ...(ngDevMode ? [{ debugName: "titleMenuGroup" }] : []));
1117
- currentPath = signal(window.location.pathname, ...(ngDevMode ? [{ debugName: "currentPath" }] : []));
1116
+ titleMenuGroup = signal('', ...(ngDevMode ? [{ debugName: "titleMenuGroup" }] : /* istanbul ignore next */ []));
1117
+ currentPath = signal(window.location.pathname, ...(ngDevMode ? [{ debugName: "currentPath" }] : /* istanbul ignore next */ []));
1118
1118
  // Lưu danh sách ID các menu group đang được mở
1119
- expandedMobileGroups = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedMobileGroups" }] : []));
1119
+ expandedMobileGroups = signal(new Set(), ...(ngDevMode ? [{ debugName: "expandedMobileGroups" }] : /* istanbul ignore next */ []));
1120
1120
  constructor() {
1121
1121
  // Bind title khi menus thay đổi
1122
1122
  effect(() => {
@@ -1239,10 +1239,10 @@ class SidebarMobileOverlayComponent {
1239
1239
  return this.#normalizePath(this.currentPath()).startsWith(this.#normalizePath(path));
1240
1240
  };
1241
1241
  #normalizePath = (p) => p.endsWith('/') ? p : p + '/';
1242
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SidebarMobileOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1243
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.23", type: SidebarMobileOverlayComponent, isStandalone: true, selector: "sd-sidebar-mobile-overlay", inputs: { isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: false, transformFunction: null }, menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: true, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { showSideBar: "showSideBar", expandSideBar: "expandSideBar", popupUserMenuOpened: "popupUserMenuOpened", popupUserMenuClosed: "popupUserMenuClosed", titleMenuGroupChanged: "titleMenuGroupChanged" }, ngImport: i0, template: "@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div\n class=\"m-backdrop\"\n [class.m-backdrop--visible]=\"isShowSidebar()\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onClose()\"\n (keydown.escape)=\"onClose()\">\n </div>\n\n <div class=\"m-wrapper\" [class.m-wrapper--open]=\"isShowSidebar()\">\n <div class=\"m-header\">\n <div class=\"m-title-group\">\n @if (_sidebar.logoUrl) {\n <img class=\"m-logo\" alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n }\n <span class=\"m-title\">{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n <button class=\"m-close-btn\" (click)=\"onClose()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n\n <div class=\"m-user-section\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"true\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\">\n </lib-layout-user>\n </div>\n\n <div class=\"m-menu-list\">\n @for (group of menus(); track group.id) {\n <div class=\"m-menu-card\">\n <button class=\"m-card-header\" (click)=\"toggleMobileGroup(group.id)\">\n <div class=\"m-card-header-left\">\n @if (group.iconUrl) {\n <img class=\"m-group-icon\" [src]=\"group.iconUrl\" [alt]=\"group.title\" />\n } @else {\n <mat-icon class=\"m-group-icon\">{{ group.icon || 'widgets' }}</mat-icon>\n }\n <span class=\"m-group-title\">{{ group.title }}</span>\n </div>\n <mat-icon class=\"m-expand-icon\">\n {{ expandedMobileGroups().has(group.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </button>\n\n @if (expandedMobileGroups().has(group.id ?? '') && hasChildren(group)) {\n <div class=\"m-card-body\">\n @for (child of getChildren(group); track child.id) {\n @if (hasChildren(child)) {\n <div class=\"m-sub-group\">\n <button class=\"m-sub-group-header\" (click)=\"toggleMobileGroup(child.id)\">\n <div class=\"m-item-left\">\n @if (child.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'folder' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ child.title }}</span>\n </div>\n <mat-icon class=\"m-expand-icon\">\n {{ expandedMobileGroups().has(child.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </button>\n @if (expandedMobileGroups().has(child.id ?? '')) {\n @for (subChild of getChildren(child); track subChild.id) {\n <button class=\"m-menu-item m-menu-item--indented\"\n (click)=\"navigate({ path: getPath(subChild), queryParams: getQueryParams(subChild) })\">\n <div class=\"m-item-left\">\n @if (subChild.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"subChild.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ subChild.icon || 'insert_drive_file' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ subChild.title }}</span>\n </div>\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\n </button>\n }\n }\n </div>\n } @else {\n <button class=\"m-menu-item\" (click)=\"navigate({ path: getPath(child), queryParams: getQueryParams(child) })\">\n <div class=\"m-item-left\">\n @if (child.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'insert_drive_file' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ child.title }}</span>\n </div>\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\n </button>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n}\n", styles: [":host{display:block;position:fixed;inset:0;z-index:1000;pointer-events:none}.m-backdrop{position:absolute;inset:0;background:#0006;opacity:0;pointer-events:none;transition:opacity .3s ease;cursor:pointer;outline:none}.m-backdrop--visible{opacity:1;pointer-events:auto}.m-wrapper{display:flex;flex-direction:column;position:absolute;inset:0;background-color:#f2f2f6;padding:16px;box-sizing:border-box;overflow-y:auto;pointer-events:none;padding-top:max(16px,env(safe-area-inset-top));padding-bottom:max(16px,env(safe-area-inset-bottom));transform:translate(-100%);transition:transform .3s cubic-bezier(.4,0,.2,1)}.m-wrapper--open{transform:translate(0);pointer-events:auto}.m-wrapper .m-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:24px}.m-wrapper .m-header .m-title-group{display:flex;align-items:center;gap:12px}.m-wrapper .m-header .m-title-group .m-logo{width:32px;height:32px;object-fit:contain}.m-wrapper .m-header .m-title-group .m-title{font-size:18px;font-weight:600;color:#1f1f1f}.m-wrapper .m-header .m-close-btn{background:transparent;border:none;padding:0;color:#1f1f1f;display:flex;align-items:center;justify-content:center;cursor:pointer}.m-wrapper .m-header .m-close-btn mat-icon{font-size:28px;width:28px;height:28px}.m-wrapper .m-user-section{background-color:#fff;border-radius:12px;padding:12px 16px;margin-bottom:24px;box-shadow:0 1px 2px #00000005;border:1px solid #EBEBEB}.m-wrapper .m-user-section lib-layout-user{display:block;width:100%}.m-wrapper .m-menu-list{display:flex;flex-direction:column;gap:16px}.m-wrapper .m-menu-card{background-color:#fff;border-radius:12px;border:1px solid #EBEBEB;overflow:hidden}.m-wrapper .m-menu-card .m-card-header{display:flex;justify-content:space-between;align-items:center;width:100%;padding:16px;cursor:pointer;-webkit-user-select:none;user-select:none;border:none;background:transparent;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-header .m-card-header-left{display:flex;align-items:center;gap:16px}.m-wrapper .m-menu-card .m-card-header .m-card-header-left .m-group-icon{font-size:24px;width:24px;height:24px;color:#1f1f1f;object-fit:contain}.m-wrapper .m-menu-card .m-card-header .m-card-header-left .m-group-title{font-size:16px;font-weight:600;color:#1f1f1f}.m-wrapper .m-menu-card .m-card-header .m-expand-icon{color:#1f1f1f;transition:transform .2s ease}.m-wrapper .m-menu-card .m-card-body{display:flex;flex-direction:column;padding-bottom:8px}.m-wrapper .m-menu-card .m-card-body .m-menu-item{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px 12px 24px;cursor:pointer;border:none;background:transparent;transition:background-color .2s;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-body .m-menu-item:active{background-color:#f5f5f5}.m-wrapper .m-menu-card .m-card-body .m-menu-item--indented{padding-left:48px}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left{display:flex;align-items:center;gap:12px}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-icon{font-size:20px;width:20px;height:20px;color:#8c8c8c}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-icon-img{width:20px;height:20px;object-fit:contain;opacity:.7}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-title{font-size:15px;color:#333}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-nav-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}.m-wrapper .m-menu-card .m-card-body .m-sub-group{border-top:1px solid #EBEBEB}.m-wrapper .m-menu-card .m-card-body .m-sub-group:first-child{border-top:none}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px 12px 24px;cursor:pointer;border:none;background:#fafafa;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header:active{background-color:#f0f0f0}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left{display:flex;align-items:center;gap:12px}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-icon{font-size:20px;width:20px;height:20px;color:#8c8c8c}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-icon-img{width:20px;height:20px;object-fit:contain;opacity:.7}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-title{font-size:15px;font-weight:500;color:#333}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-expand-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: LayoutUserComponent, selector: "lib-layout-user", inputs: ["isMobileOrTablet", "isMenuLock", "isShowSidebar", "userInfo"], outputs: ["menuClosed", "menuOpened", "toggleMenuLock"] }] });
1242
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SidebarMobileOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1243
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SidebarMobileOverlayComponent, isStandalone: true, selector: "sd-sidebar-mobile-overlay", inputs: { isShowSidebar: { classPropertyName: "isShowSidebar", publicName: "isShowSidebar", isSignal: true, isRequired: false, transformFunction: null }, menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: true, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { showSideBar: "showSideBar", expandSideBar: "expandSideBar", popupUserMenuOpened: "popupUserMenuOpened", popupUserMenuClosed: "popupUserMenuClosed", titleMenuGroupChanged: "titleMenuGroupChanged" }, ngImport: i0, template: "@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar) {\n <div\n class=\"m-backdrop\"\n [class.m-backdrop--visible]=\"isShowSidebar()\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onClose()\"\n (keydown.escape)=\"onClose()\">\n </div>\n\n <div class=\"m-wrapper\" [class.m-wrapper--open]=\"isShowSidebar()\">\n <div class=\"m-header\">\n <div class=\"m-title-group\">\n @if (_sidebar.logoUrl) {\n <img class=\"m-logo\" alt=\"logo\" [src]=\"_sidebar.logoUrl\" />\n }\n <span class=\"m-title\">{{ titleMenuGroup() || _sidebar.defaultTitle || 'Back Office' }}</span>\n </div>\n <button class=\"m-close-btn\" (click)=\"onClose()\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n\n <div class=\"m-user-section\">\n <lib-layout-user\n [userInfo]=\"_userInfo\"\n [isMobileOrTablet]=\"true\"\n (menuOpened)=\"onUserMenuOpened()\"\n (menuClosed)=\"onUserMenuClosed()\">\n </lib-layout-user>\n </div>\n\n <div class=\"m-menu-list\">\n @for (group of menus(); track group.id) {\n <div class=\"m-menu-card\">\n <button class=\"m-card-header\" (click)=\"toggleMobileGroup(group.id)\">\n <div class=\"m-card-header-left\">\n @if (group.iconUrl) {\n <img class=\"m-group-icon\" [src]=\"group.iconUrl\" [alt]=\"group.title\" />\n } @else {\n <mat-icon class=\"m-group-icon\">{{ group.icon || 'widgets' }}</mat-icon>\n }\n <span class=\"m-group-title\">{{ group.title }}</span>\n </div>\n <mat-icon class=\"m-expand-icon\">\n {{ expandedMobileGroups().has(group.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </button>\n\n @if (expandedMobileGroups().has(group.id ?? '') && hasChildren(group)) {\n <div class=\"m-card-body\">\n @for (child of getChildren(group); track child.id) {\n @if (hasChildren(child)) {\n <div class=\"m-sub-group\">\n <button class=\"m-sub-group-header\" (click)=\"toggleMobileGroup(child.id)\">\n <div class=\"m-item-left\">\n @if (child.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'folder' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ child.title }}</span>\n </div>\n <mat-icon class=\"m-expand-icon\">\n {{ expandedMobileGroups().has(child.id ?? '') ? 'keyboard_arrow_up' : 'keyboard_arrow_down' }}\n </mat-icon>\n </button>\n @if (expandedMobileGroups().has(child.id ?? '')) {\n @for (subChild of getChildren(child); track subChild.id) {\n <button class=\"m-menu-item m-menu-item--indented\"\n (click)=\"navigate({ path: getPath(subChild), queryParams: getQueryParams(subChild) })\">\n <div class=\"m-item-left\">\n @if (subChild.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"subChild.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ subChild.icon || 'insert_drive_file' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ subChild.title }}</span>\n </div>\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\n </button>\n }\n }\n </div>\n } @else {\n <button class=\"m-menu-item\" (click)=\"navigate({ path: getPath(child), queryParams: getQueryParams(child) })\">\n <div class=\"m-item-left\">\n @if (child.iconUrl) {\n <img class=\"m-item-icon-img\" [src]=\"child.iconUrl\" alt=\"icon\" />\n } @else {\n <mat-icon class=\"m-item-icon\">{{ child.icon || 'insert_drive_file' }}</mat-icon>\n }\n <span class=\"m-item-title\">{{ child.title }}</span>\n </div>\n <mat-icon class=\"m-nav-icon\">chevron_right</mat-icon>\n </button>\n }\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n}\n", styles: [":host{display:block;position:fixed;inset:0;z-index:1000;pointer-events:none}.m-backdrop{position:absolute;inset:0;background:#0006;opacity:0;pointer-events:none;transition:opacity .3s ease;cursor:pointer;outline:none}.m-backdrop--visible{opacity:1;pointer-events:auto}.m-wrapper{display:flex;flex-direction:column;position:absolute;inset:0;background-color:#f2f2f6;padding:16px;box-sizing:border-box;overflow-y:auto;pointer-events:none;padding-top:max(16px,env(safe-area-inset-top));padding-bottom:max(16px,env(safe-area-inset-bottom));transform:translate(-100%);transition:transform .3s cubic-bezier(.4,0,.2,1)}.m-wrapper--open{transform:translate(0);pointer-events:auto}.m-wrapper .m-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:24px}.m-wrapper .m-header .m-title-group{display:flex;align-items:center;gap:12px}.m-wrapper .m-header .m-title-group .m-logo{width:32px;height:32px;object-fit:contain}.m-wrapper .m-header .m-title-group .m-title{font-size:18px;font-weight:600;color:#1f1f1f}.m-wrapper .m-header .m-close-btn{background:transparent;border:none;padding:0;color:#1f1f1f;display:flex;align-items:center;justify-content:center;cursor:pointer}.m-wrapper .m-header .m-close-btn mat-icon{font-size:28px;width:28px;height:28px}.m-wrapper .m-user-section{background-color:#fff;border-radius:12px;padding:12px 16px;margin-bottom:24px;box-shadow:0 1px 2px #00000005;border:1px solid #EBEBEB}.m-wrapper .m-user-section lib-layout-user{display:block;width:100%}.m-wrapper .m-menu-list{display:flex;flex-direction:column;gap:16px}.m-wrapper .m-menu-card{background-color:#fff;border-radius:12px;border:1px solid #EBEBEB;overflow:hidden}.m-wrapper .m-menu-card .m-card-header{display:flex;justify-content:space-between;align-items:center;width:100%;padding:16px;cursor:pointer;-webkit-user-select:none;user-select:none;border:none;background:transparent;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-header .m-card-header-left{display:flex;align-items:center;gap:16px}.m-wrapper .m-menu-card .m-card-header .m-card-header-left .m-group-icon{font-size:24px;width:24px;height:24px;color:#1f1f1f;object-fit:contain}.m-wrapper .m-menu-card .m-card-header .m-card-header-left .m-group-title{font-size:16px;font-weight:600;color:#1f1f1f}.m-wrapper .m-menu-card .m-card-header .m-expand-icon{color:#1f1f1f;transition:transform .2s ease}.m-wrapper .m-menu-card .m-card-body{display:flex;flex-direction:column;padding-bottom:8px}.m-wrapper .m-menu-card .m-card-body .m-menu-item{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px 12px 24px;cursor:pointer;border:none;background:transparent;transition:background-color .2s;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-body .m-menu-item:active{background-color:#f5f5f5}.m-wrapper .m-menu-card .m-card-body .m-menu-item--indented{padding-left:48px}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left{display:flex;align-items:center;gap:12px}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-icon{font-size:20px;width:20px;height:20px;color:#8c8c8c}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-icon-img{width:20px;height:20px;object-fit:contain;opacity:.7}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-item-left .m-item-title{font-size:15px;color:#333}.m-wrapper .m-menu-card .m-card-body .m-menu-item .m-nav-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}.m-wrapper .m-menu-card .m-card-body .m-sub-group{border-top:1px solid #EBEBEB}.m-wrapper .m-menu-card .m-card-body .m-sub-group:first-child{border-top:none}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header{display:flex;justify-content:space-between;align-items:center;width:100%;padding:12px 16px 12px 24px;cursor:pointer;border:none;background:#fafafa;-webkit-tap-highlight-color:transparent}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header:active{background-color:#f0f0f0}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left{display:flex;align-items:center;gap:12px}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-icon{font-size:20px;width:20px;height:20px;color:#8c8c8c}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-icon-img{width:20px;height:20px;object-fit:contain;opacity:.7}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-item-left .m-item-title{font-size:15px;font-weight:500;color:#333}.m-wrapper .m-menu-card .m-card-body .m-sub-group .m-sub-group-header .m-expand-icon{color:#8c8c8c;font-size:20px;width:20px;height:20px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: LayoutUserComponent, selector: "lib-layout-user", inputs: ["isMobileOrTablet", "isMenuLock", "isShowSidebar", "userInfo"], outputs: ["menuClosed", "menuOpened", "toggleMenuLock"] }] });
1244
1244
  }
1245
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SidebarMobileOverlayComponent, decorators: [{
1245
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SidebarMobileOverlayComponent, decorators: [{
1246
1246
  type: Component,
1247
1247
  args: [{ selector: 'sd-sidebar-mobile-overlay', standalone: true, imports: [
1248
1248
  CommonModule,
@@ -1254,12 +1254,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImpo
1254
1254
 
1255
1255
  class SidebarMobileV1Component {
1256
1256
  #layoutStorageService = inject(SdLayoutStorageService);
1257
- menus = input([], ...(ngDevMode ? [{ debugName: "menus" }] : []));
1258
- userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : []));
1259
- sidebar = input.required(...(ngDevMode ? [{ debugName: "sidebar" }] : []));
1257
+ menus = input([], ...(ngDevMode ? [{ debugName: "menus" }] : /* istanbul ignore next */ []));
1258
+ userInfo = input.required(...(ngDevMode ? [{ debugName: "userInfo" }] : /* istanbul ignore next */ []));
1259
+ sidebar = input.required(...(ngDevMode ? [{ debugName: "sidebar" }] : /* istanbul ignore next */ []));
1260
1260
  // Sidebar luôn bắt đầu đóng trên mobile
1261
- isShowSidebar = signal(false, ...(ngDevMode ? [{ debugName: "isShowSidebar" }] : []));
1262
- titleMenuGroup = signal('', ...(ngDevMode ? [{ debugName: "titleMenuGroup" }] : []));
1261
+ isShowSidebar = signal(false, ...(ngDevMode ? [{ debugName: "isShowSidebar" }] : /* istanbul ignore next */ []));
1262
+ titleMenuGroup = signal('', ...(ngDevMode ? [{ debugName: "titleMenuGroup" }] : /* istanbul ignore next */ []));
1263
1263
  constructor() {
1264
1264
  effect(() => {
1265
1265
  const isShow = this.isShowSidebar();
@@ -1281,10 +1281,10 @@ class SidebarMobileV1Component {
1281
1281
  onTitleMenuGroupChanged = (title) => {
1282
1282
  this.titleMenuGroup.set(title);
1283
1283
  };
1284
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SidebarMobileV1Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
1285
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.23", type: SidebarMobileV1Component, isStandalone: true, selector: "sidebar-mobile-v1", inputs: { menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"c-mobile-layout\">\n <div class=\"c-mobile-topbar\">\n <div class=\"c-topbar-brand\">\n @if (sidebar().logoUrl) {\n <img class=\"c-topbar-logo\" [src]=\"sidebar().logoUrl\" alt=\"logo\" />\n }\n <span class=\"c-topbar-title\">{{ titleMenuGroup() || sidebar().defaultTitle || 'Back Office' }}</span>\n </div>\n <button class=\"c-hamburger-btn\" (click)=\"openSidebar()\">\n <mat-icon>menu</mat-icon>\n </button>\n </div>\n\n <div class=\"c-mobile-content\">\n <ng-content></ng-content>\n </div>\n\n <sd-sidebar-mobile-overlay\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\"\n (titleMenuGroupChanged)=\"onTitleMenuGroupChanged($event)\">\n </sd-sidebar-mobile-overlay>\n</div>\n", styles: [":host{display:block;height:100vh;position:relative;overflow:hidden}.c-mobile-layout{display:flex;flex-direction:column;height:100%;position:relative}.c-mobile-topbar{display:flex;align-items:center;justify-content:space-between;padding:0 16px;height:56px;background-color:#fff;border-bottom:1px solid #e0e0e0;flex-shrink:0}.c-mobile-topbar .c-topbar-brand{display:flex;align-items:center;gap:10px;overflow:hidden}.c-mobile-topbar .c-topbar-brand .c-topbar-logo{width:28px;height:28px;object-fit:contain;flex-shrink:0}.c-mobile-topbar .c-topbar-brand .c-topbar-title{font-size:16px;font-weight:600;color:#1f1f1f;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.c-mobile-topbar .c-hamburger-btn{display:flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:6px;border-radius:50%;color:#333;flex-shrink:0}.c-mobile-topbar .c-hamburger-btn:hover{background-color:#0000000f}.c-mobile-content{flex:1;overflow-y:auto}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: SidebarMobileOverlayComponent, selector: "sd-sidebar-mobile-overlay", inputs: ["isShowSidebar", "menus", "userInfo", "sidebar"], outputs: ["showSideBar", "expandSideBar", "popupUserMenuOpened", "popupUserMenuClosed", "titleMenuGroupChanged"] }] });
1284
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SidebarMobileV1Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
1285
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SidebarMobileV1Component, isStandalone: true, selector: "sidebar-mobile-v1", inputs: { menus: { classPropertyName: "menus", publicName: "menus", isSignal: true, isRequired: false, transformFunction: null }, userInfo: { classPropertyName: "userInfo", publicName: "userInfo", isSignal: true, isRequired: true, transformFunction: null }, sidebar: { classPropertyName: "sidebar", publicName: "sidebar", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"c-mobile-layout\">\n <div class=\"c-mobile-topbar\">\n <div class=\"c-topbar-brand\">\n @if (sidebar().logoUrl) {\n <img class=\"c-topbar-logo\" [src]=\"sidebar().logoUrl\" alt=\"logo\" />\n }\n <span class=\"c-topbar-title\">{{ titleMenuGroup() || sidebar().defaultTitle || 'Back Office' }}</span>\n </div>\n <button class=\"c-hamburger-btn\" (click)=\"openSidebar()\">\n <mat-icon>menu</mat-icon>\n </button>\n </div>\n\n <div class=\"c-mobile-content\">\n <ng-content></ng-content>\n </div>\n\n <sd-sidebar-mobile-overlay\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\"\n (titleMenuGroupChanged)=\"onTitleMenuGroupChanged($event)\">\n </sd-sidebar-mobile-overlay>\n</div>\n", styles: [":host{display:block;height:100vh;position:relative;overflow:hidden}.c-mobile-layout{display:flex;flex-direction:column;height:100%;position:relative}.c-mobile-topbar{display:flex;align-items:center;justify-content:space-between;padding:0 16px;height:56px;background-color:#fff;border-bottom:1px solid #e0e0e0;flex-shrink:0}.c-mobile-topbar .c-topbar-brand{display:flex;align-items:center;gap:10px;overflow:hidden}.c-mobile-topbar .c-topbar-brand .c-topbar-logo{width:28px;height:28px;object-fit:contain;flex-shrink:0}.c-mobile-topbar .c-topbar-brand .c-topbar-title{font-size:16px;font-weight:600;color:#1f1f1f;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.c-mobile-topbar .c-hamburger-btn{display:flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:6px;border-radius:50%;color:#333;flex-shrink:0}.c-mobile-topbar .c-hamburger-btn:hover{background-color:#0000000f}.c-mobile-content{flex:1;overflow-y:auto}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: CommonModule }, { kind: "component", type: SidebarMobileOverlayComponent, selector: "sd-sidebar-mobile-overlay", inputs: ["isShowSidebar", "menus", "userInfo", "sidebar"], outputs: ["showSideBar", "expandSideBar", "popupUserMenuOpened", "popupUserMenuClosed", "titleMenuGroupChanged"] }] });
1286
1286
  }
1287
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SidebarMobileV1Component, decorators: [{
1287
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SidebarMobileV1Component, decorators: [{
1288
1288
  type: Component,
1289
1289
  args: [{ selector: 'sidebar-mobile-v1', imports: [MatIconModule, CommonModule, SidebarMobileOverlayComponent], standalone: true, template: "<div class=\"c-mobile-layout\">\n <div class=\"c-mobile-topbar\">\n <div class=\"c-topbar-brand\">\n @if (sidebar().logoUrl) {\n <img class=\"c-topbar-logo\" [src]=\"sidebar().logoUrl\" alt=\"logo\" />\n }\n <span class=\"c-topbar-title\">{{ titleMenuGroup() || sidebar().defaultTitle || 'Back Office' }}</span>\n </div>\n <button class=\"c-hamburger-btn\" (click)=\"openSidebar()\">\n <mat-icon>menu</mat-icon>\n </button>\n </div>\n\n <div class=\"c-mobile-content\">\n <ng-content></ng-content>\n </div>\n\n <sd-sidebar-mobile-overlay\n [menus]=\"menus()\"\n [userInfo]=\"userInfo()\"\n [sidebar]=\"sidebar()\"\n [isShowSidebar]=\"isShowSidebar()\"\n (showSideBar)=\"onToggle($event)\"\n (expandSideBar)=\"onExpandSideBar()\"\n (popupUserMenuOpened)=\"onPopupOfSideBarOpened()\"\n (popupUserMenuClosed)=\"onPopupOfSideBarClosed()\"\n (titleMenuGroupChanged)=\"onTitleMenuGroupChanged($event)\">\n </sd-sidebar-mobile-overlay>\n</div>\n", styles: [":host{display:block;height:100vh;position:relative;overflow:hidden}.c-mobile-layout{display:flex;flex-direction:column;height:100%;position:relative}.c-mobile-topbar{display:flex;align-items:center;justify-content:space-between;padding:0 16px;height:56px;background-color:#fff;border-bottom:1px solid #e0e0e0;flex-shrink:0}.c-mobile-topbar .c-topbar-brand{display:flex;align-items:center;gap:10px;overflow:hidden}.c-mobile-topbar .c-topbar-brand .c-topbar-logo{width:28px;height:28px;object-fit:contain;flex-shrink:0}.c-mobile-topbar .c-topbar-brand .c-topbar-title{font-size:16px;font-weight:600;color:#1f1f1f;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.c-mobile-topbar .c-hamburger-btn{display:flex;align-items:center;justify-content:center;background:none;border:none;cursor:pointer;padding:6px;border-radius:50%;color:#333;flex-shrink:0}.c-mobile-topbar .c-hamburger-btn:hover{background-color:#0000000f}.c-mobile-content{flex:1;overflow-y:auto}\n"] }]
1290
1290
  }], ctorParameters: () => [], propDecorators: { menus: [{ type: i0.Input, args: [{ isSignal: true, alias: "menus", required: false }] }], userInfo: [{ type: i0.Input, args: [{ isSignal: true, alias: "userInfo", required: true }] }], sidebar: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebar", required: true }] }] } });
@@ -1298,18 +1298,18 @@ class SdLayoutComponent {
1298
1298
  // ==========================================
1299
1299
  // SIGNAL INPUTS
1300
1300
  // ==========================================
1301
- menusInput = input([], ...(ngDevMode ? [{ debugName: "menusInput", alias: 'menus' }] : [{ alias: 'menus' }]));
1302
- menus = computed(() => this.#menuPipe.transform(this.menusInput() || []), ...(ngDevMode ? [{ debugName: "menus" }] : []));
1301
+ menusInput = input([], { ...(ngDevMode ? { debugName: "menusInput" } : /* istanbul ignore next */ {}), alias: 'menus' });
1302
+ menus = computed(() => this.#menuPipe.transform(this.menusInput() || []), ...(ngDevMode ? [{ debugName: "menus" }] : /* istanbul ignore next */ []));
1303
1303
  // ==========================================
1304
1304
  // CONSUME SHARED STATE
1305
1305
  // ==========================================
1306
1306
  userInfo = this.#layoutService.userInfo;
1307
1307
  sidebar = this.#layoutService.sidebar;
1308
- isMobileOrTablet = signal(BrowserUtilities.isMobile(), ...(ngDevMode ? [{ debugName: "isMobileOrTablet" }] : []));
1309
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1310
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.23", type: SdLayoutComponent, isStandalone: true, selector: "sd-layout", inputs: { menusInput: { classPropertyName: "menusInput", publicName: "menus", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-template #projectedContent>\n <ng-content></ng-content>\n</ng-template>\n\n@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar?.version === 1) {\n @if (!isMobileOrTablet()) {\n <sidebar-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sidebar-v1>\n } @else {\n <sidebar-mobile-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sidebar-mobile-v1>\n }\n}\n", styles: [""], dependencies: [{ kind: "component", type: SidebarV1Component, selector: "sidebar-v1", inputs: ["menus", "userInfo", "sidebar"] }, { kind: "component", type: SidebarMobileV1Component, selector: "sidebar-mobile-v1", inputs: ["menus", "userInfo", "sidebar"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
1308
+ isMobileOrTablet = signal(BrowserUtilities.isMobile(), ...(ngDevMode ? [{ debugName: "isMobileOrTablet" }] : /* istanbul ignore next */ []));
1309
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1310
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: SdLayoutComponent, isStandalone: true, selector: "sd-layout", inputs: { menusInput: { classPropertyName: "menusInput", publicName: "menus", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ng-template #projectedContent>\n <ng-content></ng-content>\n</ng-template>\n\n@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar?.version === 1) {\n @if (!isMobileOrTablet()) {\n <sidebar-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sidebar-v1>\n } @else {\n <sidebar-mobile-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sidebar-mobile-v1>\n }\n}\n", styles: [""], dependencies: [{ kind: "component", type: SidebarV1Component, selector: "sidebar-v1", inputs: ["menus", "userInfo", "sidebar"] }, { kind: "component", type: SidebarMobileV1Component, selector: "sidebar-mobile-v1", inputs: ["menus", "userInfo", "sidebar"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
1311
1311
  }
1312
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutComponent, decorators: [{
1312
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutComponent, decorators: [{
1313
1313
  type: Component,
1314
1314
  args: [{ selector: 'sd-layout', imports: [SidebarV1Component, SidebarMobileV1Component, NgTemplateOutlet], standalone: true, template: "<ng-template #projectedContent>\n <ng-content></ng-content>\n</ng-template>\n\n@let _userInfo = userInfo();\n@let _sidebar = sidebar();\n\n@if (_userInfo && _sidebar?.version === 1) {\n @if (!isMobileOrTablet()) {\n <sidebar-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sidebar-v1>\n } @else {\n <sidebar-mobile-v1 [menus]=\"menus()\" [userInfo]=\"_userInfo\" [sidebar]=\"_sidebar!\">\n <ng-container [ngTemplateOutlet]=\"projectedContent\"></ng-container>\n </sidebar-mobile-v1>\n }\n}\n" }]
1315
1315
  }], propDecorators: { menusInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "menus", required: false }] }] } });
@@ -1334,7 +1334,7 @@ let HomePageComponent = class HomePageComponent {
1334
1334
  // SIGNALS (STATE)
1335
1335
  // ==========================================
1336
1336
  // Lấy snapshot một lần lúc khởi tạo và đưa vào signal
1337
- todayInfo = signal(this.#getTodayInfo(new Date()), ...(ngDevMode ? [{ debugName: "todayInfo" }] : []));
1337
+ todayInfo = signal(this.#getTodayInfo(new Date()), ...(ngDevMode ? [{ debugName: "todayInfo" }] : /* istanbul ignore next */ []));
1338
1338
  userInfo = this.#layoutService.userInfo;
1339
1339
  // WHY: static data, không cần signal. `storage` + `schema` thay cho `database` + `account_tree`
1340
1340
  // để đảm bảo render trên mọi version của Material Icons mặc định.
@@ -1370,8 +1370,8 @@ let HomePageComponent = class HomePageComponent {
1370
1370
  const formatted = this.#i18n.t('core.module.layout.today-info.format', { weekday, date: dateStr });
1371
1371
  return `${formatted} (${this.#getTimezone()})`;
1372
1372
  }
1373
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HomePageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1374
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.23", type: HomePageComponent, isStandalone: true, selector: "app-home-page", ngImport: i0, template: "@let _userInfo = userInfo();\n<sd-page>\n <div class=\"d-flex flex-column\" headerLeft>\n <div class=\"font-weight-medium fs-20\">\n {{ 'core.module.layout.greeting.hello' | translate: { name: _userInfo?.fullName ?? _userInfo?.email ?? _userInfo?.username ?? '' } }}\n </div>\n <span class=\"T12R text-secondary\">{{ todayInfo() }}</span>\n </div>\n\n <div class=\"wrapper\">\n <div class=\"bento\">\n <!-- Hero -->\n <div class=\"card hero-card\">\n <div class=\"hero-ring ring-3\"></div>\n <div class=\"hero-ring ring-2\"></div>\n <div class=\"hero-ring ring-1\"></div>\n <div class=\"hero-core\">\n <mat-icon class=\"hero-icon\">space_dashboard</mat-icon>\n </div>\n <div class=\"hero-decoration\">\n <span class=\"dot d1\"></span>\n <span class=\"dot d2\"></span>\n <span class=\"dot d3\"></span>\n </div>\n </div>\n\n <!-- Features -->\n @for (feature of features; track feature.key; let i = $index) {\n <div\n class=\"card feature-card\"\n [class.feature-wide]=\"feature.area === 'audit' || feature.area === 'integ'\"\n [style.gridArea]=\"feature.area\"\n [style.animation-delay.ms]=\"(i + 1) * 80\"\n >\n <div class=\"feature-accent\"></div>\n <div class=\"feature-content\">\n <div class=\"feature-icon-wrap\">\n <mat-icon class=\"feature-icon\">{{ feature.icon }}</mat-icon>\n </div>\n <span class=\"feature-label\">{{ feature.key | translate }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n</sd-page>\n", styles: [":host{display:contents}.wrapper{display:flex;align-items:center;justify-content:center;padding:32px 24px;height:100%;width:100%;background:radial-gradient(circle at 15% 25%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 14%,transparent),transparent 55%),radial-gradient(circle at 85% 75%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 10%,transparent),transparent 55%),linear-gradient(135deg,#fafbfc,#f4f6fa);overflow:auto}.bento{display:grid;width:100%;max-width:1080px;gap:16px;grid-template-columns:repeat(4,1fr);grid-template-rows:repeat(3,minmax(140px,1fr));grid-template-areas:\"hero hero data report\" \"hero hero users flow\" \"audit audit integ integ\"}.card{position:relative;background:#fff;border:1px solid rgba(0,0,0,.06);border-radius:20px;overflow:hidden;opacity:0;transform:translateY(8px);animation:card-in .5s ease-out forwards;transition:transform .3s ease,box-shadow .3s ease}.card:hover{transform:translateY(-4px);box-shadow:0 16px 40px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 18%,transparent),0 4px 12px #0000000f}.hero-card{grid-area:hero;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle at 30% 30%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 18%,white),#fff 60%),#fff;border:1px solid color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 15%,transparent)}.hero-card .hero-ring{position:absolute;border-radius:50%;border:1px solid color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 25%,transparent);animation:hero-pulse 3s ease-in-out infinite;pointer-events:none}.hero-card .hero-ring.ring-1{inset:calc(50% - 70px);animation-delay:0s}.hero-card .hero-ring.ring-2{inset:calc(50% - 105px);animation-delay:.6s}.hero-card .hero-ring.ring-3{inset:calc(50% - 140px);animation-delay:1.2s}.hero-card .hero-core{position:relative;z-index:1;width:140px;height:140px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 22%,white),#fff);box-shadow:0 0 60px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 30%,transparent),0 10px 30px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 20%,transparent)}.hero-card .hero-icon{font-size:72px;width:72px;height:72px;color:var(--mat-sys-primary, #1f49bf)}.hero-card .hero-decoration{position:absolute;inset:0;pointer-events:none}.hero-card .hero-decoration .dot{position:absolute;width:8px;height:8px;border-radius:50%;background:color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 50%,transparent);animation:dot-float 4s ease-in-out infinite}.hero-card .hero-decoration .d1{top:16%;left:12%;animation-delay:0s}.hero-card .hero-decoration .d2{bottom:20%;right:14%;animation-delay:1s}.hero-card .hero-decoration .d3{top:60%;left:80%;animation-delay:2s;width:5px;height:5px}.feature-card{display:flex;align-items:stretch;cursor:default}.feature-card .feature-accent{position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 60%,transparent),var(--mat-sys-primary, #1f49bf),color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 60%,transparent))}.feature-card .feature-content{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px 16px 18px;gap:10px}.feature-card .feature-icon-wrap{width:56px;height:56px;border-radius:50%;background:color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 12%,white);display:flex;align-items:center;justify-content:center}.feature-card .feature-icon{font-size:28px;width:28px;height:28px;color:var(--mat-sys-primary, #1f49bf)}.feature-card .feature-label{font-size:14px;font-weight:500;text-align:center;color:#000000c7;line-height:20px}.feature-card.feature-wide .feature-content{flex-direction:row;justify-content:flex-start;padding:18px 24px;gap:18px}.feature-card.feature-wide .feature-icon-wrap{width:64px;height:64px}.feature-card.feature-wide .feature-icon{font-size:32px;width:32px;height:32px}.feature-card.feature-wide .feature-label{text-align:left;font-size:16px}@keyframes card-in{to{opacity:1;transform:translateY(0)}}@keyframes hero-pulse{0%,to{transform:scale(1);opacity:.7}50%{transform:scale(1.06);opacity:.3}}@keyframes dot-float{0%,to{transform:translateY(0);opacity:.8}50%{transform:translateY(-8px);opacity:.4}}@media(max-width:1024px){.bento{grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(4,minmax(120px,1fr));grid-template-areas:\"hero hero data\" \"hero hero report\" \"users flow audit\" \"integ integ integ\"}.hero-card .hero-core{width:120px;height:120px}.hero-card .hero-icon{font-size:60px;width:60px;height:60px}}@media(max-width:640px){.wrapper{padding:16px 12px}.bento{grid-template-columns:1fr;grid-template-rows:auto;grid-template-areas:\"hero\" \"data\" \"report\" \"users\" \"flow\" \"audit\" \"integ\";gap:12px}.hero-card{min-height:220px}.hero-card .hero-core{width:100px;height:100px}.hero-card .hero-icon{font-size:52px;width:52px;height:52px}}@media(prefers-reduced-motion:reduce){.card{animation:none;opacity:1;transform:none}.hero-card .hero-ring{animation:none;opacity:.4}.hero-card .hero-decoration .dot{animation:none}}\n"], dependencies: [{ kind: "component", type: SdPageComponent, selector: "sd-page", inputs: ["title", "description", "noHeader"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1373
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HomePageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1374
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: HomePageComponent, isStandalone: true, selector: "app-home-page", ngImport: i0, template: "@let _userInfo = userInfo();\n<sd-page>\n <div class=\"d-flex flex-column\" headerLeft>\n <div class=\"font-weight-medium fs-20\">\n {{ 'core.module.layout.greeting.hello' | translate: { name: _userInfo?.fullName ?? _userInfo?.email ?? _userInfo?.username ?? '' } }}\n </div>\n <span class=\"T12R text-secondary\">{{ todayInfo() }}</span>\n </div>\n\n <div class=\"wrapper\">\n <div class=\"bento\">\n <!-- Hero -->\n <div class=\"card hero-card\">\n <div class=\"hero-ring ring-3\"></div>\n <div class=\"hero-ring ring-2\"></div>\n <div class=\"hero-ring ring-1\"></div>\n <div class=\"hero-core\">\n <mat-icon class=\"hero-icon\">space_dashboard</mat-icon>\n </div>\n <div class=\"hero-decoration\">\n <span class=\"dot d1\"></span>\n <span class=\"dot d2\"></span>\n <span class=\"dot d3\"></span>\n </div>\n </div>\n\n <!-- Features -->\n @for (feature of features; track feature.key; let i = $index) {\n <div\n class=\"card feature-card\"\n [class.feature-wide]=\"feature.area === 'audit' || feature.area === 'integ'\"\n [style.gridArea]=\"feature.area\"\n [style.animation-delay.ms]=\"(i + 1) * 80\"\n >\n <div class=\"feature-accent\"></div>\n <div class=\"feature-content\">\n <div class=\"feature-icon-wrap\">\n <mat-icon class=\"feature-icon\">{{ feature.icon }}</mat-icon>\n </div>\n <span class=\"feature-label\">{{ feature.key | translate }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n</sd-page>\n", styles: [":host{display:contents}.wrapper{display:flex;align-items:center;justify-content:center;padding:32px 24px;height:100%;width:100%;background:radial-gradient(circle at 15% 25%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 14%,transparent),transparent 55%),radial-gradient(circle at 85% 75%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 10%,transparent),transparent 55%),linear-gradient(135deg,#fafbfc,#f4f6fa);overflow:auto}.bento{display:grid;width:100%;max-width:1080px;gap:16px;grid-template-columns:repeat(4,1fr);grid-template-rows:repeat(3,minmax(140px,1fr));grid-template-areas:\"hero hero data report\" \"hero hero users flow\" \"audit audit integ integ\"}.card{position:relative;background:#fff;border:1px solid rgba(0,0,0,.06);border-radius:20px;overflow:hidden;opacity:0;transform:translateY(8px);animation:card-in .5s ease-out forwards;transition:transform .3s ease,box-shadow .3s ease}.card:hover{transform:translateY(-4px);box-shadow:0 16px 40px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 18%,transparent),0 4px 12px #0000000f}.hero-card{grid-area:hero;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle at 30% 30%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 18%,white),#fff 60%),#fff;border:1px solid color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 15%,transparent)}.hero-card .hero-ring{position:absolute;border-radius:50%;border:1px solid color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 25%,transparent);animation:hero-pulse 3s ease-in-out infinite;pointer-events:none}.hero-card .hero-ring.ring-1{inset:calc(50% - 70px);animation-delay:0s}.hero-card .hero-ring.ring-2{inset:calc(50% - 105px);animation-delay:.6s}.hero-card .hero-ring.ring-3{inset:calc(50% - 140px);animation-delay:1.2s}.hero-card .hero-core{position:relative;z-index:1;width:140px;height:140px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 22%,white),#fff);box-shadow:0 0 60px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 30%,transparent),0 10px 30px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 20%,transparent)}.hero-card .hero-icon{font-size:72px;width:72px;height:72px;color:var(--mat-sys-primary, #1f49bf)}.hero-card .hero-decoration{position:absolute;inset:0;pointer-events:none}.hero-card .hero-decoration .dot{position:absolute;width:8px;height:8px;border-radius:50%;background:color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 50%,transparent);animation:dot-float 4s ease-in-out infinite}.hero-card .hero-decoration .d1{top:16%;left:12%;animation-delay:0s}.hero-card .hero-decoration .d2{bottom:20%;right:14%;animation-delay:1s}.hero-card .hero-decoration .d3{top:60%;left:80%;animation-delay:2s;width:5px;height:5px}.feature-card{display:flex;align-items:stretch;cursor:default}.feature-card .feature-accent{position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 60%,transparent),var(--mat-sys-primary, #1f49bf),color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 60%,transparent))}.feature-card .feature-content{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px 16px 18px;gap:10px}.feature-card .feature-icon-wrap{width:56px;height:56px;border-radius:50%;background:color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 12%,white);display:flex;align-items:center;justify-content:center}.feature-card .feature-icon{font-size:28px;width:28px;height:28px;color:var(--mat-sys-primary, #1f49bf)}.feature-card .feature-label{font-size:14px;font-weight:500;text-align:center;color:#000000c7;line-height:20px}.feature-card.feature-wide .feature-content{flex-direction:row;justify-content:flex-start;padding:18px 24px;gap:18px}.feature-card.feature-wide .feature-icon-wrap{width:64px;height:64px}.feature-card.feature-wide .feature-icon{font-size:32px;width:32px;height:32px}.feature-card.feature-wide .feature-label{text-align:left;font-size:16px}@keyframes card-in{to{opacity:1;transform:translateY(0)}}@keyframes hero-pulse{0%,to{transform:scale(1);opacity:.7}50%{transform:scale(1.06);opacity:.3}}@keyframes dot-float{0%,to{transform:translateY(0);opacity:.8}50%{transform:translateY(-8px);opacity:.4}}@media(max-width:1024px){.bento{grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(4,minmax(120px,1fr));grid-template-areas:\"hero hero data\" \"hero hero report\" \"users flow audit\" \"integ integ integ\"}.hero-card .hero-core{width:120px;height:120px}.hero-card .hero-icon{font-size:60px;width:60px;height:60px}}@media(max-width:640px){.wrapper{padding:16px 12px}.bento{grid-template-columns:1fr;grid-template-rows:auto;grid-template-areas:\"hero\" \"data\" \"report\" \"users\" \"flow\" \"audit\" \"integ\";gap:12px}.hero-card{min-height:220px}.hero-card .hero-core{width:100px;height:100px}.hero-card .hero-icon{font-size:52px;width:52px;height:52px}}@media(prefers-reduced-motion:reduce){.card{animation:none;opacity:1;transform:none}.hero-card .hero-ring{animation:none;opacity:.4}.hero-card .hero-decoration .dot{animation:none}}\n"], dependencies: [{ kind: "component", type: SdPageComponent, selector: "sd-page", inputs: ["title", "description", "noHeader"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1375
1375
  };
1376
1376
  HomePageComponent = __decorate([
1377
1377
  SdTabComponent({
@@ -1394,7 +1394,7 @@ HomePageComponent = __decorate([
1394
1394
  color: 'primary',
1395
1395
  })
1396
1396
  ], HomePageComponent);
1397
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HomePageComponent, decorators: [{
1397
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HomePageComponent, decorators: [{
1398
1398
  type: Component,
1399
1399
  args: [{ selector: 'app-home-page', imports: [SdPageComponent, TranslatePipe, MatIconModule], standalone: true, template: "@let _userInfo = userInfo();\n<sd-page>\n <div class=\"d-flex flex-column\" headerLeft>\n <div class=\"font-weight-medium fs-20\">\n {{ 'core.module.layout.greeting.hello' | translate: { name: _userInfo?.fullName ?? _userInfo?.email ?? _userInfo?.username ?? '' } }}\n </div>\n <span class=\"T12R text-secondary\">{{ todayInfo() }}</span>\n </div>\n\n <div class=\"wrapper\">\n <div class=\"bento\">\n <!-- Hero -->\n <div class=\"card hero-card\">\n <div class=\"hero-ring ring-3\"></div>\n <div class=\"hero-ring ring-2\"></div>\n <div class=\"hero-ring ring-1\"></div>\n <div class=\"hero-core\">\n <mat-icon class=\"hero-icon\">space_dashboard</mat-icon>\n </div>\n <div class=\"hero-decoration\">\n <span class=\"dot d1\"></span>\n <span class=\"dot d2\"></span>\n <span class=\"dot d3\"></span>\n </div>\n </div>\n\n <!-- Features -->\n @for (feature of features; track feature.key; let i = $index) {\n <div\n class=\"card feature-card\"\n [class.feature-wide]=\"feature.area === 'audit' || feature.area === 'integ'\"\n [style.gridArea]=\"feature.area\"\n [style.animation-delay.ms]=\"(i + 1) * 80\"\n >\n <div class=\"feature-accent\"></div>\n <div class=\"feature-content\">\n <div class=\"feature-icon-wrap\">\n <mat-icon class=\"feature-icon\">{{ feature.icon }}</mat-icon>\n </div>\n <span class=\"feature-label\">{{ feature.key | translate }}</span>\n </div>\n </div>\n }\n </div>\n </div>\n</sd-page>\n", styles: [":host{display:contents}.wrapper{display:flex;align-items:center;justify-content:center;padding:32px 24px;height:100%;width:100%;background:radial-gradient(circle at 15% 25%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 14%,transparent),transparent 55%),radial-gradient(circle at 85% 75%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 10%,transparent),transparent 55%),linear-gradient(135deg,#fafbfc,#f4f6fa);overflow:auto}.bento{display:grid;width:100%;max-width:1080px;gap:16px;grid-template-columns:repeat(4,1fr);grid-template-rows:repeat(3,minmax(140px,1fr));grid-template-areas:\"hero hero data report\" \"hero hero users flow\" \"audit audit integ integ\"}.card{position:relative;background:#fff;border:1px solid rgba(0,0,0,.06);border-radius:20px;overflow:hidden;opacity:0;transform:translateY(8px);animation:card-in .5s ease-out forwards;transition:transform .3s ease,box-shadow .3s ease}.card:hover{transform:translateY(-4px);box-shadow:0 16px 40px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 18%,transparent),0 4px 12px #0000000f}.hero-card{grid-area:hero;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle at 30% 30%,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 18%,white),#fff 60%),#fff;border:1px solid color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 15%,transparent)}.hero-card .hero-ring{position:absolute;border-radius:50%;border:1px solid color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 25%,transparent);animation:hero-pulse 3s ease-in-out infinite;pointer-events:none}.hero-card .hero-ring.ring-1{inset:calc(50% - 70px);animation-delay:0s}.hero-card .hero-ring.ring-2{inset:calc(50% - 105px);animation-delay:.6s}.hero-card .hero-ring.ring-3{inset:calc(50% - 140px);animation-delay:1.2s}.hero-card .hero-core{position:relative;z-index:1;width:140px;height:140px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:radial-gradient(circle,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 22%,white),#fff);box-shadow:0 0 60px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 30%,transparent),0 10px 30px color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 20%,transparent)}.hero-card .hero-icon{font-size:72px;width:72px;height:72px;color:var(--mat-sys-primary, #1f49bf)}.hero-card .hero-decoration{position:absolute;inset:0;pointer-events:none}.hero-card .hero-decoration .dot{position:absolute;width:8px;height:8px;border-radius:50%;background:color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 50%,transparent);animation:dot-float 4s ease-in-out infinite}.hero-card .hero-decoration .d1{top:16%;left:12%;animation-delay:0s}.hero-card .hero-decoration .d2{bottom:20%;right:14%;animation-delay:1s}.hero-card .hero-decoration .d3{top:60%;left:80%;animation-delay:2s;width:5px;height:5px}.feature-card{display:flex;align-items:stretch;cursor:default}.feature-card .feature-accent{position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 60%,transparent),var(--mat-sys-primary, #1f49bf),color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 60%,transparent))}.feature-card .feature-content{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:24px 16px 18px;gap:10px}.feature-card .feature-icon-wrap{width:56px;height:56px;border-radius:50%;background:color-mix(in srgb,var(--mat-sys-primary, #1f49bf) 12%,white);display:flex;align-items:center;justify-content:center}.feature-card .feature-icon{font-size:28px;width:28px;height:28px;color:var(--mat-sys-primary, #1f49bf)}.feature-card .feature-label{font-size:14px;font-weight:500;text-align:center;color:#000000c7;line-height:20px}.feature-card.feature-wide .feature-content{flex-direction:row;justify-content:flex-start;padding:18px 24px;gap:18px}.feature-card.feature-wide .feature-icon-wrap{width:64px;height:64px}.feature-card.feature-wide .feature-icon{font-size:32px;width:32px;height:32px}.feature-card.feature-wide .feature-label{text-align:left;font-size:16px}@keyframes card-in{to{opacity:1;transform:translateY(0)}}@keyframes hero-pulse{0%,to{transform:scale(1);opacity:.7}50%{transform:scale(1.06);opacity:.3}}@keyframes dot-float{0%,to{transform:translateY(0);opacity:.8}50%{transform:translateY(-8px);opacity:.4}}@media(max-width:1024px){.bento{grid-template-columns:repeat(3,1fr);grid-template-rows:repeat(4,minmax(120px,1fr));grid-template-areas:\"hero hero data\" \"hero hero report\" \"users flow audit\" \"integ integ integ\"}.hero-card .hero-core{width:120px;height:120px}.hero-card .hero-icon{font-size:60px;width:60px;height:60px}}@media(max-width:640px){.wrapper{padding:16px 12px}.bento{grid-template-columns:1fr;grid-template-rows:auto;grid-template-areas:\"hero\" \"data\" \"report\" \"users\" \"flow\" \"audit\" \"integ\";gap:12px}.hero-card{min-height:220px}.hero-card .hero-core{width:100px;height:100px}.hero-card .hero-icon{font-size:52px;width:52px;height:52px}}@media(prefers-reduced-motion:reduce){.card{animation:none;opacity:1;transform:none}.hero-card .hero-ring{animation:none;opacity:.4}.hero-card .hero-decoration .dot{animation:none}}\n"] }]
1400
1400
  }] });
@@ -1416,10 +1416,10 @@ class HomeRedirectGuard {
1416
1416
  // Nếu không có homeUrl, cho phép kích hoạt route
1417
1417
  return true;
1418
1418
  }
1419
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HomeRedirectGuard, deps: [{ token: i1$6.Router }, { token: SD_LAYOUT_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Injectable });
1420
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HomeRedirectGuard, providedIn: 'root' });
1419
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HomeRedirectGuard, deps: [{ token: i1$6.Router }, { token: SD_LAYOUT_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Injectable });
1420
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HomeRedirectGuard, providedIn: 'root' });
1421
1421
  }
1422
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HomeRedirectGuard, decorators: [{
1422
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HomeRedirectGuard, decorators: [{
1423
1423
  type: Injectable,
1424
1424
  args: [{
1425
1425
  providedIn: 'root',
@@ -1437,11 +1437,11 @@ const routes = [
1437
1437
  },
1438
1438
  ];
1439
1439
  class HomeRoutingModule {
1440
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HomeRoutingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1441
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.23", ngImport: i0, type: HomeRoutingModule, imports: [i1$6.RouterModule], exports: [RouterModule] });
1442
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HomeRoutingModule, imports: [RouterModule.forChild(routes), RouterModule] });
1440
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HomeRoutingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1441
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: HomeRoutingModule, imports: [i1$6.RouterModule], exports: [RouterModule] });
1442
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HomeRoutingModule, imports: [RouterModule.forChild(routes), RouterModule] });
1443
1443
  }
1444
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HomeRoutingModule, decorators: [{
1444
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HomeRoutingModule, decorators: [{
1445
1445
  type: NgModule,
1446
1446
  args: [{
1447
1447
  imports: [RouterModule.forChild(routes)],
@@ -1450,11 +1450,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImpo
1450
1450
  }] });
1451
1451
 
1452
1452
  class HomeModule {
1453
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HomeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1454
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.23", ngImport: i0, type: HomeModule, imports: [CommonModule, HomeRoutingModule] });
1455
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HomeModule, imports: [CommonModule, HomeRoutingModule] });
1453
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HomeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1454
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: HomeModule, imports: [CommonModule, HomeRoutingModule] });
1455
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HomeModule, imports: [CommonModule, HomeRoutingModule] });
1456
1456
  }
1457
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: HomeModule, decorators: [{
1457
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: HomeModule, decorators: [{
1458
1458
  type: NgModule,
1459
1459
  args: [{
1460
1460
  declarations: [],
@@ -1479,8 +1479,8 @@ let RootComponent$1 = class RootComponent {
1479
1479
  // SIGNALS (STATE)
1480
1480
  // ==========================================
1481
1481
  // Lấy snapshot một lần lúc khởi tạo và đưa vào signal
1482
- url = signal(this.#route.snapshot.queryParams?.['url'] || '', ...(ngDevMode ? [{ debugName: "url" }] : []));
1483
- todayInfo = signal(this.#getTodayInfo(new Date()), ...(ngDevMode ? [{ debugName: "todayInfo" }] : []));
1482
+ url = signal(this.#route.snapshot.queryParams?.['url'] || '', ...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
1483
+ todayInfo = signal(this.#getTodayInfo(new Date()), ...(ngDevMode ? [{ debugName: "todayInfo" }] : /* istanbul ignore next */ []));
1484
1484
  userInfo = this.#layoutService.userInfo;
1485
1485
  // ==========================================
1486
1486
  // PRIVATE METHODS
@@ -1501,10 +1501,10 @@ let RootComponent$1 = class RootComponent {
1501
1501
  reload() {
1502
1502
  window.location.href = '';
1503
1503
  }
1504
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: RootComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1505
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.23", type: RootComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "@let _userInfo = userInfo();\n<sd-page>\n <div class=\"d-flex flex-column\" headerLeft>\n <div class=\"font-weight-medium fs-20\">{{ 'core.module.layout.greeting.hello' | translate: { name: _userInfo?.fullName ?? _userInfo?.email ?? _userInfo?.username ?? '' } }}</div>\n <span class=\"T12R text-secondary\">{{ todayInfo() }}</span>\n </div>\n\n <div class=\"h-full d-flex flex-column align-items-center\">\n <div class=\"h-full d-flex flex-column align-items-center justify-content-center text-center wrapper\">\n <img alt=\"not-found\" class=\"sd-image-not-found\" />\n <span class=\"T16M mt-24\">{{ 'core.module.layout.not-found.title' | translate }}</span>\n <span class=\"T16R text-secondary mt-4\">\n {{ 'core.module.layout.not-found.message' | translate }}\n </span>\n <sd-button class=\"mt-16\" type=\"fill\" color=\"primary\" (click)=\"reload()\" [title]=\"'core.module.layout.not-found.back' | translate\" prefixIcon=\"arrow_back\"> </sd-button>\n </div>\n </div>\n</sd-page>\n", styles: [".wrapper{width:300px}\n"], dependencies: [{ kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdPageComponent, selector: "sd-page", inputs: ["title", "description", "noHeader"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1504
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RootComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1505
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: RootComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "@let _userInfo = userInfo();\n<sd-page>\n <div class=\"d-flex flex-column\" headerLeft>\n <div class=\"font-weight-medium fs-20\">{{ 'core.module.layout.greeting.hello' | translate: { name: _userInfo?.fullName ?? _userInfo?.email ?? _userInfo?.username ?? '' } }}</div>\n <span class=\"T12R text-secondary\">{{ todayInfo() }}</span>\n </div>\n\n <div class=\"h-full d-flex flex-column align-items-center\">\n <div class=\"h-full d-flex flex-column align-items-center justify-content-center text-center wrapper\">\n <img alt=\"not-found\" class=\"sd-image-not-found\" />\n <span class=\"T16M mt-24\">{{ 'core.module.layout.not-found.title' | translate }}</span>\n <span class=\"T16R text-secondary mt-4\">\n {{ 'core.module.layout.not-found.message' | translate }}\n </span>\n <sd-button class=\"mt-16\" type=\"fill\" color=\"primary\" (click)=\"reload()\" [title]=\"'core.module.layout.not-found.back' | translate\" prefixIcon=\"arrow_back\"> </sd-button>\n </div>\n </div>\n</sd-page>\n", styles: [".wrapper{width:300px}\n"], dependencies: [{ kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdPageComponent, selector: "sd-page", inputs: ["title", "description", "noHeader"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1506
1506
  };
1507
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: RootComponent$1, decorators: [{
1507
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RootComponent$1, decorators: [{
1508
1508
  type: Component,
1509
1509
  args: [{ imports: [SdButton, SdPageComponent, TranslatePipe], template: "@let _userInfo = userInfo();\n<sd-page>\n <div class=\"d-flex flex-column\" headerLeft>\n <div class=\"font-weight-medium fs-20\">{{ 'core.module.layout.greeting.hello' | translate: { name: _userInfo?.fullName ?? _userInfo?.email ?? _userInfo?.username ?? '' } }}</div>\n <span class=\"T12R text-secondary\">{{ todayInfo() }}</span>\n </div>\n\n <div class=\"h-full d-flex flex-column align-items-center\">\n <div class=\"h-full d-flex flex-column align-items-center justify-content-center text-center wrapper\">\n <img alt=\"not-found\" class=\"sd-image-not-found\" />\n <span class=\"T16M mt-24\">{{ 'core.module.layout.not-found.title' | translate }}</span>\n <span class=\"T16R text-secondary mt-4\">\n {{ 'core.module.layout.not-found.message' | translate }}\n </span>\n <sd-button class=\"mt-16\" type=\"fill\" color=\"primary\" (click)=\"reload()\" [title]=\"'core.module.layout.not-found.back' | translate\" prefixIcon=\"arrow_back\"> </sd-button>\n </div>\n </div>\n</sd-page>\n", styles: [".wrapper{width:300px}\n"] }]
1510
1510
  }] });
@@ -1512,11 +1512,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImpo
1512
1512
  const Routes$2 = [{ path: '', component: RootComponent$1 }];
1513
1513
 
1514
1514
  class NotFoundModule {
1515
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: NotFoundModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1516
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.23", ngImport: i0, type: NotFoundModule, imports: [CommonModule, i1$6.RouterModule] });
1517
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: NotFoundModule, imports: [CommonModule, RouterModule.forChild(Routes$2)] });
1515
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NotFoundModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1516
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: NotFoundModule, imports: [CommonModule, i1$6.RouterModule] });
1517
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NotFoundModule, imports: [CommonModule, RouterModule.forChild(Routes$2)] });
1518
1518
  }
1519
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: NotFoundModule, decorators: [{
1519
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: NotFoundModule, decorators: [{
1520
1520
  type: NgModule,
1521
1521
  args: [{
1522
1522
  imports: [CommonModule, RouterModule.forChild(Routes$2)],
@@ -1541,8 +1541,8 @@ class RootComponent {
1541
1541
  // SIGNALS (STATE)
1542
1542
  // ==========================================
1543
1543
  // Lấy snapshot một lần lúc khởi tạo và đưa vào signal
1544
- url = signal(this.#route.snapshot.queryParams?.['url'] || '', ...(ngDevMode ? [{ debugName: "url" }] : []));
1545
- todayInfo = signal(this.#getTodayInfo(new Date()), ...(ngDevMode ? [{ debugName: "todayInfo" }] : []));
1544
+ url = signal(this.#route.snapshot.queryParams?.['url'] || '', ...(ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []));
1545
+ todayInfo = signal(this.#getTodayInfo(new Date()), ...(ngDevMode ? [{ debugName: "todayInfo" }] : /* istanbul ignore next */ []));
1546
1546
  userInfo = this.#layoutService.userInfo;
1547
1547
  // ==========================================
1548
1548
  // PRIVATE METHODS
@@ -1563,10 +1563,10 @@ class RootComponent {
1563
1563
  reload() {
1564
1564
  window.location.href = '';
1565
1565
  }
1566
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: RootComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1567
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.23", type: RootComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "@let _userInfo = userInfo();\n<sd-page>\n <div class=\"d-flex flex-column\" headerLeft>\n <div class=\"font-weight-medium fs-20\">{{ 'core.module.layout.greeting.hello' | translate: { name: _userInfo?.fullName ?? _userInfo?.email ?? _userInfo?.username ?? '' } }}</div>\n <span class=\"T12R text-secondary\">{{ todayInfo() }}</span>\n </div>\n <div class=\"h-full d-flex flex-column align-items-center\">\n <div class=\"h-full d-flex flex-column align-items-center justify-content-center text-center wrapper\">\n <img alt=\"forbidden\" class=\"sd-image-forbidden\" />\n <span class=\"T16M mt-24\">{{ 'core.module.layout.forbidden.title' | translate }}</span>\n <span class=\"T14R text-secondary mt-4\"\n >{{ 'core.module.layout.forbidden.message' | translate }}</span\n >\n <sd-button class=\"mt-16\" type=\"fill\" color=\"primary\" (click)=\"reload()\" [title]=\"'core.module.layout.forbidden.back-home' | translate\"> </sd-button>\n </div>\n </div>\n</sd-page>\n", styles: [".wrapper{width:300px}\n"], dependencies: [{ kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdPageComponent, selector: "sd-page", inputs: ["title", "description", "noHeader"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1566
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RootComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1567
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: RootComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "@let _userInfo = userInfo();\n<sd-page>\n <div class=\"d-flex flex-column\" headerLeft>\n <div class=\"font-weight-medium fs-20\">{{ 'core.module.layout.greeting.hello' | translate: { name: _userInfo?.fullName ?? _userInfo?.email ?? _userInfo?.username ?? '' } }}</div>\n <span class=\"T12R text-secondary\">{{ todayInfo() }}</span>\n </div>\n <div class=\"h-full d-flex flex-column align-items-center\">\n <div class=\"h-full d-flex flex-column align-items-center justify-content-center text-center wrapper\">\n <img alt=\"forbidden\" class=\"sd-image-forbidden\" />\n <span class=\"T16M mt-24\">{{ 'core.module.layout.forbidden.title' | translate }}</span>\n <span class=\"T14R text-secondary mt-4\"\n >{{ 'core.module.layout.forbidden.message' | translate }}</span\n >\n <sd-button class=\"mt-16\" type=\"fill\" color=\"primary\" (click)=\"reload()\" [title]=\"'core.module.layout.forbidden.back-home' | translate\"> </sd-button>\n </div>\n </div>\n</sd-page>\n", styles: [".wrapper{width:300px}\n"], dependencies: [{ kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdPageComponent, selector: "sd-page", inputs: ["title", "description", "noHeader"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1568
1568
  }
1569
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: RootComponent, decorators: [{
1569
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: RootComponent, decorators: [{
1570
1570
  type: Component,
1571
1571
  args: [{ imports: [SdButton, SdPageComponent, TranslatePipe], template: "@let _userInfo = userInfo();\n<sd-page>\n <div class=\"d-flex flex-column\" headerLeft>\n <div class=\"font-weight-medium fs-20\">{{ 'core.module.layout.greeting.hello' | translate: { name: _userInfo?.fullName ?? _userInfo?.email ?? _userInfo?.username ?? '' } }}</div>\n <span class=\"T12R text-secondary\">{{ todayInfo() }}</span>\n </div>\n <div class=\"h-full d-flex flex-column align-items-center\">\n <div class=\"h-full d-flex flex-column align-items-center justify-content-center text-center wrapper\">\n <img alt=\"forbidden\" class=\"sd-image-forbidden\" />\n <span class=\"T16M mt-24\">{{ 'core.module.layout.forbidden.title' | translate }}</span>\n <span class=\"T14R text-secondary mt-4\"\n >{{ 'core.module.layout.forbidden.message' | translate }}</span\n >\n <sd-button class=\"mt-16\" type=\"fill\" color=\"primary\" (click)=\"reload()\" [title]=\"'core.module.layout.forbidden.back-home' | translate\"> </sd-button>\n </div>\n </div>\n</sd-page>\n", styles: [".wrapper{width:300px}\n"] }]
1572
1572
  }] });
@@ -1574,11 +1574,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImpo
1574
1574
  const Routes$1 = [{ path: '', component: RootComponent }];
1575
1575
 
1576
1576
  class ForbiddenModule {
1577
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ForbiddenModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1578
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.23", ngImport: i0, type: ForbiddenModule, imports: [CommonModule, i1$6.RouterModule] });
1579
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ForbiddenModule, imports: [CommonModule, RouterModule.forChild(Routes$1)] });
1577
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ForbiddenModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1578
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: ForbiddenModule, imports: [CommonModule, i1$6.RouterModule] });
1579
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ForbiddenModule, imports: [CommonModule, RouterModule.forChild(Routes$1)] });
1580
1580
  }
1581
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: ForbiddenModule, decorators: [{
1581
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ForbiddenModule, decorators: [{
1582
1582
  type: NgModule,
1583
1583
  args: [{
1584
1584
  imports: [CommonModule, RouterModule.forChild(Routes$1)],
@@ -1612,11 +1612,11 @@ const Routes = [
1612
1612
  ];
1613
1613
 
1614
1614
  class SdLayoutModule {
1615
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1616
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutModule, imports: [i1$6.RouterModule] });
1617
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutModule, imports: [RouterModule.forChild(Routes)] });
1615
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1616
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutModule, imports: [i1$6.RouterModule] });
1617
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutModule, imports: [RouterModule.forChild(Routes)] });
1618
1618
  }
1619
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.23", ngImport: i0, type: SdLayoutModule, decorators: [{
1619
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: SdLayoutModule, decorators: [{
1620
1620
  type: NgModule,
1621
1621
  args: [{
1622
1622
  declarations: [],