@sdcorejs/angular 19.0.9 → 19.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (257) hide show
  1. package/README.md +270 -140
  2. package/assets/STYLE-GUIDE.md +2 -2
  3. package/assets/scss/core/_inline-edit.scss +1 -1
  4. package/assets/scss/core/form.scss +1 -1
  5. package/assets/scss/core/utilities/_grid.scss +25 -19
  6. package/assets/scss/themes/default.scss +2 -2
  7. package/components/anchor/src/models/sd-anchor.model.d.ts +1 -1
  8. package/components/badge/src/badge.component.d.ts +3 -14
  9. package/components/button/src/button.component.d.ts +5 -3
  10. package/components/document-builder/src/document-builder.component.d.ts +2 -2
  11. package/components/document-builder/src/plugins/paste-handler/filters/parse.d.ts +1 -1
  12. package/components/editor/src/plugins/image-upload/utils/batch.utils.d.ts +3 -3
  13. package/components/form-generic/src/components/form-builder/components/attribute-expression/attribute-expression.component.d.ts +10 -6
  14. package/components/form-generic/src/components/form-builder/components/attribute-expression/form-expression-query-adapter.d.ts +6 -0
  15. package/components/form-generic/src/components/form-builder/components/attribute-parameter/attribute-parameter.component.d.ts +2 -2
  16. package/components/form-generic/src/components/form-builder/components/attribute-selection/attribute-selection.component.d.ts +2 -2
  17. package/components/form-generic/src/components/form-builder/components/attribute-selection/components/build-queries/build-queries.component.d.ts +2 -2
  18. package/components/form-generic/src/components/form-builder/components/attribute-selection/components/build-variables/build-variables.component.d.ts +2 -2
  19. package/components/form-generic/src/components/form-builder/components/attribute-table/attribute-table.component.d.ts +2 -4
  20. package/components/form-generic/src/components/form-builder/components/attribute-template/attribute-template.component.d.ts +2 -4
  21. package/components/form-generic/src/components/form-builder/components/checkbox/attribute/checkbox-attribute.component.d.ts +2 -2
  22. package/components/form-generic/src/components/form-builder/components/chip-calendar/attribute/chip-calendar-attribute.component.d.ts +2 -2
  23. package/components/form-generic/src/components/form-builder/components/chip-calendar/control/chip-calendar-control.component.d.ts +2 -2
  24. package/components/form-generic/src/components/form-builder/components/chip-string/attribute/chip-string-attribute.component.d.ts +2 -2
  25. package/components/form-generic/src/components/form-builder/components/chip-string/control/chip-string-control.component.d.ts +2 -2
  26. package/components/form-generic/src/components/form-builder/components/configure-validation/configure-validation.component.d.ts +6 -7
  27. package/components/form-generic/src/components/form-builder/components/datetime/attribute/datetime-attribute.component.d.ts +2 -2
  28. package/components/form-generic/src/components/form-builder/components/datetime/control/datetime-control.component.d.ts +2 -2
  29. package/components/form-generic/src/components/form-builder/components/expression-builder/expression-builder.component.d.ts +2 -2
  30. package/components/form-generic/src/components/form-builder/components/html/attribute/components/build-queries/build-queries.component.d.ts +2 -2
  31. package/components/form-generic/src/components/form-builder/components/html/control/html-control.component.d.ts +2 -2
  32. package/components/form-generic/src/components/form-builder/components/number/attribute/number-attribute.component.d.ts +2 -2
  33. package/components/form-generic/src/components/form-builder/components/number/control/number-control.component.d.ts +2 -2
  34. package/components/form-generic/src/components/form-builder/components/radio/attribute/radio-attribute.component.d.ts +2 -2
  35. package/components/form-generic/src/components/form-builder/components/radio/control/radio-control.component.d.ts +2 -2
  36. package/components/form-generic/src/components/form-builder/components/select/attribute/select-attribute.component.d.ts +2 -2
  37. package/components/form-generic/src/components/form-builder/components/select/control/select-control.component.d.ts +2 -2
  38. package/components/form-generic/src/components/form-builder/components/table/attribute/table-attribute.component.d.ts +2 -2
  39. package/components/form-generic/src/components/form-builder/components/table/control/table-control.component.d.ts +2 -2
  40. package/components/form-generic/src/components/form-builder/components/textarea/attribute/textarea-attribute.component.d.ts +2 -2
  41. package/components/form-generic/src/components/form-builder/components/textarea/control/textarea-control.component.d.ts +2 -2
  42. package/components/form-generic/src/components/form-builder/components/textfield/attribute/textfield-attribute.component.d.ts +2 -2
  43. package/components/form-generic/src/components/form-builder/components/textfield/control/textfield-control.component.d.ts +2 -2
  44. package/components/form-generic/src/components/form-builder/components/upload/attribute/upload-attribute.component.d.ts +2 -2
  45. package/components/form-generic/src/components/form-builder/components/upload/control/upload-control.component.d.ts +2 -2
  46. package/components/form-generic/src/components/form-builder/form-builder-layout.d.ts +22 -0
  47. package/components/form-generic/src/components/form-builder/form-builder.component.d.ts +24 -5
  48. package/components/form-generic/src/components/form-render/components/item/components/chip-calendar/chip-calendar.component.d.ts +2 -2
  49. package/components/form-generic/src/components/form-render/components/item/components/chip-string/chip-string.component.d.ts +2 -2
  50. package/components/form-generic/src/components/form-render/components/item/components/datetime/datetime.component.d.ts +2 -2
  51. package/components/form-generic/src/components/form-render/components/item/components/html/html.component.d.ts +2 -2
  52. package/components/form-generic/src/components/form-render/components/item/components/number/number.component.d.ts +2 -2
  53. package/components/form-generic/src/components/form-render/components/item/components/radio/radio.component.d.ts +2 -2
  54. package/components/form-generic/src/components/form-render/components/item/components/select/select.component.d.ts +2 -2
  55. package/components/form-generic/src/components/form-render/components/item/components/table/table.component.d.ts +2 -2
  56. package/components/form-generic/src/components/form-render/components/item/components/textarea/textarea.component.d.ts +2 -2
  57. package/components/form-generic/src/components/form-render/components/item/components/textfield/textfield.component.d.ts +2 -2
  58. package/components/form-generic/src/components/form-render/components/item/components/upload/upload.component.d.ts +2 -2
  59. package/components/form-generic/src/components/form-render/components/variable/variable.component.d.ts +2 -2
  60. package/components/form-generic/src/components/form-render/form-render.component.d.ts +4 -6
  61. package/components/form-generic/src/components/sd-feel-expression/sd-feel-expression.component.d.ts +2 -2
  62. package/components/form-generic/src/configurations/form.configuration.d.ts +1 -1
  63. package/components/form-generic/src/models/form-generic-component.model.d.ts +2 -2
  64. package/components/form-generic/src/services/form-generic.service.d.ts +1 -3
  65. package/components/import-excel/src/import-excel.model.d.ts +2 -2
  66. package/components/inform/src/inform.component.d.ts +2 -8
  67. package/components/mini-editor/src/mini-editor.component.d.ts +4 -4
  68. package/components/modal/src/modal.component.d.ts +1 -1
  69. package/components/query-builder/src/query-builder.component.d.ts +3 -3
  70. package/components/query-builder/src/query-builder.model.d.ts +4 -4
  71. package/components/splitter/src/splitter-state.service.d.ts +1 -1
  72. package/components/tab-router/src/models/tab-router.model.d.ts +2 -1
  73. package/components/tab-router/src/services/tab-router.service.d.ts +0 -1
  74. package/components/table/src/components/command/desktop-command.component.d.ts +7 -7
  75. package/components/table/src/components/command/pipes/command.pipe.d.ts +1 -12
  76. package/components/table/src/components/command/pipes/filter.pipe.d.ts +1 -8
  77. package/components/table/src/components/filter/column-filter/column-filter.component.d.ts +1 -0
  78. package/components/table/src/models/table-column.model.d.ts +3 -2
  79. package/components/table/src/models/table-command.model.d.ts +3 -3
  80. package/components/table/src/models/table-option-selector.model.d.ts +5 -5
  81. package/components/table/src/pipes/selection-disabled.pipe.d.ts +1 -1
  82. package/components/table/src/services/config.service.d.ts +4 -5
  83. package/components/tree/src/tree.model.d.ts +3 -2
  84. package/components/view/src/view.component.d.ts +1 -1
  85. package/configurations/src/sd-core.configuration.d.ts +2 -2
  86. package/fesm2022/sdcorejs-angular-components-anchor.mjs +20 -24
  87. package/fesm2022/sdcorejs-angular-components-anchor.mjs.map +1 -1
  88. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs +4 -5
  89. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs.map +1 -1
  90. package/fesm2022/sdcorejs-angular-components-avatar.mjs.map +1 -1
  91. package/fesm2022/sdcorejs-angular-components-badge.mjs +14 -13
  92. package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
  93. package/fesm2022/sdcorejs-angular-components-button.mjs +15 -17
  94. package/fesm2022/sdcorejs-angular-components-button.mjs.map +1 -1
  95. package/fesm2022/sdcorejs-angular-components-chart.mjs.map +1 -1
  96. package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs.map +1 -1
  97. package/fesm2022/sdcorejs-angular-components-code-editor.mjs +5 -6
  98. package/fesm2022/sdcorejs-angular-components-code-editor.mjs.map +1 -1
  99. package/fesm2022/sdcorejs-angular-components-document-builder.mjs +17 -26
  100. package/fesm2022/sdcorejs-angular-components-document-builder.mjs.map +1 -1
  101. package/fesm2022/sdcorejs-angular-components-editor.mjs +11 -7
  102. package/fesm2022/sdcorejs-angular-components-editor.mjs.map +1 -1
  103. package/fesm2022/sdcorejs-angular-components-form-generic.mjs +715 -436
  104. package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
  105. package/fesm2022/sdcorejs-angular-components-history.mjs +2 -2
  106. package/fesm2022/sdcorejs-angular-components-history.mjs.map +1 -1
  107. package/fesm2022/sdcorejs-angular-components-import-excel.mjs +38 -23
  108. package/fesm2022/sdcorejs-angular-components-import-excel.mjs.map +1 -1
  109. package/fesm2022/sdcorejs-angular-components-inform.mjs +5 -16
  110. package/fesm2022/sdcorejs-angular-components-inform.mjs.map +1 -1
  111. package/fesm2022/sdcorejs-angular-components-mini-editor.mjs.map +1 -1
  112. package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs +5 -6
  113. package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs.map +1 -1
  114. package/fesm2022/sdcorejs-angular-components-modal.mjs +28 -18
  115. package/fesm2022/sdcorejs-angular-components-modal.mjs.map +1 -1
  116. package/fesm2022/sdcorejs-angular-components-operator.mjs +1 -1
  117. package/fesm2022/sdcorejs-angular-components-operator.mjs.map +1 -1
  118. package/fesm2022/sdcorejs-angular-components-org-chart.mjs +4 -5
  119. package/fesm2022/sdcorejs-angular-components-org-chart.mjs.map +1 -1
  120. package/fesm2022/sdcorejs-angular-components-preview.mjs +40 -37
  121. package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
  122. package/fesm2022/sdcorejs-angular-components-query-bar.mjs +38 -55
  123. package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
  124. package/fesm2022/sdcorejs-angular-components-query-builder.mjs +5 -7
  125. package/fesm2022/sdcorejs-angular-components-query-builder.mjs.map +1 -1
  126. package/fesm2022/sdcorejs-angular-components-quick-action.mjs.map +1 -1
  127. package/fesm2022/sdcorejs-angular-components-section.mjs +3 -5
  128. package/fesm2022/sdcorejs-angular-components-section.mjs.map +1 -1
  129. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +6 -7
  130. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
  131. package/fesm2022/sdcorejs-angular-components-splitter.mjs +4 -4
  132. package/fesm2022/sdcorejs-angular-components-splitter.mjs.map +1 -1
  133. package/fesm2022/sdcorejs-angular-components-stepper.mjs +3 -4
  134. package/fesm2022/sdcorejs-angular-components-stepper.mjs.map +1 -1
  135. package/fesm2022/sdcorejs-angular-components-tab-router.mjs +36 -37
  136. package/fesm2022/sdcorejs-angular-components-tab-router.mjs.map +1 -1
  137. package/fesm2022/sdcorejs-angular-components-tab.mjs +3 -4
  138. package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
  139. package/fesm2022/sdcorejs-angular-components-table.mjs +79 -101
  140. package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
  141. package/fesm2022/sdcorejs-angular-components-tree.mjs +6 -8
  142. package/fesm2022/sdcorejs-angular-components-tree.mjs.map +1 -1
  143. package/fesm2022/sdcorejs-angular-components-upload-file.mjs +14 -15
  144. package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
  145. package/fesm2022/sdcorejs-angular-components-view.mjs +3 -9
  146. package/fesm2022/sdcorejs-angular-components-view.mjs.map +1 -1
  147. package/fesm2022/sdcorejs-angular-configurations.mjs.map +1 -1
  148. package/fesm2022/sdcorejs-angular-directives.mjs +2 -7
  149. package/fesm2022/sdcorejs-angular-directives.mjs.map +1 -1
  150. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +5 -10
  151. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
  152. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
  153. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +9 -11
  154. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
  155. package/fesm2022/sdcorejs-angular-forms-chip.mjs +7 -9
  156. package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
  157. package/fesm2022/sdcorejs-angular-forms-date-range.mjs +8 -12
  158. package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
  159. package/fesm2022/sdcorejs-angular-forms-date.mjs +8 -12
  160. package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
  161. package/fesm2022/sdcorejs-angular-forms-datetime.mjs +7 -13
  162. package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
  163. package/fesm2022/sdcorejs-angular-forms-inline-text.mjs +4 -5
  164. package/fesm2022/sdcorejs-angular-forms-inline-text.mjs.map +1 -1
  165. package/fesm2022/sdcorejs-angular-forms-input-color.mjs +3 -3
  166. package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
  167. package/fesm2022/sdcorejs-angular-forms-input-number.mjs +6 -8
  168. package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
  169. package/fesm2022/sdcorejs-angular-forms-input.mjs +5 -7
  170. package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
  171. package/fesm2022/sdcorejs-angular-forms-label.mjs +4 -6
  172. package/fesm2022/sdcorejs-angular-forms-label.mjs.map +1 -1
  173. package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
  174. package/fesm2022/sdcorejs-angular-forms-radio.mjs +12 -4
  175. package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
  176. package/fesm2022/sdcorejs-angular-forms-select.mjs +51 -22
  177. package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
  178. package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
  179. package/fesm2022/sdcorejs-angular-forms-textarea.mjs +7 -9
  180. package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
  181. package/fesm2022/sdcorejs-angular-handlers.mjs +3 -6
  182. package/fesm2022/sdcorejs-angular-handlers.mjs.map +1 -1
  183. package/fesm2022/sdcorejs-angular-i18n.mjs +11 -7
  184. package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
  185. package/fesm2022/sdcorejs-angular-interceptors.mjs +0 -2
  186. package/fesm2022/sdcorejs-angular-interceptors.mjs.map +1 -1
  187. package/fesm2022/sdcorejs-angular-modules-auth.mjs +14 -38
  188. package/fesm2022/sdcorejs-angular-modules-auth.mjs.map +1 -1
  189. package/fesm2022/sdcorejs-angular-modules-authom.mjs +14 -14
  190. package/fesm2022/sdcorejs-angular-modules-authom.mjs.map +1 -1
  191. package/fesm2022/sdcorejs-angular-modules-icon.mjs +523 -0
  192. package/fesm2022/sdcorejs-angular-modules-icon.mjs.map +1 -0
  193. package/fesm2022/sdcorejs-angular-modules-keycloak.mjs +22 -11
  194. package/fesm2022/sdcorejs-angular-modules-keycloak.mjs.map +1 -1
  195. package/fesm2022/sdcorejs-angular-modules-layout.mjs +53 -52
  196. package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
  197. package/fesm2022/sdcorejs-angular-modules-permission.mjs +5 -12
  198. package/fesm2022/sdcorejs-angular-modules-permission.mjs.map +1 -1
  199. package/fesm2022/sdcorejs-angular-modules.mjs +1 -0
  200. package/fesm2022/sdcorejs-angular-modules.mjs.map +1 -1
  201. package/fesm2022/sdcorejs-angular-pipes.mjs +71 -17
  202. package/fesm2022/sdcorejs-angular-pipes.mjs.map +1 -1
  203. package/fesm2022/sdcorejs-angular-services-api.mjs +0 -2
  204. package/fesm2022/sdcorejs-angular-services-api.mjs.map +1 -1
  205. package/fesm2022/sdcorejs-angular-services-cache.mjs +5 -11
  206. package/fesm2022/sdcorejs-angular-services-cache.mjs.map +1 -1
  207. package/fesm2022/sdcorejs-angular-services-confirm.mjs +19 -25
  208. package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
  209. package/fesm2022/sdcorejs-angular-services-docx.mjs +2 -8
  210. package/fesm2022/sdcorejs-angular-services-docx.mjs.map +1 -1
  211. package/fesm2022/sdcorejs-angular-services-excel.mjs +24 -16
  212. package/fesm2022/sdcorejs-angular-services-excel.mjs.map +1 -1
  213. package/fesm2022/sdcorejs-angular-services-license.mjs +5 -12
  214. package/fesm2022/sdcorejs-angular-services-license.mjs.map +1 -1
  215. package/fesm2022/sdcorejs-angular-services-notify.mjs +70 -87
  216. package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
  217. package/fesm2022/sdcorejs-angular-services-storage.mjs +6 -15
  218. package/fesm2022/sdcorejs-angular-services-storage.mjs.map +1 -1
  219. package/fesm2022/sdcorejs-angular-utilities-data-state.mjs.map +1 -1
  220. package/fesm2022/sdcorejs-angular-utilities-extensions.mjs +47 -5
  221. package/fesm2022/sdcorejs-angular-utilities-extensions.mjs.map +1 -1
  222. package/fesm2022/sdcorejs-angular-utilities-models.mjs +21 -5
  223. package/fesm2022/sdcorejs-angular-utilities-models.mjs.map +1 -1
  224. package/fesm2022/sdcorejs-angular.mjs.map +1 -1
  225. package/forms/chip/src/chip.component.d.ts +2 -2
  226. package/forms/chip-calendar/src/chip-calendar.component.d.ts +2 -2
  227. package/forms/input-color/src/input-color.component.d.ts +2 -1
  228. package/forms/select/src/select-footer-action.directive.d.ts +5 -1
  229. package/forms/select/src/select.component.d.ts +4 -0
  230. package/modules/auth/guards/auth.guard.d.ts +2 -4
  231. package/modules/auth/guards/portal.guard.d.ts +2 -4
  232. package/modules/auth/services/auth.service.d.ts +3 -4
  233. package/modules/icon/index.d.ts +1 -0
  234. package/modules/icon/src/icon.component.d.ts +101 -0
  235. package/modules/icon/src/icon.model.d.ts +59 -0
  236. package/modules/icon/src/icon.provider.d.ts +33 -0
  237. package/modules/icon/src/index.d.ts +3 -0
  238. package/modules/index.d.ts +1 -0
  239. package/modules/layout/modules/home/guards/home-redirect.guard.d.ts +3 -5
  240. package/modules/permission/src/configurations/permission.configuration.d.ts +3 -3
  241. package/modules/permission/src/guards/permission.guard.d.ts +2 -5
  242. package/package.json +11 -6
  243. package/pipes/index.d.ts +3 -0
  244. package/pipes/src/format-date.pipe.d.ts +8 -0
  245. package/pipes/src/format-datetime.pipe.d.ts +8 -0
  246. package/pipes/src/format-number.pipe.d.ts +1 -3
  247. package/pipes/src/view.pipe.d.ts +7 -0
  248. package/services/confirm/src/lib/components/dialog-confirm/dialog-confirm.component.d.ts +3 -3
  249. package/services/excel/src/lib/spreadsheet-formula-injection.util.d.ts +5 -0
  250. package/services/license/src/license.service.d.ts +2 -3
  251. package/services/notify/src/components/toast/toast.component.d.ts +9 -13
  252. package/services/notify/src/notify.service.d.ts +4 -5
  253. package/services/storage/src/storage.service.d.ts +3 -4
  254. package/utilities/extensions/index.d.ts +1 -0
  255. package/utilities/extensions/src/object.extension.d.ts +8 -0
  256. package/utilities/models/src/icon.model.d.ts +4 -2
  257. package/components/document-builder/src/plugins/paste-handler/filters/replacetabswithinprewithspaces.d.ts +0 -24
@@ -1 +1 @@
1
- {"version":3,"file":"sdcorejs-angular-services-excel.mjs","sources":["../../../projects/sdcorejs-angular/services/excel/src/lib/excel.service.ts","../../../projects/sdcorejs-angular/services/excel/sdcorejs-angular-services-excel.ts"],"sourcesContent":["import { inject, Injectable } from '@angular/core';\nimport type { CellValue, Style } from 'exceljs';\n// import hash from 'object-hash';\nimport { DateUtilities } from '@sdcorejs/angular/utilities/extensions';\nimport { BrowserUtilities } from '@sdcorejs/utils/fns';\nimport { I18nService } from '@sdcorejs/angular/i18n';\nimport { SdExcelExportOption, SdExcelTemplate } from './excel.model';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SdExcelService {\n readonly #i18n = inject(I18nService);\n #fieldStyle: Partial<Style> = {\n border: {\n bottom: { style: 'thin' },\n left: { style: 'thin' },\n right: { style: 'thin' },\n },\n alignment: {\n vertical: 'middle',\n horizontal: 'center',\n wrapText: true,\n },\n font: {\n bold: true,\n size: 11,\n color: { argb: '000000' },\n },\n fill: {\n type: 'pattern',\n pattern: 'solid',\n fgColor: {\n argb: 'FAFAFA',\n },\n },\n };\n #titleColor = 'FFFFFF';\n #titleFgColor = '143180';\n #titleStyle: Partial<Style> = {\n border: {\n bottom: { style: 'thin' },\n left: { style: 'thin' },\n right: { style: 'thin' },\n },\n alignment: {\n vertical: 'middle',\n horizontal: 'center',\n wrapText: true,\n },\n font: {\n bold: true,\n size: 11,\n color: { argb: this.#titleColor },\n },\n fill: {\n type: 'pattern',\n pattern: 'solid',\n fgColor: {\n argb: this.#titleFgColor,\n },\n },\n };\n\n #requiredStyle: Partial<Style> = {\n border: {\n bottom: { style: 'thin' },\n left: { style: 'thin' },\n right: { style: 'thin' },\n },\n alignment: {\n vertical: 'middle',\n horizontal: 'center',\n wrapText: true,\n },\n font: {\n italic: true,\n size: 11,\n color: { argb: 'FFFFFF' },\n },\n fill: {\n type: 'pattern',\n pattern: 'solid',\n fgColor: {\n argb: 'FF1744',\n },\n },\n };\n\n #descriptionStyle: Partial<Style> = {\n border: {\n bottom: { style: 'thin' },\n left: { style: 'thin' },\n right: { style: 'thin' },\n },\n alignment: {\n wrapText: true,\n },\n font: {\n italic: true,\n size: 9,\n color: { argb: '000000' },\n },\n fill: {\n type: 'pattern',\n pattern: 'solid',\n fgColor: {\n argb: 'CFD8DC',\n },\n },\n };\n\n #cellStyle: Partial<Style> = {\n alignment: {\n vertical: 'middle',\n wrapText: true,\n },\n };\n\n constructor() {}\n\n // exceljs là CJS module — khi dynamic import từ ESM, named export `Workbook`\n // có thể nằm trên `mod.Workbook` hoặc bị bọc trong `mod.default.Workbook` tuỳ bundler.\n // Helper này chuẩn hoá cả hai trường hợp.\n async #loadWorkbook(): Promise<new () => import('exceljs').Workbook> {\n const mod: any = await import('exceljs');\n return mod.Workbook ?? mod.default?.Workbook;\n }\n\n generateTemplate = async (template: SdExcelTemplate) => {\n const { fileName, columns, sheets } = template;\n if (!Array.isArray(columns)) {\n throw new Error('Excel template columns must be an array');\n }\n for (const [idx, column] of columns.entries()) {\n if (!column.field) {\n throw new Error(`Column ${idx + 1}: Field is required`);\n }\n if (!column.title) {\n throw new Error(`Column ${idx + 1}: Title is required`);\n }\n }\n const hasDescription = columns.some(column => column.description);\n const Workbook = await this.#loadWorkbook();\n const workbook = new Workbook();\n const firstSheet = workbook.addWorksheet('template'); // Lấy ra sheet đầu tiên\n columns.forEach((column, index) => {\n const { required, fill, fontColor } = column;\n const cellField = firstSheet.getCell(1, index + 1);\n const cellTitle = firstSheet.getCell(2, index + 1);\n const cellDescription = firstSheet.getCell(3, index + 1);\n let width = 120;\n if (column.width && column.width.endsWith('px')) {\n width = +column.width.replace('px', '');\n }\n firstSheet.getColumn(index + 1).width = width / 7 || 20;\n cellField.style = this.#fieldStyle;\n if (required) {\n cellField.style = this.#requiredStyle;\n } else {\n cellField.style = this.#fieldStyle;\n }\n cellTitle.style = {\n ...this.#titleStyle,\n font: {\n ...this.#titleStyle?.font,\n color: {\n ...this.#titleStyle?.font?.color,\n argb: fontColor || this.#titleStyle?.font?.color?.argb,\n },\n },\n fill: {\n type: 'pattern',\n pattern: 'solid',\n fgColor: {\n argb: fill || this.#titleFgColor,\n },\n },\n };\n cellField.value = column.field;\n cellTitle.value = column.title;\n if (hasDescription) {\n cellDescription.style = this.#descriptionStyle;\n cellDescription.value = column.description || '';\n }\n });\n if (sheets?.length) {\n for (const sheet of sheets) {\n if (sheet.name && Array.isArray(sheet.items) && Array.isArray(sheet.headers)) {\n const newSheet = workbook.addWorksheet(sheet.name);\n sheet.headers.forEach((header, index) => {\n newSheet.getColumn(index + 1).width = 30;\n newSheet.getCell(1, index + 1).style = this.#titleStyle;\n newSheet.getCell(1, index + 1).value = header.value;\n newSheet.getCell(2, index + 1).style = this.#titleStyle;\n newSheet.getCell(2, index + 1).value = header.display || header.value;\n });\n sheet.items.forEach((item, idx1) => {\n sheet.headers.forEach((header, idx2) => {\n newSheet.getCell(3 + idx1, 1 + idx2).value = item[header.value];\n newSheet.getCell(3 + idx1, 1 + idx2).style = this.#cellStyle;\n });\n });\n }\n }\n }\n const file = await workbook.xlsx.writeBuffer();\n BrowserUtilities.downloadBlob(\n new Blob([file], {\n type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n }),\n fileName\n );\n };\n\n exportCSV = async (option: SdExcelExportOption): Promise<void> => {\n const { columns, items, fileName } = option;\n const filename = `${fileName || 'CSV'}_${DateUtilities.toFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss')}.csv`;\n\n // Escape CSV cell: bọc trong dấu \" nếu chứa dấu phẩy / xuống dòng / dấu ngoặc kép.\n // Dấu \" bên trong được nhân đôi theo chuẩn RFC 4180.\n const escape = (v: unknown): string => {\n if (v == null) return '';\n const s = String(v);\n return /[\",\\n\\r]/.test(s) ? `\"${s.replace(/\"/g, '\"\"')}\"` : s;\n };\n\n const headerLine = columns.map(c => escape(c.title)).join(',');\n const dataLines = items.map(item =>\n columns.map(c => escape((item as Record<string, unknown>)[c.field])).join(','),\n );\n\n // Prepend UTF-8 BOM () để Excel mở đúng encoding cho tiếng Việt có dấu.\n // Dùng CRLF vì Excel trên Windows ưu tiên, macOS Excel cũng chấp nhận.\n const csv = '' + [headerLine, ...dataLines].join('\\r\\n');\n\n BrowserUtilities.downloadBlob(\n new Blob([csv], { type: 'text/csv;charset=utf-8;' }),\n filename,\n );\n };\n\n export = async (option: SdExcelExportOption) => {\n const { columns, items, fileName, sheets } = option;\n let hasDescription = false;\n for (const [idx, column] of columns.entries()) {\n if (!column.field) {\n throw new Error(`Column ${idx + 1}: Field is required`);\n }\n if (!column.title) {\n throw new Error(`Column ${idx + 1}: Title is required`);\n }\n if (column.description) {\n hasDescription = true;\n }\n }\n const Workbook = await this.#loadWorkbook();\n const workbook = new Workbook(); //await XlsxPopulate.fromBlankAsync(); // Đọc file sau khi đã download\n const firstSheet = workbook.addWorksheet('data'); // Lấy ra sheet đầu tiên\n columns.forEach((column, index) => {\n let width = 120;\n if (column.width && column.width.endsWith('px')) {\n width = +column.width.replace('px', '');\n }\n firstSheet.getColumn(index + 1).width = width / 7 || 20;\n firstSheet.getCell(1, index + 1).style = this.#fieldStyle;\n if (column.required) {\n firstSheet.getCell(2, index + 1).style = this.#requiredStyle;\n } else {\n firstSheet.getCell(2, index + 1).style = this.#titleStyle;\n }\n firstSheet.getCell(1, index + 1).value = column.field;\n firstSheet.getCell(2, index + 1).value = column.title;\n if (hasDescription) {\n firstSheet.getCell(3, index + 1).style = this.#descriptionStyle;\n firstSheet.getCell(3, index + 1).value = column.description || '';\n }\n });\n if (sheets?.length) {\n for (const sheet of sheets) {\n if (sheet.name && Array.isArray(sheet.items) && Array.isArray(sheet.headers)) {\n const newSheet = workbook.addWorksheet(sheet.name);\n sheet.headers.forEach((header, index) => {\n newSheet.getColumn(index + 1).width = 30;\n newSheet.getCell(1, index + 1).style = this.#titleStyle;\n newSheet.getCell(1, index + 1).value = header.value;\n newSheet.getCell(2, index + 1).style = this.#titleStyle;\n newSheet.getCell(2, index + 1).value = header.display || header.value;\n });\n sheet.items.forEach((item, idx1) => {\n sheet.headers.forEach((header, idx2) => {\n newSheet.getCell(3 + idx1, 1 + idx2).value = item[header.value];\n newSheet.getCell(3 + idx1, 1 + idx2).style = this.#cellStyle;\n });\n });\n }\n }\n }\n\n const fromRow = hasDescription ? 4 : 3;\n items.forEach((e, idx1) => {\n columns.forEach((column, idx2) => {\n if (typeof e[column.field] === 'number') {\n // Format mặc định với kiểu số\n firstSheet.getCell(fromRow + idx1, 1 + idx2).value = +e[column.field];\n firstSheet.getCell(fromRow + idx1, 1 + idx2).numFmt = '#';\n } else {\n firstSheet.getCell(fromRow + idx1, 1 + idx2).value = e[column.field];\n }\n firstSheet.getCell(fromRow + idx1, 1 + idx2).style = {\n ...this.#cellStyle,\n };\n });\n });\n const file = await workbook.xlsx.writeBuffer();\n BrowserUtilities.downloadBlob(\n new Blob([file], {\n type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n }),\n fileName\n );\n };\n\n // Helper để lấy giá trị text chuẩn từ ô Excel (xử lý RichText, Formula, Hyperlink)\n #getCellValue = (value: CellValue): string | number | null | undefined | boolean | Date => {\n if (value && typeof value === 'object') {\n // Xử lý Rich Text (vd: ô bôi đậm)\n if ('richText' in value) {\n return value.richText.map(t => t.text).join('');\n }\n // Xử lý Hyperlink\n if ('text' in value) {\n return value.text as string; // hoặc value.result nếu là công thức\n }\n // Xử lý Formula\n if ('result' in value) {\n return value.result as any;\n }\n }\n return value as any;\n };\n upload = async (): Promise<{ items: Record<string, any>[]; file: File | null }> => {\n try {\n const fileResult = await BrowserUtilities.upload({\n extensions: ['xlsx'],\n maxSizeInMb: 10,\n });\n\n // Chuẩn hóa file đầu vào (nếu upload trả về mảng thì lấy phần tử đầu)\n const file = Array.isArray(fileResult) ? fileResult[0] : fileResult;\n\n if (!file) {\n return { items: [], file: null };\n }\n\n return await this.parse(file);\n } catch (error) {\n console.error('Upload error:', error);\n throw error; // Hoặc return { items: [], file: null } tùy logic nghiệp vụ\n }\n };\n parse = async (file: File): Promise<{ items: Record<string, any>[]; file: File | null }> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = async e => {\n try {\n const buffer = e.target?.result as ArrayBuffer;\n if (!buffer) {\n throw new Error(this.#i18n.t('core.excel.cannot-read-file'));\n }\n\n const Workbook = await this.#loadWorkbook();\n const wb = new Workbook();\n await wb.xlsx.load(buffer);\n\n const sheet = wb.worksheets[0];\n if (!sheet) {\n throw new Error(this.#i18n.t('core.excel.no-sheet'));\n }\n\n const items: Record<string, any>[] = [];\n\n // Lấy row Header (Row 1)\n const headerRow = sheet.getRow(1);\n // Map: Column Index (bắt đầu từ 1) -> Tên trường (Key)\n const headerMap: Record<number, string> = {};\n\n // Duyệt qua các ô có dữ liệu thực tế của dòng Header\n headerRow.eachCell((cell, colNumber) => {\n const cellValue = this.#getCellValue(cell.value);\n if (cellValue) {\n // Ép kiểu về string và trim để làm key\n headerMap[colNumber] = String(cellValue).trim();\n }\n });\n\n // Duyệt dữ liệu từ dòng 2 trở đi\n sheet.eachRow((row, rowIndex) => {\n if (rowIndex <= 1 || !row.hasValues) return;\n\n const item: Record<string, any> = {};\n\n // Chỉ duyệt qua các cột đã định nghĩa trong headerMap\n // Cách này an toàn hơn là duyệt mảng values\n Object.keys(headerMap).forEach(colKey => {\n const colNumber = Number(colKey);\n const fieldKey = headerMap[colNumber];\n\n // Lấy giá trị ô tại cột tương ứng\n const rawValue = this.#getCellValue(row.getCell(colNumber).value);\n\n let finalValue = rawValue;\n\n // Xử lý string: trim\n if (typeof finalValue === 'string') {\n finalValue = finalValue.trim();\n }\n\n // Xử lý các keyword đặc biệt\n if (finalValue === '' || finalValue === undefined) {\n finalValue = null;\n } else if (finalValue === 'SET_NULL') {\n finalValue = null;\n } else if (finalValue === 'SET_EMPTY') {\n finalValue = '';\n }\n\n item[fieldKey] = finalValue;\n });\n\n // Chỉ push nếu item có dữ liệu (tùy chọn)\n if (Object.keys(item).length > 0) {\n items.push(item);\n }\n });\n\n resolve({ items, file });\n } catch (err) {\n reject(err);\n }\n };\n\n reader.onerror = error => reject(error);\n reader.readAsArrayBuffer(file);\n });\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdcorejs-angular-services-excel.mjs","sources":["../../../projects/sdcorejs-angular/services/excel/src/lib/spreadsheet-formula-injection.util.ts","../../../projects/sdcorejs-angular/services/excel/src/lib/excel.service.ts","../../../projects/sdcorejs-angular/services/excel/sdcorejs-angular-services-excel.ts"],"sourcesContent":["const DANGEROUS_SPREADSHEET_FORMULA_PREFIX = /^[=+\\-@\\t\\r\\n]/;\n\n/**\n * Prefix spreadsheet formula-like strings so exported files treat them as text.\n */\nexport function neutralizeSpreadsheetFormula(value: string): string;\nexport function neutralizeSpreadsheetFormula<T>(value: T): T;\nexport function neutralizeSpreadsheetFormula(value: unknown): unknown {\n if (typeof value !== 'string' || value === '' || value.startsWith(\"'\")) {\n return value;\n }\n\n return DANGEROUS_SPREADSHEET_FORMULA_PREFIX.test(value) ? `'${value}` : value;\n}\n","import { inject, Injectable } from '@angular/core';\nimport type { CellValue, Style } from 'exceljs';\n// import hash from 'object-hash';\nimport { DateUtilities } from '@sdcorejs/angular/utilities/extensions';\nimport { BrowserUtilities } from '@sdcorejs/utils/fns';\nimport { I18nService } from '@sdcorejs/angular/i18n';\nimport { SdExcelExportOption, SdExcelTemplate } from './excel.model';\nimport { neutralizeSpreadsheetFormula } from './spreadsheet-formula-injection.util';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SdExcelService {\n readonly #i18n = inject(I18nService);\n #fieldStyle: Partial<Style> = {\n border: {\n bottom: { style: 'thin' },\n left: { style: 'thin' },\n right: { style: 'thin' },\n },\n alignment: {\n vertical: 'middle',\n horizontal: 'center',\n wrapText: true,\n },\n font: {\n bold: true,\n size: 11,\n color: { argb: '000000' },\n },\n fill: {\n type: 'pattern',\n pattern: 'solid',\n fgColor: {\n argb: 'FAFAFA',\n },\n },\n };\n #titleColor = 'FFFFFF';\n #titleFgColor = '143180';\n #titleStyle: Partial<Style> = {\n border: {\n bottom: { style: 'thin' },\n left: { style: 'thin' },\n right: { style: 'thin' },\n },\n alignment: {\n vertical: 'middle',\n horizontal: 'center',\n wrapText: true,\n },\n font: {\n bold: true,\n size: 11,\n color: { argb: this.#titleColor },\n },\n fill: {\n type: 'pattern',\n pattern: 'solid',\n fgColor: {\n argb: this.#titleFgColor,\n },\n },\n };\n\n #requiredStyle: Partial<Style> = {\n border: {\n bottom: { style: 'thin' },\n left: { style: 'thin' },\n right: { style: 'thin' },\n },\n alignment: {\n vertical: 'middle',\n horizontal: 'center',\n wrapText: true,\n },\n font: {\n italic: true,\n size: 11,\n color: { argb: 'FFFFFF' },\n },\n fill: {\n type: 'pattern',\n pattern: 'solid',\n fgColor: {\n argb: 'FF1744',\n },\n },\n };\n\n #descriptionStyle: Partial<Style> = {\n border: {\n bottom: { style: 'thin' },\n left: { style: 'thin' },\n right: { style: 'thin' },\n },\n alignment: {\n wrapText: true,\n },\n font: {\n italic: true,\n size: 9,\n color: { argb: '000000' },\n },\n fill: {\n type: 'pattern',\n pattern: 'solid',\n fgColor: {\n argb: 'CFD8DC',\n },\n },\n };\n\n #cellStyle: Partial<Style> = {\n alignment: {\n vertical: 'middle',\n wrapText: true,\n },\n };\n\n constructor() {}\n\n // exceljs là CJS module — khi dynamic import từ ESM, named export `Workbook`\n // có thể nằm trên `mod.Workbook` hoặc bị bọc trong `mod.default.Workbook` tuỳ bundler.\n // Helper này chuẩn hoá cả hai trường hợp.\n async #loadWorkbook(): Promise<new () => import('exceljs').Workbook> {\n const mod: any = await import('exceljs');\n return mod.Workbook ?? mod.default?.Workbook;\n }\n\n generateTemplate = async (template: SdExcelTemplate) => {\n const { fileName, columns, sheets } = template;\n if (!Array.isArray(columns)) {\n throw new Error('Excel template columns must be an array');\n }\n for (const [idx, column] of columns.entries()) {\n if (!column.field) {\n throw new Error(`Column ${idx + 1}: Field is required`);\n }\n if (!column.title) {\n throw new Error(`Column ${idx + 1}: Title is required`);\n }\n }\n const hasDescription = columns.some(column => column.description);\n const Workbook = await this.#loadWorkbook();\n const workbook = new Workbook();\n const firstSheet = workbook.addWorksheet('template'); // Lấy ra sheet đầu tiên\n columns.forEach((column, index) => {\n const { required, fill, fontColor } = column;\n const cellField = firstSheet.getCell(1, index + 1);\n const cellTitle = firstSheet.getCell(2, index + 1);\n const cellDescription = firstSheet.getCell(3, index + 1);\n let width = 120;\n if (column.width && column.width.endsWith('px')) {\n width = +column.width.replace('px', '');\n }\n firstSheet.getColumn(index + 1).width = width / 7 || 20;\n cellField.style = this.#fieldStyle;\n if (required) {\n cellField.style = this.#requiredStyle;\n } else {\n cellField.style = this.#fieldStyle;\n }\n cellTitle.style = {\n ...this.#titleStyle,\n font: {\n ...this.#titleStyle?.font,\n color: {\n ...this.#titleStyle?.font?.color,\n argb: fontColor || this.#titleStyle?.font?.color?.argb,\n },\n },\n fill: {\n type: 'pattern',\n pattern: 'solid',\n fgColor: {\n argb: fill || this.#titleFgColor,\n },\n },\n };\n cellField.value = neutralizeSpreadsheetFormula(column.field);\n cellTitle.value = neutralizeSpreadsheetFormula(column.title);\n if (hasDescription) {\n cellDescription.style = this.#descriptionStyle;\n cellDescription.value = neutralizeSpreadsheetFormula(column.description || '');\n }\n });\n if (sheets?.length) {\n for (const sheet of sheets) {\n if (sheet.name && Array.isArray(sheet.items) && Array.isArray(sheet.headers)) {\n const newSheet = workbook.addWorksheet(sheet.name);\n sheet.headers.forEach((header, index) => {\n newSheet.getColumn(index + 1).width = 30;\n newSheet.getCell(1, index + 1).style = this.#titleStyle;\n newSheet.getCell(1, index + 1).value = neutralizeSpreadsheetFormula(header.value);\n newSheet.getCell(2, index + 1).style = this.#titleStyle;\n newSheet.getCell(2, index + 1).value = neutralizeSpreadsheetFormula(header.display || header.value);\n });\n sheet.items.forEach((item, idx1) => {\n sheet.headers.forEach((header, idx2) => {\n newSheet.getCell(3 + idx1, 1 + idx2).value = neutralizeSpreadsheetFormula(item[header.value]) as CellValue;\n newSheet.getCell(3 + idx1, 1 + idx2).style = this.#cellStyle;\n });\n });\n }\n }\n }\n const file = await workbook.xlsx.writeBuffer();\n BrowserUtilities.downloadBlob(\n new Blob([file], {\n type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n }),\n fileName\n );\n };\n\n exportCSV = async (option: SdExcelExportOption): Promise<void> => {\n const { columns, items, fileName } = option;\n const filename = `${fileName || 'CSV'}_${DateUtilities.toFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss')}.csv`;\n\n // Escape CSV cell: bọc trong dấu \" nếu chứa dấu phẩy / xuống dòng / dấu ngoặc kép.\n // Dấu \" bên trong được nhân đôi theo chuẩn RFC 4180.\n const escape = (v: unknown): string => {\n if (v == null) return '';\n const s = typeof v === 'string' ? neutralizeSpreadsheetFormula(v) : String(v);\n return /[\",\\n\\r]/.test(s) ? `\"${s.replace(/\"/g, '\"\"')}\"` : s;\n };\n\n const headerLine = columns.map(c => escape(c.title)).join(',');\n const dataLines = items.map(item => columns.map(c => escape((item as Record<string, unknown>)[c.field])).join(','));\n\n // Prepend UTF-8 BOM so Excel opens Vietnamese text with the correct encoding.\n // Dùng CRLF vì Excel trên Windows ưu tiên, macOS Excel cũng chấp nhận.\n const csv = '\\uFEFF' + [headerLine, ...dataLines].join('\\r\\n');\n\n BrowserUtilities.downloadBlob(new Blob([csv], { type: 'text/csv;charset=utf-8;' }), filename);\n };\n\n export = async (option: SdExcelExportOption) => {\n const { columns, items, fileName, sheets } = option;\n let hasDescription = false;\n for (const [idx, column] of columns.entries()) {\n if (!column.field) {\n throw new Error(`Column ${idx + 1}: Field is required`);\n }\n if (!column.title) {\n throw new Error(`Column ${idx + 1}: Title is required`);\n }\n if (column.description) {\n hasDescription = true;\n }\n }\n const Workbook = await this.#loadWorkbook();\n const workbook = new Workbook(); //await XlsxPopulate.fromBlankAsync(); // Đọc file sau khi đã download\n const firstSheet = workbook.addWorksheet('data'); // Lấy ra sheet đầu tiên\n columns.forEach((column, index) => {\n let width = 120;\n if (column.width && column.width.endsWith('px')) {\n width = +column.width.replace('px', '');\n }\n firstSheet.getColumn(index + 1).width = width / 7 || 20;\n firstSheet.getCell(1, index + 1).style = this.#fieldStyle;\n if (column.required) {\n firstSheet.getCell(2, index + 1).style = this.#requiredStyle;\n } else {\n firstSheet.getCell(2, index + 1).style = this.#titleStyle;\n }\n firstSheet.getCell(1, index + 1).value = neutralizeSpreadsheetFormula(column.field);\n firstSheet.getCell(2, index + 1).value = neutralizeSpreadsheetFormula(column.title);\n if (hasDescription) {\n firstSheet.getCell(3, index + 1).style = this.#descriptionStyle;\n firstSheet.getCell(3, index + 1).value = neutralizeSpreadsheetFormula(column.description || '');\n }\n });\n if (sheets?.length) {\n for (const sheet of sheets) {\n if (sheet.name && Array.isArray(sheet.items) && Array.isArray(sheet.headers)) {\n const newSheet = workbook.addWorksheet(sheet.name);\n sheet.headers.forEach((header, index) => {\n newSheet.getColumn(index + 1).width = 30;\n newSheet.getCell(1, index + 1).style = this.#titleStyle;\n newSheet.getCell(1, index + 1).value = neutralizeSpreadsheetFormula(header.value);\n newSheet.getCell(2, index + 1).style = this.#titleStyle;\n newSheet.getCell(2, index + 1).value = neutralizeSpreadsheetFormula(header.display || header.value);\n });\n sheet.items.forEach((item, idx1) => {\n sheet.headers.forEach((header, idx2) => {\n newSheet.getCell(3 + idx1, 1 + idx2).value = neutralizeSpreadsheetFormula(item[header.value]) as CellValue;\n newSheet.getCell(3 + idx1, 1 + idx2).style = this.#cellStyle;\n });\n });\n }\n }\n }\n\n const fromRow = hasDescription ? 4 : 3;\n items.forEach((e, idx1) => {\n columns.forEach((column, idx2) => {\n if (typeof e[column.field] === 'number') {\n // Format mặc định với kiểu số\n firstSheet.getCell(fromRow + idx1, 1 + idx2).value = +e[column.field];\n firstSheet.getCell(fromRow + idx1, 1 + idx2).numFmt = '#';\n } else {\n firstSheet.getCell(fromRow + idx1, 1 + idx2).value = neutralizeSpreadsheetFormula(e[column.field]) as CellValue;\n }\n firstSheet.getCell(fromRow + idx1, 1 + idx2).style = {\n ...this.#cellStyle,\n };\n });\n });\n const file = await workbook.xlsx.writeBuffer();\n BrowserUtilities.downloadBlob(\n new Blob([file], {\n type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n }),\n fileName\n );\n };\n\n // Helper để lấy giá trị text chuẩn từ ô Excel (xử lý RichText, Formula, Hyperlink)\n #getCellValue = (value: CellValue): string | number | null | undefined | boolean | Date => {\n if (value && typeof value === 'object') {\n // Xử lý Rich Text (vd: ô bôi đậm)\n if ('richText' in value) {\n return value.richText.map(t => t.text).join('');\n }\n // Xử lý Hyperlink\n if ('text' in value) {\n return value.text as string; // hoặc value.result nếu là công thức\n }\n // Xử lý Formula\n if ('result' in value) {\n return value.result as any;\n }\n }\n return value as any;\n };\n upload = async (): Promise<{ items: Record<string, any>[]; file: File | null }> => {\n try {\n const fileResult = await BrowserUtilities.upload({\n extensions: ['xlsx'],\n maxSizeInMb: 10,\n });\n\n // Chuẩn hóa file đầu vào (nếu upload trả về mảng thì lấy phần tử đầu)\n const file = Array.isArray(fileResult) ? fileResult[0] : fileResult;\n\n if (!file) {\n return { items: [], file: null };\n }\n\n return await this.parse(file);\n } catch (error) {\n console.error('Upload error:', error);\n throw error; // Hoặc return { items: [], file: null } tùy logic nghiệp vụ\n }\n };\n parse = async (file: File): Promise<{ items: Record<string, any>[]; file: File | null }> => {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = async e => {\n try {\n const buffer = e.target?.result as ArrayBuffer;\n if (!buffer) {\n throw new Error(this.#i18n.t('core.excel.cannot-read-file'));\n }\n\n const Workbook = await this.#loadWorkbook();\n const wb = new Workbook();\n await wb.xlsx.load(buffer);\n\n const sheet = wb.worksheets[0];\n if (!sheet) {\n throw new Error(this.#i18n.t('core.excel.no-sheet'));\n }\n\n const items: Record<string, any>[] = [];\n\n // Lấy row Header (Row 1)\n const headerRow = sheet.getRow(1);\n // Map: Column Index (bắt đầu từ 1) -> Tên trường (Key)\n const headerMap: Record<number, string> = {};\n\n // Duyệt qua các ô có dữ liệu thực tế của dòng Header\n headerRow.eachCell((cell, colNumber) => {\n const cellValue = this.#getCellValue(cell.value);\n if (cellValue) {\n // Ép kiểu về string và trim để làm key\n headerMap[colNumber] = String(cellValue).trim();\n }\n });\n\n // Duyệt dữ liệu từ dòng 2 trở đi\n sheet.eachRow((row, rowIndex) => {\n if (rowIndex <= 1 || !row.hasValues) return;\n\n const item: Record<string, any> = {};\n\n // Chỉ duyệt qua các cột đã định nghĩa trong headerMap\n // Cách này an toàn hơn là duyệt mảng values\n Object.keys(headerMap).forEach(colKey => {\n const colNumber = Number(colKey);\n const fieldKey = headerMap[colNumber];\n\n // Lấy giá trị ô tại cột tương ứng\n const rawValue = this.#getCellValue(row.getCell(colNumber).value);\n\n let finalValue = rawValue;\n\n // Xử lý string: trim\n if (typeof finalValue === 'string') {\n finalValue = finalValue.trim();\n }\n\n // Xử lý các keyword đặc biệt\n if (finalValue === '' || finalValue === undefined) {\n finalValue = null;\n } else if (finalValue === 'SET_NULL') {\n finalValue = null;\n } else if (finalValue === 'SET_EMPTY') {\n finalValue = '';\n }\n\n item[fieldKey] = finalValue;\n });\n\n // Chỉ push nếu item có dữ liệu (tùy chọn)\n if (Object.keys(item).length > 0) {\n items.push(item);\n }\n });\n\n resolve({ items, file });\n } catch (err) {\n reject(err);\n }\n };\n\n reader.onerror = error => reject(error);\n reader.readAsArrayBuffer(file);\n });\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,13 +1,12 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Inject, Optional, Injectable } from '@angular/core';
2
+ import { inject, Injectable } from '@angular/core';
3
3
  import { SD_CORE_CONFIGURATION } from '@sdcorejs/angular/configurations';
4
4
 
5
5
  class SdLicenseService {
6
- coreConfiguration;
7
6
  #SALT = 'angular-core-976e2fa6f8b44dadbc63f87b057a331f';
8
7
  #isValid = false;
9
- constructor(coreConfiguration) {
10
- this.coreConfiguration = coreConfiguration;
8
+ coreConfiguration = inject(SD_CORE_CONFIGURATION, { optional: true });
9
+ constructor() {
11
10
  this.#verify();
12
11
  }
13
12
  enforceLicense = () => {
@@ -19,7 +18,6 @@ class SdLicenseService {
19
18
  const hostname = window.location.hostname; // Ví dụ: store.uat.nexa.mobi
20
19
  // 1. Bypass Localhost
21
20
  if (this.#isLocalhost(hostname)) {
22
- console.log('%c [SdAngularCore] Dev Mode ', 'background: #222; color: #bada55');
23
21
  this.#isValid = true;
24
22
  return;
25
23
  }
@@ -81,7 +79,7 @@ class SdLicenseService {
81
79
  #throwSecurityError = () => {
82
80
  throw new Error(`[Security] Unauthorized usage of UI Lib on domain: ${window.location.hostname}`);
83
81
  };
84
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdLicenseService, deps: [{ token: SD_CORE_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
82
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdLicenseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
85
83
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdLicenseService, providedIn: 'root' });
86
84
  }
87
85
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdLicenseService, decorators: [{
@@ -89,12 +87,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
89
87
  args: [{
90
88
  providedIn: 'root',
91
89
  }]
92
- }], ctorParameters: () => [{ type: undefined, decorators: [{
93
- type: Inject,
94
- args: [SD_CORE_CONFIGURATION]
95
- }, {
96
- type: Optional
97
- }] }] });
90
+ }], ctorParameters: () => [] });
98
91
 
99
92
  /**
100
93
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"sdcorejs-angular-services-license.mjs","sources":["../../../projects/sdcorejs-angular/services/license/src/license.service.ts","../../../projects/sdcorejs-angular/services/license/sdcorejs-angular-services-license.ts"],"sourcesContent":["import { Inject, Injectable, Optional } from '@angular/core';\nimport { ISdCoreConfiguration, SD_CORE_CONFIGURATION } from '@sdcorejs/angular/configurations';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SdLicenseService {\n readonly #SALT = 'angular-core-976e2fa6f8b44dadbc63f87b057a331f';\n #isValid = false;\n\n constructor(\n @Inject(SD_CORE_CONFIGURATION)\n @Optional()\n private readonly coreConfiguration: ISdCoreConfiguration | undefined\n ) {\n this.#verify();\n }\n\n enforceLicense = () => {\n if (!this.#isValid) {\n this.#throwSecurityError();\n }\n };\n\n #verify = () => {\n const hostname = window.location.hostname; // Ví dụ: store.uat.nexa.mobi\n\n // 1. Bypass Localhost\n if (this.#isLocalhost(hostname)) {\n console.log('%c [SdAngularCore] Dev Mode ', 'background: #222; color: #bada55');\n this.#isValid = true;\n return;\n }\n\n const configKeys = this.#getConfiguredKeys();\n if (configKeys.length === 0) {\n this.#isValid = false;\n this.#throwSecurityError();\n return;\n }\n\n // 2. CHECK EXACT MATCH (Ưu tiên khớp chính xác 100%)\n // Hash chuỗi: \"store.uat.nexa.mobi\" + SALT\n if (this.#checkMatch(hostname, configKeys)) {\n this.#isValid = true;\n return;\n }\n\n // 3. CHECK WILDCARD MATCH (Thử các trường hợp có dấu *)\n const parts = hostname.split('.'); // [\"store\", \"uat\", \"nexa\", \"mobi\"]\n\n // Lặp để cắt dần subdomain bên trái và thêm \"*.\" vào\n // Điều kiện > 2 để đảm bảo không check các case vô nghĩa như *.mobi hay *.com\n while (parts.length > 2) {\n parts.shift(); // Bỏ phần đầu: [\"uat\", \"nexa\", \"mobi\"]\n \n // Tạo domain wildcard: \"*.uat.nexa.mobi\"\n const wildcardDomain = '*.' + parts.join('.'); \n \n // Hash chuỗi: \"*.uat.nexa.mobi\" + SALT\n if (this.#checkMatch(wildcardDomain, configKeys)) {\n this.#isValid = true;\n return;\n }\n }\n\n // Nếu chạy hết vòng lặp mà không khớp cái nào\n this.#isValid = false;\n this.#throwSecurityError();\n };\n\n // Helper để check xem hash của input có nằm trong list key không\n #checkMatch = (inputString: string, validKeys: string[]): boolean => {\n const hash = this.#generateHash(inputString + this.#SALT);\n return validKeys.includes(hash);\n };\n\n #getConfiguredKeys = (): string[] => {\n const keyOrKeys = this.coreConfiguration?.licenseKey;\n if (!keyOrKeys) return [];\n return Array.isArray(keyOrKeys) ? keyOrKeys : [keyOrKeys];\n };\n\n #isLocalhost = (domain: string) => {\n return domain === 'localhost' || domain === '127.0.0.1' || domain.includes('localhost');\n };\n\n #generateHash = (input: string): string => {\n let hash = 0;\n if (input.length === 0) return hash.toString();\n for (let i = 0; i < input.length; i++) {\n const char = input.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n return btoa(hash.toString() + 'signed');\n };\n\n #throwSecurityError = () => {\n throw new Error(`[Security] Unauthorized usage of UI Lib on domain: ${window.location.hostname}`);\n };\n}","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdcorejs-angular-services-license.mjs","sources":["../../../projects/sdcorejs-angular/services/license/src/license.service.ts","../../../projects/sdcorejs-angular/services/license/sdcorejs-angular-services-license.ts"],"sourcesContent":["import { inject, Injectable } from '@angular/core';\nimport { ISdCoreConfiguration, SD_CORE_CONFIGURATION } from '@sdcorejs/angular/configurations';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SdLicenseService {\n readonly #SALT = 'angular-core-976e2fa6f8b44dadbc63f87b057a331f';\n #isValid = false;\n private readonly coreConfiguration: ISdCoreConfiguration | null = inject(SD_CORE_CONFIGURATION, { optional: true });\n\n constructor() {\n this.#verify();\n }\n\n enforceLicense = () => {\n if (!this.#isValid) {\n this.#throwSecurityError();\n }\n };\n\n #verify = () => {\n const hostname = window.location.hostname; // Ví dụ: store.uat.nexa.mobi\n\n // 1. Bypass Localhost\n if (this.#isLocalhost(hostname)) {\n this.#isValid = true;\n return;\n }\n\n const configKeys = this.#getConfiguredKeys();\n if (configKeys.length === 0) {\n this.#isValid = false;\n this.#throwSecurityError();\n return;\n }\n\n // 2. CHECK EXACT MATCH (Ưu tiên khớp chính xác 100%)\n // Hash chuỗi: \"store.uat.nexa.mobi\" + SALT\n if (this.#checkMatch(hostname, configKeys)) {\n this.#isValid = true;\n return;\n }\n\n // 3. CHECK WILDCARD MATCH (Thử các trường hợp có dấu *)\n const parts = hostname.split('.'); // [\"store\", \"uat\", \"nexa\", \"mobi\"]\n\n // Lặp để cắt dần subdomain bên trái và thêm \"*.\" vào\n // Điều kiện > 2 để đảm bảo không check các case vô nghĩa như *.mobi hay *.com\n while (parts.length > 2) {\n parts.shift(); // Bỏ phần đầu: [\"uat\", \"nexa\", \"mobi\"]\n\n // Tạo domain wildcard: \"*.uat.nexa.mobi\"\n const wildcardDomain = '*.' + parts.join('.');\n\n // Hash chuỗi: \"*.uat.nexa.mobi\" + SALT\n if (this.#checkMatch(wildcardDomain, configKeys)) {\n this.#isValid = true;\n return;\n }\n }\n\n // Nếu chạy hết vòng lặp mà không khớp cái nào\n this.#isValid = false;\n this.#throwSecurityError();\n };\n\n // Helper để check xem hash của input có nằm trong list key không\n #checkMatch = (inputString: string, validKeys: string[]): boolean => {\n const hash = this.#generateHash(inputString + this.#SALT);\n return validKeys.includes(hash);\n };\n\n #getConfiguredKeys = (): string[] => {\n const keyOrKeys = this.coreConfiguration?.licenseKey;\n if (!keyOrKeys) return [];\n return Array.isArray(keyOrKeys) ? keyOrKeys : [keyOrKeys];\n };\n\n #isLocalhost = (domain: string) => {\n return domain === 'localhost' || domain === '127.0.0.1' || domain.includes('localhost');\n };\n\n #generateHash = (input: string): string => {\n let hash = 0;\n if (input.length === 0) return hash.toString();\n for (let i = 0; i < input.length; i++) {\n const char = input.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash;\n }\n return btoa(hash.toString() + 'signed');\n };\n\n #throwSecurityError = () => {\n throw new Error(`[Security] Unauthorized usage of UI Lib on domain: ${window.location.hostname}`);\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -1,69 +1,62 @@
1
1
  import { CommonModule, DOCUMENT } from '@angular/common';
2
2
  import * as i0 from '@angular/core';
3
- import { signal, SecurityContext, HostListener, Input, Component, createComponent, Inject, Injectable } from '@angular/core';
3
+ import { signal, computed, SecurityContext, HostListener, Input, ChangeDetectionStrategy, Component, inject, ApplicationRef, EnvironmentInjector, createComponent, Injectable } from '@angular/core';
4
4
  import { Utilities } from '@sdcorejs/utils/fns';
5
- import { trigger, transition, style, animate } from '@angular/animations';
6
- import { TranslatePipe } from '@sdcorejs/angular/i18n';
5
+ import { TranslatePipe, I18nService } from '@sdcorejs/angular/i18n';
7
6
  import * as i2 from '@angular/platform-browser';
8
7
 
8
+ const TOAST_EXIT_ANIMATION_MS = 200;
9
9
  class ToastComponent {
10
10
  notifyService;
11
11
  sanitizer;
12
12
  data;
13
13
  isExpanded = signal(false);
14
+ isClosing = signal(false);
15
+ hostClasses = computed(() => (this.isClosing() ? 'bg-white sd-toast sd-toast--closing' : 'bg-white sd-toast'));
14
16
  MAX_SHOW = 2;
15
- // --- Logic Timer ---
16
- timer;
17
- start;
18
- remaining;
17
+ timer = null;
18
+ closeTimer = null;
19
+ start = 0;
20
+ remaining = 0;
19
21
  constructor(notifyService, sanitizer) {
20
22
  this.notifyService = notifyService;
21
23
  this.sanitizer = sanitizer;
22
24
  }
23
- /**
24
- * Sanitize HTML tường minh trước khi render qua `[innerHTML]` — strip
25
- * `<script>`, event handler (`on*`), `javascript:` URL. Chỉ chạy ở nhánh
26
- * `data.html === true`; nhánh mặc định render text (auto-escape) nên không
27
- * có sink này. // why: phơi rõ việc sanitize cho review/scanner bảo mật.
28
- */
29
- sanitizeHtml(value) {
30
- return this.sanitizer.sanitize(SecurityContext.HTML, value) ?? '';
31
- }
32
- /** Message ở dạng chuỗi đơn (chỉ dùng khi !isMultiMessage). */
33
- get singleMessage() {
34
- return this.data.message;
35
- }
36
25
  ngOnInit() {
37
- // Khởi tạo thời gian còn lại bằng duration ban đầu
38
26
  this.remaining = this.data.duration;
39
- // Bắt đầu đếm ngược ngay khi hiện ra
40
27
  this.resumeTimer();
41
28
  }
42
29
  ngOnDestroy() {
43
- clearTimeout(this.timer);
30
+ this.clearAutoDismissTimer();
31
+ this.clearCloseTimer();
44
32
  }
45
- // --- Logic Pause/Resume ---
46
33
  pauseTimer() {
47
- if (this.timer) {
48
- // Xóa timer hiện tại
49
- clearTimeout(this.timer);
50
- this.timer = null;
51
- // Tính toán thời gian đã trôi qua để trừ đi
52
- this.remaining -= Date.now() - this.start;
34
+ if (!this.timer || this.isClosing()) {
35
+ return;
53
36
  }
37
+ clearTimeout(this.timer);
38
+ this.timer = null;
39
+ this.remaining = Math.max(this.remaining - (Date.now() - this.start), 0);
54
40
  }
55
41
  resumeTimer() {
56
- // Chỉ chạy tiếp nếu còn thời gian và timer chưa chạy
57
- if (this.remaining > 0 && !this.timer) {
58
- this.start = Date.now();
59
- this.timer = setTimeout(() => {
60
- this.close();
61
- }, this.remaining);
42
+ if (this.remaining <= 0 || this.timer || this.isClosing()) {
43
+ return;
62
44
  }
45
+ this.start = Date.now();
46
+ this.timer = setTimeout(() => {
47
+ this.close();
48
+ }, this.remaining);
63
49
  }
64
- // --- Logic cũ ---
65
50
  close() {
66
- this.notifyService.remove(this.data.id);
51
+ if (this.isClosing()) {
52
+ return;
53
+ }
54
+ this.clearAutoDismissTimer();
55
+ this.isClosing.set(true);
56
+ this.closeTimer = setTimeout(() => {
57
+ this.closeTimer = null;
58
+ this.notifyService.remove(this.data.id);
59
+ }, TOAST_EXIT_ANIMATION_MS);
67
60
  }
68
61
  onActionClick() {
69
62
  this.data.onAction?.();
@@ -71,6 +64,12 @@ class ToastComponent {
71
64
  toggleExpand() {
72
65
  this.isExpanded.update(v => !v);
73
66
  }
67
+ sanitizeHtml(value) {
68
+ return this.sanitizer.sanitize(SecurityContext.HTML, value) ?? '';
69
+ }
70
+ get singleMessage() {
71
+ return this.data.message;
72
+ }
74
73
  get isMultiMessage() {
75
74
  return Array.isArray(this.data.message);
76
75
  }
@@ -89,48 +88,38 @@ class ToastComponent {
89
88
  get hasMore() {
90
89
  return this.isMultiMessage && this.messages.length > this.MAX_SHOW;
91
90
  }
92
- /** autoid theo loại toast để E2E chọn trực tiếp, vd `services-notify-toast-success`. */
93
91
  get autoId() {
94
92
  return `services-notify-toast-${this.data.type}`;
95
93
  }
96
- /** Gộp message (mảng nối ' | ') để phơi ra data-message cho E2E. */
97
94
  get dataMessage() {
98
95
  return Array.isArray(this.data.message) ? this.data.message.join(' | ') : this.data.message;
99
96
  }
97
+ clearAutoDismissTimer() {
98
+ if (!this.timer) {
99
+ return;
100
+ }
101
+ clearTimeout(this.timer);
102
+ this.timer = null;
103
+ }
104
+ clearCloseTimer() {
105
+ if (!this.closeTimer) {
106
+ return;
107
+ }
108
+ clearTimeout(this.closeTimer);
109
+ this.closeTimer = null;
110
+ }
100
111
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ToastComponent, deps: [{ token: SdNotifyService }, { token: i2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
101
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ToastComponent, isStandalone: true, selector: "toast", inputs: { data: "data" }, host: { listeners: { "mouseenter": "pauseTimer()", "mouseleave": "resumeTimer()" }, properties: { "@toastAnimation": "true", "class": "\"bg-white sd-toast\"", "attr.data-autoid": "autoId", "attr.data-type": "data.type", "attr.data-title": "data.title ?? null", "attr.data-message": "dataMessage" } }, ngImport: i0, template: "<div class=\"sd-toast__bar\" [class]=\"'bg-' + data.type\"></div>\n\n<div class=\"sd-toast__icon\" [class]=\"'text-' + data.type\">\n @switch (data.type) {\n @case ('success') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\"/></svg>\n }\n @case ('info') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z\"/></svg>\n }\n @case ('warning') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z\"/></svg>\n }\n @case ('error') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/></svg>\n }\n }\n</div>\n\n<div class=\"sd-toast__content\">\n <div class=\"sd-toast__header\">\n <strong class=\"sd-toast__title\">{{ data.title || ('core.notify.type.' + data.type | translate) }}</strong>\n <button class=\"sd-toast__close\" (click)=\"close()\">\u2715</button>\n </div>\n\n <div class=\"sd-toast__body\">\n @if (!isMultiMessage) {\n <!-- why: m\u1EB7c \u0111\u1ECBnh render TEXT (auto-escape) \u2014 an to\u00E0n. Ch\u1EC9 render HTML\n (\u0111\u00E3 sanitize) khi data.html=true. -->\n @if (data.html) {\n <div [innerHTML]=\"sanitizeHtml(singleMessage)\"></div>\n } @else {\n <div>{{ singleMessage }}</div>\n }\n }\n @else {\n <ul class=\"msg-list\">\n @for (msg of displayMessages; track msg) {\n @if (data.html) {\n <li [innerHTML]=\"sanitizeHtml('- ' + msg)\"></li>\n } @else {\n <li>{{ '- ' + msg }}</li>\n }\n }\n </ul>\n\n @if (hasMore) {\n <button type=\"button\" \n class=\"toggle-more btn-link\" \n [class]=\"'text-' + data.type\" \n (click)=\"toggleExpand()\">\n {{ isExpanded() ? ('core.notify.show-less' | translate) : ('core.notify.show-more' | translate: { count: restCount }) }}\n </button>\n }\n }\n </div>\n\n @if (data.actionLabel) {\n <div class=\"sd-toast__actions\">\n <button class=\"btn-action\" \n [class]=\"'bg-' + data.type + '-light text-' + data.type\"\n (click)=\"onActionClick()\">\n {{ data.actionLabel }}\n </button>\n </div>\n }\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;width:350px;border-radius:8px;box-shadow:0 4px 12px #00000026;margin-bottom:12px;overflow:hidden;position:relative;font-family:Roboto,sans-serif;pointer-events:auto}.sd-toast__bar{width:6px;flex-shrink:0}.sd-toast__icon{padding:12px 0 0 12px;flex-shrink:0}.sd-toast__icon svg{width:24px;height:24px}.sd-toast__content{flex-grow:1;padding:12px;display:flex;flex-direction:column}.sd-toast__header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:4px}.sd-toast__title{font-size:16px;font-weight:600}.sd-toast__close{background:none;border:none;font-size:16px;cursor:pointer;line-height:1;padding:0;opacity:.5;transition:opacity .2s}.sd-toast__close:hover{opacity:1}.sd-toast__body{font-size:14px;line-height:1.4;word-break:break-word}.sd-toast__actions{display:flex;justify-content:flex-end;margin-top:8px}.msg-list{padding-left:0;list-style:none;margin:0}.toggle-more{background:none;border:none;padding:0;font:inherit;cursor:pointer;font-size:13px;margin-top:4px;font-weight:500;text-align:left}.toggle-more:hover{text-decoration:underline}.toggle-more:focus-visible{outline:2px solid currentColor;outline-offset:2px}.btn-action{border:none;padding:6px 12px;border-radius:4px;font-weight:600;cursor:pointer;font-size:13px;transition:filter .2s}.btn-action:hover{filter:brightness(.95)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }], animations: [
102
- trigger('toastAnimation', [
103
- transition(':enter', [
104
- style({ transform: 'translateX(100%)', opacity: 0 }),
105
- animate('300ms ease-out', style({ transform: 'translateX(0)', opacity: 1 }))
106
- ]),
107
- transition(':leave', [
108
- animate('200ms ease-in', style({ transform: 'translateX(100%)', opacity: 0 }))
109
- ])
110
- ])
111
- ] });
112
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ToastComponent, isStandalone: true, selector: "toast", inputs: { data: "data" }, host: { listeners: { "mouseenter": "pauseTimer()", "mouseleave": "resumeTimer()" }, properties: { "class": "hostClasses()", "attr.data-autoid": "autoId", "attr.data-type": "data.type", "attr.data-title": "data.title ?? null", "attr.data-message": "dataMessage" } }, ngImport: i0, template: "<div class=\"sd-toast__bar\" [class]=\"'bg-' + data.type\"></div>\n\n<div class=\"sd-toast__icon\" [class]=\"'text-' + data.type\">\n @switch (data.type) {\n @case ('success') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\"/></svg>\n }\n @case ('info') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z\"/></svg>\n }\n @case ('warning') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z\"/></svg>\n }\n @case ('error') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/></svg>\n }\n }\n</div>\n\n<div class=\"sd-toast__content\">\n <div class=\"sd-toast__header\">\n <strong class=\"sd-toast__title\">{{ data.title || ('core.notify.type.' + data.type | translate) }}</strong>\n <button class=\"sd-toast__close\" (click)=\"close()\">&times;</button>\n </div>\n\n <div class=\"sd-toast__body\">\n @if (!isMultiMessage) {\n <!-- Text rendering is the default safe path; HTML is opt-in and sanitized. -->\n @if (data.html) {\n <div [innerHTML]=\"sanitizeHtml(singleMessage)\"></div>\n } @else {\n <div>{{ singleMessage }}</div>\n }\n } @else {\n <ul class=\"msg-list\">\n @for (msg of displayMessages; track msg) {\n @if (data.html) {\n <li [innerHTML]=\"sanitizeHtml('- ' + msg)\"></li>\n } @else {\n <li>{{ '- ' + msg }}</li>\n }\n }\n </ul>\n\n @if (hasMore) {\n <button\n type=\"button\"\n class=\"toggle-more btn-link\"\n [class]=\"'text-' + data.type\"\n (click)=\"toggleExpand()\">\n {{ isExpanded() ? ('core.notify.show-less' | translate) : ('core.notify.show-more' | translate: { count: restCount }) }}\n </button>\n }\n }\n </div>\n\n @if (data.actionLabel) {\n <div class=\"sd-toast__actions\">\n <button\n class=\"btn-action\"\n [class]=\"'bg-' + data.type + '-light text-' + data.type\"\n (click)=\"onActionClick()\">\n {{ data.actionLabel }}\n </button>\n </div>\n }\n</div>\n", styles: [":host{display:flex;width:350px;border-radius:8px;box-shadow:0 4px 12px #00000026;margin-bottom:12px;overflow:hidden;position:relative;font-family:Roboto,sans-serif;pointer-events:auto;animation:sd-toast-enter .3s ease-out}:host(.sd-toast--closing){pointer-events:none;animation:sd-toast-leave .2s ease-in forwards}@keyframes sd-toast-enter{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes sd-toast-leave{0%{transform:translate(0);opacity:1}to{transform:translate(100%);opacity:0}}@media(prefers-reduced-motion:reduce){:host,:host(.sd-toast--closing){animation:none}}.sd-toast__bar{width:6px;flex-shrink:0}.sd-toast__icon{padding:12px 0 0 12px;flex-shrink:0}.sd-toast__icon svg{width:24px;height:24px}.sd-toast__content{flex-grow:1;padding:12px;display:flex;flex-direction:column}.sd-toast__header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:4px}.sd-toast__title{font-size:16px;font-weight:600}.sd-toast__close{background:none;border:none;font-size:16px;cursor:pointer;line-height:1;padding:0;opacity:.5;transition:opacity .2s}.sd-toast__close:hover{opacity:1}.sd-toast__body{font-size:14px;line-height:1.4;word-break:break-word}.sd-toast__actions{display:flex;justify-content:flex-end;margin-top:8px}.msg-list{padding-left:0;list-style:none;margin:0}.toggle-more{background:none;border:none;padding:0;font:inherit;cursor:pointer;font-size:13px;margin-top:4px;font-weight:500;text-align:left}.toggle-more:hover{text-decoration:underline}.toggle-more:focus-visible{outline:2px solid currentColor;outline-offset:2px}.btn-action{border:none;padding:6px 12px;border-radius:4px;font-weight:600;cursor:pointer;font-size:13px;transition:filter .2s}.btn-action:hover{filter:brightness(.95)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
112
113
  }
113
114
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ToastComponent, decorators: [{
114
115
  type: Component,
115
- args: [{ selector: 'toast', standalone: true, imports: [CommonModule, TranslatePipe], animations: [
116
- trigger('toastAnimation', [
117
- transition(':enter', [
118
- style({ transform: 'translateX(100%)', opacity: 0 }),
119
- animate('300ms ease-out', style({ transform: 'translateX(0)', opacity: 1 }))
120
- ]),
121
- transition(':leave', [
122
- animate('200ms ease-in', style({ transform: 'translateX(100%)', opacity: 0 }))
123
- ])
124
- ])
125
- ], host: {
126
- '[@toastAnimation]': 'true',
127
- '[class]': '"bg-white sd-toast"',
128
- // E2E hooks đọc bởi sd-autoid-inspector: autoid theo loại + state type/title/message.
116
+ args: [{ selector: 'toast', standalone: true, imports: [CommonModule, TranslatePipe], changeDetection: ChangeDetectionStrategy.OnPush, host: {
117
+ '[class]': 'hostClasses()',
129
118
  '[attr.data-autoid]': 'autoId',
130
119
  '[attr.data-type]': 'data.type',
131
120
  '[attr.data-title]': 'data.title ?? null',
132
- '[attr.data-message]': 'dataMessage'
133
- }, template: "<div class=\"sd-toast__bar\" [class]=\"'bg-' + data.type\"></div>\n\n<div class=\"sd-toast__icon\" [class]=\"'text-' + data.type\">\n @switch (data.type) {\n @case ('success') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\"/></svg>\n }\n @case ('info') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z\"/></svg>\n }\n @case ('warning') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z\"/></svg>\n }\n @case ('error') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/></svg>\n }\n }\n</div>\n\n<div class=\"sd-toast__content\">\n <div class=\"sd-toast__header\">\n <strong class=\"sd-toast__title\">{{ data.title || ('core.notify.type.' + data.type | translate) }}</strong>\n <button class=\"sd-toast__close\" (click)=\"close()\">\u2715</button>\n </div>\n\n <div class=\"sd-toast__body\">\n @if (!isMultiMessage) {\n <!-- why: m\u1EB7c \u0111\u1ECBnh render TEXT (auto-escape) \u2014 an to\u00E0n. Ch\u1EC9 render HTML\n (\u0111\u00E3 sanitize) khi data.html=true. -->\n @if (data.html) {\n <div [innerHTML]=\"sanitizeHtml(singleMessage)\"></div>\n } @else {\n <div>{{ singleMessage }}</div>\n }\n }\n @else {\n <ul class=\"msg-list\">\n @for (msg of displayMessages; track msg) {\n @if (data.html) {\n <li [innerHTML]=\"sanitizeHtml('- ' + msg)\"></li>\n } @else {\n <li>{{ '- ' + msg }}</li>\n }\n }\n </ul>\n\n @if (hasMore) {\n <button type=\"button\" \n class=\"toggle-more btn-link\" \n [class]=\"'text-' + data.type\" \n (click)=\"toggleExpand()\">\n {{ isExpanded() ? ('core.notify.show-less' | translate) : ('core.notify.show-more' | translate: { count: restCount }) }}\n </button>\n }\n }\n </div>\n\n @if (data.actionLabel) {\n <div class=\"sd-toast__actions\">\n <button class=\"btn-action\" \n [class]=\"'bg-' + data.type + '-light text-' + data.type\"\n (click)=\"onActionClick()\">\n {{ data.actionLabel }}\n </button>\n </div>\n }\n</div>", styles: ["@charset \"UTF-8\";:host{display:flex;width:350px;border-radius:8px;box-shadow:0 4px 12px #00000026;margin-bottom:12px;overflow:hidden;position:relative;font-family:Roboto,sans-serif;pointer-events:auto}.sd-toast__bar{width:6px;flex-shrink:0}.sd-toast__icon{padding:12px 0 0 12px;flex-shrink:0}.sd-toast__icon svg{width:24px;height:24px}.sd-toast__content{flex-grow:1;padding:12px;display:flex;flex-direction:column}.sd-toast__header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:4px}.sd-toast__title{font-size:16px;font-weight:600}.sd-toast__close{background:none;border:none;font-size:16px;cursor:pointer;line-height:1;padding:0;opacity:.5;transition:opacity .2s}.sd-toast__close:hover{opacity:1}.sd-toast__body{font-size:14px;line-height:1.4;word-break:break-word}.sd-toast__actions{display:flex;justify-content:flex-end;margin-top:8px}.msg-list{padding-left:0;list-style:none;margin:0}.toggle-more{background:none;border:none;padding:0;font:inherit;cursor:pointer;font-size:13px;margin-top:4px;font-weight:500;text-align:left}.toggle-more:hover{text-decoration:underline}.toggle-more:focus-visible{outline:2px solid currentColor;outline-offset:2px}.btn-action{border:none;padding:6px 12px;border-radius:4px;font-weight:600;cursor:pointer;font-size:13px;transition:filter .2s}.btn-action:hover{filter:brightness(.95)}\n"] }]
121
+ '[attr.data-message]': 'dataMessage',
122
+ }, template: "<div class=\"sd-toast__bar\" [class]=\"'bg-' + data.type\"></div>\n\n<div class=\"sd-toast__icon\" [class]=\"'text-' + data.type\">\n @switch (data.type) {\n @case ('success') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\"/></svg>\n }\n @case ('info') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z\"/></svg>\n }\n @case ('warning') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z\"/></svg>\n }\n @case ('error') {\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/></svg>\n }\n }\n</div>\n\n<div class=\"sd-toast__content\">\n <div class=\"sd-toast__header\">\n <strong class=\"sd-toast__title\">{{ data.title || ('core.notify.type.' + data.type | translate) }}</strong>\n <button class=\"sd-toast__close\" (click)=\"close()\">&times;</button>\n </div>\n\n <div class=\"sd-toast__body\">\n @if (!isMultiMessage) {\n <!-- Text rendering is the default safe path; HTML is opt-in and sanitized. -->\n @if (data.html) {\n <div [innerHTML]=\"sanitizeHtml(singleMessage)\"></div>\n } @else {\n <div>{{ singleMessage }}</div>\n }\n } @else {\n <ul class=\"msg-list\">\n @for (msg of displayMessages; track msg) {\n @if (data.html) {\n <li [innerHTML]=\"sanitizeHtml('- ' + msg)\"></li>\n } @else {\n <li>{{ '- ' + msg }}</li>\n }\n }\n </ul>\n\n @if (hasMore) {\n <button\n type=\"button\"\n class=\"toggle-more btn-link\"\n [class]=\"'text-' + data.type\"\n (click)=\"toggleExpand()\">\n {{ isExpanded() ? ('core.notify.show-less' | translate) : ('core.notify.show-more' | translate: { count: restCount }) }}\n </button>\n }\n }\n </div>\n\n @if (data.actionLabel) {\n <div class=\"sd-toast__actions\">\n <button\n class=\"btn-action\"\n [class]=\"'bg-' + data.type + '-light text-' + data.type\"\n (click)=\"onActionClick()\">\n {{ data.actionLabel }}\n </button>\n </div>\n }\n</div>\n", styles: [":host{display:flex;width:350px;border-radius:8px;box-shadow:0 4px 12px #00000026;margin-bottom:12px;overflow:hidden;position:relative;font-family:Roboto,sans-serif;pointer-events:auto;animation:sd-toast-enter .3s ease-out}:host(.sd-toast--closing){pointer-events:none;animation:sd-toast-leave .2s ease-in forwards}@keyframes sd-toast-enter{0%{transform:translate(100%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes sd-toast-leave{0%{transform:translate(0);opacity:1}to{transform:translate(100%);opacity:0}}@media(prefers-reduced-motion:reduce){:host,:host(.sd-toast--closing){animation:none}}.sd-toast__bar{width:6px;flex-shrink:0}.sd-toast__icon{padding:12px 0 0 12px;flex-shrink:0}.sd-toast__icon svg{width:24px;height:24px}.sd-toast__content{flex-grow:1;padding:12px;display:flex;flex-direction:column}.sd-toast__header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:4px}.sd-toast__title{font-size:16px;font-weight:600}.sd-toast__close{background:none;border:none;font-size:16px;cursor:pointer;line-height:1;padding:0;opacity:.5;transition:opacity .2s}.sd-toast__close:hover{opacity:1}.sd-toast__body{font-size:14px;line-height:1.4;word-break:break-word}.sd-toast__actions{display:flex;justify-content:flex-end;margin-top:8px}.msg-list{padding-left:0;list-style:none;margin:0}.toggle-more{background:none;border:none;padding:0;font:inherit;cursor:pointer;font-size:13px;margin-top:4px;font-weight:500;text-align:left}.toggle-more:hover{text-decoration:underline}.toggle-more:focus-visible{outline:2px solid currentColor;outline-offset:2px}.btn-action{border:none;padding:6px 12px;border-radius:4px;font-weight:600;cursor:pointer;font-size:13px;transition:filter .2s}.btn-action:hover{filter:brightness(.95)}\n"] }]
134
123
  }], ctorParameters: () => [{ type: SdNotifyService }, { type: i2.DomSanitizer }], propDecorators: { data: [{
135
124
  type: Input,
136
125
  args: [{ required: true }]
@@ -165,9 +154,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
165
154
  }] });
166
155
 
167
156
  class SdNotifyService {
168
- appRef;
169
- injector;
170
- document;
171
157
  toasts = signal([]);
172
158
  // Constants
173
159
  #DEBOUNCE_TIME = 500;
@@ -177,10 +163,11 @@ class SdNotifyService {
177
163
  // State
178
164
  #buffer = {};
179
165
  #timers = {};
180
- constructor(appRef, injector, document) {
181
- this.appRef = appRef;
182
- this.injector = injector;
183
- this.document = document;
166
+ appRef = inject(ApplicationRef);
167
+ injector = inject(EnvironmentInjector);
168
+ document = inject(DOCUMENT);
169
+ #i18n = inject(I18nService);
170
+ constructor() {
184
171
  this.#initContainer();
185
172
  }
186
173
  #initContainer() {
@@ -206,14 +193,14 @@ class SdNotifyService {
206
193
  this.#addToBuffer('error', message, option);
207
194
  }
208
195
  remove(id) {
209
- this.toasts.update((current) => current.filter((t) => t.id !== id));
196
+ this.toasts.update(current => current.filter(t => t.id !== id));
210
197
  }
211
198
  clearAll() {
212
199
  this.toasts.set([]);
213
200
  this.#clearAllTimers();
214
201
  }
215
202
  clearByType(type) {
216
- this.toasts.update((current) => current.filter((t) => t.type !== type));
203
+ this.toasts.update(current => current.filter(t => t.type !== type));
217
204
  }
218
205
  // Private helpers
219
206
  #addImmediate(type, message, option) {
@@ -225,9 +212,9 @@ class SdNotifyService {
225
212
  duration: option?.duration ?? this.#DEFAULT_SUCCESS_DURATION,
226
213
  actionLabel: option?.actionLabel,
227
214
  onAction: option?.onAction,
228
- html: option?.html
215
+ html: option?.html,
229
216
  };
230
- this.toasts.update((current) => {
217
+ this.toasts.update(current => {
231
218
  const updated = [newToast, ...current];
232
219
  return updated.slice(0, this.#MAX_TOASTS);
233
220
  });
@@ -253,8 +240,7 @@ class SdNotifyService {
253
240
  this.#timers[type] = null;
254
241
  if (messages.length === 0)
255
242
  return;
256
- const typeLabel = type === 'error' ? 'Error' : 'Warning';
257
- const title = option?.title ?? typeLabel;
243
+ const title = option?.title ?? this.#i18n.t(`core.notify.type.${type}`);
258
244
  const finalTitle = messages.length > 1 ? `${title} (${messages.length})` : title;
259
245
  const newToast = {
260
246
  id: Utilities.generateUuid(),
@@ -264,9 +250,9 @@ class SdNotifyService {
264
250
  duration: option?.duration ?? this.#DEFAULT_BUFFERED_DURATION,
265
251
  actionLabel: option?.actionLabel,
266
252
  onAction: option?.onAction,
267
- html: option?.html
253
+ html: option?.html,
268
254
  };
269
- this.toasts.update((current) => {
255
+ this.toasts.update(current => {
270
256
  const updated = [newToast, ...current];
271
257
  return updated.slice(0, this.#MAX_TOASTS);
272
258
  });
@@ -278,7 +264,7 @@ class SdNotifyService {
278
264
  });
279
265
  this.#timers = {};
280
266
  }
281
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdNotifyService, deps: [{ token: i0.ApplicationRef }, { token: i0.EnvironmentInjector }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable });
267
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdNotifyService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
282
268
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdNotifyService, providedIn: 'root' });
283
269
  }
284
270
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdNotifyService, decorators: [{
@@ -286,10 +272,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
286
272
  args: [{
287
273
  providedIn: 'root',
288
274
  }]
289
- }], ctorParameters: () => [{ type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }, { type: Document, decorators: [{
290
- type: Inject,
291
- args: [DOCUMENT]
292
- }] }] });
275
+ }], ctorParameters: () => [] });
293
276
 
294
277
  /**
295
278
  * Generated bundle index. Do not edit.