@sdcorejs/angular 21.1.6 → 21.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/README.md +10 -0
  2. package/assets/scss/core/menu.scss +18 -0
  3. package/assets/scss/core/utilities/_misc.scss +15 -0
  4. package/assets/scss/sd-core.scss +1 -0
  5. package/fesm2022/sdcorejs-angular-components-anchor.mjs +37 -13
  6. package/fesm2022/sdcorejs-angular-components-anchor.mjs.map +1 -1
  7. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs +2 -2
  8. package/fesm2022/sdcorejs-angular-components-autoid-inspector.mjs.map +1 -1
  9. package/fesm2022/sdcorejs-angular-components-badge.mjs +15 -2
  10. package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
  11. package/fesm2022/sdcorejs-angular-components-button.mjs +2 -2
  12. package/fesm2022/sdcorejs-angular-components-button.mjs.map +1 -1
  13. package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs +1 -1
  14. package/fesm2022/sdcorejs-angular-components-ckeditor-styles.mjs.map +1 -1
  15. package/fesm2022/sdcorejs-angular-components-code-editor.mjs +3 -3
  16. package/fesm2022/sdcorejs-angular-components-code-editor.mjs.map +1 -1
  17. package/fesm2022/sdcorejs-angular-components-data-state.mjs +3 -3
  18. package/fesm2022/sdcorejs-angular-components-data-state.mjs.map +1 -1
  19. package/fesm2022/sdcorejs-angular-components-editor.mjs +2 -2
  20. package/fesm2022/sdcorejs-angular-components-editor.mjs.map +1 -1
  21. package/fesm2022/sdcorejs-angular-components-form-generic.mjs +324 -192
  22. package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
  23. package/fesm2022/sdcorejs-angular-components-history.mjs +4 -4
  24. package/fesm2022/sdcorejs-angular-components-history.mjs.map +1 -1
  25. package/fesm2022/sdcorejs-angular-components-import-excel.mjs +13 -5
  26. package/fesm2022/sdcorejs-angular-components-import-excel.mjs.map +1 -1
  27. package/fesm2022/sdcorejs-angular-components-inform.mjs +3 -3
  28. package/fesm2022/sdcorejs-angular-components-inform.mjs.map +1 -1
  29. package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs +164 -8
  30. package/fesm2022/sdcorejs-angular-components-modal-resizable.mjs.map +1 -1
  31. package/fesm2022/sdcorejs-angular-components-modal.mjs +30 -18
  32. package/fesm2022/sdcorejs-angular-components-modal.mjs.map +1 -1
  33. package/fesm2022/sdcorejs-angular-components-org-chart.mjs +60 -13
  34. package/fesm2022/sdcorejs-angular-components-org-chart.mjs.map +1 -1
  35. package/fesm2022/sdcorejs-angular-components-preview.mjs +27 -17
  36. package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
  37. package/fesm2022/sdcorejs-angular-components-query-bar.mjs +192 -30
  38. package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
  39. package/fesm2022/sdcorejs-angular-components-query-builder.mjs +187 -127
  40. package/fesm2022/sdcorejs-angular-components-query-builder.mjs.map +1 -1
  41. package/fesm2022/sdcorejs-angular-components-section.mjs +16 -2
  42. package/fesm2022/sdcorejs-angular-components-section.mjs.map +1 -1
  43. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +83 -24
  44. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
  45. package/fesm2022/sdcorejs-angular-components-splitter.mjs +57 -21
  46. package/fesm2022/sdcorejs-angular-components-splitter.mjs.map +1 -1
  47. package/fesm2022/sdcorejs-angular-components-stepper.mjs +2 -2
  48. package/fesm2022/sdcorejs-angular-components-stepper.mjs.map +1 -1
  49. package/fesm2022/sdcorejs-angular-components-tab-router.mjs +68 -20
  50. package/fesm2022/sdcorejs-angular-components-tab-router.mjs.map +1 -1
  51. package/fesm2022/sdcorejs-angular-components-tab.mjs +3 -2
  52. package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
  53. package/fesm2022/sdcorejs-angular-components-table.mjs +542 -255
  54. package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
  55. package/fesm2022/sdcorejs-angular-components-tree.mjs +80 -17
  56. package/fesm2022/sdcorejs-angular-components-tree.mjs.map +1 -1
  57. package/fesm2022/sdcorejs-angular-components-upload-file.mjs +48 -13
  58. package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
  59. package/fesm2022/sdcorejs-angular-components.mjs +6 -1
  60. package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
  61. package/fesm2022/sdcorejs-angular-configurations.mjs.map +1 -1
  62. package/fesm2022/sdcorejs-angular-directives.mjs +45 -8
  63. package/fesm2022/sdcorejs-angular-directives.mjs.map +1 -1
  64. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +40 -29
  65. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
  66. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +5 -5
  67. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
  68. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +67 -50
  69. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
  70. package/fesm2022/sdcorejs-angular-forms-chip.mjs +57 -43
  71. package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
  72. package/fesm2022/sdcorejs-angular-forms-date-range.mjs +232 -61
  73. package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
  74. package/fesm2022/sdcorejs-angular-forms-date.mjs +96 -24
  75. package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
  76. package/fesm2022/sdcorejs-angular-forms-datetime.mjs +131 -27
  77. package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
  78. package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs +40 -16
  79. package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs.map +1 -1
  80. package/fesm2022/sdcorejs-angular-forms-input-color.mjs +16 -5
  81. package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
  82. package/fesm2022/sdcorejs-angular-forms-input-number.mjs +24 -9
  83. package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
  84. package/fesm2022/sdcorejs-angular-forms-input.mjs +58 -10
  85. package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
  86. package/fesm2022/sdcorejs-angular-forms-models.mjs +227 -6
  87. package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
  88. package/fesm2022/sdcorejs-angular-forms-radio.mjs +4 -4
  89. package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
  90. package/fesm2022/sdcorejs-angular-forms-select.mjs +136 -38
  91. package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
  92. package/fesm2022/sdcorejs-angular-forms-switch.mjs +18 -3
  93. package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
  94. package/fesm2022/sdcorejs-angular-forms-textarea.mjs +51 -62
  95. package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
  96. package/fesm2022/sdcorejs-angular-forms-time-range.mjs +57 -12
  97. package/fesm2022/sdcorejs-angular-forms-time-range.mjs.map +1 -1
  98. package/fesm2022/sdcorejs-angular-forms-time.mjs +16 -5
  99. package/fesm2022/sdcorejs-angular-forms-time.mjs.map +1 -1
  100. package/fesm2022/sdcorejs-angular-forms-tree-select.mjs +100 -9
  101. package/fesm2022/sdcorejs-angular-forms-tree-select.mjs.map +1 -1
  102. package/fesm2022/sdcorejs-angular-forms.mjs +91 -46
  103. package/fesm2022/sdcorejs-angular-forms.mjs.map +1 -1
  104. package/fesm2022/sdcorejs-angular-handlers.mjs +18 -3
  105. package/fesm2022/sdcorejs-angular-handlers.mjs.map +1 -1
  106. package/fesm2022/sdcorejs-angular-i18n.mjs +490 -68
  107. package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
  108. package/fesm2022/sdcorejs-angular-interceptors.mjs +87 -29
  109. package/fesm2022/sdcorejs-angular-interceptors.mjs.map +1 -1
  110. package/fesm2022/sdcorejs-angular-modules-auth.mjs +25 -15
  111. package/fesm2022/sdcorejs-angular-modules-auth.mjs.map +1 -1
  112. package/fesm2022/sdcorejs-angular-modules-icon.mjs +2 -2
  113. package/fesm2022/sdcorejs-angular-modules-icon.mjs.map +1 -1
  114. package/fesm2022/sdcorejs-angular-modules-keycloak.mjs +32 -3
  115. package/fesm2022/sdcorejs-angular-modules-keycloak.mjs.map +1 -1
  116. package/fesm2022/sdcorejs-angular-modules-layout.mjs +332 -111
  117. package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
  118. package/fesm2022/sdcorejs-angular-modules-permission.mjs +177 -40
  119. package/fesm2022/sdcorejs-angular-modules-permission.mjs.map +1 -1
  120. package/fesm2022/sdcorejs-angular-pipes.mjs +62 -28
  121. package/fesm2022/sdcorejs-angular-pipes.mjs.map +1 -1
  122. package/fesm2022/sdcorejs-angular-services-api.mjs +123 -13
  123. package/fesm2022/sdcorejs-angular-services-api.mjs.map +1 -1
  124. package/fesm2022/sdcorejs-angular-services-cache.mjs +53 -3
  125. package/fesm2022/sdcorejs-angular-services-cache.mjs.map +1 -1
  126. package/fesm2022/sdcorejs-angular-services-confirm.mjs +25 -73
  127. package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
  128. package/fesm2022/sdcorejs-angular-services-excel.mjs +12 -10
  129. package/fesm2022/sdcorejs-angular-services-excel.mjs.map +1 -1
  130. package/fesm2022/sdcorejs-angular-services-loading.mjs +75 -84
  131. package/fesm2022/sdcorejs-angular-services-loading.mjs.map +1 -1
  132. package/fesm2022/sdcorejs-angular-services-notify.mjs +46 -5
  133. package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
  134. package/fesm2022/sdcorejs-angular-services-storage.mjs +4 -0
  135. package/fesm2022/sdcorejs-angular-services-storage.mjs.map +1 -1
  136. package/fesm2022/sdcorejs-angular-services.mjs +0 -1
  137. package/fesm2022/sdcorejs-angular-services.mjs.map +1 -1
  138. package/fesm2022/sdcorejs-angular-utilities-extensions.mjs +225 -80
  139. package/fesm2022/sdcorejs-angular-utilities-extensions.mjs.map +1 -1
  140. package/fesm2022/sdcorejs-angular-utilities-models.mjs +1 -63
  141. package/fesm2022/sdcorejs-angular-utilities-models.mjs.map +1 -1
  142. package/fesm2022/sdcorejs-angular.mjs +17 -10
  143. package/fesm2022/sdcorejs-angular.mjs.map +1 -1
  144. package/package.json +32 -25
  145. package/types/sdcorejs-angular-components-anchor.d.ts +3 -1
  146. package/types/sdcorejs-angular-components-badge.d.ts +1 -0
  147. package/types/sdcorejs-angular-components-ckeditor-styles.d.ts +1 -1
  148. package/types/sdcorejs-angular-components-form-generic.d.ts +44 -33
  149. package/types/sdcorejs-angular-components-import-excel.d.ts +1 -0
  150. package/types/sdcorejs-angular-components-mini-editor.d.ts +1 -1
  151. package/types/sdcorejs-angular-components-modal-resizable.d.ts +92 -0
  152. package/types/sdcorejs-angular-components-modal.d.ts +3 -2
  153. package/types/sdcorejs-angular-components-org-chart.d.ts +6 -0
  154. package/types/sdcorejs-angular-components-preview.d.ts +1 -0
  155. package/types/sdcorejs-angular-components-query-bar.d.ts +55 -17
  156. package/types/sdcorejs-angular-components-query-builder.d.ts +150 -98
  157. package/types/sdcorejs-angular-components-section.d.ts +3 -0
  158. package/types/sdcorejs-angular-components-tab-router.d.ts +19 -19
  159. package/types/sdcorejs-angular-components-table.d.ts +251 -109
  160. package/types/sdcorejs-angular-components-tree.d.ts +48 -30
  161. package/types/sdcorejs-angular-components-upload-file.d.ts +6 -3
  162. package/types/sdcorejs-angular-components.d.ts +6 -1
  163. package/types/sdcorejs-angular-configurations.d.ts +1 -2
  164. package/types/sdcorejs-angular-forms-autocomplete.d.ts +5 -2
  165. package/types/sdcorejs-angular-forms-chip-calendar.d.ts +10 -0
  166. package/types/sdcorejs-angular-forms-date-range.d.ts +14 -2
  167. package/types/sdcorejs-angular-forms-date.d.ts +13 -2
  168. package/types/sdcorejs-angular-forms-datetime.d.ts +13 -2
  169. package/types/sdcorejs-angular-forms-entity-picker.d.ts +9 -3
  170. package/types/sdcorejs-angular-forms-input-color.d.ts +4 -0
  171. package/types/sdcorejs-angular-forms-input-number.d.ts +3 -0
  172. package/types/sdcorejs-angular-forms-input.d.ts +3 -0
  173. package/types/sdcorejs-angular-forms-models.d.ts +119 -4
  174. package/types/sdcorejs-angular-forms-select.d.ts +27 -4
  175. package/types/sdcorejs-angular-forms-switch.d.ts +7 -1
  176. package/types/sdcorejs-angular-forms-textarea.d.ts +5 -3
  177. package/types/sdcorejs-angular-forms-time-range.d.ts +22 -1
  178. package/types/sdcorejs-angular-forms-tree-select.d.ts +36 -5
  179. package/types/sdcorejs-angular-forms.d.ts +22 -13
  180. package/types/sdcorejs-angular-i18n.d.ts +95 -16
  181. package/types/sdcorejs-angular-interceptors.d.ts +13 -3
  182. package/types/sdcorejs-angular-modules-auth.d.ts +1 -1
  183. package/types/sdcorejs-angular-modules-keycloak.d.ts +1 -0
  184. package/types/sdcorejs-angular-modules-layout.d.ts +94 -28
  185. package/types/sdcorejs-angular-modules-permission.d.ts +66 -4
  186. package/types/sdcorejs-angular-pipes.d.ts +27 -5
  187. package/types/sdcorejs-angular-services-api.d.ts +21 -1
  188. package/types/sdcorejs-angular-services-cache.d.ts +11 -1
  189. package/types/sdcorejs-angular-services-notify.d.ts +1 -1
  190. package/types/sdcorejs-angular-services.d.ts +0 -1
  191. package/types/sdcorejs-angular-utilities-extensions.d.ts +83 -61
  192. package/types/sdcorejs-angular-utilities-models.d.ts +2 -76
  193. package/types/sdcorejs-angular.d.ts +11 -2
  194. package/fesm2022/sdcorejs-angular-components-base.mjs +0 -23
  195. package/fesm2022/sdcorejs-angular-components-base.mjs.map +0 -1
  196. package/fesm2022/sdcorejs-angular-components-document-builder.mjs +0 -5038
  197. package/fesm2022/sdcorejs-angular-components-document-builder.mjs.map +0 -1
  198. package/fesm2022/sdcorejs-angular-models.mjs +0 -6
  199. package/fesm2022/sdcorejs-angular-models.mjs.map +0 -1
  200. package/fesm2022/sdcorejs-angular-services-docx.mjs +0 -291
  201. package/fesm2022/sdcorejs-angular-services-docx.mjs.map +0 -1
  202. package/fesm2022/sdcorejs-angular-services-license.mjs +0 -97
  203. package/fesm2022/sdcorejs-angular-services-license.mjs.map +0 -1
  204. package/types/sdcorejs-angular-components-base.d.ts +0 -11
  205. package/types/sdcorejs-angular-components-document-builder.d.ts +0 -252
  206. package/types/sdcorejs-angular-models.d.ts +0 -2
  207. package/types/sdcorejs-angular-services-docx.d.ts +0 -27
  208. package/types/sdcorejs-angular-services-license.d.ts +0 -12
package/README.md CHANGED
@@ -21,6 +21,16 @@ Install the package major that matches your Angular application.
21
21
 
22
22
  The package manifests accept Angular 19–21 peers, while releases provide an Angular-aligned package line for each major. The first version number is reserved for Angular compatibility, so read the [changelog](https://github.com/sdcorejs/sdcorejs-angular/blob/main/CHANGELOG.md) for explicitly labeled breaking changes before upgrading.
23
23
 
24
+ ### Peer dependencies
25
+
26
+ The package declares these peers. A standard Angular CLI application already provides all of them except `@angular/material` and `@angular/material-date-fns-adapter`, which is why only those two appear in the install commands above.
27
+
28
+ | Peer | Range |
29
+ | --- | --- |
30
+ | `@angular/animations` · `@angular/cdk` · `@angular/common` · `@angular/core` · `@angular/forms` · `@angular/platform-browser` · `@angular/router` | `^19.0.0 \|\| ^20.0.0 \|\| ^21.0.0` |
31
+ | `@angular/material` · `@angular/material-date-fns-adapter` | `^19.0.0 \|\| ^20.0.0 \|\| ^21.0.0` |
32
+ | `rxjs` | `^7.8.0` |
33
+
24
34
  ## Installation and setup
25
35
 
26
36
  The examples below use Angular 19; replace `19` with your application's Angular major.
@@ -0,0 +1,18 @@
1
+ // why: Material tạo khoảng cách giữa leading icon và nhãn của menu item bằng `margin-right` đặt trên
2
+ // `.mat-icon`. Với `<sd-icon>` thì `.mat-icon` nằm BÊN TRONG host, nên margin đó không đẩy nhãn ra —
3
+ // nó chỉ làm glyph lệch và bị xén trong host (sd-icon đã trung hoà margin đó ở cấp component). Rule
4
+ // dưới đây trả khoảng cách về đúng cấp: host `<sd-icon>` khi nó là icon dẫn đầu của menu item.
5
+ //
6
+ // Đặt ở cấp host nên Material font icon và Lucide SVG hành xử giống hệt nhau — Lucide không render
7
+ // `.mat-icon` nên trước đây không nhận được khoảng cách nào từ Material.
8
+ //
9
+ // Chỉ nhắm con TRỰC TIẾP: menu tự bọc icon trong wrapper flex có `gap` riêng (sd-table command,
10
+ // sd-tree command) không được cộng thêm margin. Angular slot nội dung không phải `mat-icon` vào
11
+ // trong `.mat-mdc-menu-item-text`, nên phải liệt kê cả hai cấp.
12
+ //
13
+ // Bọc trong `:where()` để specificity bằng 0: bất kỳ rule nào của menu cụ thể — kể cả một class đơn —
14
+ // cũng thắng, nên đây là default an toàn chứ không phải thứ phải đi vá bằng `!important`.
15
+ :where(.mat-mdc-menu-item > sd-icon:first-child),
16
+ :where(.mat-mdc-menu-item > .mat-mdc-menu-item-text > sd-icon:first-child) {
17
+ margin-right: var(--mat-menu-item-spacing, 12px);
18
+ }
@@ -18,3 +18,18 @@
18
18
  // --------------------------------------------------------------------------
19
19
  .visible { visibility: visible !important; }
20
20
  .invisible { visibility: hidden !important; }
21
+
22
+ // --------------------------------------------------------------------------
23
+ // Screen-reader-only text (visually hidden, still in the accessibility tree)
24
+ // --------------------------------------------------------------------------
25
+ .sd-visually-hidden {
26
+ position: absolute !important;
27
+ width: 1px !important;
28
+ height: 1px !important;
29
+ padding: 0 !important;
30
+ margin: -1px !important;
31
+ overflow: hidden !important;
32
+ clip: rect(0, 0, 0, 0) !important;
33
+ white-space: nowrap !important;
34
+ border: 0 !important;
35
+ }
@@ -4,6 +4,7 @@
4
4
  @use './core/color.scss';
5
5
  @use './core/form.scss';
6
6
  @use './core/image.scss';
7
+ @use './core/menu.scss';
7
8
  @use './core/scrollbar.scss';
8
9
  @use './themes/default.scss';
9
10
  @use './themes/material-theme.scss';
@@ -2,7 +2,8 @@ import * as i1 from '@angular/common';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
4
  import { input, inject, ElementRef, effect, Component, computed, output, ChangeDetectionStrategy, viewChild, contentChildren, booleanAttribute, signal, afterNextRender, untracked } from '@angular/core';
5
- import { Utilities, BrowserUtilities } from '@sdcorejs/utils/fns';
5
+ import { Utilities } from '@sdcorejs/utils/fns';
6
+ import { SdViewportService } from '@sdcorejs/angular/services/viewport';
6
7
  import { Subject, Subscription, debounceTime, fromEvent, take } from 'rxjs';
7
8
  import { SdIcon } from '@sdcorejs/angular/modules/icon';
8
9
 
@@ -36,7 +37,7 @@ class AnchorNav {
36
37
  // autoId được forward từ <sd-anchor>. Derive per-item autoId theo `key` của item (nếu có).
37
38
  parentAutoId = input(undefined, ...(ngDevMode ? [{ debugName: "parentAutoId" }] : /* istanbul ignore next */ []));
38
39
  color = input('primary', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
39
- // CSS var binding cho active state — map SdColor → global token `--sd-{color}`.
40
+ // CSS var binding cho active state — map Color → global token `--sd-{color}`.
40
41
  // SCSS đọc qua `var(--anchor-active-color)` cho border + text + icon.
41
42
  cssActiveVar = computed(() => `var(--sd-${this.color()})`, ...(ngDevMode ? [{ debugName: "cssActiveVar" }] : /* istanbul ignore next */ []));
42
43
  itemAutoId(section) {
@@ -73,11 +74,20 @@ class SdAnchor {
73
74
  sidebarWidth = input('200px', ...(ngDevMode ? [{ debugName: "sidebarWidth" }] : /* istanbul ignore next */ []));
74
75
  ellipsis = input(false, { ...(ngDevMode ? { debugName: "ellipsis" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
75
76
  overScroll = input(false, { ...(ngDevMode ? { debugName: "overScroll" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
76
- // Mobile: mặc định ẩn nav (sidebar TOC chiếm chỗ trên màn hình hẹp).
77
- // Consumer truyền `[hideNav]="false"` để buộc hiển thị trên mobile.
78
- hideNav = input(BrowserUtilities.isMobile(), { ...(ngDevMode ? { debugName: "hideNav" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
77
+ // why: default `BrowserUtilities.isMobile()` đọc UA ngay lúc class được KHỞI TẠO
78
+ // (module evaluation). Trên SSR không có `navigator` nên giá trị server khác client → hydration
79
+ // lệch; hằng số nên resize/xoay máy không bao giờ đánh giá lại. Giờ `hideNav` chỉ còn
80
+ // là cờ ép ẩn thủ công (default false), còn trạng thái mobile lấy từ SdViewportService — signal
81
+ // SSR-safe, tự cập nhật theo breakpoint khi resize.
82
+ hideNav = input(false, { ...(ngDevMode ? { debugName: "hideNav" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
83
+ // why: giữ lại đường thoát cũ (`[hideNav]="false"` để buộc hiện TOC trên mobile) dưới dạng input
84
+ // riêng, vì `hideNav=false` giờ là default nên không còn phân biệt được "không set" và "set false".
85
+ hideNavOnMobile = input(true, { ...(ngDevMode ? { debugName: "hideNavOnMobile" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
79
86
  // Màu highlight active nav (text + icon + vertical bar). Default 'primary'.
80
87
  color = input('primary', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
88
+ #viewport = inject(SdViewportService);
89
+ // Trạng thái ẩn/hiện thực tế của nav: ép ẩn thủ công HOẶC đang ở breakpoint mobile.
90
+ navHidden = computed(() => this.hideNav() || (this.hideNavOnMobile() && this.#viewport.isMobile()), ...(ngDevMode ? [{ debugName: "navHidden" }] : /* istanbul ignore next */ []));
81
91
  activeSectionId = signal('', ...(ngDevMode ? [{ debugName: "activeSectionId" }] : /* istanbul ignore next */ []));
82
92
  #initialized = false;
83
93
  #isClickScrolling = false;
@@ -89,16 +99,19 @@ class SdAnchor {
89
99
  constructor() {
90
100
  afterNextRender(() => {
91
101
  this.#initialized = true;
92
- if (!this.hideNav()) {
102
+ if (!this.navHidden()) {
93
103
  this.#registerIntersectionObserver();
94
104
  }
95
105
  });
96
106
  // Lắng nghe thay đổi sections để đăng ký lại observer cho từng section.
107
+ // why: navHidden() phụ thuộc breakpoint nên effect chạy lại khi viewport đổi — phải
108
+ // disconnect observer lúc nav bị ẩn, nếu không observer treo lại trên DOM đã tháo.
97
109
  effect(() => {
98
110
  this.sections();
99
- if (!this.hideNav() && this.#initialized) {
100
- untracked(() => this.#registerIntersectionObserver());
101
- }
111
+ const hidden = this.navHidden();
112
+ if (!this.#initialized)
113
+ return;
114
+ untracked(() => (hidden ? this.#cleanIntersectionObserver() : this.#registerIntersectionObserver()));
102
115
  });
103
116
  }
104
117
  #registerIntersectionObserver() {
@@ -131,9 +144,20 @@ class SdAnchor {
131
144
  }
132
145
  }, { root: wrapperEl, threshold: 0 });
133
146
  // Đăng ký theo dõi từng section có trong anchor.
134
- for (const section of this.sections()) {
147
+ const sections = this.sections();
148
+ for (const section of sections) {
135
149
  this.#intersectionObserver.observe(section.elementRef.nativeElement);
136
150
  }
151
+ // why: activeSectionId chỉ được ghi bởi callback của IntersectionObserver và bởi
152
+ // scrollSectionByClick — chưa cuộn thì không callback nào ghi, nên TOC mở ra không có mục nào
153
+ // sáng. Cùng lỗi đó tái diễn khi resize mobile→desktop: nav vừa hiện lại đã trắng cho tới khi
154
+ // người dùng cuộn. Seed ngay tại đây (nơi DUY NHẤT observer được dựng) về section đầu tiên.
155
+ // Chỉ seed khi giá trị hiện tại KHÔNG còn trỏ vào section nào đang sống — vừa xử lý '' ban
156
+ // đầu, vừa xử lý section bị gỡ, mà không đạp lên lựa chọn hợp lệ của người dùng.
157
+ const active = this.activeSectionId();
158
+ if (sections.length > 0 && !sections.some(section => section.id === active)) {
159
+ this.activeSectionId.set(sections[0].id);
160
+ }
137
161
  }
138
162
  scrollSectionByClick(idSectionTarget) {
139
163
  this.activeSectionId.set(idSectionTarget);
@@ -177,12 +201,12 @@ class SdAnchor {
177
201
  this.#cleanIntersectionObserver();
178
202
  }
179
203
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdAnchor, deps: [], target: i0.ɵɵFactoryTarget.Component });
180
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SdAnchor, isStandalone: true, selector: "sd-anchor", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, sidebarWidth: { classPropertyName: "sidebarWidth", publicName: "sidebarWidth", isSignal: true, isRequired: false, transformFunction: null }, ellipsis: { classPropertyName: "ellipsis", publicName: "ellipsis", isSignal: true, isRequired: false, transformFunction: null }, overScroll: { classPropertyName: "overScroll", publicName: "overScroll", isSignal: true, isRequired: false, transformFunction: null }, hideNav: { classPropertyName: "hideNav", publicName: "hideNav", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "sections", predicate: SdAnchorItem, isSignal: true }], viewQueries: [{ propertyName: "wrapper", first: true, predicate: ["wrapper"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"c-anchor-vertical\" [ngClass]=\"{ 'c-stop-scroll-propagation': !overScroll() }\" #wrapper>\n <div class=\"c-anchor-content\">\n <ng-content></ng-content>\n </div>\n\n @if (!hideNav()) {\n <div class=\"c-anchor-list\" [style.flex-basis]=\"sidebarWidth()\">\n <anchor-nav\n [sections]=\"sections()\"\n [ellipsis]=\"ellipsis()\"\n [sidebarWidth]=\"sidebarWidth()\"\n [activeSectionId]=\"activeSectionId()\"\n [parentAutoId]=\"autoId()\"\n [color]=\"color()\"\n (clickSection)=\"scrollSectionByClick($event)\">\n </anchor-nav>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.c-anchor-vertical{position:relative;display:flex;height:100%;width:100%;gap:16px;overflow-y:auto}.c-anchor-vertical.c-stop-scroll-propagation{overscroll-behavior:contain}.c-anchor-vertical .c-anchor-content{flex:1 1 auto;min-width:0}.c-anchor-vertical .c-anchor-list{flex:0 0 auto;position:sticky;top:0;right:6px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AnchorNav, selector: "anchor-nav", inputs: ["sections", "activeSectionId", "ellipsis", "sidebarWidth", "parentAutoId", "color"], outputs: ["clickSection"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
204
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SdAnchor, isStandalone: true, selector: "sd-anchor", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, sidebarWidth: { classPropertyName: "sidebarWidth", publicName: "sidebarWidth", isSignal: true, isRequired: false, transformFunction: null }, ellipsis: { classPropertyName: "ellipsis", publicName: "ellipsis", isSignal: true, isRequired: false, transformFunction: null }, overScroll: { classPropertyName: "overScroll", publicName: "overScroll", isSignal: true, isRequired: false, transformFunction: null }, hideNav: { classPropertyName: "hideNav", publicName: "hideNav", isSignal: true, isRequired: false, transformFunction: null }, hideNavOnMobile: { classPropertyName: "hideNavOnMobile", publicName: "hideNavOnMobile", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "sections", predicate: SdAnchorItem, isSignal: true }], viewQueries: [{ propertyName: "wrapper", first: true, predicate: ["wrapper"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"c-anchor-vertical\" [ngClass]=\"{ 'c-stop-scroll-propagation': !overScroll() }\" #wrapper>\n <div class=\"c-anchor-content\">\n <ng-content></ng-content>\n </div>\n\n @if (!navHidden()) {\n <div class=\"c-anchor-list\" [style.flex-basis]=\"sidebarWidth()\">\n <anchor-nav\n [sections]=\"sections()\"\n [ellipsis]=\"ellipsis()\"\n [sidebarWidth]=\"sidebarWidth()\"\n [activeSectionId]=\"activeSectionId()\"\n [parentAutoId]=\"autoId()\"\n [color]=\"color()\"\n (clickSection)=\"scrollSectionByClick($event)\">\n </anchor-nav>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.c-anchor-vertical{position:relative;display:flex;height:100%;width:100%;gap:16px;overflow-y:auto}.c-anchor-vertical.c-stop-scroll-propagation{overscroll-behavior:contain}.c-anchor-vertical .c-anchor-content{flex:1 1 auto;min-width:0}.c-anchor-vertical .c-anchor-list{flex:0 0 auto;position:sticky;top:0;right:6px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: AnchorNav, selector: "anchor-nav", inputs: ["sections", "activeSectionId", "ellipsis", "sidebarWidth", "parentAutoId", "color"], outputs: ["clickSection"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
181
205
  }
182
206
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdAnchor, decorators: [{
183
207
  type: Component,
184
- args: [{ selector: 'sd-anchor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, AnchorNav], standalone: true, template: "<div class=\"c-anchor-vertical\" [ngClass]=\"{ 'c-stop-scroll-propagation': !overScroll() }\" #wrapper>\n <div class=\"c-anchor-content\">\n <ng-content></ng-content>\n </div>\n\n @if (!hideNav()) {\n <div class=\"c-anchor-list\" [style.flex-basis]=\"sidebarWidth()\">\n <anchor-nav\n [sections]=\"sections()\"\n [ellipsis]=\"ellipsis()\"\n [sidebarWidth]=\"sidebarWidth()\"\n [activeSectionId]=\"activeSectionId()\"\n [parentAutoId]=\"autoId()\"\n [color]=\"color()\"\n (clickSection)=\"scrollSectionByClick($event)\">\n </anchor-nav>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.c-anchor-vertical{position:relative;display:flex;height:100%;width:100%;gap:16px;overflow-y:auto}.c-anchor-vertical.c-stop-scroll-propagation{overscroll-behavior:contain}.c-anchor-vertical .c-anchor-content{flex:1 1 auto;min-width:0}.c-anchor-vertical .c-anchor-list{flex:0 0 auto;position:sticky;top:0;right:6px}\n"] }]
185
- }], ctorParameters: () => [], propDecorators: { wrapper: [{ type: i0.ViewChild, args: ['wrapper', { isSignal: true }] }], sections: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SdAnchorItem), { isSignal: true }] }], autoIdInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoId", required: false }] }], sidebarWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarWidth", required: false }] }], ellipsis: [{ type: i0.Input, args: [{ isSignal: true, alias: "ellipsis", required: false }] }], overScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "overScroll", required: false }] }], hideNav: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideNav", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }] } });
208
+ args: [{ selector: 'sd-anchor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, AnchorNav], standalone: true, template: "<div class=\"c-anchor-vertical\" [ngClass]=\"{ 'c-stop-scroll-propagation': !overScroll() }\" #wrapper>\n <div class=\"c-anchor-content\">\n <ng-content></ng-content>\n </div>\n\n @if (!navHidden()) {\n <div class=\"c-anchor-list\" [style.flex-basis]=\"sidebarWidth()\">\n <anchor-nav\n [sections]=\"sections()\"\n [ellipsis]=\"ellipsis()\"\n [sidebarWidth]=\"sidebarWidth()\"\n [activeSectionId]=\"activeSectionId()\"\n [parentAutoId]=\"autoId()\"\n [color]=\"color()\"\n (clickSection)=\"scrollSectionByClick($event)\">\n </anchor-nav>\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";.c-anchor-vertical{position:relative;display:flex;height:100%;width:100%;gap:16px;overflow-y:auto}.c-anchor-vertical.c-stop-scroll-propagation{overscroll-behavior:contain}.c-anchor-vertical .c-anchor-content{flex:1 1 auto;min-width:0}.c-anchor-vertical .c-anchor-list{flex:0 0 auto;position:sticky;top:0;right:6px}\n"] }]
209
+ }], ctorParameters: () => [], propDecorators: { wrapper: [{ type: i0.ViewChild, args: ['wrapper', { isSignal: true }] }], sections: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => SdAnchorItem), { isSignal: true }] }], autoIdInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoId", required: false }] }], sidebarWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarWidth", required: false }] }], ellipsis: [{ type: i0.Input, args: [{ isSignal: true, alias: "ellipsis", required: false }] }], overScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "overScroll", required: false }] }], hideNav: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideNav", required: false }] }], hideNavOnMobile: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideNavOnMobile", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }] } });
186
210
 
187
211
  /**
188
212
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"sdcorejs-angular-components-anchor.mjs","sources":["../../../projects/sdcorejs-angular/components/anchor/src/components/anchor-item/anchor-item.component.ts","../../../projects/sdcorejs-angular/components/anchor/src/components/anchor-item/anchor-item.component.html","../../../projects/sdcorejs-angular/components/anchor/src/components/anchor-nav/anchor-nav.component.ts","../../../projects/sdcorejs-angular/components/anchor/src/components/anchor-nav/anchor-nav.component.html","../../../projects/sdcorejs-angular/components/anchor/src/components/anchor/anchor.component.ts","../../../projects/sdcorejs-angular/components/anchor/src/components/anchor/anchor.component.html","../../../projects/sdcorejs-angular/components/anchor/sdcorejs-angular-components-anchor.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { Component, ElementRef, effect, inject, input } from '@angular/core';\nimport { IAnchorItem } from '../../models';\nimport { Utilities } from '@sdcorejs/utils/fns';\n\n@Component({\n selector: 'sd-anchor-item',\n templateUrl: './anchor-item.component.html',\n styleUrl: './anchor-item.component.scss',\n imports: [CommonModule],\n standalone: true,\n})\nexport class SdAnchorItem implements IAnchorItem {\n title = input.required<string>();\n icon = input<string | undefined>();\n // Stable key dùng cho data-autoId. Nếu không truyền thì fallback về uuid (không stable giữa các lần render).\n key = input<string | undefined>(undefined);\n id: string = Utilities.generateUuid();\n elementRef = inject(ElementRef);\n\n constructor() {\n effect(() => {\n if (this.title()) {\n this.elementRef.nativeElement.removeAttribute('title');\n }\n });\n }\n}\n","<section>\n <ng-content></ng-content>\n</section>\n","import { ChangeDetectionStrategy, Component, OnDestroy, computed, input, output } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Color } from '@sdcorejs/utils/models';\nimport { Subject, Subscription, debounceTime } from 'rxjs';\n\nimport { SdAnchorItem } from '../anchor-item/anchor-item.component';\nimport { SdIcon } from '@sdcorejs/angular/modules/icon';\n\n@Component({\n selector: 'anchor-nav',\n templateUrl: './anchor-nav.component.html',\n styleUrl: './anchor-nav.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SdIcon, CommonModule],\n standalone: true,\n})\nexport class AnchorNav implements OnDestroy {\n sections = input.required<readonly SdAnchorItem[]>();\n activeSectionId = input<string>('');\n ellipsis = input<boolean>(false);\n sidebarWidth = input<string>('');\n // autoId được forward từ <sd-anchor>. Derive per-item autoId theo `key` của item (nếu có).\n parentAutoId = input<string | undefined | null>(undefined);\n color = input<Color>('primary');\n\n // CSS var binding cho active state — map SdColor → global token `--sd-{color}`.\n // SCSS đọc qua `var(--anchor-active-color)` cho border + text + icon.\n cssActiveVar = computed(() => `var(--sd-${this.color()})`);\n\n itemAutoId(section: SdAnchorItem): string | undefined {\n const parent = this.parentAutoId();\n const key = section.key();\n return parent && key ? `${parent}-${key}` : undefined;\n }\n\n clickSection = output<string>();\n\n #delay = 200;\n #clickSectionSubject = new Subject<string>();\n #subscription = new Subscription();\n\n constructor() {\n this.#subscription.add(this.#clickSectionSubject.pipe(debounceTime(this.#delay)).subscribe((id: string) => this.clickSection.emit(id)));\n }\n\n onClickSection = (id: string): void => {\n this.#clickSectionSubject.next(id);\n };\n\n ngOnDestroy(): void {\n this.#subscription.unsubscribe();\n }\n}\n","<div\n class=\"c-anchor-list\"\n [style.width]=\"sidebarWidth()\"\n [style.--anchor-active-color]=\"cssActiveVar()\">\n @for (section of sections(); track section.id) {\n <div\n class=\"c-anchor-list-item\"\n [class.active]=\"section.id === activeSectionId()\"\n (click)=\"onClickSection(section.id)\"\n (keydown.enter)=\"onClickSection(section.id)\"\n [attr.data-autoId]=\"itemAutoId(section)\"\n tabindex=\"0\">\n @if (section.icon()) {\n <sd-icon class=\"c-anchor-list-item-icon\" [name]=\"section.icon()\"></sd-icon>\n }\n <div class=\"c-anchor-list-item-text\" [class.ellipsis]=\"ellipsis()\">\n {{ section.title() }}\n </div>\n </div>\n }\n</div>\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n OnDestroy,\n afterNextRender,\n booleanAttribute,\n computed,\n contentChildren,\n effect,\n input,\n signal,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { BrowserUtilities } from '@sdcorejs/utils/fns';\nimport { Color } from '@sdcorejs/utils/models';\nimport { Subscription, fromEvent, take } from 'rxjs';\nimport { AnchorNav } from '../anchor-nav/anchor-nav.component';\nimport { SdAnchorItem } from '../anchor-item/anchor-item.component';\n\n@Component({\n selector: 'sd-anchor',\n templateUrl: './anchor.component.html',\n styleUrl: './anchor.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CommonModule, AnchorNav],\n standalone: true,\n})\nexport class SdAnchor implements OnDestroy {\n wrapper = viewChild.required<ElementRef>('wrapper');\n sections = contentChildren(SdAnchorItem);\n\n readonly autoIdInput = input<string | undefined | null>(undefined, { alias: 'autoId' });\n readonly autoId = computed(() => (this.autoIdInput() ? `components-anchor-${this.autoIdInput()}` : undefined));\n\n sidebarWidth = input<string>('200px');\n ellipsis = input(false, { transform: booleanAttribute });\n overScroll = input(false, { transform: booleanAttribute });\n // Mobile: mặc định ẩn nav (sidebar TOC chiếm chỗ trên màn hình hẹp).\n // Consumer truyền `[hideNav]=\"false\"` để buộc hiển thị trên mobile.\n hideNav = input(BrowserUtilities.isMobile(), { transform: booleanAttribute });\n // Màu highlight active nav (text + icon + vertical bar). Default 'primary'.\n color = input<Color>('primary');\n\n activeSectionId = signal<string>('');\n\n #initialized = false;\n #isClickScrolling = false;\n #clickScrollSubscription: Subscription | null = null;\n #intersectionObserver: IntersectionObserver | null = null;\n #visibleSections = new Set<Element>();\n #timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n #timeoutScrollFallback = 200;\n\n constructor() {\n afterNextRender(() => {\n this.#initialized = true;\n if (!this.hideNav()) {\n this.#registerIntersectionObserver();\n }\n });\n\n // Lắng nghe thay đổi sections để đăng ký lại observer cho từng section.\n effect(() => {\n this.sections();\n if (!this.hideNav() && this.#initialized) {\n untracked(() => this.#registerIntersectionObserver());\n }\n });\n }\n\n #registerIntersectionObserver(): void {\n this.#cleanIntersectionObserver();\n const wrapperEl = this.wrapper().nativeElement;\n\n // Browser API IntersectionObserver hỗ trợ xác định section đang hiển thị trong wrapperEl.\n this.#intersectionObserver = new IntersectionObserver(\n entries => {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n // Nếu section mới đi vào vùng nhìn thấy thì thêm vào set.\n this.#visibleSections.add(entry.target);\n } else {\n // Nếu section đã đi ra khỏi vùng nhìn thấy thì xóa khỏi set.\n this.#visibleSections.delete(entry.target);\n }\n }\n\n // Nếu đang scroll do click section thì không cần quét section đang active.\n if (this.#isClickScrolling) {\n return;\n }\n\n for (const section of this.sections()) {\n // Kiểm tra DOM của section nào đang nằm trong danh sách nhìn thấy để active chính xác.\n if (this.#visibleSections.has(section.elementRef.nativeElement)) {\n if (this.activeSectionId() !== section.id) {\n this.activeSectionId.set(section.id);\n }\n break;\n }\n }\n },\n { root: wrapperEl, threshold: 0 }\n );\n\n // Đăng ký theo dõi từng section có trong anchor.\n for (const section of this.sections()) {\n this.#intersectionObserver.observe(section.elementRef.nativeElement);\n }\n }\n\n scrollSectionByClick(idSectionTarget: string): void {\n this.activeSectionId.set(idSectionTarget);\n const targetSection = this.sections().find(s => s.id === idSectionTarget)?.elementRef;\n if (!targetSection) {\n return;\n }\n this.#cleanScrollSectionByClickObserver();\n this.#isClickScrolling = true;\n\n const wrapperEl = this.wrapper().nativeElement;\n const targetElement = targetSection.nativeElement;\n\n const prevScrollTop = wrapperEl.scrollTop; // Lưu lại vị trí cuộn hiện tại của container.\n const scrollTop = prevScrollTop + targetElement.getBoundingClientRect().top - wrapperEl.getBoundingClientRect().top; // Vị trí section cần scroll tới.\n\n // Đăng ký sự kiện khi scroll hoàn tất.\n this.#clickScrollSubscription = fromEvent(wrapperEl, 'scrollend')\n .pipe(take(1))\n .subscribe(() => {\n this.#isClickScrolling = false;\n });\n\n // Nếu sectionTarget đã ở đúng vị trí (click nhưng không scroll) thì kích hoạt lại IntersectionObserver sau timeout.\n this.#timeoutId = setTimeout(() => {\n if (wrapperEl.scrollTop === prevScrollTop) {\n this.#isClickScrolling = false;\n this.#clickScrollSubscription?.unsubscribe();\n }\n }, this.#timeoutScrollFallback);\n\n wrapperEl.scrollTo({ top: scrollTop, behavior: 'smooth' });\n }\n\n #cleanScrollSectionByClickObserver = (): void => {\n if (this.#timeoutId) {\n clearTimeout(this.#timeoutId);\n }\n this.#clickScrollSubscription?.unsubscribe();\n };\n\n #cleanIntersectionObserver = (): void => {\n this.#intersectionObserver?.disconnect();\n this.#visibleSections.clear();\n };\n\n ngOnDestroy(): void {\n this.#cleanScrollSectionByClickObserver();\n this.#cleanIntersectionObserver();\n }\n}\n","<div class=\"c-anchor-vertical\" [ngClass]=\"{ 'c-stop-scroll-propagation': !overScroll() }\" #wrapper>\n <div class=\"c-anchor-content\">\n <ng-content></ng-content>\n </div>\n\n @if (!hideNav()) {\n <div class=\"c-anchor-list\" [style.flex-basis]=\"sidebarWidth()\">\n <anchor-nav\n [sections]=\"sections()\"\n [ellipsis]=\"ellipsis()\"\n [sidebarWidth]=\"sidebarWidth()\"\n [activeSectionId]=\"activeSectionId()\"\n [parentAutoId]=\"autoId()\"\n [color]=\"color()\"\n (clickSection)=\"scrollSectionByClick($event)\">\n </anchor-nav>\n </div>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdcorejs-angular-components-anchor.mjs","sources":["../../../projects/sdcorejs-angular/components/anchor/src/components/anchor-item/anchor-item.component.ts","../../../projects/sdcorejs-angular/components/anchor/src/components/anchor-item/anchor-item.component.html","../../../projects/sdcorejs-angular/components/anchor/src/components/anchor-nav/anchor-nav.component.ts","../../../projects/sdcorejs-angular/components/anchor/src/components/anchor-nav/anchor-nav.component.html","../../../projects/sdcorejs-angular/components/anchor/src/components/anchor/anchor.component.ts","../../../projects/sdcorejs-angular/components/anchor/src/components/anchor/anchor.component.html","../../../projects/sdcorejs-angular/components/anchor/sdcorejs-angular-components-anchor.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { Component, ElementRef, effect, inject, input } from '@angular/core';\nimport { IAnchorItem } from '../../models';\nimport { Utilities } from '@sdcorejs/utils/fns';\n\n@Component({\n selector: 'sd-anchor-item',\n templateUrl: './anchor-item.component.html',\n styleUrl: './anchor-item.component.scss',\n imports: [CommonModule],\n standalone: true,\n})\nexport class SdAnchorItem implements IAnchorItem {\n title = input.required<string>();\n icon = input<string | undefined>();\n // Stable key dùng cho data-autoId. Nếu không truyền thì fallback về uuid (không stable giữa các lần render).\n key = input<string | undefined>(undefined);\n id: string = Utilities.generateUuid();\n elementRef = inject(ElementRef);\n\n constructor() {\n effect(() => {\n if (this.title()) {\n this.elementRef.nativeElement.removeAttribute('title');\n }\n });\n }\n}\n","<section>\n <ng-content></ng-content>\n</section>\n","import { ChangeDetectionStrategy, Component, OnDestroy, computed, input, output } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Color } from '@sdcorejs/utils/models';\nimport { Subject, Subscription, debounceTime } from 'rxjs';\n\nimport { SdAnchorItem } from '../anchor-item/anchor-item.component';\nimport { SdIcon } from '@sdcorejs/angular/modules/icon';\n\n@Component({\n selector: 'anchor-nav',\n templateUrl: './anchor-nav.component.html',\n styleUrl: './anchor-nav.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [SdIcon, CommonModule],\n standalone: true,\n})\nexport class AnchorNav implements OnDestroy {\n sections = input.required<readonly SdAnchorItem[]>();\n activeSectionId = input<string>('');\n ellipsis = input<boolean>(false);\n sidebarWidth = input<string>('');\n // autoId được forward từ <sd-anchor>. Derive per-item autoId theo `key` của item (nếu có).\n parentAutoId = input<string | undefined | null>(undefined);\n color = input<Color>('primary');\n\n // CSS var binding cho active state — map Color → global token `--sd-{color}`.\n // SCSS đọc qua `var(--anchor-active-color)` cho border + text + icon.\n cssActiveVar = computed(() => `var(--sd-${this.color()})`);\n\n itemAutoId(section: SdAnchorItem): string | undefined {\n const parent = this.parentAutoId();\n const key = section.key();\n return parent && key ? `${parent}-${key}` : undefined;\n }\n\n clickSection = output<string>();\n\n #delay = 200;\n #clickSectionSubject = new Subject<string>();\n #subscription = new Subscription();\n\n constructor() {\n this.#subscription.add(this.#clickSectionSubject.pipe(debounceTime(this.#delay)).subscribe((id: string) => this.clickSection.emit(id)));\n }\n\n onClickSection = (id: string): void => {\n this.#clickSectionSubject.next(id);\n };\n\n ngOnDestroy(): void {\n this.#subscription.unsubscribe();\n }\n}\n","<div\n class=\"c-anchor-list\"\n [style.width]=\"sidebarWidth()\"\n [style.--anchor-active-color]=\"cssActiveVar()\">\n @for (section of sections(); track section.id) {\n <div\n class=\"c-anchor-list-item\"\n [class.active]=\"section.id === activeSectionId()\"\n (click)=\"onClickSection(section.id)\"\n (keydown.enter)=\"onClickSection(section.id)\"\n [attr.data-autoId]=\"itemAutoId(section)\"\n tabindex=\"0\">\n @if (section.icon()) {\n <sd-icon class=\"c-anchor-list-item-icon\" [name]=\"section.icon()\"></sd-icon>\n }\n <div class=\"c-anchor-list-item-text\" [class.ellipsis]=\"ellipsis()\">\n {{ section.title() }}\n </div>\n </div>\n }\n</div>\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n OnDestroy,\n afterNextRender,\n booleanAttribute,\n computed,\n contentChildren,\n effect,\n inject,\n input,\n signal,\n untracked,\n viewChild,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { Color } from '@sdcorejs/utils/models';\nimport { SdViewportService } from '@sdcorejs/angular/services/viewport';\nimport { Subscription, fromEvent, take } from 'rxjs';\nimport { AnchorNav } from '../anchor-nav/anchor-nav.component';\nimport { SdAnchorItem } from '../anchor-item/anchor-item.component';\n\n@Component({\n selector: 'sd-anchor',\n templateUrl: './anchor.component.html',\n styleUrl: './anchor.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [CommonModule, AnchorNav],\n standalone: true,\n})\nexport class SdAnchor implements OnDestroy {\n wrapper = viewChild.required<ElementRef>('wrapper');\n sections = contentChildren(SdAnchorItem);\n\n readonly autoIdInput = input<string | undefined | null>(undefined, { alias: 'autoId' });\n readonly autoId = computed(() => (this.autoIdInput() ? `components-anchor-${this.autoIdInput()}` : undefined));\n\n sidebarWidth = input<string>('200px');\n ellipsis = input(false, { transform: booleanAttribute });\n overScroll = input(false, { transform: booleanAttribute });\n // why: default cũ là `BrowserUtilities.isMobile()` — đọc UA ngay lúc class được KHỞI TẠO\n // (module evaluation). Trên SSR không có `navigator` nên giá trị server khác client → hydration\n // lệch; và vì là hằng số nên resize/xoay máy không bao giờ đánh giá lại. Giờ `hideNav` chỉ còn\n // là cờ ép ẩn thủ công (default false), còn trạng thái mobile lấy từ SdViewportService — signal\n // SSR-safe, tự cập nhật theo breakpoint khi resize.\n hideNav = input(false, { transform: booleanAttribute });\n // why: giữ lại đường thoát cũ (`[hideNav]=\"false\"` để buộc hiện TOC trên mobile) dưới dạng input\n // riêng, vì `hideNav=false` giờ là default nên không còn phân biệt được \"không set\" và \"set false\".\n hideNavOnMobile = input(true, { transform: booleanAttribute });\n // Màu highlight active nav (text + icon + vertical bar). Default 'primary'.\n color = input<Color>('primary');\n\n readonly #viewport = inject(SdViewportService);\n // Trạng thái ẩn/hiện thực tế của nav: ép ẩn thủ công HOẶC đang ở breakpoint mobile.\n readonly navHidden = computed(() => this.hideNav() || (this.hideNavOnMobile() && this.#viewport.isMobile()));\n\n activeSectionId = signal<string>('');\n\n #initialized = false;\n #isClickScrolling = false;\n #clickScrollSubscription: Subscription | null = null;\n #intersectionObserver: IntersectionObserver | null = null;\n #visibleSections = new Set<Element>();\n #timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n #timeoutScrollFallback = 200;\n\n constructor() {\n afterNextRender(() => {\n this.#initialized = true;\n if (!this.navHidden()) {\n this.#registerIntersectionObserver();\n }\n });\n\n // Lắng nghe thay đổi sections để đăng ký lại observer cho từng section.\n // why: navHidden() phụ thuộc breakpoint nên effect chạy lại khi viewport đổi — phải\n // disconnect observer lúc nav bị ẩn, nếu không observer treo lại trên DOM đã tháo.\n effect(() => {\n this.sections();\n const hidden = this.navHidden();\n if (!this.#initialized) return;\n untracked(() => (hidden ? this.#cleanIntersectionObserver() : this.#registerIntersectionObserver()));\n });\n }\n\n #registerIntersectionObserver(): void {\n this.#cleanIntersectionObserver();\n const wrapperEl = this.wrapper().nativeElement;\n\n // Browser API IntersectionObserver hỗ trợ xác định section đang hiển thị trong wrapperEl.\n this.#intersectionObserver = new IntersectionObserver(\n entries => {\n for (const entry of entries) {\n if (entry.isIntersecting) {\n // Nếu section mới đi vào vùng nhìn thấy thì thêm vào set.\n this.#visibleSections.add(entry.target);\n } else {\n // Nếu section đã đi ra khỏi vùng nhìn thấy thì xóa khỏi set.\n this.#visibleSections.delete(entry.target);\n }\n }\n\n // Nếu đang scroll do click section thì không cần quét section đang active.\n if (this.#isClickScrolling) {\n return;\n }\n\n for (const section of this.sections()) {\n // Kiểm tra DOM của section nào đang nằm trong danh sách nhìn thấy để active chính xác.\n if (this.#visibleSections.has(section.elementRef.nativeElement)) {\n if (this.activeSectionId() !== section.id) {\n this.activeSectionId.set(section.id);\n }\n break;\n }\n }\n },\n { root: wrapperEl, threshold: 0 }\n );\n\n // Đăng ký theo dõi từng section có trong anchor.\n const sections = this.sections();\n for (const section of sections) {\n this.#intersectionObserver.observe(section.elementRef.nativeElement);\n }\n\n // why: activeSectionId chỉ được ghi bởi callback của IntersectionObserver và bởi\n // scrollSectionByClick — chưa cuộn thì không callback nào ghi, nên TOC mở ra không có mục nào\n // sáng. Cùng lỗi đó tái diễn khi resize mobile→desktop: nav vừa hiện lại đã trắng cho tới khi\n // người dùng cuộn. Seed ngay tại đây (nơi DUY NHẤT observer được dựng) về section đầu tiên.\n // Chỉ seed khi giá trị hiện tại KHÔNG còn trỏ vào section nào đang sống — vừa xử lý '' ban\n // đầu, vừa xử lý section bị gỡ, mà không đạp lên lựa chọn hợp lệ của người dùng.\n const active = this.activeSectionId();\n if (sections.length > 0 && !sections.some(section => section.id === active)) {\n this.activeSectionId.set(sections[0].id);\n }\n }\n\n scrollSectionByClick(idSectionTarget: string): void {\n this.activeSectionId.set(idSectionTarget);\n const targetSection = this.sections().find(s => s.id === idSectionTarget)?.elementRef;\n if (!targetSection) {\n return;\n }\n this.#cleanScrollSectionByClickObserver();\n this.#isClickScrolling = true;\n\n const wrapperEl = this.wrapper().nativeElement;\n const targetElement = targetSection.nativeElement;\n\n const prevScrollTop = wrapperEl.scrollTop; // Lưu lại vị trí cuộn hiện tại của container.\n const scrollTop = prevScrollTop + targetElement.getBoundingClientRect().top - wrapperEl.getBoundingClientRect().top; // Vị trí section cần scroll tới.\n\n // Đăng ký sự kiện khi scroll hoàn tất.\n this.#clickScrollSubscription = fromEvent(wrapperEl, 'scrollend')\n .pipe(take(1))\n .subscribe(() => {\n this.#isClickScrolling = false;\n });\n\n // Nếu sectionTarget đã ở đúng vị trí (click nhưng không scroll) thì kích hoạt lại IntersectionObserver sau timeout.\n this.#timeoutId = setTimeout(() => {\n if (wrapperEl.scrollTop === prevScrollTop) {\n this.#isClickScrolling = false;\n this.#clickScrollSubscription?.unsubscribe();\n }\n }, this.#timeoutScrollFallback);\n\n wrapperEl.scrollTo({ top: scrollTop, behavior: 'smooth' });\n }\n\n #cleanScrollSectionByClickObserver = (): void => {\n if (this.#timeoutId) {\n clearTimeout(this.#timeoutId);\n }\n this.#clickScrollSubscription?.unsubscribe();\n };\n\n #cleanIntersectionObserver = (): void => {\n this.#intersectionObserver?.disconnect();\n this.#visibleSections.clear();\n };\n\n ngOnDestroy(): void {\n this.#cleanScrollSectionByClickObserver();\n this.#cleanIntersectionObserver();\n }\n}\n","<div class=\"c-anchor-vertical\" [ngClass]=\"{ 'c-stop-scroll-propagation': !overScroll() }\" #wrapper>\n <div class=\"c-anchor-content\">\n <ng-content></ng-content>\n </div>\n\n @if (!navHidden()) {\n <div class=\"c-anchor-list\" [style.flex-basis]=\"sidebarWidth()\">\n <anchor-nav\n [sections]=\"sections()\"\n [ellipsis]=\"ellipsis()\"\n [sidebarWidth]=\"sidebarWidth()\"\n [activeSectionId]=\"activeSectionId()\"\n [parentAutoId]=\"autoId()\"\n [color]=\"color()\"\n (clickSection)=\"scrollSectionByClick($event)\">\n </anchor-nav>\n </div>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}