@sd-angular/core 19.0.0-beta.6 → 19.0.0-beta.60

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 (219) hide show
  1. package/README.md +686 -33
  2. package/assets/scss/ckeditor5.scss +60 -2
  3. package/assets/scss/core/bootstrap.scss +17 -0
  4. package/assets/scss/core/form.scss +4 -1
  5. package/assets/scss/core/grid.scss +40 -0
  6. package/assets/scss/sd-core.scss +1 -0
  7. package/components/avatar/index.d.ts +1 -0
  8. package/components/avatar/src/avatar.component.d.ts +19 -0
  9. package/components/badge/src/badge.component.d.ts +77 -19
  10. package/components/button/src/button.component.d.ts +30 -28
  11. package/components/code-editor/index.d.ts +1 -0
  12. package/components/code-editor/src/code-editor.component.d.ts +25 -0
  13. package/components/document-builder/index.d.ts +1 -0
  14. package/components/document-builder/src/document-builder.component.d.ts +12 -41
  15. package/components/document-builder/src/document-builder.model.d.ts +14 -11
  16. package/components/document-builder/src/plugins/block-space/block-space.plugin.d.ts +9 -0
  17. package/components/document-builder/src/plugins/ck-comment/ck-comment.plugin.d.ts +44 -0
  18. package/components/document-builder/src/plugins/ck-comment/ck-comment.plugin.model.d.ts +57 -0
  19. package/components/document-builder/src/plugins/heading/heading.plugin.d.ts +1 -0
  20. package/components/document-builder/src/plugins/highlight-range/highlight-range.plugin.d.ts +4 -0
  21. package/components/document-builder/src/plugins/image-custom/image-custom.plugin.d.ts +31 -0
  22. package/components/document-builder/src/plugins/index.d.ts +7 -2
  23. package/components/document-builder/src/plugins/page-orientation/page-orientation.plugin.d.ts +2 -2
  24. package/components/document-builder/src/plugins/paste-handler/filters/bookmark.d.ts +14 -0
  25. package/components/document-builder/src/plugins/paste-handler/filters/br.d.ts +15 -0
  26. package/components/document-builder/src/plugins/paste-handler/filters/image.d.ts +25 -0
  27. package/components/document-builder/src/plugins/paste-handler/filters/list.d.ts +29 -0
  28. package/components/document-builder/src/plugins/paste-handler/filters/parse.d.ts +35 -0
  29. package/components/document-builder/src/plugins/paste-handler/filters/removeboldwrapper.d.ts +15 -0
  30. package/components/document-builder/src/plugins/paste-handler/filters/removegooglesheetstag.d.ts +15 -0
  31. package/components/document-builder/src/plugins/paste-handler/filters/removeinvalidtablewidth.d.ts +15 -0
  32. package/components/document-builder/src/plugins/paste-handler/filters/removemsattributes.d.ts +15 -0
  33. package/components/document-builder/src/plugins/paste-handler/filters/removestyleblock.d.ts +15 -0
  34. package/components/document-builder/src/plugins/paste-handler/filters/removexmlns.d.ts +15 -0
  35. package/components/document-builder/src/plugins/paste-handler/filters/replacemsfootnotes.d.ts +54 -0
  36. package/components/document-builder/src/plugins/paste-handler/filters/replacetabswithinprewithspaces.d.ts +24 -0
  37. package/components/document-builder/src/plugins/paste-handler/filters/space.d.ts +27 -0
  38. package/components/document-builder/src/plugins/paste-handler/filters/table.d.ts +16 -0
  39. package/components/document-builder/src/plugins/paste-handler/filters/utils.d.ts +25 -0
  40. package/components/document-builder/src/plugins/paste-handler/index.d.ts +35 -0
  41. package/components/document-builder/src/plugins/paste-handler/normalizers/googledocsnormalizer.d.ts +31 -0
  42. package/components/document-builder/src/plugins/paste-handler/normalizers/googlesheetsnormalizer.d.ts +31 -0
  43. package/components/document-builder/src/plugins/paste-handler/normalizers/mswordnormalizer.d.ts +29 -0
  44. package/components/document-builder/src/plugins/paste-handler/types.d.ts +30 -0
  45. package/components/document-builder/src/plugins/table-custom/index.d.ts +34 -0
  46. package/components/document-builder/src/plugins/variable/variable.plugin.d.ts +39 -0
  47. package/components/index.d.ts +4 -0
  48. package/components/mini-editor/index.d.ts +2 -0
  49. package/components/mini-editor/src/mini-editor.component.d.ts +90 -0
  50. package/components/mini-editor/src/mini-editor.model.d.ts +44 -0
  51. package/components/section/src/section.component.d.ts +10 -11
  52. package/components/side-drawer/src/side-drawer.component.d.ts +11 -24
  53. package/components/tab-router/src/components/tab-router-item/tab-router-item.component.d.ts +4 -1
  54. package/components/tab-router/src/components/tab-router-outlet/tab-router-outlet.component.d.ts +3 -15
  55. package/components/table/src/components/column-filter/column-filter.component.d.ts +3 -3
  56. package/components/table/src/components/desktop-cell/desktop-cell.component.d.ts +12 -2
  57. package/components/table/src/components/desktop-cell-view/desktop-cell-view.component.d.ts +12 -2
  58. package/components/table/src/components/external-filter/external-filter.component.d.ts +1 -1
  59. package/components/table/src/components/selector-action/action-filter.pipe.d.ts +11 -10
  60. package/components/table/src/components/selector-action/selector-action.component.d.ts +5 -3
  61. package/components/table/src/directives/index.d.ts +2 -0
  62. package/components/table/src/directives/sd-table-column-filter-def.directive.d.ts +9 -0
  63. package/components/table/src/directives/sticky-shadow.directive.d.ts +17 -0
  64. package/components/table/src/models/table-column.model.d.ts +34 -34
  65. package/components/table/src/models/table-command.model.d.ts +7 -3
  66. package/components/table/src/models/table-item.model.d.ts +5 -4
  67. package/components/table/src/models/table-option-config.model.d.ts +5 -0
  68. package/components/table/src/models/table-option-export.model.d.ts +3 -2
  69. package/components/table/src/models/table-option-selector.model.d.ts +11 -10
  70. package/components/table/src/models/table-option.model.d.ts +10 -9
  71. package/components/table/src/services/index.d.ts +3 -0
  72. package/components/table/src/services/table-export/table-export.service.d.ts +26 -0
  73. package/components/table/src/services/table-filter/table-filter.model.d.ts +5 -4
  74. package/components/table/src/services/table-format/table-format.service.d.ts +16 -0
  75. package/components/table/src/table.component.d.ts +39 -53
  76. package/components/upload-file/src/configurations/upload-file.configuration.d.ts +1 -1
  77. package/components/upload-file/src/services/upload-file.service.d.ts +0 -1
  78. package/components/upload-file/src/upload-file.component.d.ts +49 -54
  79. package/components/view/index.d.ts +1 -0
  80. package/components/view/src/view.component.d.ts +16 -0
  81. package/components/workflow/src/models/form-generic-component.model.d.ts +5 -4
  82. package/components/workflow/src/models/index.d.ts +1 -0
  83. package/directives/index.d.ts +1 -0
  84. package/directives/src/sd-href.directive.d.ts +9 -0
  85. package/fesm2022/sd-angular-core-components-avatar.mjs +103 -0
  86. package/fesm2022/sd-angular-core-components-avatar.mjs.map +1 -0
  87. package/fesm2022/sd-angular-core-components-badge.mjs +101 -91
  88. package/fesm2022/sd-angular-core-components-badge.mjs.map +1 -1
  89. package/fesm2022/sd-angular-core-components-button.mjs +70 -96
  90. package/fesm2022/sd-angular-core-components-button.mjs.map +1 -1
  91. package/fesm2022/sd-angular-core-components-code-editor.mjs +129 -0
  92. package/fesm2022/sd-angular-core-components-code-editor.mjs.map +1 -0
  93. package/fesm2022/sd-angular-core-components-document-builder.mjs +3994 -608
  94. package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
  95. package/fesm2022/sd-angular-core-components-history.mjs +1 -1
  96. package/fesm2022/sd-angular-core-components-history.mjs.map +1 -1
  97. package/fesm2022/sd-angular-core-components-import-excel.mjs +1 -1
  98. package/fesm2022/sd-angular-core-components-import-excel.mjs.map +1 -1
  99. package/fesm2022/sd-angular-core-components-mini-editor.mjs +326 -0
  100. package/fesm2022/sd-angular-core-components-mini-editor.mjs.map +1 -0
  101. package/fesm2022/sd-angular-core-components-preview.mjs +1 -1
  102. package/fesm2022/sd-angular-core-components-preview.mjs.map +1 -1
  103. package/fesm2022/sd-angular-core-components-section.mjs +24 -42
  104. package/fesm2022/sd-angular-core-components-section.mjs.map +1 -1
  105. package/fesm2022/sd-angular-core-components-side-drawer.mjs +78 -84
  106. package/fesm2022/sd-angular-core-components-side-drawer.mjs.map +1 -1
  107. package/fesm2022/sd-angular-core-components-tab-router.mjs +152 -226
  108. package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
  109. package/fesm2022/sd-angular-core-components-table.mjs +1129 -1131
  110. package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
  111. package/fesm2022/sd-angular-core-components-upload-file.mjs +339 -444
  112. package/fesm2022/sd-angular-core-components-upload-file.mjs.map +1 -1
  113. package/fesm2022/sd-angular-core-components-view.mjs +45 -0
  114. package/fesm2022/sd-angular-core-components-view.mjs.map +1 -0
  115. package/fesm2022/sd-angular-core-components-workflow.mjs +47 -57
  116. package/fesm2022/sd-angular-core-components-workflow.mjs.map +1 -1
  117. package/fesm2022/sd-angular-core-components.mjs +4 -0
  118. package/fesm2022/sd-angular-core-components.mjs.map +1 -1
  119. package/fesm2022/sd-angular-core-directives.mjs +80 -27
  120. package/fesm2022/sd-angular-core-directives.mjs.map +1 -1
  121. package/fesm2022/sd-angular-core-forms-autocomplete.mjs +274 -364
  122. package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
  123. package/fesm2022/sd-angular-core-forms-chip-calendar.mjs +5 -2
  124. package/fesm2022/sd-angular-core-forms-chip-calendar.mjs.map +1 -1
  125. package/fesm2022/sd-angular-core-forms-chip.mjs +5 -2
  126. package/fesm2022/sd-angular-core-forms-chip.mjs.map +1 -1
  127. package/fesm2022/sd-angular-core-forms-date-range.mjs +160 -245
  128. package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
  129. package/fesm2022/sd-angular-core-forms-date.mjs +153 -273
  130. package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
  131. package/fesm2022/sd-angular-core-forms-datetime.mjs +152 -288
  132. package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
  133. package/fesm2022/sd-angular-core-forms-input-number.mjs +191 -338
  134. package/fesm2022/sd-angular-core-forms-input-number.mjs.map +1 -1
  135. package/fesm2022/sd-angular-core-forms-input.mjs +149 -287
  136. package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
  137. package/fesm2022/sd-angular-core-forms-radio.mjs +3 -2
  138. package/fesm2022/sd-angular-core-forms-radio.mjs.map +1 -1
  139. package/fesm2022/sd-angular-core-forms-select.mjs +375 -448
  140. package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
  141. package/fesm2022/sd-angular-core-forms-textarea.mjs +138 -227
  142. package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
  143. package/fesm2022/sd-angular-core-modules-keycloak.mjs +126 -0
  144. package/fesm2022/sd-angular-core-modules-keycloak.mjs.map +1 -0
  145. package/fesm2022/sd-angular-core-modules-layout.mjs +454 -453
  146. package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
  147. package/fesm2022/sd-angular-core-modules.mjs +1 -1
  148. package/fesm2022/sd-angular-core-services-api.mjs +5 -10
  149. package/fesm2022/sd-angular-core-services-api.mjs.map +1 -1
  150. package/fesm2022/sd-angular-core-services-confirm.mjs +2 -2
  151. package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
  152. package/fesm2022/sd-angular-core-services-docx.mjs +173 -0
  153. package/fesm2022/sd-angular-core-services-docx.mjs.map +1 -0
  154. package/fesm2022/sd-angular-core-services-notify.mjs +2 -2
  155. package/fesm2022/sd-angular-core-services-notify.mjs.map +1 -1
  156. package/fesm2022/sd-angular-core-services.mjs +1 -0
  157. package/fesm2022/sd-angular-core-services.mjs.map +1 -1
  158. package/fesm2022/sd-angular-core-utilities-extensions.mjs +21 -45
  159. package/fesm2022/sd-angular-core-utilities-extensions.mjs.map +1 -1
  160. package/fesm2022/sd-angular-core-utilities-models.mjs +15 -1
  161. package/fesm2022/sd-angular-core-utilities-models.mjs.map +1 -1
  162. package/forms/autocomplete/src/autocomplete.component.d.ts +50 -55
  163. package/forms/chip/src/chip.component.d.ts +3 -2
  164. package/forms/chip-calendar/src/chip-calendar.component.d.ts +3 -2
  165. package/forms/date/src/date.component.d.ts +43 -46
  166. package/forms/date-range/src/date-range.component.d.ts +30 -34
  167. package/forms/datetime/src/datetime.component.d.ts +43 -49
  168. package/forms/input/src/input.component.d.ts +48 -57
  169. package/forms/input-number/src/input-number.component.d.ts +48 -54
  170. package/forms/select/src/select.component.d.ts +62 -64
  171. package/forms/textarea/src/textarea.component.d.ts +36 -42
  172. package/modules/index.d.ts +1 -1
  173. package/modules/keycloak/index.d.ts +4 -0
  174. package/modules/keycloak/keycloak.configuration.d.ts +11 -0
  175. package/modules/keycloak/keycloak.interceptor.d.ts +2 -0
  176. package/modules/keycloak/keycloak.module.d.ts +18 -0
  177. package/modules/keycloak/keycloak.service.d.ts +14 -0
  178. package/modules/layout/components/layout-main/layout-main.component.d.ts +7 -12
  179. package/modules/layout/components/page/page.component.d.ts +5 -7
  180. package/modules/layout/components/sidebar-v1/components/sidebar/sidebar.component.d.ts +22 -29
  181. package/modules/layout/components/sidebar-v1/components/user/user.component.d.ts +11 -17
  182. package/modules/layout/components/sidebar-v1/main.component.d.ts +14 -14
  183. package/modules/layout/configurations/layout.configuration.d.ts +46 -3
  184. package/modules/layout/modules/forbidden/pages/root/root.component.d.ts +3 -8
  185. package/modules/layout/modules/home/components/home-page/home-page.component.d.ts +2 -5
  186. package/modules/layout/modules/not-found/pages/root/root.component.d.ts +3 -8
  187. package/modules/layout/pipes/high-light-search.pipe.d.ts +1 -1
  188. package/modules/layout/services/index.d.ts +1 -0
  189. package/modules/layout/services/layout.service.d.ts +10 -0
  190. package/modules/layout/services/menu/menu.model.d.ts +2 -0
  191. package/modules/layout/services/storage/storage.service.d.ts +0 -3
  192. package/package.json +93 -70
  193. package/sd-angular-core-19.0.0-beta.60.tgz +0 -0
  194. package/services/api/src/api.model.d.ts +6 -1
  195. package/services/confirm/src/lib/confirm.service.d.ts +1 -0
  196. package/services/docx/index.d.ts +1 -0
  197. package/services/docx/src/lib/docx.model.d.ts +9 -0
  198. package/services/docx/src/lib/docx.service.d.ts +13 -0
  199. package/services/docx/src/public-api.d.ts +2 -0
  200. package/services/index.d.ts +1 -0
  201. package/services/notify/index.d.ts +1 -0
  202. package/services/notify/src/notify.model.d.ts +1 -1
  203. package/services/notify/src/notify.service.d.ts +5 -5
  204. package/utilities/extensions/src/string.extension.d.ts +2 -0
  205. package/utilities/extensions/src/utility.extension.d.ts +1 -0
  206. package/utilities/models/index.d.ts +3 -0
  207. package/utilities/models/src/filter.model.d.ts +14 -2
  208. package/utilities/models/src/icon.model.d.ts +2 -0
  209. package/utilities/models/src/nested-key-of.model.d.ts +5 -0
  210. package/utilities/models/src/pattern.model.d.ts +1 -1
  211. package/utilities/models/src/unwrap-signal.model.d.ts +6 -0
  212. package/components/document-builder/src/plugins/comment/comment.plugin.d.ts +0 -4
  213. package/components/document-builder/src/plugins/table-fit/table-fit.plugin.d.ts +0 -4
  214. package/fesm2022/sd-angular-core-modules-oidc.mjs +0 -127
  215. package/fesm2022/sd-angular-core-modules-oidc.mjs.map +0 -1
  216. package/modules/oidc/dynamic-sts.loader.d.ts +0 -11
  217. package/modules/oidc/index.d.ts +0 -2
  218. package/modules/oidc/oidc.configuration.d.ts +0 -11
  219. package/modules/oidc/oidc.module.d.ts +0 -14
@@ -1 +1 @@
1
- {"version":3,"file":"sd-angular-core-services-api.mjs","sources":["../../../projects/sd-angular/services/api/src/api.model.ts","../../../projects/sd-angular/services/api/src/api.service.ts","../../../projects/sd-angular/services/api/src/interceptors/api.interceptor.ts","../../../projects/sd-angular/services/api/src/api.module.ts","../../../projects/sd-angular/services/api/sd-angular-core-services-api.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { HttpClient, HttpErrorResponse, HttpRequest, HttpResponse } from '@angular/common/http';\r\nimport { InjectionToken } from '@angular/core';\r\nimport { SdCacheOption } from '@sd-angular/core/services/cache';\r\nimport { SdUtilities } from '@sd-angular/core/utilities';\r\n// import hash from 'object-hash';\r\n\r\nexport interface SdApiOption {\r\n cacheOption?: SdCacheOption;\r\n timeout?: number; // Default: 30000 (30s)\r\n autoCache?: boolean; // Default: true\r\n}\r\ntype HttpGetOption = Parameters<HttpClient['get']>[1];\r\nexport type SdGetOption = HttpGetOption & SdApiOption;\r\n\r\ntype HttpPostOption = Parameters<HttpClient['post']>[2];\r\nexport type SdPostOption = HttpPostOption & SdApiOption;\r\n\r\ntype HttpPutOption = Parameters<HttpClient['put']>[2];\r\nexport type SdPutOption = HttpPutOption & SdApiOption;\r\n\r\ntype HttpDeleteOption = Parameters<HttpClient['delete']>[1];\r\nexport type SdDeleteOption = HttpDeleteOption & SdApiOption;\r\n\r\nexport interface SdApiHandler {\r\n hosts: string[];\r\n // Can thiệp header, token ... theo từng host sử dụng interceptor\r\n intercept?: (request: HttpRequest<any>) => HttpRequest<any>;\r\n beforeRemote?: (request: HttpRequest<any>) => void | Promise<void>;\r\n afterRemote?: (response: HttpResponse<any> | HttpErrorResponse | Error) => void | Promise<void>;\r\n mapResponse?: <Tres = any, Tdata = any>(response: Tres) => Tdata;\r\n timeout?: number; // Default 30s\r\n}\r\n\r\nexport interface ISdApiConfiguration {\r\n handlers: SdApiHandler[];\r\n}\r\n\r\nexport const SD_API_CONFIG = new InjectionToken<ISdApiConfiguration>('sd-api.configuration');\r\n\r\nexport const TOKEN = SdUtilities.hash({\r\n origin: location.origin,\r\n key: 'ed4a2ffc-af43-41fb-9ac9-970f43d99571',\r\n});\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Inject, Injectable, Optional } from '@angular/core';\r\nimport { SdCacheService } from '@sd-angular/core/services/cache';\r\nimport { SdUtilities } from '@sd-angular/core/utilities/extensions';\r\nimport { lastValueFrom, Observable } from 'rxjs';\r\nimport { catchError, map, shareReplay, timeout } from 'rxjs/operators';\r\nimport { v4 } from 'uuid';\r\nimport { ISdApiConfiguration, SD_API_CONFIG, SdApiHandler, SdDeleteOption, SdGetOption, SdPostOption, SdPutOption } from './api.model';\r\n\r\n// Gom nhóm các Option lại cho gọn\r\ntype SdHttpOptions = SdGetOption & SdPostOption & SdPutOption & SdDeleteOption;\r\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SdApiService {\r\n readonly #defaultTimeout = 60000; // 60s\r\n readonly #dedupCacheDuration = 1000; // 1s (Deduplication cache duration)\r\n\r\n // Thay đổi cấu trúc Cache: Lưu Observable thay vì Subject phức tạp\r\n // Key: hash string -> Value: { stream$: Observable, expiry: number }\r\n #inFlightRequests: Map<string, { stream$: Observable<any>; expiry: number }> = new Map();\r\n\r\n constructor(\r\n private httpClient: HttpClient,\r\n @Inject(SD_API_CONFIG) @Optional() private configurations: ISdApiConfiguration[],\r\n private cacheService: SdCacheService\r\n ) {\r\n // Optional: Cơ chế dọn dẹp cache định kỳ (mỗi 1 phút dọn dẹp các key hết hạn)\r\n setInterval(() => this.#cleanupCache(), 60000);\r\n }\r\n\r\n get http() {\r\n return this.httpClient;\r\n }\r\n\r\n // --- PUBLIC METHODS ---\r\n\r\n get = <T = any>(url: string, option?: SdGetOption): Promise<T> => {\r\n return this.#executeWithLayeredCache<T>(url, 'GET', undefined, option);\r\n };\r\n\r\n post = <T = any>(url: string, body?: any, option?: SdPostOption): Promise<T> => {\r\n return this.#executeWithLayeredCache<T>(url, 'POST', body, option);\r\n };\r\n\r\n put = <T = any>(url: string, body?: any, option?: SdPutOption): Promise<T> => {\r\n return this.#executeWithLayeredCache<T>(url, 'PUT', body, option);\r\n };\r\n\r\n delete = <T = any>(url: string, option?: SdDeleteOption): Promise<T> => {\r\n return this.#executeWithLayeredCache<T>(url, 'DELETE', undefined, option);\r\n };\r\n\r\n // Upload file logic giữ nguyên nhưng refactor nhẹ\r\n upload = async (url: string, option?: { extensions?: string[]; maxSizeInMb?: number }): Promise<any> => {\r\n const file = await SdUtilities.upload(option);\r\n if (!Array.isArray(file) && file) {\r\n return this.uploadFile(url, file);\r\n }\r\n };\r\n\r\n uploadFile = async (url: string, file: File): Promise<any> => {\r\n if (!file) return null;\r\n if (file.name.lastIndexOf('.') === -1) throw new Error('Invalid file extension');\r\n\r\n const formData = new FormData();\r\n formData.append('file', file, file.name);\r\n // Upload thường không cần deduplication cache, set autoCache: false\r\n return await this.post(url, formData, { autoCache: false });\r\n };\r\n\r\n // --- PRIVATE CORE LOGIC ---\r\n\r\n /**\r\n * Hàm trung gian xử lý Layer Cache (SdCacheService) trước khi gọi API thực tế\r\n */\r\n #executeWithLayeredCache = async <T>(url: string, method: HttpMethod, body?: any, option?: SdHttpOptions): Promise<T> => {\r\n // Layer 1: Persistent Cache (SdCacheService)\r\n if (option?.cacheOption) {\r\n const key = this.#generateKey(url, method, body, option);\r\n const { get, set, has } = this.cacheService.create(key, option.cacheOption);\r\n\r\n if (has()) {\r\n return get();\r\n }\r\n\r\n const result = await this.#request<T>(url, method, body, option);\r\n set(result);\r\n return result;\r\n }\r\n\r\n // Không có cache dài hạn thì gọi trực tiếp logic deduplication\r\n return this.#request<T>(url, method, body, option);\r\n };\r\n\r\n /**\r\n * Core Request: Xử lý Deduplication, Timeout, Mapping Response\r\n */\r\n #request = <T>(url: string, method: HttpMethod, body: any, option?: SdHttpOptions): Promise<T> => {\r\n const key = this.#generateKey(url, method, body, option);\r\n\r\n // Layer 2: Deduplication Cache (In-Flight Request / Short-term cache)\r\n const now = Date.now();\r\n const cachedItem = this.#inFlightRequests.get(key);\r\n\r\n // Nếu đã có request đang chạy hoặc mới chạy xong trong vòng 1s -> Trả về stream đó luôn\r\n if (cachedItem && cachedItem.expiry > now) {\r\n return lastValueFrom(cachedItem.stream$);\r\n }\r\n\r\n // Setup request mới\r\n const handler = this.#getHandler(url);\r\n const apiTimeout = option?.timeout ?? handler?.timeout ?? this.#defaultTimeout;\r\n\r\n // Tạo Observable call API\r\n const request$ = this.httpClient\r\n .request(method, url, {\r\n body,\r\n headers: option?.headers,\r\n params: option?.params,\r\n observe: 'response', // Lấy full response để check status\r\n responseType: option?.responseType,\r\n })\r\n .pipe(\r\n timeout(apiTimeout),\r\n map(res => {\r\n // Normalize Response Logic\r\n const bodyRes = res.body as any;\r\n // Logic check response cũ của bạn\r\n if (bodyRes && typeof bodyRes === 'object' && 'ok' in bodyRes && !bodyRes.ok) {\r\n throw bodyRes; // Giả sử structure trả về { ok: false, ... } là lỗi\r\n }\r\n\r\n if (handler?.mapResponse) {\r\n return handler.mapResponse(bodyRes);\r\n }\r\n\r\n return bodyRes;\r\n }),\r\n catchError(err => {\r\n // Xóa cache ngay lập tức nếu lỗi để user có thể retry\r\n this.#inFlightRequests.delete(key);\r\n throw err;\r\n }),\r\n // QUAN TRỌNG: shareReplay(1) giúp share kết quả cho các subscriber đến sau (trong 1s)\r\n shareReplay(1)\r\n );\r\n\r\n // Lưu vào Map\r\n this.#inFlightRequests.set(key, {\r\n stream$: request$,\r\n expiry: now + this.#dedupCacheDuration,\r\n });\r\n\r\n // Chuyển đổi sang Promise cho đúng return type của bạn\r\n return lastValueFrom(request$);\r\n };\r\n\r\n // --- HELPERS ---\r\n\r\n #getHandler = (url: string): SdApiHandler | undefined => {\r\n const handlers = this.configurations?.flatMap(b => b?.handlers || []) || [];\r\n return handlers.find(e => e.hosts.some(host => url.startsWith(host)));\r\n };\r\n\r\n #generateKey = (url: string, method: HttpMethod, body: any, option?: SdHttpOptions): string => {\r\n // FormData không hash được nội dung file, luôn generate key mới\r\n if (body instanceof FormData || option?.autoCache === false) {\r\n return v4();\r\n }\r\n return SdUtilities.hash({\r\n url,\r\n method,\r\n params: option?.params,\r\n headers: option?.headers,\r\n body,\r\n });\r\n };\r\n\r\n // Dọn dẹp memory leak\r\n #cleanupCache() {\r\n const now = Date.now();\r\n this.#inFlightRequests.forEach((value, key) => {\r\n if (value.expiry < now) {\r\n this.#inFlightRequests.delete(key);\r\n }\r\n });\r\n }\r\n}\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';\r\nimport { Inject, Injectable, Optional } from '@angular/core';\r\nimport { from, Observable, throwError } from 'rxjs';\r\nimport { catchError, map, switchMap } from 'rxjs/operators';\r\nimport { SD_API_CONFIG, ISdApiConfiguration, SdApiHandler } from '../api.model';\r\n\r\n@Injectable()\r\nexport class SdHttpInterceptor implements HttpInterceptor {\r\n constructor(\r\n @Inject(SD_API_CONFIG)\r\n @Optional()\r\n private configurations: ISdApiConfiguration[]\r\n ) {}\r\n intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\r\n const url = request.url;\r\n if (!url) {\r\n throw new Error(`Invalid URL`);\r\n }\r\n const handlers = this.configurations?.reduce<SdApiHandler[]>((a, b) => [...a, ...(b?.handlers || [])], []) || [];\r\n const handler = handlers?.find(e => e.hosts.some(host => url.startsWith(host)));\r\n const intercept = handler?.intercept;\r\n if (intercept) {\r\n request = request.clone(intercept(request));\r\n }\r\n if (request.body instanceof FormData) {\r\n request = request.clone({\r\n headers: request.headers.delete('Content-Type'),\r\n });\r\n }\r\n const beforeRemoteHandler = handler?.beforeRemote;\r\n const afterRemoteHandler = handler?.afterRemote;\r\n const beforeRemote = beforeRemoteHandler?.(request);\r\n if (beforeRemote instanceof Promise) {\r\n return from(beforeRemote).pipe(\r\n switchMap(() => next.handle(request)),\r\n map((event: HttpEvent<any>) => {\r\n if (event instanceof HttpResponse) {\r\n afterRemoteHandler?.(event);\r\n }\r\n return event;\r\n }),\r\n catchError((error: HttpErrorResponse) => {\r\n afterRemoteHandler?.(error);\r\n return throwError(() => error);\r\n })\r\n );\r\n }\r\n return next.handle(request).pipe(\r\n map((event: HttpEvent<any>) => {\r\n if (event instanceof HttpResponse) {\r\n afterRemoteHandler?.(event);\r\n }\r\n return event;\r\n }),\r\n catchError((error: HttpErrorResponse) => {\r\n afterRemoteHandler?.(error);\r\n return throwError(() => error);\r\n })\r\n );\r\n }\r\n}\r\n","import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';\nimport { NgModule } from '@angular/core';\nimport { SdHttpInterceptor } from './interceptors/api.interceptor';\n\n@NgModule({\n imports: [],\n exports: [],\n providers: [provideHttpClient(withInterceptorsFromDi()), { provide: HTTP_INTERCEPTORS, useClass: SdHttpInterceptor, multi: true }],\n})\nexport class SdApiModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["SdUtilities"],"mappings":"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"}
1
+ {"version":3,"file":"sd-angular-core-services-api.mjs","sources":["../../../projects/sd-angular/services/api/src/api.model.ts","../../../projects/sd-angular/services/api/src/api.service.ts","../../../projects/sd-angular/services/api/src/interceptors/api.interceptor.ts","../../../projects/sd-angular/services/api/src/api.module.ts","../../../projects/sd-angular/services/api/sd-angular-core-services-api.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { HttpClient, HttpErrorResponse, HttpRequest, HttpResponse } from '@angular/common/http';\r\nimport { InjectionToken } from '@angular/core';\r\nimport { SdCacheOption } from '@sd-angular/core/services/cache';\r\nimport { SdUtilities } from '@sd-angular/core/utilities';\r\n// import hash from 'object-hash';\r\n\r\nexport interface SdApiOption {\r\n cacheOption?: SdCacheOption;\r\n timeout?: number; // Default: 30000 (30s)\r\n autoCache?: boolean; // Default: true\r\n}\r\ntype HttpGetOption = Parameters<HttpClient['get']>[1];\r\nexport type SdGetOption = HttpGetOption & SdApiOption;\r\n\r\ntype HttpPostOption = Parameters<HttpClient['post']>[2];\r\nexport type SdPostOption = HttpPostOption & SdApiOption;\r\n\r\ntype HttpPutOption = Parameters<HttpClient['put']>[2];\r\nexport type SdPutOption = HttpPutOption & SdApiOption;\r\n\r\ntype HttpDeleteOption = Parameters<HttpClient['delete']>[1];\r\nexport type SdDeleteOption = HttpDeleteOption & SdApiOption;\r\n\r\nexport interface SdApiHandler {\r\n /** Danh sách host URL mà handler này sẽ xử lý */\r\n hosts: string[];\r\n /** Can thiệp request: gắn header, token, transform body... */\r\n intercept?: (request: HttpRequest<any>) => HttpRequest<any>;\r\n /** Hook chạy TRƯỚC khi gửi request (dùng để log, tracking...) */\r\n beforeRemote?: (request: HttpRequest<any>) => void | Promise<void>;\r\n /** Hook chạy SAU khi nhận response (xử lý lỗi, notify...) */\r\n afterRemote?: (\r\n response: HttpResponse<any> | HttpErrorResponse | Error\r\n ) => void | Promise<void>;\r\n /** Transform response body thành kiểu dữ liệu mong muốn */\r\n mapResponse?: <Tres = any, Tdata = any>(response: Tres) => Tdata;\r\n /** Timeout tính bằng milliseconds. Mặc định: 30000 (30 giây) */\r\n timeout?: number;\r\n}\r\n\r\nexport interface ISdApiConfiguration {\r\n handlers: SdApiHandler[];\r\n}\r\n\r\nexport const SD_API_CONFIG = new InjectionToken<ISdApiConfiguration>('sd-api.configuration');\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Inject, Injectable, Optional } from '@angular/core';\r\nimport { SdCacheService } from '@sd-angular/core/services/cache';\r\nimport { SdUtilities } from '@sd-angular/core/utilities/extensions';\r\nimport { lastValueFrom, Observable } from 'rxjs';\r\nimport { catchError, map, shareReplay, timeout } from 'rxjs/operators';\r\nimport { v4 } from 'uuid';\r\nimport { ISdApiConfiguration, SD_API_CONFIG, SdApiHandler, SdDeleteOption, SdGetOption, SdPostOption, SdPutOption } from './api.model';\r\n\r\n// Gom nhóm các Option lại cho gọn\r\ntype SdHttpOptions = SdGetOption & SdPostOption & SdPutOption & SdDeleteOption;\r\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SdApiService {\r\n readonly #defaultTimeout = 60000; // 60s\r\n readonly #dedupCacheDuration = 1000; // 1s (Deduplication cache duration)\r\n\r\n // Thay đổi cấu trúc Cache: Lưu Observable thay vì Subject phức tạp\r\n // Key: hash string -> Value: { stream$: Observable, expiry: number }\r\n #inFlightRequests: Map<string, { stream$: Observable<any>; expiry: number }> = new Map();\r\n\r\n constructor(\r\n private httpClient: HttpClient,\r\n @Inject(SD_API_CONFIG) @Optional() private configurations: ISdApiConfiguration[],\r\n private cacheService: SdCacheService\r\n ) {\r\n // Optional: Cơ chế dọn dẹp cache định kỳ (mỗi 1 phút dọn dẹp các key hết hạn)\r\n setInterval(() => this.#cleanupCache(), 60000);\r\n }\r\n\r\n get http() {\r\n return this.httpClient;\r\n }\r\n\r\n // --- PUBLIC METHODS ---\r\n\r\n get = <T = any>(url: string, option?: SdGetOption): Promise<T> => {\r\n return this.#executeWithLayeredCache<T>(url, 'GET', undefined, option);\r\n };\r\n\r\n post = <T = any>(url: string, body?: any, option?: SdPostOption): Promise<T> => {\r\n return this.#executeWithLayeredCache<T>(url, 'POST', body, option);\r\n };\r\n\r\n put = <T = any>(url: string, body?: any, option?: SdPutOption): Promise<T> => {\r\n return this.#executeWithLayeredCache<T>(url, 'PUT', body, option);\r\n };\r\n\r\n delete = <T = any>(url: string, option?: SdDeleteOption): Promise<T> => {\r\n return this.#executeWithLayeredCache<T>(url, 'DELETE', undefined, option);\r\n };\r\n\r\n // Upload file logic giữ nguyên nhưng refactor nhẹ\r\n upload = async (url: string, option?: { extensions?: string[]; maxSizeInMb?: number }): Promise<any> => {\r\n const file = await SdUtilities.upload(option);\r\n if (!Array.isArray(file) && file) {\r\n return this.uploadFile(url, file);\r\n }\r\n };\r\n\r\n uploadFile = async (url: string, file: File): Promise<any> => {\r\n if (!file) return null;\r\n if (file.name.lastIndexOf('.') === -1) throw new Error('Invalid file extension');\r\n\r\n const formData = new FormData();\r\n formData.append('file', file, file.name);\r\n // Upload thường không cần deduplication cache, set autoCache: false\r\n return await this.post(url, formData, { autoCache: false });\r\n };\r\n\r\n // --- PRIVATE CORE LOGIC ---\r\n\r\n /**\r\n * Hàm trung gian xử lý Layer Cache (SdCacheService) trước khi gọi API thực tế\r\n */\r\n #executeWithLayeredCache = async <T>(url: string, method: HttpMethod, body?: any, option?: SdHttpOptions): Promise<T> => {\r\n // Layer 1: Persistent Cache (SdCacheService)\r\n if (option?.cacheOption) {\r\n const key = this.#generateKey(url, method, body, option);\r\n const { get, set, has } = this.cacheService.create(key, option.cacheOption);\r\n\r\n if (has()) {\r\n return get();\r\n }\r\n\r\n const result = await this.#request<T>(url, method, body, option);\r\n set(result);\r\n return result;\r\n }\r\n\r\n // Không có cache dài hạn thì gọi trực tiếp logic deduplication\r\n return this.#request<T>(url, method, body, option);\r\n };\r\n\r\n /**\r\n * Core Request: Xử lý Deduplication, Timeout, Mapping Response\r\n */\r\n #request = <T>(url: string, method: HttpMethod, body: any, option?: SdHttpOptions): Promise<T> => {\r\n const key = this.#generateKey(url, method, body, option);\r\n\r\n // Layer 2: Deduplication Cache (In-Flight Request / Short-term cache)\r\n const now = Date.now();\r\n const cachedItem = this.#inFlightRequests.get(key);\r\n\r\n // Nếu đã có request đang chạy hoặc mới chạy xong trong vòng 1s -> Trả về stream đó luôn\r\n if (cachedItem && cachedItem.expiry > now) {\r\n return lastValueFrom(cachedItem.stream$);\r\n }\r\n\r\n // Setup request mới\r\n const handler = this.#getHandler(url);\r\n const apiTimeout = option?.timeout ?? handler?.timeout ?? this.#defaultTimeout;\r\n\r\n // Tạo Observable call API\r\n const request$ = this.httpClient\r\n .request(method, url, {\r\n body,\r\n headers: option?.headers,\r\n params: option?.params,\r\n observe: 'response', // Lấy full response để check status\r\n responseType: option?.responseType,\r\n })\r\n .pipe(\r\n timeout(apiTimeout),\r\n map(res => {\r\n // Normalize Response Logic\r\n const bodyRes = res.body as any;\r\n // Logic check response cũ của bạn\r\n if (bodyRes && typeof bodyRes === 'object' && 'ok' in bodyRes && !bodyRes.ok) {\r\n throw bodyRes; // Giả sử structure trả về { ok: false, ... } là lỗi\r\n }\r\n\r\n if (handler?.mapResponse) {\r\n return handler.mapResponse(bodyRes);\r\n }\r\n\r\n return bodyRes;\r\n }),\r\n catchError(err => {\r\n // Xóa cache ngay lập tức nếu lỗi để user có thể retry\r\n this.#inFlightRequests.delete(key);\r\n throw err;\r\n }),\r\n // QUAN TRỌNG: shareReplay(1) giúp share kết quả cho các subscriber đến sau (trong 1s)\r\n shareReplay(1)\r\n );\r\n\r\n // Lưu vào Map\r\n this.#inFlightRequests.set(key, {\r\n stream$: request$,\r\n expiry: now + this.#dedupCacheDuration,\r\n });\r\n\r\n // Chuyển đổi sang Promise cho đúng return type của bạn\r\n return lastValueFrom(request$);\r\n };\r\n\r\n // --- HELPERS ---\r\n\r\n #getHandler = (url: string): SdApiHandler | undefined => {\r\n const handlers = this.configurations?.flatMap(b => b?.handlers || []) || [];\r\n return handlers.find(e => e.hosts.some(host => url.startsWith(host)));\r\n };\r\n\r\n #generateKey = (url: string, method: HttpMethod, body: any, option?: SdHttpOptions): string => {\r\n // FormData không hash được nội dung file, luôn generate key mới\r\n if (body instanceof FormData || option?.autoCache === false) {\r\n return v4();\r\n }\r\n return SdUtilities.hash({\r\n url,\r\n method,\r\n params: option?.params,\r\n headers: option?.headers,\r\n body,\r\n });\r\n };\r\n\r\n // Dọn dẹp memory leak\r\n #cleanupCache() {\r\n const now = Date.now();\r\n this.#inFlightRequests.forEach((value, key) => {\r\n if (value.expiry < now) {\r\n this.#inFlightRequests.delete(key);\r\n }\r\n });\r\n }\r\n}\r\n","/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';\r\nimport { Inject, Injectable, Optional } from '@angular/core';\r\nimport { from, Observable, throwError } from 'rxjs';\r\nimport { catchError, map, switchMap } from 'rxjs/operators';\r\nimport { SD_API_CONFIG, ISdApiConfiguration, SdApiHandler } from '../api.model';\r\n\r\n@Injectable()\r\nexport class SdHttpInterceptor implements HttpInterceptor {\r\n constructor(\r\n @Inject(SD_API_CONFIG)\r\n @Optional()\r\n private configurations: ISdApiConfiguration[]\r\n ) {}\r\n intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\r\n const url = request.url;\r\n if (!url) {\r\n throw new Error(`Invalid URL`);\r\n }\r\n const handlers = this.configurations?.reduce<SdApiHandler[]>((a, b) => [...a, ...(b?.handlers || [])], []) || [];\r\n const handler = handlers?.find(e => e.hosts.some(host => url.startsWith(host)));\r\n const intercept = handler?.intercept;\r\n if (intercept) {\r\n request = request.clone(intercept(request));\r\n }\r\n if (request.body instanceof FormData) {\r\n request = request.clone({\r\n headers: request.headers.delete('Content-Type'),\r\n });\r\n }\r\n const beforeRemoteHandler = handler?.beforeRemote;\r\n const afterRemoteHandler = handler?.afterRemote;\r\n const beforeRemote = beforeRemoteHandler?.(request);\r\n if (beforeRemote instanceof Promise) {\r\n return from(beforeRemote).pipe(\r\n switchMap(() => next.handle(request)),\r\n map((event: HttpEvent<any>) => {\r\n if (event instanceof HttpResponse) {\r\n afterRemoteHandler?.(event);\r\n }\r\n return event;\r\n }),\r\n catchError((error: HttpErrorResponse) => {\r\n afterRemoteHandler?.(error);\r\n return throwError(() => error);\r\n })\r\n );\r\n }\r\n return next.handle(request).pipe(\r\n map((event: HttpEvent<any>) => {\r\n if (event instanceof HttpResponse) {\r\n afterRemoteHandler?.(event);\r\n }\r\n return event;\r\n }),\r\n catchError((error: HttpErrorResponse) => {\r\n afterRemoteHandler?.(error);\r\n return throwError(() => error);\r\n })\r\n );\r\n }\r\n}\r\n","import { HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';\nimport { NgModule } from '@angular/core';\nimport { SdHttpInterceptor } from './interceptors/api.interceptor';\n\n@NgModule({\n imports: [],\n exports: [],\n providers: [provideHttpClient(withInterceptorsFromDi()), { provide: HTTP_INTERCEPTORS, useClass: SdHttpInterceptor, multi: true }],\n})\nexport class SdApiModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -49,7 +49,7 @@ class DialogConfirmComponent {
49
49
  }
50
50
  };
51
51
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: DialogConfirmComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
52
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: DialogConfirmComponent, isStandalone: true, selector: "sd-dialog-confirm", ngImport: i0, template: "<div mat-dialog-title class=\"\">\r\n @if (data.icon) {\r\n <mat-icon>\r\n {{ data.icon }}\r\n </mat-icon>\r\n }\r\n <span class=\"T28M\" [innerHtml]=\"data.title || 'Confirm'\"></span>\r\n</div>\r\n<div mat-dialog-content>\r\n <div class=\"T14R mb-4\" [innerHtml]=\"data.message\"></div>\r\n @if (data.input) {\r\n <mat-form-field appearance=\"outline\">\r\n <textarea\r\n style=\"width: 100%\"\r\n matInput\r\n [placeholder]=\"data.input.placeholder\"\r\n [(ngModel)]=\"value\"\r\n autocomplete=\"off\"\r\n rows=\"5\"\r\n [maxlength]=\"data.input.maxlength!\"></textarea>\r\n </mat-form-field>\r\n }\r\n @if (data.date) {\r\n <sd-date\r\n [placeholder]=\"data.date.placeholder\"\r\n [(model)]=\"value\"\r\n type=\"date\"\r\n [min]=\"data.date.min!\"\r\n [max]=\"data.date.max!\"\r\n [required]=\"data.date.required\">\r\n </sd-date>\r\n }\r\n @if (data.radio) {\r\n <sd-radio\r\n [items]=\"data.radio.items\"\r\n [valueField]=\"data.radio.valueField\"\r\n [displayField]=\"data.radio.displayField\"\r\n [display]=\"data.radio.display || 'column'\"\r\n [(model)]=\"value\"\r\n [required]=\"data.radio.required\">\r\n </sd-radio>\r\n }\r\n</div>\r\n<div mat-dialog-actions align=\"end\">\r\n @if (data.noTitle) {\r\n <sd-button [color]=\"data.noButtonColor || 'secondary'\" [title]=\"data.noTitle\" (click)=\"onCancel()\"></sd-button>\r\n }\r\n @if (data.yesTitle) {\r\n <sd-button\r\n class=\"ml-8\"\r\n type=\"fill\"\r\n [color]=\"data.yesButtonColor || 'primary'\"\r\n [disabled]=\"required && !value\"\r\n cdkFocusInitial\r\n [title]=\"data.yesTitle\"\r\n (click)=\"onAccept()\"></sd-button>\r\n }\r\n</div>\r\n", styles: [".text-primary{color:var(--sd-primary)!important}.bg-primary{background:var(--sd-primary)!important}.border-primary{border-color:var(--sd-primary)!important}.text-primary-light{color:var(--sd-primary-light)!important}.bg-primary-light{background:var(--sd-primary-light)!important}.border-primary-light{border-color:var(--sd-primary-light)!important}.text-primary-dark{color:var(--sd-primary-dark)!important}.bg-primary-dark{background:var(--sd-primary-dark)!important}.border-primary-dark{border-color:var(--sd-primary-dark)!important}.text-info{color:var(--sd-info)!important}.bg-info{background:var(--sd-info)!important}.border-info{border-color:var(--sd-info)!important}.text-info-light{color:var(--sd-info-light)!important}.bg-info-light{background:var(--sd-info-light)!important}.border-info-light{border-color:var(--sd-info-light)!important}.text-info-dark{color:var(--sd-info-dark)!important}.bg-info-dark{background:var(--sd-info-dark)!important}.border-info-dark{border-color:var(--sd-info-dark)!important}.text-success{color:var(--sd-success)!important}.bg-success{background:var(--sd-success)!important}.border-success{border-color:var(--sd-success)!important}.text-success-light{color:var(--sd-success-light)!important}.bg-success-light{background:var(--sd-success-light)!important}.border-success-light{border-color:var(--sd-success-light)!important}.text-success-dark{color:var(--sd-success-dark)!important}.bg-success-dark{background:var(--sd-success-dark)!important}.border-success-dark{border-color:var(--sd-success-dark)!important}.text-warning{color:var(--sd-warning)!important}.bg-warning{background:var(--sd-warning)!important}.border-warning{border-color:var(--sd-warning)!important}.text-warning-light{color:var(--sd-warning-light)!important}.bg-warning-light{background:var(--sd-warning-light)!important}.border-warning-light{border-color:var(--sd-warning-light)!important}.text-warning-dark{color:var(--sd-warning-dark)!important}.bg-warning-dark{background:var(--sd-warning-dark)!important}.border-warning-dark{border-color:var(--sd-warning-dark)!important}.text-error{color:var(--sd-error)!important}.bg-error{background:var(--sd-error)!important}.border-error{border-color:var(--sd-error)!important}.text-error-light{color:var(--sd-error-light)!important}.bg-error-light{background:var(--sd-error-light)!important}.border-error-light{border-color:var(--sd-error-light)!important}.text-error-dark{color:var(--sd-error-dark)!important}.bg-error-dark{background:var(--sd-error-dark)!important}.border-error-dark{border-color:var(--sd-error-dark)!important}.text-secondary{color:var(--sd-secondary)!important}.bg-secondary{background:var(--sd-secondary)!important}.border-secondary{border-color:var(--sd-secondary)!important}.text-secondary-light{color:var(--sd-secondary-light)!important}.bg-secondary-light{background:var(--sd-secondary-light)!important}.border-secondary-light{border-color:var(--sd-secondary-light)!important}.text-secondary-dark{color:var(--sd-secondary-dark)!important}.bg-secondary-dark{background:var(--sd-secondary-dark)!important}.border-secondary-dark{border-color:var(--sd-secondary-dark)!important}.text-light{color:var(--sd-light)!important}.bg-light{background:var(--sd-light)!important}.border-light{border-color:var(--sd-light)!important}.text-dark{color:var(--sd-dark)!important}.bg-dark{background:var(--sd-dark)!important}.border-dark{border-color:var(--sd-dark)!important}.text-black500{color:var(--sd-black500)!important}.bg-black500{background:var(--sd-black500)!important}.border-black500{border-color:var(--sd-black500)!important}.text-black400{color:var(--sd-black400)!important}.bg-black400{background:var(--sd-black400)!important}.border-black400{border-color:var(--sd-black400)!important}.text-black300{color:var(--sd-black300)!important}.bg-black300{background:var(--sd-black300)!important}.border-black300{border-color:var(--sd-black300)!important}.text-black200{color:var(--sd-black200)!important}.bg-black200{background:var(--sd-black200)!important}.border-black200{border-color:var(--sd-black200)!important}.text-black100{color:var(--sd-black100)!important}.bg-black100{background:var(--sd-black100)!important}.border-black100{border-color:var(--sd-black100)!important}.text-white{color:#fff!important}.bg-white{background:#fff!important}.border-white{border-color:#fff!important}.text-black{color:#000!important}.bg-black{background:#000!important}.border-black{border-color:#000!important}:host .mat-dialog-content{margin:0 -16px 16px!important}:host .mat-button{background-color:#f5f5f5}:host ::ng-deep .mat-dialog-title{display:flex;align-items:center;justify-content:flex-start}:host ::ng-deep .mat-dialog-title .mat-icon{margin-right:5px}:host{display:block}:host ::ng-deep .mat-dialog-title .mat-icon.info{color:var(--sd-info)}:host ::ng-deep .mat-dialog-title .mat-icon.warning{color:var(--sd-warning)}:host ::ng-deep .mat-dialog-title .mat-icon.success{color:var(--sd-success)}:host ::ng-deep .mat-dialog-title .mat-icon.error{color:var(--sd-error)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "title", "width", "size", "tooltip", "prefixIcon", "suffixIcon", "fontSet", "disabled", "loading"], outputs: ["click"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "appearance", "hideInlineError", "min", "max", "size", "form", "disabled", "viewed", "hyperlink", "required", "inlineError", "label", "helperText", "placeholder", "minDate", "maxDate", "model"], outputs: ["sdChange", "sdFocus", "modelChange"] }, { kind: "component", type: SdRadio, selector: "sd-radio", inputs: ["autoId", "name", "form", "label", "placeholder", "display", "model", "items", "valueField", "displayField", "required", "inlineError", "disabled", "viewed", "hyperlink"], outputs: ["modelChange", "sdChange", "sdSelection"] }] });
52
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: DialogConfirmComponent, isStandalone: true, selector: "sd-dialog-confirm", ngImport: i0, template: "<div mat-dialog-title class=\"\">\r\n @if (data.icon) {\r\n <mat-icon>\r\n {{ data.icon }}\r\n </mat-icon>\r\n }\r\n <span class=\"T28M\" [innerHtml]=\"data.title || 'Confirm'\"></span>\r\n</div>\r\n<div mat-dialog-content>\r\n <div class=\"T14R mb-4\" [innerHtml]=\"data.message\"></div>\r\n @if (data.input) {\r\n <mat-form-field appearance=\"outline\">\r\n <textarea\r\n style=\"width: 100%\"\r\n matInput\r\n [placeholder]=\"data.input.placeholder\"\r\n [(ngModel)]=\"value\"\r\n autocomplete=\"off\"\r\n rows=\"5\"\r\n [maxlength]=\"data.input.maxlength!\"></textarea>\r\n </mat-form-field>\r\n }\r\n @if (data.date) {\r\n <sd-date\r\n [placeholder]=\"data.date.placeholder\"\r\n [(model)]=\"value\"\r\n type=\"date\"\r\n [min]=\"data.date.min!\"\r\n [max]=\"data.date.max!\"\r\n [required]=\"data.date.required\">\r\n </sd-date>\r\n }\r\n @if (data.radio) {\r\n <sd-radio\r\n [items]=\"data.radio.items\"\r\n [valueField]=\"data.radio.valueField\"\r\n [displayField]=\"data.radio.displayField\"\r\n [display]=\"data.radio.display || 'column'\"\r\n [(model)]=\"value\"\r\n [required]=\"data.radio.required\">\r\n </sd-radio>\r\n }\r\n</div>\r\n<div mat-dialog-actions align=\"end\">\r\n @if (data.noTitle) {\r\n <sd-button [color]=\"data.noButtonColor || 'secondary'\" [title]=\"data.noTitle\" (click)=\"onCancel()\"></sd-button>\r\n }\r\n @if (data.yesTitle) {\r\n <sd-button\r\n class=\"ml-8\"\r\n type=\"fill\"\r\n [color]=\"data.yesButtonColor || 'primary'\"\r\n [disabled]=\"required && !value\"\r\n cdkFocusInitial\r\n [title]=\"data.yesTitle\"\r\n (click)=\"onAccept()\"></sd-button>\r\n }\r\n</div>\r\n", styles: [".text-primary{color:var(--sd-primary)!important}.bg-primary{background:var(--sd-primary)!important}.border-primary{border-color:var(--sd-primary)!important}.text-primary-light{color:var(--sd-primary-light)!important}.bg-primary-light{background:var(--sd-primary-light)!important}.border-primary-light{border-color:var(--sd-primary-light)!important}.text-primary-dark{color:var(--sd-primary-dark)!important}.bg-primary-dark{background:var(--sd-primary-dark)!important}.border-primary-dark{border-color:var(--sd-primary-dark)!important}.text-info{color:var(--sd-info)!important}.bg-info{background:var(--sd-info)!important}.border-info{border-color:var(--sd-info)!important}.text-info-light{color:var(--sd-info-light)!important}.bg-info-light{background:var(--sd-info-light)!important}.border-info-light{border-color:var(--sd-info-light)!important}.text-info-dark{color:var(--sd-info-dark)!important}.bg-info-dark{background:var(--sd-info-dark)!important}.border-info-dark{border-color:var(--sd-info-dark)!important}.text-success{color:var(--sd-success)!important}.bg-success{background:var(--sd-success)!important}.border-success{border-color:var(--sd-success)!important}.text-success-light{color:var(--sd-success-light)!important}.bg-success-light{background:var(--sd-success-light)!important}.border-success-light{border-color:var(--sd-success-light)!important}.text-success-dark{color:var(--sd-success-dark)!important}.bg-success-dark{background:var(--sd-success-dark)!important}.border-success-dark{border-color:var(--sd-success-dark)!important}.text-warning{color:var(--sd-warning)!important}.bg-warning{background:var(--sd-warning)!important}.border-warning{border-color:var(--sd-warning)!important}.text-warning-light{color:var(--sd-warning-light)!important}.bg-warning-light{background:var(--sd-warning-light)!important}.border-warning-light{border-color:var(--sd-warning-light)!important}.text-warning-dark{color:var(--sd-warning-dark)!important}.bg-warning-dark{background:var(--sd-warning-dark)!important}.border-warning-dark{border-color:var(--sd-warning-dark)!important}.text-error{color:var(--sd-error)!important}.bg-error{background:var(--sd-error)!important}.border-error{border-color:var(--sd-error)!important}.text-error-light{color:var(--sd-error-light)!important}.bg-error-light{background:var(--sd-error-light)!important}.border-error-light{border-color:var(--sd-error-light)!important}.text-error-dark{color:var(--sd-error-dark)!important}.bg-error-dark{background:var(--sd-error-dark)!important}.border-error-dark{border-color:var(--sd-error-dark)!important}.text-secondary{color:var(--sd-secondary)!important}.bg-secondary{background:var(--sd-secondary)!important}.border-secondary{border-color:var(--sd-secondary)!important}.text-secondary-light{color:var(--sd-secondary-light)!important}.bg-secondary-light{background:var(--sd-secondary-light)!important}.border-secondary-light{border-color:var(--sd-secondary-light)!important}.text-secondary-dark{color:var(--sd-secondary-dark)!important}.bg-secondary-dark{background:var(--sd-secondary-dark)!important}.border-secondary-dark{border-color:var(--sd-secondary-dark)!important}.text-light{color:var(--sd-light)!important}.bg-light{background:var(--sd-light)!important}.border-light{border-color:var(--sd-light)!important}.text-dark{color:var(--sd-dark)!important}.bg-dark{background:var(--sd-dark)!important}.border-dark{border-color:var(--sd-dark)!important}.text-black500{color:var(--sd-black500)!important}.bg-black500{background:var(--sd-black500)!important}.border-black500{border-color:var(--sd-black500)!important}.text-black400{color:var(--sd-black400)!important}.bg-black400{background:var(--sd-black400)!important}.border-black400{border-color:var(--sd-black400)!important}.text-black300{color:var(--sd-black300)!important}.bg-black300{background:var(--sd-black300)!important}.border-black300{border-color:var(--sd-black300)!important}.text-black200{color:var(--sd-black200)!important}.bg-black200{background:var(--sd-black200)!important}.border-black200{border-color:var(--sd-black200)!important}.text-black100{color:var(--sd-black100)!important}.bg-black100{background:var(--sd-black100)!important}.border-black100{border-color:var(--sd-black100)!important}.text-white{color:#fff!important}.bg-white{background:#fff!important}.border-white{border-color:#fff!important}.text-black{color:#000!important}.bg-black{background:#000!important}.border-black{border-color:#000!important}:host .mat-dialog-content{margin:0 -16px 16px!important}:host .mat-button{background-color:#f5f5f5}:host ::ng-deep .mat-dialog-title{display:flex;align-items:center;justify-content:flex-start}:host ::ng-deep .mat-dialog-title .mat-icon{margin-right:5px}:host{display:block}:host ::ng-deep .mat-dialog-title .mat-icon.info{color:var(--sd-info)}:host ::ng-deep .mat-dialog-title .mat-icon.warning{color:var(--sd-warning)}:host ::ng-deep .mat-dialog-title .mat-icon.success{color:var(--sd-success)}:host ::ng-deep .mat-dialog-title .mat-icon.error{color:var(--sd-error)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdRadio, selector: "sd-radio", inputs: ["autoId", "name", "form", "label", "placeholder", "display", "model", "items", "valueField", "displayField", "required", "inlineError", "disabled", "viewed", "hyperlink"], outputs: ["modelChange", "sdChange", "sdSelection"] }] });
53
53
  }
54
54
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: DialogConfirmComponent, decorators: [{
55
55
  type: Component,
@@ -66,7 +66,7 @@ class SdConfirmService {
66
66
  }
67
67
  confirm = (message, option = {}) => {
68
68
  const dialogRef = this.dialog.open(DialogConfirmComponent, {
69
- width: '400px',
69
+ width: option?.width || '400px',
70
70
  data: {
71
71
  title: option?.title || 'Xác nhận',
72
72
  message,
@@ -1 +1 @@
1
- {"version":3,"file":"sd-angular-core-services-confirm.mjs","sources":["../../../projects/sd-angular/services/confirm/src/lib/components/dialog-confirm/dialog-confirm.component.ts","../../../projects/sd-angular/services/confirm/src/lib/components/dialog-confirm/dialog-confirm.component.html","../../../projects/sd-angular/services/confirm/src/lib/confirm.service.ts","../../../projects/sd-angular/services/confirm/src/public-api.ts","../../../projects/sd-angular/services/confirm/sd-angular-core-services-confirm.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\r\nimport { Component, Inject } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { SdButton } from '@sd-angular/core/components/button';\r\nimport { SdDate } from '@sd-angular/core/forms/date';\r\nimport { SdRadio } from '@sd-angular/core/forms/radio';\r\nimport { SdColor } from '@sd-angular/core/utilities/models';\r\nimport * as uuid from 'uuid';\r\n\r\nexport interface DialogData {\r\n icon?: string;\r\n title?: string;\r\n message?: string;\r\n yesTitle?: string;\r\n noTitle?: string;\r\n yesButtonColor?: SdColor;\r\n noButtonColor?: SdColor;\r\n input?: {\r\n placeholder?: string;\r\n minlength?: number;\r\n maxlength?: number;\r\n required?: boolean;\r\n defaultValue?: string;\r\n };\r\n date?: {\r\n required?: boolean;\r\n placeholder?: string;\r\n defaultValue?: string | Date;\r\n min?: string | Date;\r\n max?: string | Date;\r\n };\r\n radio?: {\r\n required?: boolean;\r\n defaultValue?: string | number;\r\n items: any[];\r\n valueField: string;\r\n displayField: string;\r\n display?: 'row' | 'column';\r\n };\r\n}\r\n\r\n@Component({\r\n selector: 'sd-dialog-confirm',\r\n templateUrl: 'dialog-confirm.component.html',\r\n styleUrls: ['./dialog-confirm.component.scss'],\r\n imports: [CommonModule, FormsModule, MatDialogModule, MatFormFieldModule, MatIconModule, SdButton, SdDate, SdRadio],\r\n})\r\nexport class DialogConfirmComponent {\r\n value: any;\r\n required = false;\r\n id = `I${uuid.v4()}`;\r\n constructor(\r\n public dialogRef: MatDialogRef<DialogConfirmComponent>,\r\n @Inject(MAT_DIALOG_DATA) public data: DialogData\r\n ) {\r\n if (data?.input) {\r\n this.value = data?.input?.defaultValue ?? '';\r\n this.required = data?.input?.required || false;\r\n }\r\n if (data?.date) {\r\n this.value = data?.date?.defaultValue ?? '';\r\n this.required = data?.date?.required || false;\r\n }\r\n if (data?.radio) {\r\n this.value = data?.radio?.defaultValue ?? '';\r\n this.required = data?.radio?.required || false;\r\n }\r\n }\r\n\r\n onCancel = () => {\r\n this.dialogRef.close({ action: 'CANCEL', value: null });\r\n };\r\n\r\n onAccept = () => {\r\n // Always return an object with action and value for consistency\r\n if (this.data?.radio || this.data?.input || this.data?.date) {\r\n this.dialogRef.close({ action: 'ACCEPT', value: this.value });\r\n } else {\r\n this.dialogRef.close({ action: 'ACCEPT', value: null });\r\n }\r\n };\r\n}\r\n","<div mat-dialog-title class=\"\">\r\n @if (data.icon) {\r\n <mat-icon>\r\n {{ data.icon }}\r\n </mat-icon>\r\n }\r\n <span class=\"T28M\" [innerHtml]=\"data.title || 'Confirm'\"></span>\r\n</div>\r\n<div mat-dialog-content>\r\n <div class=\"T14R mb-4\" [innerHtml]=\"data.message\"></div>\r\n @if (data.input) {\r\n <mat-form-field appearance=\"outline\">\r\n <textarea\r\n style=\"width: 100%\"\r\n matInput\r\n [placeholder]=\"data.input.placeholder\"\r\n [(ngModel)]=\"value\"\r\n autocomplete=\"off\"\r\n rows=\"5\"\r\n [maxlength]=\"data.input.maxlength!\"></textarea>\r\n </mat-form-field>\r\n }\r\n @if (data.date) {\r\n <sd-date\r\n [placeholder]=\"data.date.placeholder\"\r\n [(model)]=\"value\"\r\n type=\"date\"\r\n [min]=\"data.date.min!\"\r\n [max]=\"data.date.max!\"\r\n [required]=\"data.date.required\">\r\n </sd-date>\r\n }\r\n @if (data.radio) {\r\n <sd-radio\r\n [items]=\"data.radio.items\"\r\n [valueField]=\"data.radio.valueField\"\r\n [displayField]=\"data.radio.displayField\"\r\n [display]=\"data.radio.display || 'column'\"\r\n [(model)]=\"value\"\r\n [required]=\"data.radio.required\">\r\n </sd-radio>\r\n }\r\n</div>\r\n<div mat-dialog-actions align=\"end\">\r\n @if (data.noTitle) {\r\n <sd-button [color]=\"data.noButtonColor || 'secondary'\" [title]=\"data.noTitle\" (click)=\"onCancel()\"></sd-button>\r\n }\r\n @if (data.yesTitle) {\r\n <sd-button\r\n class=\"ml-8\"\r\n type=\"fill\"\r\n [color]=\"data.yesButtonColor || 'primary'\"\r\n [disabled]=\"required && !value\"\r\n cdkFocusInitial\r\n [title]=\"data.yesTitle\"\r\n (click)=\"onAccept()\"></sd-button>\r\n }\r\n</div>\r\n","import { Injectable } from '@angular/core';\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { DialogConfirmComponent } from './components/dialog-confirm/dialog-confirm.component';\r\nimport { SdColor } from '@sd-angular/core/utilities/models';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SdConfirmService {\r\n constructor(private dialog: MatDialog) {}\r\n\r\n confirm = (\r\n message: string,\r\n option: {\r\n title?: string;\r\n yesTitle?: string;\r\n noTitle?: string;\r\n yesButtonColor?: SdColor;\r\n noButtonColor?: SdColor;\r\n } = {}\r\n ) => {\r\n const dialogRef = this.dialog.open(DialogConfirmComponent, {\r\n width: '400px',\r\n data: {\r\n title: option?.title || 'Xác nhận',\r\n message,\r\n yesTitle: option?.yesTitle || 'Đồng ý',\r\n noTitle: option?.noTitle || 'Hủy bỏ',\r\n noButtonColor: option?.noButtonColor || 'secondary',\r\n yesButtonColor: option?.yesButtonColor || 'primary',\r\n },\r\n });\r\n return new Promise((resolve, reject) => {\r\n dialogRef.afterClosed().subscribe(result => {\r\n if (result) {\r\n if (result.action === 'CANCEL') {\r\n reject(result.action);\r\n } else if (result.action === 'ACCEPT') {\r\n resolve(result.value);\r\n }\r\n }\r\n });\r\n });\r\n };\r\n\r\n withInput = (\r\n message?: string,\r\n option?: {\r\n title?: string;\r\n yesTitle?: string;\r\n noTitle?: string;\r\n required?: boolean;\r\n maxlength?: number;\r\n yesButtonColor?: SdColor;\r\n noButtonColor?: SdColor;\r\n defaultValue?: string;\r\n }\r\n ): Promise<string> => {\r\n const dialogRef = this.dialog.open(DialogConfirmComponent, {\r\n width: '400px',\r\n data: {\r\n title: option?.title || 'Xác nhận',\r\n message,\r\n yesTitle: option?.yesTitle || 'Có',\r\n noTitle: option?.noTitle || 'Không',\r\n noButtonColor: option?.noButtonColor || 'secondary',\r\n yesButtonColor: option?.yesButtonColor || 'primary',\r\n input: {\r\n maxlength: option?.maxlength || 255,\r\n required: option?.required,\r\n defaultValue: option?.defaultValue || '',\r\n },\r\n },\r\n });\r\n return new Promise((resolve, reject) => {\r\n dialogRef.afterClosed().subscribe(result => {\r\n if (result) {\r\n if (result.action === 'CANCEL') {\r\n reject(result.action);\r\n } else if (result.action === 'ACCEPT') {\r\n resolve(result.value);\r\n }\r\n }\r\n });\r\n });\r\n };\r\n\r\n withRadio = (\r\n message?: string,\r\n option?: {\r\n title?: string;\r\n yesTitle?: string;\r\n noTitle?: string;\r\n required?: boolean;\r\n yesButtonColor?: SdColor;\r\n noButtonColor?: SdColor;\r\n defaultValue?: string | number;\r\n items: any[];\r\n valueField: string;\r\n displayField: string;\r\n display?: 'row' | 'column';\r\n }\r\n ): Promise<string> => {\r\n const dialogRef = this.dialog.open(DialogConfirmComponent, {\r\n width: '400px',\r\n data: {\r\n title: option?.title || 'Xác nhận',\r\n message,\r\n yesTitle: option?.yesTitle || 'Có',\r\n noTitle: option?.noTitle || 'Không',\r\n noButtonColor: option?.noButtonColor || 'secondary',\r\n yesButtonColor: option?.yesButtonColor || 'primary',\r\n radio: {\r\n items: option?.items || [],\r\n valueField: option?.valueField || 'value',\r\n displayField: option?.displayField || 'label',\r\n display: option?.display || 'row',\r\n required: option?.required,\r\n defaultValue: option?.defaultValue,\r\n },\r\n },\r\n });\r\n return new Promise((resolve, reject) => {\r\n dialogRef.afterClosed().subscribe(result => {\r\n if (result) {\r\n if (result.action === 'CANCEL') {\r\n reject(result.action);\r\n } else if (result.action === 'ACCEPT') {\r\n resolve(result.value);\r\n }\r\n }\r\n });\r\n });\r\n };\r\n\r\n withDate = (\r\n message?: string,\r\n option?: {\r\n title?: string;\r\n\r\n yesTitle?: string;\r\n noTitle?: string;\r\n required?: boolean;\r\n yesButtonColor?: SdColor;\r\n noButtonColor?: SdColor;\r\n defaultValue?: string | Date;\r\n placeholder?: string;\r\n }\r\n ): Promise<string> => {\r\n const dialogRef = this.dialog.open(DialogConfirmComponent, {\r\n width: '400px',\r\n data: {\r\n title: option?.title || 'Xác nhận',\r\n message,\r\n yesTitle: option?.yesTitle || 'Có',\r\n noTitle: option?.noTitle || 'Không',\r\n noButtonColor: option?.noButtonColor || 'secondary',\r\n yesButtonColor: option?.yesButtonColor || 'primary',\r\n date: {\r\n placeholder: option?.placeholder,\r\n required: option?.required,\r\n defaultValue: option?.defaultValue || '',\r\n },\r\n },\r\n });\r\n return new Promise((resolve, reject) => {\r\n dialogRef.afterClosed().subscribe(result => {\r\n if (result) {\r\n if (result.action === 'CANCEL') {\r\n reject(result.action);\r\n } else if (result.action === 'ACCEPT') {\r\n resolve(result.value);\r\n }\r\n }\r\n });\r\n });\r\n };\r\n}\r\n","/*\n * Public API Surface of superdev-angular-core\n */\n\nexport * from './lib/components/dialog-confirm/dialog-confirm.component';\nexport * from './lib/confirm.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sd-angular-core-services-confirm.mjs","sources":["../../../projects/sd-angular/services/confirm/src/lib/components/dialog-confirm/dialog-confirm.component.ts","../../../projects/sd-angular/services/confirm/src/lib/components/dialog-confirm/dialog-confirm.component.html","../../../projects/sd-angular/services/confirm/src/lib/confirm.service.ts","../../../projects/sd-angular/services/confirm/src/public-api.ts","../../../projects/sd-angular/services/confirm/sd-angular-core-services-confirm.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\r\nimport { Component, Inject } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { MatDialogRef, MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { SdButton } from '@sd-angular/core/components/button';\r\nimport { SdDate } from '@sd-angular/core/forms/date';\r\nimport { SdRadio } from '@sd-angular/core/forms/radio';\r\nimport { SdColor } from '@sd-angular/core/utilities/models';\r\nimport * as uuid from 'uuid';\r\n\r\nexport interface DialogData {\r\n icon?: string;\r\n title?: string;\r\n message?: string;\r\n yesTitle?: string;\r\n noTitle?: string;\r\n yesButtonColor?: SdColor;\r\n noButtonColor?: SdColor;\r\n input?: {\r\n placeholder?: string;\r\n minlength?: number;\r\n maxlength?: number;\r\n required?: boolean;\r\n defaultValue?: string;\r\n };\r\n date?: {\r\n required?: boolean;\r\n placeholder?: string;\r\n defaultValue?: string | Date;\r\n min?: string | Date;\r\n max?: string | Date;\r\n };\r\n radio?: {\r\n required?: boolean;\r\n defaultValue?: string | number;\r\n items: any[];\r\n valueField: string;\r\n displayField: string;\r\n display?: 'row' | 'column';\r\n };\r\n}\r\n\r\n@Component({\r\n selector: 'sd-dialog-confirm',\r\n templateUrl: 'dialog-confirm.component.html',\r\n styleUrls: ['./dialog-confirm.component.scss'],\r\n imports: [CommonModule, FormsModule, MatDialogModule, MatFormFieldModule, MatIconModule, SdButton, SdDate, SdRadio],\r\n})\r\nexport class DialogConfirmComponent {\r\n value: any;\r\n required = false;\r\n id = `I${uuid.v4()}`;\r\n constructor(\r\n public dialogRef: MatDialogRef<DialogConfirmComponent>,\r\n @Inject(MAT_DIALOG_DATA) public data: DialogData\r\n ) {\r\n if (data?.input) {\r\n this.value = data?.input?.defaultValue ?? '';\r\n this.required = data?.input?.required || false;\r\n }\r\n if (data?.date) {\r\n this.value = data?.date?.defaultValue ?? '';\r\n this.required = data?.date?.required || false;\r\n }\r\n if (data?.radio) {\r\n this.value = data?.radio?.defaultValue ?? '';\r\n this.required = data?.radio?.required || false;\r\n }\r\n }\r\n\r\n onCancel = () => {\r\n this.dialogRef.close({ action: 'CANCEL', value: null });\r\n };\r\n\r\n onAccept = () => {\r\n // Always return an object with action and value for consistency\r\n if (this.data?.radio || this.data?.input || this.data?.date) {\r\n this.dialogRef.close({ action: 'ACCEPT', value: this.value });\r\n } else {\r\n this.dialogRef.close({ action: 'ACCEPT', value: null });\r\n }\r\n };\r\n}\r\n","<div mat-dialog-title class=\"\">\r\n @if (data.icon) {\r\n <mat-icon>\r\n {{ data.icon }}\r\n </mat-icon>\r\n }\r\n <span class=\"T28M\" [innerHtml]=\"data.title || 'Confirm'\"></span>\r\n</div>\r\n<div mat-dialog-content>\r\n <div class=\"T14R mb-4\" [innerHtml]=\"data.message\"></div>\r\n @if (data.input) {\r\n <mat-form-field appearance=\"outline\">\r\n <textarea\r\n style=\"width: 100%\"\r\n matInput\r\n [placeholder]=\"data.input.placeholder\"\r\n [(ngModel)]=\"value\"\r\n autocomplete=\"off\"\r\n rows=\"5\"\r\n [maxlength]=\"data.input.maxlength!\"></textarea>\r\n </mat-form-field>\r\n }\r\n @if (data.date) {\r\n <sd-date\r\n [placeholder]=\"data.date.placeholder\"\r\n [(model)]=\"value\"\r\n type=\"date\"\r\n [min]=\"data.date.min!\"\r\n [max]=\"data.date.max!\"\r\n [required]=\"data.date.required\">\r\n </sd-date>\r\n }\r\n @if (data.radio) {\r\n <sd-radio\r\n [items]=\"data.radio.items\"\r\n [valueField]=\"data.radio.valueField\"\r\n [displayField]=\"data.radio.displayField\"\r\n [display]=\"data.radio.display || 'column'\"\r\n [(model)]=\"value\"\r\n [required]=\"data.radio.required\">\r\n </sd-radio>\r\n }\r\n</div>\r\n<div mat-dialog-actions align=\"end\">\r\n @if (data.noTitle) {\r\n <sd-button [color]=\"data.noButtonColor || 'secondary'\" [title]=\"data.noTitle\" (click)=\"onCancel()\"></sd-button>\r\n }\r\n @if (data.yesTitle) {\r\n <sd-button\r\n class=\"ml-8\"\r\n type=\"fill\"\r\n [color]=\"data.yesButtonColor || 'primary'\"\r\n [disabled]=\"required && !value\"\r\n cdkFocusInitial\r\n [title]=\"data.yesTitle\"\r\n (click)=\"onAccept()\"></sd-button>\r\n }\r\n</div>\r\n","import { Injectable } from '@angular/core';\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { DialogConfirmComponent } from './components/dialog-confirm/dialog-confirm.component';\r\nimport { SdColor } from '@sd-angular/core/utilities/models';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SdConfirmService {\r\n constructor(private dialog: MatDialog) {}\r\n\r\n confirm = (\r\n message: string,\r\n option: {\r\n title?: string;\r\n yesTitle?: string;\r\n noTitle?: string;\r\n yesButtonColor?: SdColor;\r\n noButtonColor?: SdColor;\r\n width?: string;\r\n } = {}\r\n ) => {\r\n const dialogRef = this.dialog.open(DialogConfirmComponent, {\r\n width: option?.width || '400px',\r\n data: {\r\n title: option?.title || 'Xác nhận',\r\n message,\r\n yesTitle: option?.yesTitle || 'Đồng ý',\r\n noTitle: option?.noTitle || 'Hủy bỏ',\r\n noButtonColor: option?.noButtonColor || 'secondary',\r\n yesButtonColor: option?.yesButtonColor || 'primary',\r\n },\r\n });\r\n return new Promise((resolve, reject) => {\r\n dialogRef.afterClosed().subscribe(result => {\r\n if (result) {\r\n if (result.action === 'CANCEL') {\r\n reject(result.action);\r\n } else if (result.action === 'ACCEPT') {\r\n resolve(result.value);\r\n }\r\n }\r\n });\r\n });\r\n };\r\n\r\n withInput = (\r\n message?: string,\r\n option?: {\r\n title?: string;\r\n yesTitle?: string;\r\n noTitle?: string;\r\n required?: boolean;\r\n maxlength?: number;\r\n yesButtonColor?: SdColor;\r\n noButtonColor?: SdColor;\r\n defaultValue?: string;\r\n }\r\n ): Promise<string> => {\r\n const dialogRef = this.dialog.open(DialogConfirmComponent, {\r\n width: '400px',\r\n data: {\r\n title: option?.title || 'Xác nhận',\r\n message,\r\n yesTitle: option?.yesTitle || 'Có',\r\n noTitle: option?.noTitle || 'Không',\r\n noButtonColor: option?.noButtonColor || 'secondary',\r\n yesButtonColor: option?.yesButtonColor || 'primary',\r\n input: {\r\n maxlength: option?.maxlength || 255,\r\n required: option?.required,\r\n defaultValue: option?.defaultValue || '',\r\n },\r\n },\r\n });\r\n return new Promise((resolve, reject) => {\r\n dialogRef.afterClosed().subscribe(result => {\r\n if (result) {\r\n if (result.action === 'CANCEL') {\r\n reject(result.action);\r\n } else if (result.action === 'ACCEPT') {\r\n resolve(result.value);\r\n }\r\n }\r\n });\r\n });\r\n };\r\n\r\n withRadio = (\r\n message?: string,\r\n option?: {\r\n title?: string;\r\n yesTitle?: string;\r\n noTitle?: string;\r\n required?: boolean;\r\n yesButtonColor?: SdColor;\r\n noButtonColor?: SdColor;\r\n defaultValue?: string | number;\r\n items: any[];\r\n valueField: string;\r\n displayField: string;\r\n display?: 'row' | 'column';\r\n }\r\n ): Promise<string> => {\r\n const dialogRef = this.dialog.open(DialogConfirmComponent, {\r\n width: '400px',\r\n data: {\r\n title: option?.title || 'Xác nhận',\r\n message,\r\n yesTitle: option?.yesTitle || 'Có',\r\n noTitle: option?.noTitle || 'Không',\r\n noButtonColor: option?.noButtonColor || 'secondary',\r\n yesButtonColor: option?.yesButtonColor || 'primary',\r\n radio: {\r\n items: option?.items || [],\r\n valueField: option?.valueField || 'value',\r\n displayField: option?.displayField || 'label',\r\n display: option?.display || 'row',\r\n required: option?.required,\r\n defaultValue: option?.defaultValue,\r\n },\r\n },\r\n });\r\n return new Promise((resolve, reject) => {\r\n dialogRef.afterClosed().subscribe(result => {\r\n if (result) {\r\n if (result.action === 'CANCEL') {\r\n reject(result.action);\r\n } else if (result.action === 'ACCEPT') {\r\n resolve(result.value);\r\n }\r\n }\r\n });\r\n });\r\n };\r\n\r\n withDate = (\r\n message?: string,\r\n option?: {\r\n title?: string;\r\n\r\n yesTitle?: string;\r\n noTitle?: string;\r\n required?: boolean;\r\n yesButtonColor?: SdColor;\r\n noButtonColor?: SdColor;\r\n defaultValue?: string | Date;\r\n placeholder?: string;\r\n }\r\n ): Promise<string> => {\r\n const dialogRef = this.dialog.open(DialogConfirmComponent, {\r\n width: '400px',\r\n data: {\r\n title: option?.title || 'Xác nhận',\r\n message,\r\n yesTitle: option?.yesTitle || 'Có',\r\n noTitle: option?.noTitle || 'Không',\r\n noButtonColor: option?.noButtonColor || 'secondary',\r\n yesButtonColor: option?.yesButtonColor || 'primary',\r\n date: {\r\n placeholder: option?.placeholder,\r\n required: option?.required,\r\n defaultValue: option?.defaultValue || '',\r\n },\r\n },\r\n });\r\n return new Promise((resolve, reject) => {\r\n dialogRef.afterClosed().subscribe(result => {\r\n if (result) {\r\n if (result.action === 'CANCEL') {\r\n reject(result.action);\r\n } else if (result.action === 'ACCEPT') {\r\n resolve(result.value);\r\n }\r\n }\r\n });\r\n });\r\n };\r\n}\r\n","/*\n * Public API Surface of superdev-angular-core\n */\n\nexport * from './lib/components/dialog-confirm/dialog-confirm.component';\nexport * from './lib/confirm.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,173 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Injectable } from '@angular/core';
3
+ import * as mammoth from 'mammoth';
4
+ import { docxToHtml } from '@omer-go/docx-parser-converter-ts';
5
+ import * as i1 from '@sd-angular/core/services/notify';
6
+
7
+ class SdDocxService {
8
+ notifyService;
9
+ #DEFAULT_MAX_SIZE_MB = 50;
10
+ #VALID_EXTENSIONS = ['.doc', '.docx'];
11
+ #ERROR_INVALID_FORMAT = 'Định dạng không hợp lệ. Vui lòng chọn Mẫu có định dạng DOC hoặc DOCX';
12
+ #ERROR_SIZE_EXCEEDED = 'Kích thước tệp mẫu vượt quá tiêu chuẩn hỗ trợ của hệ thống. Vui lòng thử lại';
13
+ #fileInput = null;
14
+ constructor(notifyService) {
15
+ this.notifyService = notifyService;
16
+ }
17
+ async open(options) {
18
+ return new Promise(resolve => {
19
+ this.#createFileInput();
20
+ if (!this.#fileInput) {
21
+ resolve(null);
22
+ return;
23
+ }
24
+ const handleChange = async (event) => {
25
+ const input = event.target;
26
+ const file = input.files?.[0];
27
+ if (!file) {
28
+ resolve(null);
29
+ return;
30
+ }
31
+ const result = await this.convertToHtml(file, options);
32
+ resolve(result);
33
+ // Cleanup
34
+ input.value = '';
35
+ input.removeEventListener('change', handleChange);
36
+ };
37
+ this.#fileInput.addEventListener('change', handleChange, { once: true });
38
+ this.#fileInput.click();
39
+ });
40
+ }
41
+ #createFileInput() {
42
+ if (this.#fileInput) {
43
+ return;
44
+ }
45
+ this.#fileInput = document.createElement('input');
46
+ this.#fileInput.type = 'file';
47
+ this.#fileInput.accept = '.doc,.docx';
48
+ this.#fileInput.style.display = 'none';
49
+ document.body.appendChild(this.#fileInput);
50
+ }
51
+ async convertToHtml(input, options) {
52
+ const opts = {
53
+ validateFormat: true,
54
+ validateSize: true,
55
+ maxSizeInMb: this.#DEFAULT_MAX_SIZE_MB,
56
+ ...options,
57
+ };
58
+ try {
59
+ let fileName;
60
+ let fileSize;
61
+ let arrayBuffer;
62
+ if (input instanceof File) {
63
+ fileName = input.name;
64
+ fileSize = input.size;
65
+ arrayBuffer = await this.#fileToArrayBuffer(input);
66
+ }
67
+ else if (input instanceof Blob) {
68
+ fileSize = input.size;
69
+ arrayBuffer = await this.#blobToArrayBuffer(input);
70
+ }
71
+ else {
72
+ arrayBuffer = input;
73
+ }
74
+ if (opts.validateFormat && fileName) {
75
+ if (!this.#isValidFormat(fileName)) {
76
+ this.notifyService.error(this.#ERROR_INVALID_FORMAT);
77
+ return null;
78
+ }
79
+ }
80
+ if (opts.validateSize && fileSize !== undefined) {
81
+ const maxSizeInBytes = opts.maxSizeInMb * 1024 * 1024;
82
+ if (fileSize > maxSizeInBytes) {
83
+ this.notifyService.error(this.#ERROR_SIZE_EXCEEDED);
84
+ return null;
85
+ }
86
+ }
87
+ const { validateFormat, validateSize, maxSizeInMb, ...conversionOptions } = opts;
88
+ // Try @omer-go first for better formatting, fallback to mammoth on BOM error
89
+ let html;
90
+ let messages = [];
91
+ try {
92
+ html = await docxToHtml(arrayBuffer, {
93
+ styleMode: 'inline',
94
+ useSemanticTags: true,
95
+ fragmentOnly: true,
96
+ ...conversionOptions,
97
+ });
98
+ }
99
+ catch (omerError) {
100
+ console.log(omerError);
101
+ // Fallback to mammoth if @omer-go fails (e.g., BOM issue)
102
+ console.warn('@omer-go/docx-parser-converter-ts failed, falling back to mammoth:', omerError?.message);
103
+ const result = await mammoth.convertToHtml({ arrayBuffer }, conversionOptions);
104
+ html = result.value;
105
+ messages = result.messages.map(m => m.toString());
106
+ }
107
+ return {
108
+ html,
109
+ messages,
110
+ };
111
+ }
112
+ catch (error) {
113
+ console.error('DocX conversion error:', error);
114
+ this.notifyService.error('Có lỗi xảy ra khi chuyển đổi file DOCX');
115
+ return null;
116
+ }
117
+ }
118
+ async convertToHtmlString(input, options) {
119
+ const result = await this.convertToHtml(input, options);
120
+ return result?.html ?? null;
121
+ }
122
+ #isValidFormat(fileName) {
123
+ const lowerCaseName = fileName.toLowerCase();
124
+ return this.#VALID_EXTENSIONS.some(ext => lowerCaseName.endsWith(ext));
125
+ }
126
+ #fileToArrayBuffer(file) {
127
+ return new Promise((resolve, reject) => {
128
+ const reader = new FileReader();
129
+ reader.onload = e => {
130
+ const result = e.target?.result;
131
+ if (result) {
132
+ resolve(result);
133
+ }
134
+ else {
135
+ reject(new Error('Failed to read file'));
136
+ }
137
+ };
138
+ reader.onerror = () => reject(reader.error);
139
+ reader.readAsArrayBuffer(file);
140
+ });
141
+ }
142
+ #blobToArrayBuffer(blob) {
143
+ return new Promise((resolve, reject) => {
144
+ const reader = new FileReader();
145
+ reader.onload = e => {
146
+ const result = e.target?.result;
147
+ if (result) {
148
+ resolve(result);
149
+ }
150
+ else {
151
+ reject(new Error('Failed to read blob'));
152
+ }
153
+ };
154
+ reader.onerror = () => reject(reader.error);
155
+ reader.readAsArrayBuffer(blob);
156
+ });
157
+ }
158
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdDocxService, deps: [{ token: i1.SdNotifyService }], target: i0.ɵɵFactoryTarget.Injectable });
159
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdDocxService, providedIn: 'root' });
160
+ }
161
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdDocxService, decorators: [{
162
+ type: Injectable,
163
+ args: [{
164
+ providedIn: 'root',
165
+ }]
166
+ }], ctorParameters: () => [{ type: i1.SdNotifyService }] });
167
+
168
+ /**
169
+ * Generated bundle index. Do not edit.
170
+ */
171
+
172
+ export { SdDocxService };
173
+ //# sourceMappingURL=sd-angular-core-services-docx.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sd-angular-core-services-docx.mjs","sources":["../../../projects/sd-angular/services/docx/src/lib/docx.service.ts","../../../projects/sd-angular/services/docx/sd-angular-core-services-docx.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport * as mammoth from 'mammoth';\r\nimport { docxToHtml } from '@omer-go/docx-parser-converter-ts';\r\nimport { SdDocxConvertOptions, SdDocxConvertResult } from './docx.model';\r\nimport { SdNotifyService } from '@sd-angular/core/services/notify';\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class SdDocxService {\r\n readonly #DEFAULT_MAX_SIZE_MB = 50;\r\n readonly #VALID_EXTENSIONS = ['.doc', '.docx'];\r\n\r\n readonly #ERROR_INVALID_FORMAT = 'Định dạng không hợp lệ. Vui lòng chọn Mẫu có định dạng DOC hoặc DOCX';\r\n readonly #ERROR_SIZE_EXCEEDED = 'Kích thước tệp mẫu vượt quá tiêu chuẩn hỗ trợ của hệ thống. Vui lòng thử lại';\r\n\r\n #fileInput: HTMLInputElement | null = null;\r\n\r\n constructor(private notifyService: SdNotifyService) {}\r\n\r\n async open(options?: SdDocxConvertOptions): Promise<SdDocxConvertResult | null> {\r\n return new Promise(resolve => {\r\n this.#createFileInput();\r\n if (!this.#fileInput) {\r\n resolve(null);\r\n return;\r\n }\r\n\r\n const handleChange = async (event: Event) => {\r\n const input = event.target as HTMLInputElement;\r\n const file = input.files?.[0];\r\n\r\n if (!file) {\r\n resolve(null);\r\n return;\r\n }\r\n\r\n const result = await this.convertToHtml(file, options);\r\n resolve(result);\r\n\r\n // Cleanup\r\n input.value = '';\r\n input.removeEventListener('change', handleChange);\r\n };\r\n\r\n this.#fileInput.addEventListener('change', handleChange, { once: true });\r\n this.#fileInput.click();\r\n });\r\n }\r\n\r\n #createFileInput(): void {\r\n if (this.#fileInput) {\r\n return;\r\n }\r\n\r\n this.#fileInput = document.createElement('input');\r\n this.#fileInput.type = 'file';\r\n this.#fileInput.accept = '.doc,.docx';\r\n this.#fileInput.style.display = 'none';\r\n document.body.appendChild(this.#fileInput);\r\n }\r\n\r\n async convertToHtml(input: File | Blob | ArrayBuffer, options?: SdDocxConvertOptions): Promise<SdDocxConvertResult | null> {\r\n const opts = {\r\n validateFormat: true,\r\n validateSize: true,\r\n maxSizeInMb: this.#DEFAULT_MAX_SIZE_MB,\r\n ...options,\r\n };\r\n\r\n try {\r\n let fileName: string | undefined;\r\n let fileSize: number | undefined;\r\n let arrayBuffer: ArrayBuffer;\r\n\r\n if (input instanceof File) {\r\n fileName = input.name;\r\n fileSize = input.size;\r\n arrayBuffer = await this.#fileToArrayBuffer(input);\r\n } else if (input instanceof Blob) {\r\n fileSize = input.size;\r\n arrayBuffer = await this.#blobToArrayBuffer(input);\r\n } else {\r\n arrayBuffer = input;\r\n }\r\n\r\n if (opts.validateFormat && fileName) {\r\n if (!this.#isValidFormat(fileName)) {\r\n this.notifyService.error(this.#ERROR_INVALID_FORMAT);\r\n return null;\r\n }\r\n }\r\n\r\n if (opts.validateSize && fileSize !== undefined) {\r\n const maxSizeInBytes = opts.maxSizeInMb! * 1024 * 1024;\r\n if (fileSize > maxSizeInBytes) {\r\n this.notifyService.error(this.#ERROR_SIZE_EXCEEDED);\r\n return null;\r\n }\r\n }\r\n\r\n const { validateFormat, validateSize, maxSizeInMb, ...conversionOptions } = opts;\r\n\r\n // Try @omer-go first for better formatting, fallback to mammoth on BOM error\r\n let html: string;\r\n let messages: string[] = [];\r\n try {\r\n html = await docxToHtml(arrayBuffer, {\r\n styleMode: 'inline',\r\n useSemanticTags: true,\r\n fragmentOnly: true,\r\n ...conversionOptions,\r\n });\r\n } catch (omerError: any) {\r\n console.log(omerError);\r\n // Fallback to mammoth if @omer-go fails (e.g., BOM issue)\r\n console.warn('@omer-go/docx-parser-converter-ts failed, falling back to mammoth:', omerError?.message);\r\n const result = await mammoth.convertToHtml({ arrayBuffer }, conversionOptions as any);\r\n html = result.value;\r\n messages = result.messages.map(m => m.toString());\r\n }\r\n\r\n return {\r\n html,\r\n messages,\r\n };\r\n } catch (error) {\r\n console.error('DocX conversion error:', error);\r\n this.notifyService.error('Có lỗi xảy ra khi chuyển đổi file DOCX');\r\n return null;\r\n }\r\n }\r\n\r\n async convertToHtmlString(input: File | Blob | ArrayBuffer, options?: SdDocxConvertOptions): Promise<string | null> {\r\n const result = await this.convertToHtml(input, options);\r\n return result?.html ?? null;\r\n }\r\n\r\n #isValidFormat(fileName: string): boolean {\r\n const lowerCaseName = fileName.toLowerCase();\r\n return this.#VALID_EXTENSIONS.some(ext => lowerCaseName.endsWith(ext));\r\n }\r\n\r\n #fileToArrayBuffer(file: File): Promise<ArrayBuffer> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onload = e => {\r\n const result = e.target?.result as ArrayBuffer;\r\n if (result) {\r\n resolve(result);\r\n } else {\r\n reject(new Error('Failed to read file'));\r\n }\r\n };\r\n reader.onerror = () => reject(reader.error);\r\n reader.readAsArrayBuffer(file);\r\n });\r\n }\r\n\r\n #blobToArrayBuffer(blob: Blob): Promise<ArrayBuffer> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onload = e => {\r\n const result = e.target?.result as ArrayBuffer;\r\n if (result) {\r\n resolve(result);\r\n } else {\r\n reject(new Error('Failed to read blob'));\r\n }\r\n };\r\n reader.onerror = () => reject(reader.error);\r\n reader.readAsArrayBuffer(blob);\r\n });\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;MASa,aAAa,CAAA;AASJ,IAAA,aAAA;IARX,oBAAoB,GAAG,EAAE;AACzB,IAAA,iBAAiB,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAErC,qBAAqB,GAAG,sEAAsE;IAC9F,oBAAoB,GAAG,8EAA8E;IAE9G,UAAU,GAA4B,IAAI;AAE1C,IAAA,WAAA,CAAoB,aAA8B,EAAA;QAA9B,IAAA,CAAA,aAAa,GAAb,aAAa;IAAoB;IAErD,MAAM,IAAI,CAAC,OAA8B,EAAA;AACvC,QAAA,OAAO,IAAI,OAAO,CAAC,OAAO,IAAG;YAC3B,IAAI,CAAC,gBAAgB,EAAE;AACvB,YAAA,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;gBACpB,OAAO,CAAC,IAAI,CAAC;gBACb;YACF;AAEA,YAAA,MAAM,YAAY,GAAG,OAAO,KAAY,KAAI;AAC1C,gBAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B;gBAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;gBAE7B,IAAI,CAAC,IAAI,EAAE;oBACT,OAAO,CAAC,IAAI,CAAC;oBACb;gBACF;gBAEA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC;gBACtD,OAAO,CAAC,MAAM,CAAC;;AAGf,gBAAA,KAAK,CAAC,KAAK,GAAG,EAAE;AAChB,gBAAA,KAAK,CAAC,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC;AACnD,YAAA,CAAC;AAED,YAAA,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxE,YAAA,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE;AACzB,QAAA,CAAC,CAAC;IACJ;IAEA,gBAAgB,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB;QACF;QAEA,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC;AACjD,QAAA,IAAI,CAAC,UAAU,CAAC,IAAI,GAAG,MAAM;AAC7B,QAAA,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,YAAY;QACrC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM;QACtC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC;IAC5C;AAEA,IAAA,MAAM,aAAa,CAAC,KAAgC,EAAE,OAA8B,EAAA;AAClF,QAAA,MAAM,IAAI,GAAG;AACX,YAAA,cAAc,EAAE,IAAI;AACpB,YAAA,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE,IAAI,CAAC,oBAAoB;AACtC,YAAA,GAAG,OAAO;SACX;AAED,QAAA,IAAI;AACF,YAAA,IAAI,QAA4B;AAChC,YAAA,IAAI,QAA4B;AAChC,YAAA,IAAI,WAAwB;AAE5B,YAAA,IAAI,KAAK,YAAY,IAAI,EAAE;AACzB,gBAAA,QAAQ,GAAG,KAAK,CAAC,IAAI;AACrB,gBAAA,QAAQ,GAAG,KAAK,CAAC,IAAI;gBACrB,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC;YACpD;AAAO,iBAAA,IAAI,KAAK,YAAY,IAAI,EAAE;AAChC,gBAAA,QAAQ,GAAG,KAAK,CAAC,IAAI;gBACrB,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC;YACpD;iBAAO;gBACL,WAAW,GAAG,KAAK;YACrB;AAEA,YAAA,IAAI,IAAI,CAAC,cAAc,IAAI,QAAQ,EAAE;gBACnC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE;oBAClC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC;AACpD,oBAAA,OAAO,IAAI;gBACb;YACF;YAEA,IAAI,IAAI,CAAC,YAAY,IAAI,QAAQ,KAAK,SAAS,EAAE;gBAC/C,MAAM,cAAc,GAAG,IAAI,CAAC,WAAY,GAAG,IAAI,GAAG,IAAI;AACtD,gBAAA,IAAI,QAAQ,GAAG,cAAc,EAAE;oBAC7B,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC;AACnD,oBAAA,OAAO,IAAI;gBACb;YACF;AAEA,YAAA,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,iBAAiB,EAAE,GAAG,IAAI;;AAGhF,YAAA,IAAI,IAAY;YAChB,IAAI,QAAQ,GAAa,EAAE;AAC3B,YAAA,IAAI;AACF,gBAAA,IAAI,GAAG,MAAM,UAAU,CAAC,WAAW,EAAE;AACnC,oBAAA,SAAS,EAAE,QAAQ;AACnB,oBAAA,eAAe,EAAE,IAAI;AACrB,oBAAA,YAAY,EAAE,IAAI;AAClB,oBAAA,GAAG,iBAAiB;AACrB,iBAAA,CAAC;YACJ;YAAE,OAAO,SAAc,EAAE;AACvB,gBAAA,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;;gBAEtB,OAAO,CAAC,IAAI,CAAC,oEAAoE,EAAE,SAAS,EAAE,OAAO,CAAC;AACtG,gBAAA,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,EAAE,iBAAwB,CAAC;AACrF,gBAAA,IAAI,GAAG,MAAM,CAAC,KAAK;AACnB,gBAAA,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;YACnD;YAEA,OAAO;gBACL,IAAI;gBACJ,QAAQ;aACT;QACH;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC;AAC9C,YAAA,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,wCAAwC,CAAC;AAClE,YAAA,OAAO,IAAI;QACb;IACF;AAEA,IAAA,MAAM,mBAAmB,CAAC,KAAgC,EAAE,OAA8B,EAAA;QACxF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC;AACvD,QAAA,OAAO,MAAM,EAAE,IAAI,IAAI,IAAI;IAC7B;AAEA,IAAA,cAAc,CAAC,QAAgB,EAAA;AAC7B,QAAA,MAAM,aAAa,GAAG,QAAQ,CAAC,WAAW,EAAE;AAC5C,QAAA,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,IAAI,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACxE;AAEA,IAAA,kBAAkB,CAAC,IAAU,EAAA;QAC3B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAI;AACrC,YAAA,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE;AAC/B,YAAA,MAAM,CAAC,MAAM,GAAG,CAAC,IAAG;AAClB,gBAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,MAAqB;gBAC9C,IAAI,MAAM,EAAE;oBACV,OAAO,CAAC,MAAM,CAAC;gBACjB;qBAAO;AACL,oBAAA,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;gBAC1C;AACF,YAAA,CAAC;AACD,YAAA,MAAM,CAAC,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AAC3C,YAAA,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC;AAChC,QAAA,CAAC,CAAC;IACJ;AAEA,IAAA,kBAAkB,CAAC,IAAU,EAAA;QAC3B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,KAAI;AACrC,YAAA,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE;AAC/B,YAAA,MAAM,CAAC,MAAM,GAAG,CAAC,IAAG;AAClB,gBAAA,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,EAAE,MAAqB;gBAC9C,IAAI,MAAM,EAAE;oBACV,OAAO,CAAC,MAAM,CAAC;gBACjB;qBAAO;AACL,oBAAA,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;gBAC1C;AACF,YAAA,CAAC;AACD,YAAA,MAAM,CAAC,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AAC3C,YAAA,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC;AAChC,QAAA,CAAC,CAAC;IACJ;wGApKW,aAAa,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,eAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAb,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,aAAa,cAFZ,MAAM,EAAA,CAAA;;4FAEP,aAAa,EAAA,UAAA,EAAA,CAAA;kBAHzB,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE,MAAM;AACnB,iBAAA;;;ACRD;;AAEG;;;;"}
@@ -74,7 +74,7 @@ class SdToastComponent {
74
74
  return this.isMultiMessage && this.messages.length > this.MAX_SHOW;
75
75
  }
76
76
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdToastComponent, deps: [{ token: SdNotifyService }], target: i0.ɵɵFactoryTarget.Component });
77
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdToastComponent, isStandalone: true, selector: "sd-toast", inputs: { data: "data" }, host: { listeners: { "mouseenter": "pauseTimer()", "mouseleave": "resumeTimer()" }, properties: { "@toastAnimation": "true", "class": "\"bg-white sd-toast\"" } }, ngImport: i0, template: "<div class=\"sd-toast__bar\" [class]=\"'bg-' + data.type\"></div>\r\n\r\n<div class=\"sd-toast__icon\" [class]=\"'text-' + data.type\">\r\n @switch (data.type) {\r\n @case ('success') {\r\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>\r\n }\r\n @case ('info') {\r\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>\r\n }\r\n @case ('warning') {\r\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z\"/></svg>\r\n }\r\n @case ('error') {\r\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>\r\n }\r\n }\r\n</div>\r\n\r\n<div class=\"sd-toast__content\">\r\n <div class=\"sd-toast__header\">\r\n <strong class=\"sd-toast__title\">{{ data.title || (data.type | titlecase) }}</strong>\r\n <button class=\"sd-toast__close\" (click)=\"close()\">\u2715</button>\r\n </div>\r\n\r\n <div class=\"sd-toast__body\">\r\n @if (!isMultiMessage) {\r\n <div [innerHTML]=\"data.message\"></div>\r\n } \r\n @else {\r\n <ul class=\"msg-list\">\r\n @for (msg of displayMessages; track msg) {\r\n <li [innerHTML]=\"'- ' + msg\"></li>\r\n }\r\n </ul>\r\n\r\n @if (hasMore) {\r\n <button type=\"button\" \r\n class=\"toggle-more btn-link\" \r\n [class]=\"'text-' + data.type\" \r\n (click)=\"toggleExpand()\">\r\n {{ isExpanded() ? 'Show less' : 'Show more (' + restCount + ')' }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n\r\n @if (data.actionLabel) {\r\n <div class=\"sd-toast__actions\">\r\n <button class=\"btn-action\" \r\n [class]=\"'bg-' + data.type + '-light text-' + data.type\"\r\n (click)=\"onActionClick()\">\r\n {{ data.actionLabel }}\r\n </button>\r\n </div>\r\n }\r\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}.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: i2.TitleCasePipe, name: "titlecase" }], animations: [
77
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdToastComponent, isStandalone: true, selector: "sd-toast", inputs: { data: "data" }, host: { listeners: { "mouseenter": "pauseTimer()", "mouseleave": "resumeTimer()" }, properties: { "@toastAnimation": "true", "class": "\"bg-white sd-toast\"" } }, ngImport: i0, template: "<div class=\"sd-toast__bar\" [class]=\"'bg-' + data.type\"></div>\r\n\r\n<div class=\"sd-toast__icon\" [class]=\"'text-' + data.type\">\r\n @switch (data.type) {\r\n @case ('success') {\r\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>\r\n }\r\n @case ('info') {\r\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>\r\n }\r\n @case ('warning') {\r\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z\"/></svg>\r\n }\r\n @case ('error') {\r\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>\r\n }\r\n }\r\n</div>\r\n\r\n<div class=\"sd-toast__content\">\r\n <div class=\"sd-toast__header\">\r\n <strong class=\"sd-toast__title\">{{ data.title || (data.type | titlecase) }}</strong>\r\n <button class=\"sd-toast__close\" (click)=\"close()\">\u2715</button>\r\n </div>\r\n\r\n <div class=\"sd-toast__body\">\r\n @if (!isMultiMessage) {\r\n <div [innerHTML]=\"data.message\"></div>\r\n } \r\n @else {\r\n <ul class=\"msg-list\">\r\n @for (msg of displayMessages; track msg) {\r\n <li [innerHTML]=\"'- ' + msg\"></li>\r\n }\r\n </ul>\r\n\r\n @if (hasMore) {\r\n <button type=\"button\" \r\n class=\"toggle-more btn-link\" \r\n [class]=\"'text-' + data.type\" \r\n (click)=\"toggleExpand()\">\r\n {{ isExpanded() ? 'Show less' : 'Show more (' + restCount + ')' }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n\r\n @if (data.actionLabel) {\r\n <div class=\"sd-toast__actions\">\r\n <button class=\"btn-action\" \r\n [class]=\"'bg-' + data.type + '-light text-' + data.type\"\r\n (click)=\"onActionClick()\">\r\n {{ data.actionLabel }}\r\n </button>\r\n </div>\r\n }\r\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: i2.TitleCasePipe, name: "titlecase" }], animations: [
78
78
  trigger('toastAnimation', [
79
79
  transition(':enter', [
80
80
  style({ transform: 'translateX(100%)', opacity: 0 }),
@@ -101,7 +101,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImpo
101
101
  ], host: {
102
102
  '[@toastAnimation]': 'true',
103
103
  '[class]': '"bg-white sd-toast"'
104
- }, template: "<div class=\"sd-toast__bar\" [class]=\"'bg-' + data.type\"></div>\r\n\r\n<div class=\"sd-toast__icon\" [class]=\"'text-' + data.type\">\r\n @switch (data.type) {\r\n @case ('success') {\r\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>\r\n }\r\n @case ('info') {\r\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>\r\n }\r\n @case ('warning') {\r\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z\"/></svg>\r\n }\r\n @case ('error') {\r\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>\r\n }\r\n }\r\n</div>\r\n\r\n<div class=\"sd-toast__content\">\r\n <div class=\"sd-toast__header\">\r\n <strong class=\"sd-toast__title\">{{ data.title || (data.type | titlecase) }}</strong>\r\n <button class=\"sd-toast__close\" (click)=\"close()\">\u2715</button>\r\n </div>\r\n\r\n <div class=\"sd-toast__body\">\r\n @if (!isMultiMessage) {\r\n <div [innerHTML]=\"data.message\"></div>\r\n } \r\n @else {\r\n <ul class=\"msg-list\">\r\n @for (msg of displayMessages; track msg) {\r\n <li [innerHTML]=\"'- ' + msg\"></li>\r\n }\r\n </ul>\r\n\r\n @if (hasMore) {\r\n <button type=\"button\" \r\n class=\"toggle-more btn-link\" \r\n [class]=\"'text-' + data.type\" \r\n (click)=\"toggleExpand()\">\r\n {{ isExpanded() ? 'Show less' : 'Show more (' + restCount + ')' }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n\r\n @if (data.actionLabel) {\r\n <div class=\"sd-toast__actions\">\r\n <button class=\"btn-action\" \r\n [class]=\"'bg-' + data.type + '-light text-' + data.type\"\r\n (click)=\"onActionClick()\">\r\n {{ data.actionLabel }}\r\n </button>\r\n </div>\r\n }\r\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}.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"] }]
104
+ }, template: "<div class=\"sd-toast__bar\" [class]=\"'bg-' + data.type\"></div>\r\n\r\n<div class=\"sd-toast__icon\" [class]=\"'text-' + data.type\">\r\n @switch (data.type) {\r\n @case ('success') {\r\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>\r\n }\r\n @case ('info') {\r\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>\r\n }\r\n @case ('warning') {\r\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z\"/></svg>\r\n }\r\n @case ('error') {\r\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>\r\n }\r\n }\r\n</div>\r\n\r\n<div class=\"sd-toast__content\">\r\n <div class=\"sd-toast__header\">\r\n <strong class=\"sd-toast__title\">{{ data.title || (data.type | titlecase) }}</strong>\r\n <button class=\"sd-toast__close\" (click)=\"close()\">\u2715</button>\r\n </div>\r\n\r\n <div class=\"sd-toast__body\">\r\n @if (!isMultiMessage) {\r\n <div [innerHTML]=\"data.message\"></div>\r\n } \r\n @else {\r\n <ul class=\"msg-list\">\r\n @for (msg of displayMessages; track msg) {\r\n <li [innerHTML]=\"'- ' + msg\"></li>\r\n }\r\n </ul>\r\n\r\n @if (hasMore) {\r\n <button type=\"button\" \r\n class=\"toggle-more btn-link\" \r\n [class]=\"'text-' + data.type\" \r\n (click)=\"toggleExpand()\">\r\n {{ isExpanded() ? 'Show less' : 'Show more (' + restCount + ')' }}\r\n </button>\r\n }\r\n }\r\n </div>\r\n\r\n @if (data.actionLabel) {\r\n <div class=\"sd-toast__actions\">\r\n <button class=\"btn-action\" \r\n [class]=\"'bg-' + data.type + '-light text-' + data.type\"\r\n (click)=\"onActionClick()\">\r\n {{ data.actionLabel }}\r\n </button>\r\n </div>\r\n }\r\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"] }]
105
105
  }], ctorParameters: () => [{ type: SdNotifyService }], propDecorators: { data: [{
106
106
  type: Input,
107
107
  args: [{ required: true }]