@cdevhub/ngx-tw 0.5.0 → 0.6.1

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 (209) hide show
  1. package/README.md +78 -15
  2. package/fesm2022/cdevhub-ngx-tw-accordion.mjs +16 -5
  3. package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -1
  4. package/fesm2022/cdevhub-ngx-tw-avatar.mjs +26 -15
  5. package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -1
  6. package/fesm2022/cdevhub-ngx-tw-badge.mjs +17 -5
  7. package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
  8. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +27 -6
  9. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -1
  10. package/fesm2022/cdevhub-ngx-tw-button.mjs +23 -11
  11. package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
  12. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +5 -5
  13. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -1
  14. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +3 -3
  15. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -1
  16. package/fesm2022/cdevhub-ngx-tw-calendar.mjs +427 -122
  17. package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -1
  18. package/fesm2022/cdevhub-ngx-tw-card.mjs +21 -11
  19. package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
  20. package/fesm2022/cdevhub-ngx-tw-carousel.mjs +215 -96
  21. package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -1
  22. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +108 -64
  23. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
  24. package/fesm2022/cdevhub-ngx-tw-code-block.mjs +18 -6
  25. package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -1
  26. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +55 -30
  27. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
  28. package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs +218 -0
  29. package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs.map +1 -0
  30. package/fesm2022/cdevhub-ngx-tw-combobox.mjs +236 -211
  31. package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
  32. package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs +200 -0
  33. package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs.map +1 -0
  34. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +34 -7
  35. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -1
  36. package/fesm2022/cdevhub-ngx-tw-core.mjs +135 -15
  37. package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -1
  38. package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs +203 -0
  39. package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs.map +1 -0
  40. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +160 -102
  41. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
  42. package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs +209 -0
  43. package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs.map +1 -0
  44. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +182 -107
  45. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
  46. package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs +122 -0
  47. package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs.map +1 -0
  48. package/fesm2022/cdevhub-ngx-tw-dialog.mjs +11 -2
  49. package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
  50. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +1 -1
  51. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
  52. package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs +149 -0
  53. package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs.map +1 -0
  54. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +57 -67
  55. package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -1
  56. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +42 -24
  57. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
  58. package/fesm2022/cdevhub-ngx-tw-form-field.mjs +114 -21
  59. package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
  60. package/fesm2022/cdevhub-ngx-tw-icon.mjs +16 -6
  61. package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
  62. package/fesm2022/cdevhub-ngx-tw-input.mjs +52 -61
  63. package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
  64. package/fesm2022/cdevhub-ngx-tw-item.mjs +28 -4
  65. package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
  66. package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs +168 -0
  67. package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs.map +1 -0
  68. package/fesm2022/cdevhub-ngx-tw-menu.mjs +58 -21
  69. package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
  70. package/fesm2022/cdevhub-ngx-tw-number-input.mjs +34 -1
  71. package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -1
  72. package/fesm2022/cdevhub-ngx-tw-paginator.mjs +95 -45
  73. package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
  74. package/fesm2022/cdevhub-ngx-tw-popover.mjs +81 -32
  75. package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
  76. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +1 -1
  77. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
  78. package/fesm2022/cdevhub-ngx-tw-radio.mjs +131 -98
  79. package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
  80. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +207 -42
  81. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
  82. package/fesm2022/cdevhub-ngx-tw-select-testing.mjs +165 -0
  83. package/fesm2022/cdevhub-ngx-tw-select-testing.mjs.map +1 -0
  84. package/fesm2022/cdevhub-ngx-tw-select.mjs +386 -210
  85. package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
  86. package/fesm2022/{cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs → cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs} +3 -3
  87. package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs.map +1 -0
  88. package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs +129 -0
  89. package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs.map +1 -0
  90. package/fesm2022/cdevhub-ngx-tw-sheet.mjs +23 -7
  91. package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
  92. package/fesm2022/cdevhub-ngx-tw-slider.mjs +89 -54
  93. package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
  94. package/fesm2022/cdevhub-ngx-tw-sort.mjs +122 -17
  95. package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
  96. package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -19
  97. package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
  98. package/fesm2022/cdevhub-ngx-tw-stat.mjs +63 -25
  99. package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
  100. package/fesm2022/cdevhub-ngx-tw-stepper.mjs +35 -8
  101. package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
  102. package/fesm2022/cdevhub-ngx-tw-switch.mjs +54 -48
  103. package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
  104. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +12 -15
  105. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
  106. package/fesm2022/cdevhub-ngx-tw-table.mjs +74 -13
  107. package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
  108. package/fesm2022/cdevhub-ngx-tw-tabs.mjs +84 -30
  109. package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
  110. package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs +172 -0
  111. package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs.map +1 -0
  112. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +107 -71
  113. package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -1
  114. package/fesm2022/cdevhub-ngx-tw-textarea.mjs +41 -9
  115. package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
  116. package/fesm2022/cdevhub-ngx-tw-theme.mjs +257 -45
  117. package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
  118. package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs +201 -0
  119. package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs.map +1 -0
  120. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +184 -77
  121. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
  122. package/fesm2022/cdevhub-ngx-tw-timeline.mjs +110 -27
  123. package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
  124. package/fesm2022/{cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs → cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs} +107 -19
  125. package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs.map +1 -0
  126. package/fesm2022/cdevhub-ngx-tw-toast.mjs +21 -13
  127. package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
  128. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +102 -15
  129. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
  130. package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs +219 -0
  131. package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs.map +1 -0
  132. package/fesm2022/cdevhub-ngx-tw-transfer.mjs +88 -69
  133. package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -1
  134. package/fesm2022/cdevhub-ngx-tw-tree.mjs +68 -19
  135. package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -1
  136. package/index.json +1 -1
  137. package/package.json +63 -2
  138. package/theme/_base.css +13 -0
  139. package/theme/_dark.css +111 -36
  140. package/theme/_high-contrast-dark.css +367 -0
  141. package/theme/_high-contrast.css +13 -2
  142. package/theme/_light.css +332 -0
  143. package/theme/_semantic.css +60 -26
  144. package/theme/_typography.css +17 -0
  145. package/theme/index.css +86 -7
  146. package/types/cdevhub-ngx-tw-accordion.d.ts +12 -4
  147. package/types/cdevhub-ngx-tw-avatar.d.ts +10 -3
  148. package/types/cdevhub-ngx-tw-button.d.ts +1 -0
  149. package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +2 -2
  150. package/types/cdevhub-ngx-tw-calendar-testing.d.ts +1 -1
  151. package/types/cdevhub-ngx-tw-calendar.d.ts +179 -73
  152. package/types/cdevhub-ngx-tw-card.d.ts +11 -3
  153. package/types/cdevhub-ngx-tw-carousel.d.ts +89 -20
  154. package/types/cdevhub-ngx-tw-checkbox.d.ts +40 -12
  155. package/types/cdevhub-ngx-tw-code-block.d.ts +11 -2
  156. package/types/cdevhub-ngx-tw-collapsible.d.ts +32 -5
  157. package/types/cdevhub-ngx-tw-combobox-testing.d.ts +157 -0
  158. package/types/cdevhub-ngx-tw-combobox.d.ts +94 -53
  159. package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +136 -0
  160. package/types/cdevhub-ngx-tw-command-palette.d.ts +33 -5
  161. package/types/cdevhub-ngx-tw-core.d.ts +152 -21
  162. package/types/cdevhub-ngx-tw-date-picker-testing.d.ts +141 -0
  163. package/types/cdevhub-ngx-tw-date-picker.d.ts +37 -29
  164. package/types/cdevhub-ngx-tw-date-range-picker-testing.d.ts +148 -0
  165. package/types/cdevhub-ngx-tw-date-range-picker.d.ts +36 -29
  166. package/types/cdevhub-ngx-tw-dialog-testing.d.ts +98 -0
  167. package/types/cdevhub-ngx-tw-dialog.d.ts +12 -3
  168. package/types/cdevhub-ngx-tw-file-upload-testing.d.ts +120 -0
  169. package/types/cdevhub-ngx-tw-file-upload.d.ts +8 -10
  170. package/types/cdevhub-ngx-tw-flip-card.d.ts +18 -11
  171. package/types/cdevhub-ngx-tw-form-field.d.ts +19 -2
  172. package/types/cdevhub-ngx-tw-icon.d.ts +3 -3
  173. package/types/cdevhub-ngx-tw-input.d.ts +5 -8
  174. package/types/cdevhub-ngx-tw-item.d.ts +2 -0
  175. package/types/cdevhub-ngx-tw-menu-testing.d.ts +131 -0
  176. package/types/cdevhub-ngx-tw-menu.d.ts +2 -2
  177. package/types/cdevhub-ngx-tw-number-input.d.ts +20 -0
  178. package/types/cdevhub-ngx-tw-paginator.d.ts +58 -24
  179. package/types/cdevhub-ngx-tw-popover.d.ts +41 -10
  180. package/types/cdevhub-ngx-tw-progress-bar.d.ts +1 -1
  181. package/types/cdevhub-ngx-tw-radio.d.ts +68 -25
  182. package/types/cdevhub-ngx-tw-segmented-control.d.ts +79 -16
  183. package/types/cdevhub-ngx-tw-select-testing.d.ts +114 -0
  184. package/types/cdevhub-ngx-tw-select.d.ts +104 -33
  185. package/types/cdevhub-ngx-tw-sheet-testing.d.ts +104 -0
  186. package/types/cdevhub-ngx-tw-sheet.d.ts +19 -3
  187. package/types/cdevhub-ngx-tw-slider.d.ts +79 -25
  188. package/types/cdevhub-ngx-tw-sort.d.ts +45 -4
  189. package/types/cdevhub-ngx-tw-split.d.ts +32 -2
  190. package/types/cdevhub-ngx-tw-stat.d.ts +14 -4
  191. package/types/cdevhub-ngx-tw-stepper.d.ts +16 -2
  192. package/types/cdevhub-ngx-tw-switch.d.ts +35 -13
  193. package/types/cdevhub-ngx-tw-tab-nav.d.ts +7 -6
  194. package/types/cdevhub-ngx-tw-table.d.ts +53 -10
  195. package/types/cdevhub-ngx-tw-tabs.d.ts +41 -10
  196. package/types/cdevhub-ngx-tw-tags-input-testing.d.ts +135 -0
  197. package/types/cdevhub-ngx-tw-tags-input.d.ts +26 -11
  198. package/types/cdevhub-ngx-tw-textarea.d.ts +3 -2
  199. package/types/cdevhub-ngx-tw-theme.d.ts +245 -39
  200. package/types/cdevhub-ngx-tw-time-picker-testing.d.ts +129 -0
  201. package/types/cdevhub-ngx-tw-time-picker.d.ts +76 -19
  202. package/types/cdevhub-ngx-tw-timeline.d.ts +36 -12
  203. package/types/cdevhub-ngx-tw-toast.d.ts +20 -6
  204. package/types/cdevhub-ngx-tw-tooltip.d.ts +28 -6
  205. package/types/cdevhub-ngx-tw-transfer-testing.d.ts +152 -0
  206. package/types/cdevhub-ngx-tw-transfer.d.ts +21 -8
  207. package/types/cdevhub-ngx-tw-tree.d.ts +6 -1
  208. package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-ByyNluUd.mjs.map +0 -1
  209. package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-DSu4YoTy.mjs.map +0 -1
@@ -1,9 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, TemplateRef, Directive, input, contentChild, viewChild, ChangeDetectionStrategy, Component, ElementRef, computed, model, output, DestroyRef, signal, contentChildren, viewChildren, linkedSignal, afterNextRender, effect, untracked } from '@angular/core';
2
+ import { inject, TemplateRef, Directive, input, contentChild, viewChild, ChangeDetectionStrategy, Component, ElementRef, computed, model, output, DestroyRef, contentChildren, viewChildren, linkedSignal, signal, afterNextRender, effect, untracked } from '@angular/core';
3
3
  import { NgTemplateOutlet } from '@angular/common';
4
4
  import { LiveAnnouncer, FocusKeyManager } from '@angular/cdk/a11y';
5
5
  import { Directionality } from '@angular/cdk/bidi';
6
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
7
6
  import { tv } from 'tailwind-variants';
8
7
  import { twMerge } from 'tailwind-merge';
9
8
  import { tabTriggerVariants, getActiveTriggerClasses, getInactiveTriggerClasses } from '@cdevhub/ngx-tw/core';
@@ -16,7 +15,9 @@ const tabsLayoutVariants = tv({
16
15
  tablistInner: 'flex overflow-x-auto',
17
16
  panel: 'min-w-0 flex-1',
18
17
  scrollButton: 'inline-flex items-center justify-center shrink-0 cursor-pointer transition-colors duration-normal motion-reduce:transition-none disabled:opacity-30 disabled:cursor-default hover:bg-surface-muted',
19
- closeButton: 'inline-flex items-center justify-center rounded-md cursor-pointer transition-colors duration-normal motion-reduce:transition-none hover:bg-surface-muted focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500',
18
+ // No focus-visible ring: the close control is pointer-only by design
19
+ // (see the ARIA note in tabs.html), so a focus style would be dead code.
20
+ closeButton: 'inline-flex items-center justify-center rounded-md cursor-pointer transition-colors duration-normal motion-reduce:transition-none hover:bg-surface-muted',
20
21
  },
21
22
  variants: {
22
23
  variant: {
@@ -125,13 +126,13 @@ class TabComponent {
125
126
  /** Unique identifier for this tab. Used to match the active tab value. */
126
127
  value = input.required(/* @ts-ignore */
127
128
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
128
- /** Plain text label shown in the trigger. Ignored when a custom trigger template is provided. */
129
+ /** Plain text label shown in the trigger. Ignored when a custom trigger template is provided. Defaults to an empty string. */
129
130
  label = input('', /* @ts-ignore */
130
131
  ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
131
132
  /** When true, the tab cannot be selected and is skipped by keyboard navigation. Defaults to false. */
132
133
  disabled = input(false, /* @ts-ignore */
133
134
  ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
134
- /** When true, a close button is rendered in the tab trigger. Defaults to false. */
135
+ /** When true, a dismiss control is rendered in the tab trigger. The control is pointer-only; the keyboard gesture is Delete on the focused tab. Defaults to false. */
135
136
  closable = input(false, /* @ts-ignore */
136
137
  ...(ngDevMode ? [{ debugName: "closable" }] : /* istanbul ignore next */ []));
137
138
  /** When true, the tab panel content is only instantiated when the tab becomes active for the first time. Defaults to false. */
@@ -171,12 +172,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
171
172
  // ── Tab trigger element wrapper ──
172
173
  class TabTriggerElementDirective {
173
174
  elementRef = inject((ElementRef));
174
- isActive = input(false, /* @ts-ignore */
175
- ...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
175
+ /**
176
+ * Whether this trigger owns the tablist's single tab stop. Drives
177
+ * `tabindex`. Normally the active tab, but the parent falls back to the
178
+ * first enabled tab when `value` matches nothing, so the tablist is never
179
+ * left with zero tab stops. Defaults to `false`.
180
+ */
181
+ isFocusStop = input(false, /* @ts-ignore */
182
+ ...(ngDevMode ? [{ debugName: "isFocusStop" }] : /* istanbul ignore next */ []));
183
+ /** Whether this trigger is disabled. Read by `FocusKeyManager` so disabled triggers are skipped during arrow navigation. Defaults to `false`. */
176
184
  isDisabled = input(false, /* @ts-ignore */
177
185
  ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
178
- tabIndex = computed(() => this.isActive() ? 0 : -1, /* @ts-ignore */
186
+ tabIndex = computed(() => this.isFocusStop() ? 0 : -1, /* @ts-ignore */
179
187
  ...(ngDevMode ? [{ debugName: "tabIndex" }] : /* istanbul ignore next */ []));
188
+ /** Moves DOM focus to the trigger element. Called by `FocusKeyManager` during arrow-key navigation. */
180
189
  focus() {
181
190
  this.elementRef.nativeElement.focus();
182
191
  }
@@ -190,7 +199,7 @@ class TabTriggerElementDirective {
190
199
  return this.isDisabled();
191
200
  }
192
201
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TabTriggerElementDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
193
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: TabTriggerElementDirective, isStandalone: true, selector: "[twTabTriggerElement]", inputs: { isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDisabled: { classPropertyName: "isDisabled", publicName: "isDisabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.tabindex": "tabIndex()" } }, ngImport: i0 });
202
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: TabTriggerElementDirective, isStandalone: true, selector: "[twTabTriggerElement]", inputs: { isFocusStop: { classPropertyName: "isFocusStop", publicName: "isFocusStop", isSignal: true, isRequired: false, transformFunction: null }, isDisabled: { classPropertyName: "isDisabled", publicName: "isDisabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.tabindex": "tabIndex()" } }, ngImport: i0 });
194
203
  }
195
204
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TabTriggerElementDirective, decorators: [{
196
205
  type: Directive,
@@ -200,7 +209,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
200
209
  '[attr.tabindex]': 'tabIndex()',
201
210
  },
202
211
  }]
203
- }], propDecorators: { isActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "isActive", required: false }] }], isDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDisabled", required: false }] }] } });
212
+ }], propDecorators: { isFocusStop: [{ type: i0.Input, args: [{ isSignal: true, alias: "isFocusStop", required: false }] }], isDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDisabled", required: false }] }] } });
204
213
  // ── TabsComponent ──
205
214
  let nextId = 0;
206
215
  class TabsComponent {
@@ -219,21 +228,23 @@ class TabsComponent {
219
228
  /** When true, tab triggers stretch to fill the available width equally. Defaults to false. */
220
229
  fitted = input(false, /* @ts-ignore */
221
230
  ...(ngDevMode ? [{ debugName: "fitted" }] : /* istanbul ignore next */ []));
222
- /** The value of the currently active tab. Two-way bound. Updates when the user selects a tab. */
231
+ /** The value of the currently active tab. Two-way bound. Updates when the user selects a tab. Defaults to an empty string. */
223
232
  value = model('', /* @ts-ignore */
224
233
  ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
225
- /** Fires when a closable tab's close button is clicked. Payload is the tab's value. */
234
+ /** Fires when a closable tab is dismissed, either by clicking its close control or by pressing Delete while the tab has focus. Payload is the tab's value. */
226
235
  closed = output();
227
236
  destroyRef = inject(DestroyRef);
228
237
  liveAnnouncer = inject(LiveAnnouncer);
229
238
  directionality = inject(Directionality, { optional: true });
230
239
  /**
231
- * Live layout direction, mirrored into a signal so the key manager rebuilds
232
- * when it changes. Without this the tablist hardcodes 'ltr' and ArrowRight
233
- * moves to the next tab in DOM order but the *previous* tab visually in an
234
- * RTL locale. CdkStepper and `tw-split` already honour Directionality.
240
+ * Live layout direction, read straight from CDK's `Directionality.valueSignal`
241
+ * (CDK 22+) so the key-manager effect re-runs on a runtime `dir` flip with no
242
+ * manual subscription mirror. Without a live direction the tablist hardcodes
243
+ * 'ltr' and ArrowRight moves to the next tab in DOM order but the *previous*
244
+ * tab visually in an RTL locale. CdkStepper and `tw-split` already honour
245
+ * Directionality; `tw-paginator` reads `valueSignal` the same way.
235
246
  */
236
- layoutDirection = signal(this.directionality?.value ?? 'ltr', /* @ts-ignore */
247
+ layoutDirection = computed(() => this.directionality?.valueSignal() ?? 'ltr', /* @ts-ignore */
237
248
  ...(ngDevMode ? [{ debugName: "layoutDirection" }] : /* istanbul ignore next */ []));
238
249
  /** @internal */
239
250
  tabs = contentChildren(TabComponent, /* @ts-ignore */
@@ -297,16 +308,43 @@ class TabsComponent {
297
308
  return twMerge(base, orientationExtras, state);
298
309
  }
299
310
  // ── ID generation ──
311
+ /** Builds the DOM id for a tab trigger, used by the panel's `aria-labelledby`. */
300
312
  getTabId(tabValue) {
301
313
  return `${this.componentId}-tab-${tabValue}`;
302
314
  }
315
+ /** Builds the DOM id for a tab panel, used by the trigger's `aria-controls`. */
303
316
  getPanelId(tabValue) {
304
317
  return `${this.componentId}-panel-${tabValue}`;
305
318
  }
306
319
  // ── Tab visibility ──
320
+ /** Whether the tab with the given value is the currently active one. */
307
321
  isTabActive(tabValue) {
308
322
  return this.activeValue() === tabValue;
309
323
  }
324
+ /**
325
+ * @internal Value of the tab that owns the tablist's single tab stop.
326
+ *
327
+ * The active tab whenever it exists and is enabled. When `value` matches no
328
+ * tab — a stale id, a value cleared after init, or an active tab that is
329
+ * disabled — the first enabled tab takes the tab stop instead (standard
330
+ * roving-tabindex recovery). Without the fallback every trigger renders
331
+ * `tabindex="-1"` and the whole tablist silently leaves the tab order
332
+ * (WCAG SC 2.1.1).
333
+ */
334
+ focusStopValue = computed(() => {
335
+ const tabs = this.tabs();
336
+ const active = this.activeValue();
337
+ const activeTab = tabs.find(t => t.value() === active && !t.disabled());
338
+ if (activeTab)
339
+ return activeTab.value();
340
+ return tabs.find(t => !t.disabled())?.value() ?? null;
341
+ }, /* @ts-ignore */
342
+ ...(ngDevMode ? [{ debugName: "focusStopValue" }] : /* istanbul ignore next */ []));
343
+ /** Whether the tab with the given value owns the tablist's single tab stop. */
344
+ isTabFocusStop(tabValue) {
345
+ return this.focusStopValue() === tabValue;
346
+ }
347
+ /** Whether a tab's panel content should be in the DOM. Always true for eager tabs; for lazy tabs, true only once the tab has been activated at least once. */
310
348
  shouldRenderPanel(tab) {
311
349
  const value = tab.value();
312
350
  if (!tab.lazy()) {
@@ -316,6 +354,7 @@ class TabsComponent {
316
354
  return this.activatedTabs().has(value);
317
355
  }
318
356
  // ── Selection ──
357
+ /** Activates a tab, updating the two-way bound `value`, marking it rendered for lazy panels, and announcing the change via `LiveAnnouncer`. Ignored when the tab is disabled. */
319
358
  selectTab(tab) {
320
359
  if (tab.disabled())
321
360
  return;
@@ -333,6 +372,7 @@ class TabsComponent {
333
372
  const idx = tabsArr.findIndex(t => t.value() === val);
334
373
  this.liveAnnouncer.announce(`${tab.label() || val} tab, ${idx + 1} of ${tabsArr.length}`);
335
374
  }
375
+ /** Closes a closable tab, emitting `closed` with its value and moving activation to the nearest enabled sibling when the closed tab was active. */
336
376
  closeTab(tab, event) {
337
377
  event.stopPropagation();
338
378
  if (event instanceof KeyboardEvent) {
@@ -395,8 +435,10 @@ class TabsComponent {
395
435
  }
396
436
  return;
397
437
  }
398
- // Delete on a closable tab dismisses it (APG-recommended). Keyboard users
399
- // who don't want to traverse to the close button can dismiss inline.
438
+ // Delete on a closable tab dismisses it (APG-recommended). This is the
439
+ // ONLY keyboard path: the close control cannot be focusable without
440
+ // failing axe's nested-interactive rule, so `aria-keyshortcuts="Delete"`
441
+ // on the trigger advertises this gesture to assistive tech.
400
442
  if (event.key === 'Delete' && focusedIdx >= 0) {
401
443
  const tab = this.tabs()[focusedIdx];
402
444
  if (tab.closable() && !tab.disabled()) {
@@ -415,6 +457,7 @@ class TabsComponent {
415
457
  }
416
458
  }
417
459
  // ── Scrolling ──
460
+ /** Smoothly scrolls the tablist back toward its start by one step, along the current orientation's axis. */
418
461
  scrollStart() {
419
462
  const el = this.tablistInnerRef()?.nativeElement;
420
463
  if (!el)
@@ -427,6 +470,7 @@ class TabsComponent {
427
470
  el.scrollBy({ left: -120, behavior: 'smooth' });
428
471
  }
429
472
  }
473
+ /** Smoothly scrolls the tablist forward toward its end by one step, along the current orientation's axis. */
430
474
  scrollEnd() {
431
475
  const el = this.tablistInnerRef()?.nativeElement;
432
476
  if (!el)
@@ -460,12 +504,10 @@ class TabsComponent {
460
504
  afterNextRender(() => {
461
505
  this.setupScrollDetection();
462
506
  });
463
- // Track CDK Directionality so an app that flips `dir` at runtime rebuilds
464
- // the key manager with the new horizontal orientation.
465
- this.directionality?.change
466
- .pipe(takeUntilDestroyed(this.destroyRef))
467
- .subscribe((dir) => this.layoutDirection.set(dir));
468
- // Rebuild FocusKeyManager whenever triggers, orientation or direction change.
507
+ // Rebuild FocusKeyManager whenever triggers, orientation or direction
508
+ // change. `layoutDirection()` reads `Directionality.valueSignal` directly,
509
+ // so an app that flips `dir` at runtime rebuilds the manager with the new
510
+ // horizontal orientation without a subscription mirror.
469
511
  effect((onCleanup) => {
470
512
  const triggers = this.triggerElements();
471
513
  const orientation = this.orientation();
@@ -486,12 +528,24 @@ class TabsComponent {
486
528
  this.keyManager = manager;
487
529
  // Initialise the manager's active index to the active tab so the first
488
530
  // arrow press moves from the active item, not from -1.
531
+ //
532
+ // `updateActiveItem`, NOT `setActiveItem`: on a FocusKeyManager,
533
+ // `setActiveItem` also moves DOM focus to the item. Calling it here —
534
+ // during construction — makes merely MOUNTING a `<tw-tabs>` steal focus
535
+ // from wherever the user was and scroll the tablist into view. On a page
536
+ // where the tabs sit below the fold that silently jumps the viewport.
537
+ // `updateActiveItem` seeds the index without touching focus, which is
538
+ // all this needs; the keydown handler still uses `setActiveItem`, where
539
+ // moving focus is the point.
489
540
  untracked(() => {
490
- const activeVal = this.activeValue();
541
+ // Seeded from the DOM tab stop, not from `activeValue()`: when `value`
542
+ // matches no tab the tab stop falls back to the first enabled tab, and
543
+ // seeding the manager with -1 there would desynchronise the two.
544
+ const stopValue = this.focusStopValue();
491
545
  const tabs = this.tabs();
492
- const idx = tabs.findIndex(t => t.value() === activeVal);
546
+ const idx = tabs.findIndex(t => t.value() === stopValue);
493
547
  if (idx >= 0) {
494
- manager.setActiveItem(idx);
548
+ manager.updateActiveItem(idx);
495
549
  }
496
550
  });
497
551
  onCleanup(() => {
@@ -541,13 +595,13 @@ class TabsComponent {
541
595
  this.scrollCleanup = () => el.removeEventListener('scroll', onScroll);
542
596
  }
543
597
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
544
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: TabsComponent, isStandalone: true, selector: "tw-tabs", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, fitted: { classPropertyName: "fitted", publicName: "fitted", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", closed: "closed" }, host: { properties: { "class": "rootClasses()" } }, queries: [{ propertyName: "tabs", predicate: TabComponent, isSignal: true }], viewQueries: [{ propertyName: "triggerElements", predicate: TabTriggerElementDirective, descendants: true, isSignal: true }, { propertyName: "tablistInnerRef", first: true, predicate: ["tablistInner"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Tablist container. WAI-ARIA tablist owns roving focus on the tab elements\n inside; the container itself relays keydown but isn't tabbable. -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div\n [class]=\"tablistClasses()\"\n role=\"tablist\"\n [attr.aria-orientation]=\"orientation()\"\n (keydown)=\"onKeydown($event)\"\n>\n <!-- Scroll start button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollStart()\"\n (click)=\"scrollStart()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M9.78 4.22a.75.75 0 0 1 0 1.06L7.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L5.47 8.53a.75.75 0 0 1 0-1.06l3.25-3.25a.75.75 0 0 1 1.06 0Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n\n <!-- Scrollable trigger strip -->\n <div #tablistInner [class]=\"tablistInnerClasses()\" style=\"scrollbar-width: none\">\n @for (tab of tabs(); track tab.value()) {\n <!-- Trigger is rendered as <div role=\"tab\"> (not <button>) so the close\n affordance can be a native <button> child without nesting interactive\n content (invalid HTML). Activation is wired explicitly via (click)\n and the parent tablist (keydown.enter / keydown.space). -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n role=\"tab\"\n twTabTriggerElement\n [isActive]=\"isTabActive(tab.value())\"\n [isDisabled]=\"tab.disabled()\"\n [id]=\"getTabId(tab.value())\"\n [attr.aria-selected]=\"isTabActive(tab.value())\"\n [attr.aria-controls]=\"getPanelId(tab.value())\"\n [attr.aria-disabled]=\"tab.disabled() || null\"\n [class]=\"getTriggerClasses(tab.value(), isTabActive(tab.value()))\"\n [class.opacity-50]=\"tab.disabled()\"\n [class.pointer-events-none]=\"tab.disabled()\"\n (click)=\"selectTab(tab)\"\n >\n <!-- Custom trigger template or default label -->\n @if (tab.triggerTemplate(); as triggerDir) {\n <ng-container\n [ngTemplateOutlet]=\"triggerDir.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: { active: isTabActive(tab.value()), disabled: tab.disabled(), value: tab.value() } }\"\n />\n } @else {\n {{ tab.label() }}\n }\n\n <!-- Close affordance \u2014 native <button> so it is keyboard-focusable.\n Valid because the trigger is a <div role=\"tab\">, not a button. -->\n @if (tab.closable() && !tab.disabled()) {\n <button\n type=\"button\"\n [attr.aria-label]=\"'Close ' + (tab.label() || tab.value())\"\n [class]=\"closeButtonClasses()\"\n (click)=\"closeTab(tab, $event)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path d=\"M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z\"/>\n </svg>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- Scroll end button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollEnd()\"\n (click)=\"scrollEnd()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M6.22 4.22a.75.75 0 0 1 1.06 0l3.25 3.25a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06L8.94 8 6.22 5.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n</div>\n\n<!-- Tab panels -->\n@for (tab of tabs(); track tab.value()) {\n @if (shouldRenderPanel(tab)) {\n <div\n role=\"tabpanel\"\n [id]=\"getPanelId(tab.value())\"\n [attr.aria-labelledby]=\"getTabId(tab.value())\"\n [class]=\"panelClasses()\"\n [hidden]=\"!isTabActive(tab.value())\"\n tabindex=\"0\"\n >\n @if (tab.contentTemplate(); as contentDir) {\n <ng-container [ngTemplateOutlet]=\"contentDir.templateRef\" />\n } @else if (tab.implicitContentTemplate(); as implicitTpl) {\n <ng-container [ngTemplateOutlet]=\"implicitTpl\" />\n }\n </div>\n }\n}\n\n<!-- Hidden projection slot for tw-tab children -->\n<div style=\"display: none\">\n <ng-content />\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TabTriggerElementDirective, selector: "[twTabTriggerElement]", inputs: ["isActive", "isDisabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
598
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: TabsComponent, isStandalone: true, selector: "tw-tabs", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, fitted: { classPropertyName: "fitted", publicName: "fitted", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", closed: "closed" }, host: { properties: { "class": "rootClasses()" } }, queries: [{ propertyName: "tabs", predicate: TabComponent, isSignal: true }], viewQueries: [{ propertyName: "triggerElements", predicate: TabTriggerElementDirective, descendants: true, isSignal: true }, { propertyName: "tablistInnerRef", first: true, predicate: ["tablistInner"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Tablist container. WAI-ARIA tablist owns roving focus on the tab elements\n inside; the container itself relays keydown but isn't tabbable. -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div\n [class]=\"tablistClasses()\"\n role=\"tablist\"\n [attr.aria-orientation]=\"orientation()\"\n (keydown)=\"onKeydown($event)\"\n>\n <!-- Scroll start button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollStart()\"\n (click)=\"scrollStart()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M9.78 4.22a.75.75 0 0 1 0 1.06L7.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L5.47 8.53a.75.75 0 0 1 0-1.06l3.25-3.25a.75.75 0 0 1 1.06 0Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n\n <!-- Scrollable trigger strip -->\n <div #tablistInner [class]=\"tablistInnerClasses()\" style=\"scrollbar-width: none\">\n @for (tab of tabs(); track tab.value()) {\n <!-- Trigger is rendered as <div role=\"tab\">, not <button>: activation is\n wired explicitly via (click) and the parent tablist's keydown\n (Enter / Space), and the roving tab stop comes from\n twTabTriggerElement. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n role=\"tab\"\n twTabTriggerElement\n [isFocusStop]=\"isTabFocusStop(tab.value())\"\n [isDisabled]=\"tab.disabled()\"\n [id]=\"getTabId(tab.value())\"\n [attr.aria-selected]=\"isTabActive(tab.value())\"\n [attr.aria-controls]=\"getPanelId(tab.value())\"\n [attr.aria-disabled]=\"tab.disabled() || null\"\n [attr.aria-keyshortcuts]=\"tab.closable() && !tab.disabled() ? 'Delete' : null\"\n [class]=\"getTriggerClasses(tab.value(), isTabActive(tab.value()))\"\n [class.opacity-50]=\"tab.disabled()\"\n [class.pointer-events-none]=\"tab.disabled()\"\n (click)=\"selectTab(tab)\"\n >\n <!-- Custom trigger template or default label -->\n @if (tab.triggerTemplate(); as triggerDir) {\n <ng-container\n [ngTemplateOutlet]=\"triggerDir.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: { active: isTabActive(tab.value()), disabled: tab.disabled(), value: tab.value() } }\"\n />\n } @else {\n {{ tab.label() }}\n }\n\n <!-- Close affordance \u2014 a pointer-only span, deliberately NOT a button.\n Anything focusable inside an element carrying an interactive role\n fails axe's nested-interactive rule, and hoisting a real button\n out to a sibling only trades that for aria-required-children\n (a tablist may own nothing but tabs \u2014 both measured). The\n keyboard path is the APG-recommended Delete key on the tab\n itself, handled in onKeydown and advertised to assistive tech\n through aria-keyshortcuts on the trigger above. -->\n @if (tab.closable() && !tab.disabled()) {\n <span\n data-tw-tab-close\n aria-hidden=\"true\"\n [class]=\"closeButtonClasses()\"\n (click)=\"closeTab(tab, $event)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path d=\"M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z\"/>\n </svg>\n </span>\n }\n </div>\n }\n </div>\n\n <!-- Scroll end button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollEnd()\"\n (click)=\"scrollEnd()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M6.22 4.22a.75.75 0 0 1 1.06 0l3.25 3.25a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06L8.94 8 6.22 5.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n</div>\n\n<!-- Tab panels -->\n@for (tab of tabs(); track tab.value()) {\n @if (shouldRenderPanel(tab)) {\n <div\n role=\"tabpanel\"\n [id]=\"getPanelId(tab.value())\"\n [attr.aria-labelledby]=\"getTabId(tab.value())\"\n [class]=\"panelClasses()\"\n [hidden]=\"!isTabActive(tab.value())\"\n tabindex=\"0\"\n >\n @if (tab.contentTemplate(); as contentDir) {\n <ng-container [ngTemplateOutlet]=\"contentDir.templateRef\" />\n } @else if (tab.implicitContentTemplate(); as implicitTpl) {\n <ng-container [ngTemplateOutlet]=\"implicitTpl\" />\n }\n </div>\n }\n}\n\n<!-- Hidden projection slot for tw-tab children -->\n<div style=\"display: none\">\n <ng-content />\n</div>\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TabTriggerElementDirective, selector: "[twTabTriggerElement]", inputs: ["isFocusStop", "isDisabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
545
599
  }
546
600
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: TabsComponent, decorators: [{
547
601
  type: Component,
548
602
  args: [{ selector: 'tw-tabs', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet, TabTriggerElementDirective], host: {
549
603
  '[class]': 'rootClasses()',
550
- }, template: "<!-- Tablist container. WAI-ARIA tablist owns roving focus on the tab elements\n inside; the container itself relays keydown but isn't tabbable. -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div\n [class]=\"tablistClasses()\"\n role=\"tablist\"\n [attr.aria-orientation]=\"orientation()\"\n (keydown)=\"onKeydown($event)\"\n>\n <!-- Scroll start button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollStart()\"\n (click)=\"scrollStart()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M9.78 4.22a.75.75 0 0 1 0 1.06L7.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L5.47 8.53a.75.75 0 0 1 0-1.06l3.25-3.25a.75.75 0 0 1 1.06 0Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n\n <!-- Scrollable trigger strip -->\n <div #tablistInner [class]=\"tablistInnerClasses()\" style=\"scrollbar-width: none\">\n @for (tab of tabs(); track tab.value()) {\n <!-- Trigger is rendered as <div role=\"tab\"> (not <button>) so the close\n affordance can be a native <button> child without nesting interactive\n content (invalid HTML). Activation is wired explicitly via (click)\n and the parent tablist (keydown.enter / keydown.space). -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n role=\"tab\"\n twTabTriggerElement\n [isActive]=\"isTabActive(tab.value())\"\n [isDisabled]=\"tab.disabled()\"\n [id]=\"getTabId(tab.value())\"\n [attr.aria-selected]=\"isTabActive(tab.value())\"\n [attr.aria-controls]=\"getPanelId(tab.value())\"\n [attr.aria-disabled]=\"tab.disabled() || null\"\n [class]=\"getTriggerClasses(tab.value(), isTabActive(tab.value()))\"\n [class.opacity-50]=\"tab.disabled()\"\n [class.pointer-events-none]=\"tab.disabled()\"\n (click)=\"selectTab(tab)\"\n >\n <!-- Custom trigger template or default label -->\n @if (tab.triggerTemplate(); as triggerDir) {\n <ng-container\n [ngTemplateOutlet]=\"triggerDir.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: { active: isTabActive(tab.value()), disabled: tab.disabled(), value: tab.value() } }\"\n />\n } @else {\n {{ tab.label() }}\n }\n\n <!-- Close affordance \u2014 native <button> so it is keyboard-focusable.\n Valid because the trigger is a <div role=\"tab\">, not a button. -->\n @if (tab.closable() && !tab.disabled()) {\n <button\n type=\"button\"\n [attr.aria-label]=\"'Close ' + (tab.label() || tab.value())\"\n [class]=\"closeButtonClasses()\"\n (click)=\"closeTab(tab, $event)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path d=\"M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z\"/>\n </svg>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- Scroll end button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollEnd()\"\n (click)=\"scrollEnd()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M6.22 4.22a.75.75 0 0 1 1.06 0l3.25 3.25a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06L8.94 8 6.22 5.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n</div>\n\n<!-- Tab panels -->\n@for (tab of tabs(); track tab.value()) {\n @if (shouldRenderPanel(tab)) {\n <div\n role=\"tabpanel\"\n [id]=\"getPanelId(tab.value())\"\n [attr.aria-labelledby]=\"getTabId(tab.value())\"\n [class]=\"panelClasses()\"\n [hidden]=\"!isTabActive(tab.value())\"\n tabindex=\"0\"\n >\n @if (tab.contentTemplate(); as contentDir) {\n <ng-container [ngTemplateOutlet]=\"contentDir.templateRef\" />\n } @else if (tab.implicitContentTemplate(); as implicitTpl) {\n <ng-container [ngTemplateOutlet]=\"implicitTpl\" />\n }\n </div>\n }\n}\n\n<!-- Hidden projection slot for tw-tab children -->\n<div style=\"display: none\">\n <ng-content />\n</div>\n" }]
604
+ }, template: "<!-- Tablist container. WAI-ARIA tablist owns roving focus on the tab elements\n inside; the container itself relays keydown but isn't tabbable. -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div\n [class]=\"tablistClasses()\"\n role=\"tablist\"\n [attr.aria-orientation]=\"orientation()\"\n (keydown)=\"onKeydown($event)\"\n>\n <!-- Scroll start button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollStart()\"\n (click)=\"scrollStart()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M9.78 4.22a.75.75 0 0 1 0 1.06L7.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L5.47 8.53a.75.75 0 0 1 0-1.06l3.25-3.25a.75.75 0 0 1 1.06 0Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n\n <!-- Scrollable trigger strip -->\n <div #tablistInner [class]=\"tablistInnerClasses()\" style=\"scrollbar-width: none\">\n @for (tab of tabs(); track tab.value()) {\n <!-- Trigger is rendered as <div role=\"tab\">, not <button>: activation is\n wired explicitly via (click) and the parent tablist's keydown\n (Enter / Space), and the roving tab stop comes from\n twTabTriggerElement. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n role=\"tab\"\n twTabTriggerElement\n [isFocusStop]=\"isTabFocusStop(tab.value())\"\n [isDisabled]=\"tab.disabled()\"\n [id]=\"getTabId(tab.value())\"\n [attr.aria-selected]=\"isTabActive(tab.value())\"\n [attr.aria-controls]=\"getPanelId(tab.value())\"\n [attr.aria-disabled]=\"tab.disabled() || null\"\n [attr.aria-keyshortcuts]=\"tab.closable() && !tab.disabled() ? 'Delete' : null\"\n [class]=\"getTriggerClasses(tab.value(), isTabActive(tab.value()))\"\n [class.opacity-50]=\"tab.disabled()\"\n [class.pointer-events-none]=\"tab.disabled()\"\n (click)=\"selectTab(tab)\"\n >\n <!-- Custom trigger template or default label -->\n @if (tab.triggerTemplate(); as triggerDir) {\n <ng-container\n [ngTemplateOutlet]=\"triggerDir.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: { active: isTabActive(tab.value()), disabled: tab.disabled(), value: tab.value() } }\"\n />\n } @else {\n {{ tab.label() }}\n }\n\n <!-- Close affordance \u2014 a pointer-only span, deliberately NOT a button.\n Anything focusable inside an element carrying an interactive role\n fails axe's nested-interactive rule, and hoisting a real button\n out to a sibling only trades that for aria-required-children\n (a tablist may own nothing but tabs \u2014 both measured). The\n keyboard path is the APG-recommended Delete key on the tab\n itself, handled in onKeydown and advertised to assistive tech\n through aria-keyshortcuts on the trigger above. -->\n @if (tab.closable() && !tab.disabled()) {\n <span\n data-tw-tab-close\n aria-hidden=\"true\"\n [class]=\"closeButtonClasses()\"\n (click)=\"closeTab(tab, $event)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path d=\"M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z\"/>\n </svg>\n </span>\n }\n </div>\n }\n </div>\n\n <!-- Scroll end button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollEnd()\"\n (click)=\"scrollEnd()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M6.22 4.22a.75.75 0 0 1 1.06 0l3.25 3.25a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06L8.94 8 6.22 5.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n</div>\n\n<!-- Tab panels -->\n@for (tab of tabs(); track tab.value()) {\n @if (shouldRenderPanel(tab)) {\n <div\n role=\"tabpanel\"\n [id]=\"getPanelId(tab.value())\"\n [attr.aria-labelledby]=\"getTabId(tab.value())\"\n [class]=\"panelClasses()\"\n [hidden]=\"!isTabActive(tab.value())\"\n tabindex=\"0\"\n >\n @if (tab.contentTemplate(); as contentDir) {\n <ng-container [ngTemplateOutlet]=\"contentDir.templateRef\" />\n } @else if (tab.implicitContentTemplate(); as implicitTpl) {\n <ng-container [ngTemplateOutlet]=\"implicitTpl\" />\n }\n </div>\n }\n}\n\n<!-- Hidden projection slot for tw-tab children -->\n<div style=\"display: none\">\n <ng-content />\n</div>\n" }]
551
605
  }], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], fitted: [{ type: i0.Input, args: [{ isSignal: true, alias: "fitted", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], closed: [{ type: i0.Output, args: ["closed"] }], tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TabComponent), { isSignal: true }] }], triggerElements: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => TabTriggerElementDirective), { isSignal: true }] }], tablistInnerRef: [{ type: i0.ViewChild, args: ['tablistInner', { isSignal: true }] }] } });
552
606
 
553
607
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"cdevhub-ngx-tw-tabs.mjs","sources":["../../../projects/ngx-tw/tabs/tabs.ts","../../../projects/ngx-tw/tabs/tabs.html","../../../projects/ngx-tw/tabs/cdevhub-ngx-tw-tabs.ts"],"sourcesContent":["import {\n afterNextRender,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n contentChildren,\n DestroyRef,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n linkedSignal,\n model,\n output,\n signal,\n TemplateRef,\n untracked,\n viewChild,\n viewChildren,\n type AfterViewInit,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { type FocusableOption, FocusKeyManager, LiveAnnouncer } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { tv } from 'tailwind-variants';\nimport { twMerge } from 'tailwind-merge';\nimport {\n getActiveTriggerClasses,\n getInactiveTriggerClasses,\n tabTriggerVariants,\n type TabTriggerVariant,\n type TwColor,\n type TwSize,\n} from '@cdevhub/ngx-tw/core';\n\n/** Visual style of the tab strip. */\nexport type TabsVariant = TabTriggerVariant;\n\n// ── tv() config (component-local slots only — trigger config is shared) ──\n\nconst tabsLayoutVariants = tv(\n {\n slots: {\n root: 'flex',\n tablist: 'relative flex shrink-0',\n tablistInner: 'flex overflow-x-auto',\n panel: 'min-w-0 flex-1',\n scrollButton:\n 'inline-flex items-center justify-center shrink-0 cursor-pointer transition-colors duration-normal motion-reduce:transition-none disabled:opacity-30 disabled:cursor-default hover:bg-surface-muted',\n closeButton:\n 'inline-flex items-center justify-center rounded-md cursor-pointer transition-colors duration-normal motion-reduce:transition-none hover:bg-surface-muted focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500',\n },\n variants: {\n variant: {\n underline: {\n tablist: 'border-b border-border',\n tablistInner: 'gap-0',\n panel: 'pt-4',\n },\n enclosed: {\n tablist: 'border-b border-border',\n tablistInner: 'gap-0',\n panel: 'pt-4',\n },\n pill: {\n tablist: 'bg-surface-muted rounded-xl p-1',\n tablistInner: 'gap-1',\n panel: 'pt-4',\n },\n },\n // Square interactive-target scale: see CLAUDE.md \"Icon Sizing\".\n size: {\n xs: { scrollButton: 'size-5', closeButton: 'size-6' },\n sm: { scrollButton: 'size-5', closeButton: 'size-7' },\n md: { scrollButton: 'size-6', closeButton: 'size-8' },\n lg: { scrollButton: 'size-7', closeButton: 'size-9' },\n xl: { scrollButton: 'size-8', closeButton: 'size-9' },\n },\n orientation: {\n horizontal: {\n root: 'flex-col',\n tablist: '',\n tablistInner: 'flex-row',\n },\n vertical: {\n root: 'flex-row',\n tablistInner: 'flex-col overflow-y-auto overflow-x-hidden',\n },\n },\n },\n compoundVariants: [\n {\n variant: 'underline',\n orientation: 'vertical',\n class: {\n tablist: 'border-b-0 border-r border-border',\n panel: 'pt-0 pl-4',\n },\n },\n {\n variant: 'enclosed',\n orientation: 'vertical',\n class: {\n tablist: 'border-b-0 border-r border-border',\n panel: 'pt-0 pl-4',\n },\n },\n {\n variant: 'pill',\n orientation: 'vertical',\n class: {\n panel: 'pt-0 pl-4',\n },\n },\n ],\n defaultVariants: {\n variant: 'underline',\n size: 'md',\n orientation: 'horizontal',\n },\n },\n { twMerge: true },\n);\n\n// ── Per-variant/orientation trigger additions (vertical underline/enclosed\n// re-route the active border axis, hence these compound overrides). ──\n\nfunction getTriggerOrientationExtras(\n variant: TabsVariant,\n orientation: 'horizontal' | 'vertical',\n): string {\n if (orientation !== 'vertical') return '';\n switch (variant) {\n case 'underline':\n return 'border-b-0 -mb-0 border-r-2 border-transparent -mr-px';\n case 'enclosed':\n return '-mb-0 -mr-px';\n case 'pill':\n return '';\n }\n}\n\n// ── Directives ──\n\n@Directive({ selector: 'ng-template[twTabTrigger]' })\nexport class TabTriggerDirective {\n readonly templateRef = inject(TemplateRef);\n}\n\n@Directive({ selector: 'ng-template[twTabContent]' })\nexport class TabContentDirective {\n readonly templateRef = inject(TemplateRef);\n}\n\n// ── TabComponent ──\n\n@Component({\n selector: 'tw-tab',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <ng-template #implicitContent>\n <ng-content />\n </ng-template>\n `,\n host: {\n 'style': 'display: none',\n },\n})\nexport class TabComponent {\n /** Unique identifier for this tab. Used to match the active tab value. */\n readonly value = input.required<string>();\n\n /** Plain text label shown in the trigger. Ignored when a custom trigger template is provided. */\n readonly label = input('');\n\n /** When true, the tab cannot be selected and is skipped by keyboard navigation. Defaults to false. */\n readonly disabled = input(false);\n\n /** When true, a close button is rendered in the tab trigger. Defaults to false. */\n readonly closable = input(false);\n\n /** When true, the tab panel content is only instantiated when the tab becomes active for the first time. Defaults to false. */\n readonly lazy = input(false);\n\n /** @internal Custom trigger template, if provided. */\n readonly triggerTemplate = contentChild(TabTriggerDirective);\n\n /** @internal Custom content template, if provided via twTabContent. */\n readonly contentTemplate = contentChild(TabContentDirective);\n\n /** @internal Implicit content template wrapping ng-content. */\n readonly implicitContentTemplate = viewChild<TemplateRef<unknown>>('implicitContent');\n}\n\n// ── Tab trigger element wrapper ──\n\n@Directive({\n selector: '[twTabTriggerElement]',\n host: {\n '[attr.tabindex]': 'tabIndex()',\n },\n})\nexport class TabTriggerElementDirective implements FocusableOption {\n readonly elementRef = inject(ElementRef<HTMLElement>);\n\n readonly isActive = input(false);\n readonly isDisabled = input(false);\n\n readonly tabIndex = computed(() => this.isActive() ? 0 : -1);\n\n focus(): void {\n this.elementRef.nativeElement.focus();\n }\n\n /**\n * FocusableOption getter. NOTE: we cannot expose the `isDisabled` input\n * signal directly — the signal function itself is always truthy, which would\n * make FocusKeyManager treat every trigger as disabled. We resolve the\n * signal here so the manager skips the right items.\n */\n get disabled(): boolean {\n return this.isDisabled();\n }\n}\n\n// ── TabsComponent ──\n\nlet nextId = 0;\n\n@Component({\n selector: 'tw-tabs',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgTemplateOutlet, TabTriggerElementDirective],\n templateUrl: './tabs.html',\n host: {\n '[class]': 'rootClasses()',\n },\n})\nexport class TabsComponent implements AfterViewInit {\n /** Controls the visual style of the tab strip. Defaults to 'underline'. */\n readonly variant = input<TabsVariant>('underline');\n\n /** Sets the semantic color for active tab indicators and highlights. Defaults to 'primary'. */\n readonly color = input<TwColor>('primary');\n\n /** Controls padding, font size, and icon size of tab triggers. Defaults to 'md'. */\n readonly size = input<TwSize>('md');\n\n /** Layout direction of the tab strip. Defaults to 'horizontal'. */\n readonly orientation = input<'horizontal' | 'vertical'>('horizontal');\n\n /** When true, tab triggers stretch to fill the available width equally. Defaults to false. */\n readonly fitted = input(false);\n\n /** The value of the currently active tab. Two-way bound. Updates when the user selects a tab. */\n readonly value = model<string>('');\n\n /** Fires when a closable tab's close button is clicked. Payload is the tab's value. */\n readonly closed = output<string>();\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly liveAnnouncer = inject(LiveAnnouncer);\n private readonly directionality = inject(Directionality, { optional: true });\n\n /**\n * Live layout direction, mirrored into a signal so the key manager rebuilds\n * when it changes. Without this the tablist hardcodes 'ltr' and ArrowRight\n * moves to the next tab in DOM order but the *previous* tab visually in an\n * RTL locale. CdkStepper and `tw-split` already honour Directionality.\n */\n private readonly layoutDirection = signal<'ltr' | 'rtl'>(\n this.directionality?.value ?? 'ltr',\n );\n\n /** @internal */\n readonly tabs = contentChildren(TabComponent);\n\n /** @internal */\n readonly triggerElements = viewChildren(TabTriggerElementDirective);\n\n /** @internal */\n readonly tablistInnerRef = viewChild<ElementRef<HTMLElement>>('tablistInner');\n\n private readonly componentId = `tw-tabs-${nextId++}`;\n\n // ── Active tab tracking ──\n\n readonly activeValue = linkedSignal(() => this.value());\n\n // ── Lazy tab tracking — Set of tab values that have been activated at least once ──\n readonly activatedTabs = signal(new Set<string>());\n\n // ── Scroll overflow signals ──\n readonly canScrollStart = signal(false);\n readonly canScrollEnd = signal(false);\n\n private resizeObserver: ResizeObserver | null = null;\n private scrollCleanup: (() => void) | null = null;\n\n // ── Variant classes ──\n\n private readonly layoutResult = computed(() =>\n tabsLayoutVariants({\n variant: this.variant(),\n size: this.size(),\n orientation: this.orientation(),\n }),\n );\n\n private readonly triggerResult = computed(() =>\n tabTriggerVariants({\n variant: this.variant(),\n color: this.color(),\n size: this.size(),\n fitted: this.fitted(),\n }),\n );\n\n readonly rootClasses = computed(() => this.layoutResult().root());\n readonly tablistClasses = computed(() => this.layoutResult().tablist());\n readonly tablistInnerClasses = computed(() => this.layoutResult().tablistInner());\n readonly baseTriggerClasses = computed(() => this.triggerResult().trigger());\n readonly panelClasses = computed(() => this.layoutResult().panel());\n readonly scrollButtonClasses = computed(() => this.layoutResult().scrollButton());\n readonly closeButtonClasses = computed(() => this.layoutResult().closeButton());\n\n // ── Per-trigger active/inactive class computation ──\n\n /** @internal Get combined trigger classes for a given tab. */\n getTriggerClasses(_tabValue: string, isActive: boolean): string {\n const base = this.baseTriggerClasses();\n const orientationExtras = getTriggerOrientationExtras(this.variant(), this.orientation());\n const state = isActive\n ? getActiveTriggerClasses(this.variant(), this.color(), this.orientation())\n : getInactiveTriggerClasses(this.variant());\n return twMerge(base, orientationExtras, state);\n }\n\n // ── ID generation ──\n getTabId(tabValue: string): string {\n return `${this.componentId}-tab-${tabValue}`;\n }\n\n getPanelId(tabValue: string): string {\n return `${this.componentId}-panel-${tabValue}`;\n }\n\n // ── Tab visibility ──\n\n isTabActive(tabValue: string): boolean {\n return this.activeValue() === tabValue;\n }\n\n shouldRenderPanel(tab: TabComponent): boolean {\n const value = tab.value();\n if (!tab.lazy()) {\n return true;\n }\n // Lazy: render only if it has been activated at least once\n return this.activatedTabs().has(value);\n }\n\n // ── Selection ──\n\n selectTab(tab: TabComponent): void {\n if (tab.disabled()) return;\n const val = tab.value();\n this.activeValue.set(val);\n this.value.set(val);\n\n // Mark as activated for lazy tabs\n this.activatedTabs.update(set => {\n const next = new Set(set);\n next.add(val);\n return next;\n });\n\n // Announce to screen readers\n const tabsArr = this.tabs();\n const idx = tabsArr.findIndex(t => t.value() === val);\n this.liveAnnouncer.announce(\n `${tab.label() || val} tab, ${idx + 1} of ${tabsArr.length}`,\n );\n }\n\n closeTab(tab: TabComponent, event: Event): void {\n event.stopPropagation();\n if (event instanceof KeyboardEvent) {\n event.preventDefault();\n }\n const val = tab.value();\n this.closed.emit(val);\n\n // If closing the active tab, activate nearest enabled sibling\n if (this.isTabActive(val)) {\n const tabsArr = this.tabs();\n const idx = tabsArr.findIndex(t => t.value() === val);\n const next = this.findNearestEnabledTab(tabsArr, idx);\n if (next) {\n this.selectTab(next);\n }\n }\n }\n\n private findNearestEnabledTab(tabs: readonly TabComponent[], fromIndex: number): TabComponent | null {\n // Search forward first, then backward\n for (let i = fromIndex + 1; i < tabs.length; i++) {\n if (!tabs[i].disabled()) return tabs[i];\n }\n for (let i = fromIndex - 1; i >= 0; i--) {\n if (!tabs[i].disabled()) return tabs[i];\n }\n return null;\n }\n\n // ── Keyboard navigation (CDK FocusKeyManager) ──\n\n private keyManager: FocusKeyManager<TabTriggerElementDirective> | null = null;\n\n /**\n * @internal Handles keyboard navigation. The manager handles Arrow/Home/End;\n * we layer Enter/Space to select the focused tab (the wrapper is a `<div role=\"tab\">`\n * so we lose the native button activation) and Delete to close a closable tab.\n */\n onKeydown(event: KeyboardEvent): void {\n if (!this.keyManager) return;\n const triggers = this.triggerElements();\n if (triggers.length === 0) return;\n\n // Sync active item with the trigger DOM-focused by the user. We accept\n // either `event.target` (which works under shadow DOM) or the currently\n // active tab's index as a safety net (e.g. when the event was dispatched\n // on the tablist container itself, not a trigger).\n const focusedIdx = triggers.findIndex(\n t => t.elementRef.nativeElement === event.target,\n );\n const activeIdx = focusedIdx >= 0\n ? focusedIdx\n : this.tabs().findIndex(t => t.value() === this.activeValue());\n if (activeIdx >= 0 && activeIdx !== this.keyManager.activeItemIndex) {\n this.keyManager.setActiveItem(activeIdx);\n }\n\n // Enter / Space select the focused tab (we no longer get this for free\n // because the trigger is a div, not a button — see DOM restructure below).\n if (event.key === 'Enter' || event.key === ' ') {\n if (focusedIdx >= 0) {\n event.preventDefault();\n this.selectTab(this.tabs()[focusedIdx]);\n }\n return;\n }\n\n // Delete on a closable tab dismisses it (APG-recommended). Keyboard users\n // who don't want to traverse to the close button can dismiss inline.\n if (event.key === 'Delete' && focusedIdx >= 0) {\n const tab = this.tabs()[focusedIdx];\n if (tab.closable() && !tab.disabled()) {\n event.preventDefault();\n this.closeTab(tab, event);\n return;\n }\n }\n\n // Let the manager handle arrow/home/end navigation.\n const before = this.keyManager.activeItemIndex;\n this.keyManager.onKeydown(event);\n const after = this.keyManager.activeItemIndex;\n if (after !== null && after !== before && after >= 0) {\n // Automatic activation pattern (APG): selection follows focus.\n this.selectTab(this.tabs()[after]);\n }\n }\n\n // ── Scrolling ──\n\n scrollStart(): void {\n const el = this.tablistInnerRef()?.nativeElement;\n if (!el) return;\n const isVertical = this.orientation() === 'vertical';\n if (isVertical) {\n el.scrollBy({ top: -120, behavior: 'smooth' });\n } else {\n el.scrollBy({ left: -120, behavior: 'smooth' });\n }\n }\n\n scrollEnd(): void {\n const el = this.tablistInnerRef()?.nativeElement;\n if (!el) return;\n const isVertical = this.orientation() === 'vertical';\n if (isVertical) {\n el.scrollBy({ top: 120, behavior: 'smooth' });\n } else {\n el.scrollBy({ left: 120, behavior: 'smooth' });\n }\n }\n\n private updateScrollState(): void {\n const el = this.tablistInnerRef()?.nativeElement;\n if (!el) return;\n\n const isVertical = this.orientation() === 'vertical';\n if (isVertical) {\n this.canScrollStart.set(el.scrollTop > 0);\n this.canScrollEnd.set(el.scrollTop + el.clientHeight < el.scrollHeight - 1);\n } else {\n this.canScrollStart.set(el.scrollLeft > 0);\n this.canScrollEnd.set(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);\n }\n }\n\n ngAfterViewInit(): void {\n this.initializeActiveTab();\n }\n\n constructor() {\n afterNextRender(() => {\n this.setupScrollDetection();\n });\n\n // Track CDK Directionality so an app that flips `dir` at runtime rebuilds\n // the key manager with the new horizontal orientation.\n this.directionality?.change\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((dir) => this.layoutDirection.set(dir));\n\n // Rebuild FocusKeyManager whenever triggers, orientation or direction change.\n effect((onCleanup) => {\n const triggers = this.triggerElements();\n const orientation = this.orientation();\n if (triggers.length === 0) {\n this.keyManager = null;\n return;\n }\n const direction = this.layoutDirection();\n const manager = new FocusKeyManager(triggers)\n .withWrap()\n .withHomeAndEnd();\n if (orientation === 'vertical') {\n manager.withVerticalOrientation();\n } else {\n manager.withHorizontalOrientation(direction);\n }\n this.keyManager = manager;\n\n // Initialise the manager's active index to the active tab so the first\n // arrow press moves from the active item, not from -1.\n untracked(() => {\n const activeVal = this.activeValue();\n const tabs = this.tabs();\n const idx = tabs.findIndex(t => t.value() === activeVal);\n if (idx >= 0) {\n manager.setActiveItem(idx);\n }\n });\n\n onCleanup(() => {\n manager.destroy();\n });\n });\n\n this.destroyRef.onDestroy(() => {\n this.resizeObserver?.disconnect();\n this.scrollCleanup?.();\n });\n }\n\n private initializeActiveTab(): void {\n // If no value was provided, default to the first enabled tab\n if (!this.activeValue()) {\n const first = this.tabs().find(t => !t.disabled());\n if (first) {\n this.activeValue.set(first.value());\n this.value.set(first.value());\n }\n }\n\n // Mark the initial active tab as activated (for lazy tracking)\n const val = this.activeValue();\n if (val) {\n this.activatedTabs.update(set => {\n const next = new Set(set);\n next.add(val);\n return next;\n });\n }\n }\n\n private setupScrollDetection(): void {\n const el = this.tablistInnerRef()?.nativeElement;\n if (!el) return;\n\n // Initial check\n this.updateScrollState();\n\n // ResizeObserver for container size changes\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver(() => {\n this.updateScrollState();\n });\n this.resizeObserver.observe(el);\n }\n\n // Scroll event for scroll position changes\n const onScroll = () => this.updateScrollState();\n el.addEventListener('scroll', onScroll, { passive: true });\n this.scrollCleanup = () => el.removeEventListener('scroll', onScroll);\n }\n}\n","<!-- Tablist container. WAI-ARIA tablist owns roving focus on the tab elements\n inside; the container itself relays keydown but isn't tabbable. -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div\n [class]=\"tablistClasses()\"\n role=\"tablist\"\n [attr.aria-orientation]=\"orientation()\"\n (keydown)=\"onKeydown($event)\"\n>\n <!-- Scroll start button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollStart()\"\n (click)=\"scrollStart()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M9.78 4.22a.75.75 0 0 1 0 1.06L7.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L5.47 8.53a.75.75 0 0 1 0-1.06l3.25-3.25a.75.75 0 0 1 1.06 0Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n\n <!-- Scrollable trigger strip -->\n <div #tablistInner [class]=\"tablistInnerClasses()\" style=\"scrollbar-width: none\">\n @for (tab of tabs(); track tab.value()) {\n <!-- Trigger is rendered as <div role=\"tab\"> (not <button>) so the close\n affordance can be a native <button> child without nesting interactive\n content (invalid HTML). Activation is wired explicitly via (click)\n and the parent tablist (keydown.enter / keydown.space). -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n role=\"tab\"\n twTabTriggerElement\n [isActive]=\"isTabActive(tab.value())\"\n [isDisabled]=\"tab.disabled()\"\n [id]=\"getTabId(tab.value())\"\n [attr.aria-selected]=\"isTabActive(tab.value())\"\n [attr.aria-controls]=\"getPanelId(tab.value())\"\n [attr.aria-disabled]=\"tab.disabled() || null\"\n [class]=\"getTriggerClasses(tab.value(), isTabActive(tab.value()))\"\n [class.opacity-50]=\"tab.disabled()\"\n [class.pointer-events-none]=\"tab.disabled()\"\n (click)=\"selectTab(tab)\"\n >\n <!-- Custom trigger template or default label -->\n @if (tab.triggerTemplate(); as triggerDir) {\n <ng-container\n [ngTemplateOutlet]=\"triggerDir.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: { active: isTabActive(tab.value()), disabled: tab.disabled(), value: tab.value() } }\"\n />\n } @else {\n {{ tab.label() }}\n }\n\n <!-- Close affordance — native <button> so it is keyboard-focusable.\n Valid because the trigger is a <div role=\"tab\">, not a button. -->\n @if (tab.closable() && !tab.disabled()) {\n <button\n type=\"button\"\n [attr.aria-label]=\"'Close ' + (tab.label() || tab.value())\"\n [class]=\"closeButtonClasses()\"\n (click)=\"closeTab(tab, $event)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path d=\"M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z\"/>\n </svg>\n </button>\n }\n </div>\n }\n </div>\n\n <!-- Scroll end button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollEnd()\"\n (click)=\"scrollEnd()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M6.22 4.22a.75.75 0 0 1 1.06 0l3.25 3.25a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06L8.94 8 6.22 5.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n</div>\n\n<!-- Tab panels -->\n@for (tab of tabs(); track tab.value()) {\n @if (shouldRenderPanel(tab)) {\n <div\n role=\"tabpanel\"\n [id]=\"getPanelId(tab.value())\"\n [attr.aria-labelledby]=\"getTabId(tab.value())\"\n [class]=\"panelClasses()\"\n [hidden]=\"!isTabActive(tab.value())\"\n tabindex=\"0\"\n >\n @if (tab.contentTemplate(); as contentDir) {\n <ng-container [ngTemplateOutlet]=\"contentDir.templateRef\" />\n } @else if (tab.implicitContentTemplate(); as implicitTpl) {\n <ng-container [ngTemplateOutlet]=\"implicitTpl\" />\n }\n </div>\n }\n}\n\n<!-- Hidden projection slot for tw-tab children -->\n<div style=\"display: none\">\n <ng-content />\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":"cdevhub-ngx-tw-tabs.mjs","sources":["../../../projects/ngx-tw/tabs/tabs.ts","../../../projects/ngx-tw/tabs/tabs.html","../../../projects/ngx-tw/tabs/cdevhub-ngx-tw-tabs.ts"],"sourcesContent":["import {\n afterNextRender,\n ChangeDetectionStrategy,\n Component,\n computed,\n contentChild,\n contentChildren,\n DestroyRef,\n Directive,\n effect,\n ElementRef,\n inject,\n input,\n linkedSignal,\n model,\n output,\n signal,\n TemplateRef,\n untracked,\n viewChild,\n viewChildren,\n type AfterViewInit,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { type FocusableOption, FocusKeyManager, LiveAnnouncer } from '@angular/cdk/a11y';\nimport { Directionality } from '@angular/cdk/bidi';\nimport { tv } from 'tailwind-variants';\nimport { twMerge } from 'tailwind-merge';\nimport {\n getActiveTriggerClasses,\n getInactiveTriggerClasses,\n tabTriggerVariants,\n type TabTriggerVariant,\n type TwColor,\n type TwSize,\n} from '@cdevhub/ngx-tw/core';\n\n/** Visual style of the tab strip. */\nexport type TabsVariant = TabTriggerVariant;\n\n// ── tv() config (component-local slots only — trigger config is shared) ──\n\nconst tabsLayoutVariants = tv(\n {\n slots: {\n root: 'flex',\n tablist: 'relative flex shrink-0',\n tablistInner: 'flex overflow-x-auto',\n panel: 'min-w-0 flex-1',\n scrollButton:\n 'inline-flex items-center justify-center shrink-0 cursor-pointer transition-colors duration-normal motion-reduce:transition-none disabled:opacity-30 disabled:cursor-default hover:bg-surface-muted',\n // No focus-visible ring: the close control is pointer-only by design\n // (see the ARIA note in tabs.html), so a focus style would be dead code.\n closeButton:\n 'inline-flex items-center justify-center rounded-md cursor-pointer transition-colors duration-normal motion-reduce:transition-none hover:bg-surface-muted',\n },\n variants: {\n variant: {\n underline: {\n tablist: 'border-b border-border',\n tablistInner: 'gap-0',\n panel: 'pt-4',\n },\n enclosed: {\n tablist: 'border-b border-border',\n tablistInner: 'gap-0',\n panel: 'pt-4',\n },\n pill: {\n tablist: 'bg-surface-muted rounded-xl p-1',\n tablistInner: 'gap-1',\n panel: 'pt-4',\n },\n },\n // Square interactive-target scale: see CLAUDE.md \"Icon Sizing\".\n size: {\n xs: { scrollButton: 'size-5', closeButton: 'size-6' },\n sm: { scrollButton: 'size-5', closeButton: 'size-7' },\n md: { scrollButton: 'size-6', closeButton: 'size-8' },\n lg: { scrollButton: 'size-7', closeButton: 'size-9' },\n xl: { scrollButton: 'size-8', closeButton: 'size-9' },\n },\n orientation: {\n horizontal: {\n root: 'flex-col',\n tablist: '',\n tablistInner: 'flex-row',\n },\n vertical: {\n root: 'flex-row',\n tablistInner: 'flex-col overflow-y-auto overflow-x-hidden',\n },\n },\n },\n compoundVariants: [\n {\n variant: 'underline',\n orientation: 'vertical',\n class: {\n tablist: 'border-b-0 border-r border-border',\n panel: 'pt-0 pl-4',\n },\n },\n {\n variant: 'enclosed',\n orientation: 'vertical',\n class: {\n tablist: 'border-b-0 border-r border-border',\n panel: 'pt-0 pl-4',\n },\n },\n {\n variant: 'pill',\n orientation: 'vertical',\n class: {\n panel: 'pt-0 pl-4',\n },\n },\n ],\n defaultVariants: {\n variant: 'underline',\n size: 'md',\n orientation: 'horizontal',\n },\n },\n { twMerge: true },\n);\n\n// ── Per-variant/orientation trigger additions (vertical underline/enclosed\n// re-route the active border axis, hence these compound overrides). ──\n\nfunction getTriggerOrientationExtras(\n variant: TabsVariant,\n orientation: 'horizontal' | 'vertical',\n): string {\n if (orientation !== 'vertical') return '';\n switch (variant) {\n case 'underline':\n return 'border-b-0 -mb-0 border-r-2 border-transparent -mr-px';\n case 'enclosed':\n return '-mb-0 -mr-px';\n case 'pill':\n return '';\n }\n}\n\n// ── Directives ──\n\n@Directive({ selector: 'ng-template[twTabTrigger]' })\nexport class TabTriggerDirective {\n readonly templateRef = inject(TemplateRef);\n}\n\n@Directive({ selector: 'ng-template[twTabContent]' })\nexport class TabContentDirective {\n readonly templateRef = inject(TemplateRef);\n}\n\n// ── TabComponent ──\n\n@Component({\n selector: 'tw-tab',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <ng-template #implicitContent>\n <ng-content />\n </ng-template>\n `,\n host: {\n 'style': 'display: none',\n },\n})\nexport class TabComponent {\n /** Unique identifier for this tab. Used to match the active tab value. */\n readonly value = input.required<string>();\n\n /** Plain text label shown in the trigger. Ignored when a custom trigger template is provided. Defaults to an empty string. */\n readonly label = input('');\n\n /** When true, the tab cannot be selected and is skipped by keyboard navigation. Defaults to false. */\n readonly disabled = input(false);\n\n /** When true, a dismiss control is rendered in the tab trigger. The control is pointer-only; the keyboard gesture is Delete on the focused tab. Defaults to false. */\n readonly closable = input(false);\n\n /** When true, the tab panel content is only instantiated when the tab becomes active for the first time. Defaults to false. */\n readonly lazy = input(false);\n\n /** @internal Custom trigger template, if provided. */\n readonly triggerTemplate = contentChild(TabTriggerDirective);\n\n /** @internal Custom content template, if provided via twTabContent. */\n readonly contentTemplate = contentChild(TabContentDirective);\n\n /** @internal Implicit content template wrapping ng-content. */\n readonly implicitContentTemplate = viewChild<TemplateRef<unknown>>('implicitContent');\n}\n\n// ── Tab trigger element wrapper ──\n\n@Directive({\n selector: '[twTabTriggerElement]',\n host: {\n '[attr.tabindex]': 'tabIndex()',\n },\n})\nexport class TabTriggerElementDirective implements FocusableOption {\n readonly elementRef = inject(ElementRef<HTMLElement>);\n\n /**\n * Whether this trigger owns the tablist's single tab stop. Drives\n * `tabindex`. Normally the active tab, but the parent falls back to the\n * first enabled tab when `value` matches nothing, so the tablist is never\n * left with zero tab stops. Defaults to `false`.\n */\n readonly isFocusStop = input(false);\n\n /** Whether this trigger is disabled. Read by `FocusKeyManager` so disabled triggers are skipped during arrow navigation. Defaults to `false`. */\n readonly isDisabled = input(false);\n\n readonly tabIndex = computed(() => this.isFocusStop() ? 0 : -1);\n\n /** Moves DOM focus to the trigger element. Called by `FocusKeyManager` during arrow-key navigation. */\n focus(): void {\n this.elementRef.nativeElement.focus();\n }\n\n /**\n * FocusableOption getter. NOTE: we cannot expose the `isDisabled` input\n * signal directly — the signal function itself is always truthy, which would\n * make FocusKeyManager treat every trigger as disabled. We resolve the\n * signal here so the manager skips the right items.\n */\n get disabled(): boolean {\n return this.isDisabled();\n }\n}\n\n// ── TabsComponent ──\n\nlet nextId = 0;\n\n@Component({\n selector: 'tw-tabs',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [NgTemplateOutlet, TabTriggerElementDirective],\n templateUrl: './tabs.html',\n host: {\n '[class]': 'rootClasses()',\n },\n})\nexport class TabsComponent implements AfterViewInit {\n /** Controls the visual style of the tab strip. Defaults to 'underline'. */\n readonly variant = input<TabsVariant>('underline');\n\n /** Sets the semantic color for active tab indicators and highlights. Defaults to 'primary'. */\n readonly color = input<TwColor>('primary');\n\n /** Controls padding, font size, and icon size of tab triggers. Defaults to 'md'. */\n readonly size = input<TwSize>('md');\n\n /** Layout direction of the tab strip. Defaults to 'horizontal'. */\n readonly orientation = input<'horizontal' | 'vertical'>('horizontal');\n\n /** When true, tab triggers stretch to fill the available width equally. Defaults to false. */\n readonly fitted = input(false);\n\n /** The value of the currently active tab. Two-way bound. Updates when the user selects a tab. Defaults to an empty string. */\n readonly value = model<string>('');\n\n /** Fires when a closable tab is dismissed, either by clicking its close control or by pressing Delete while the tab has focus. Payload is the tab's value. */\n readonly closed = output<string>();\n\n private readonly destroyRef = inject(DestroyRef);\n private readonly liveAnnouncer = inject(LiveAnnouncer);\n private readonly directionality = inject(Directionality, { optional: true });\n\n /**\n * Live layout direction, read straight from CDK's `Directionality.valueSignal`\n * (CDK 22+) so the key-manager effect re-runs on a runtime `dir` flip with no\n * manual subscription mirror. Without a live direction the tablist hardcodes\n * 'ltr' and ArrowRight moves to the next tab in DOM order but the *previous*\n * tab visually in an RTL locale. CdkStepper and `tw-split` already honour\n * Directionality; `tw-paginator` reads `valueSignal` the same way.\n */\n private readonly layoutDirection = computed<'ltr' | 'rtl'>(\n () => this.directionality?.valueSignal() ?? 'ltr',\n );\n\n /** @internal */\n readonly tabs = contentChildren(TabComponent);\n\n /** @internal */\n readonly triggerElements = viewChildren(TabTriggerElementDirective);\n\n /** @internal */\n readonly tablistInnerRef = viewChild<ElementRef<HTMLElement>>('tablistInner');\n\n private readonly componentId = `tw-tabs-${nextId++}`;\n\n // ── Active tab tracking ──\n\n readonly activeValue = linkedSignal(() => this.value());\n\n // ── Lazy tab tracking — Set of tab values that have been activated at least once ──\n readonly activatedTabs = signal(new Set<string>());\n\n // ── Scroll overflow signals ──\n readonly canScrollStart = signal(false);\n readonly canScrollEnd = signal(false);\n\n private resizeObserver: ResizeObserver | null = null;\n private scrollCleanup: (() => void) | null = null;\n\n // ── Variant classes ──\n\n private readonly layoutResult = computed(() =>\n tabsLayoutVariants({\n variant: this.variant(),\n size: this.size(),\n orientation: this.orientation(),\n }),\n );\n\n private readonly triggerResult = computed(() =>\n tabTriggerVariants({\n variant: this.variant(),\n color: this.color(),\n size: this.size(),\n fitted: this.fitted(),\n }),\n );\n\n readonly rootClasses = computed(() => this.layoutResult().root());\n readonly tablistClasses = computed(() => this.layoutResult().tablist());\n readonly tablistInnerClasses = computed(() => this.layoutResult().tablistInner());\n readonly baseTriggerClasses = computed(() => this.triggerResult().trigger());\n readonly panelClasses = computed(() => this.layoutResult().panel());\n readonly scrollButtonClasses = computed(() => this.layoutResult().scrollButton());\n readonly closeButtonClasses = computed(() => this.layoutResult().closeButton());\n\n // ── Per-trigger active/inactive class computation ──\n\n /** @internal Get combined trigger classes for a given tab. */\n getTriggerClasses(_tabValue: string, isActive: boolean): string {\n const base = this.baseTriggerClasses();\n const orientationExtras = getTriggerOrientationExtras(this.variant(), this.orientation());\n const state = isActive\n ? getActiveTriggerClasses(this.variant(), this.color(), this.orientation())\n : getInactiveTriggerClasses(this.variant());\n return twMerge(base, orientationExtras, state);\n }\n\n // ── ID generation ──\n /** Builds the DOM id for a tab trigger, used by the panel's `aria-labelledby`. */\n getTabId(tabValue: string): string {\n return `${this.componentId}-tab-${tabValue}`;\n }\n\n /** Builds the DOM id for a tab panel, used by the trigger's `aria-controls`. */\n getPanelId(tabValue: string): string {\n return `${this.componentId}-panel-${tabValue}`;\n }\n\n // ── Tab visibility ──\n\n /** Whether the tab with the given value is the currently active one. */\n isTabActive(tabValue: string): boolean {\n return this.activeValue() === tabValue;\n }\n\n /**\n * @internal Value of the tab that owns the tablist's single tab stop.\n *\n * The active tab whenever it exists and is enabled. When `value` matches no\n * tab — a stale id, a value cleared after init, or an active tab that is\n * disabled — the first enabled tab takes the tab stop instead (standard\n * roving-tabindex recovery). Without the fallback every trigger renders\n * `tabindex=\"-1\"` and the whole tablist silently leaves the tab order\n * (WCAG SC 2.1.1).\n */\n readonly focusStopValue = computed<string | null>(() => {\n const tabs = this.tabs();\n const active = this.activeValue();\n const activeTab = tabs.find(t => t.value() === active && !t.disabled());\n if (activeTab) return activeTab.value();\n return tabs.find(t => !t.disabled())?.value() ?? null;\n });\n\n /** Whether the tab with the given value owns the tablist's single tab stop. */\n isTabFocusStop(tabValue: string): boolean {\n return this.focusStopValue() === tabValue;\n }\n\n /** Whether a tab's panel content should be in the DOM. Always true for eager tabs; for lazy tabs, true only once the tab has been activated at least once. */\n shouldRenderPanel(tab: TabComponent): boolean {\n const value = tab.value();\n if (!tab.lazy()) {\n return true;\n }\n // Lazy: render only if it has been activated at least once\n return this.activatedTabs().has(value);\n }\n\n // ── Selection ──\n\n /** Activates a tab, updating the two-way bound `value`, marking it rendered for lazy panels, and announcing the change via `LiveAnnouncer`. Ignored when the tab is disabled. */\n selectTab(tab: TabComponent): void {\n if (tab.disabled()) return;\n const val = tab.value();\n this.activeValue.set(val);\n this.value.set(val);\n\n // Mark as activated for lazy tabs\n this.activatedTabs.update(set => {\n const next = new Set(set);\n next.add(val);\n return next;\n });\n\n // Announce to screen readers\n const tabsArr = this.tabs();\n const idx = tabsArr.findIndex(t => t.value() === val);\n this.liveAnnouncer.announce(\n `${tab.label() || val} tab, ${idx + 1} of ${tabsArr.length}`,\n );\n }\n\n /** Closes a closable tab, emitting `closed` with its value and moving activation to the nearest enabled sibling when the closed tab was active. */\n closeTab(tab: TabComponent, event: Event): void {\n event.stopPropagation();\n if (event instanceof KeyboardEvent) {\n event.preventDefault();\n }\n const val = tab.value();\n this.closed.emit(val);\n\n // If closing the active tab, activate nearest enabled sibling\n if (this.isTabActive(val)) {\n const tabsArr = this.tabs();\n const idx = tabsArr.findIndex(t => t.value() === val);\n const next = this.findNearestEnabledTab(tabsArr, idx);\n if (next) {\n this.selectTab(next);\n }\n }\n }\n\n private findNearestEnabledTab(tabs: readonly TabComponent[], fromIndex: number): TabComponent | null {\n // Search forward first, then backward\n for (let i = fromIndex + 1; i < tabs.length; i++) {\n if (!tabs[i].disabled()) return tabs[i];\n }\n for (let i = fromIndex - 1; i >= 0; i--) {\n if (!tabs[i].disabled()) return tabs[i];\n }\n return null;\n }\n\n // ── Keyboard navigation (CDK FocusKeyManager) ──\n\n private keyManager: FocusKeyManager<TabTriggerElementDirective> | null = null;\n\n /**\n * @internal Handles keyboard navigation. The manager handles Arrow/Home/End;\n * we layer Enter/Space to select the focused tab (the wrapper is a `<div role=\"tab\">`\n * so we lose the native button activation) and Delete to close a closable tab.\n */\n onKeydown(event: KeyboardEvent): void {\n if (!this.keyManager) return;\n const triggers = this.triggerElements();\n if (triggers.length === 0) return;\n\n // Sync active item with the trigger DOM-focused by the user. We accept\n // either `event.target` (which works under shadow DOM) or the currently\n // active tab's index as a safety net (e.g. when the event was dispatched\n // on the tablist container itself, not a trigger).\n const focusedIdx = triggers.findIndex(\n t => t.elementRef.nativeElement === event.target,\n );\n const activeIdx = focusedIdx >= 0\n ? focusedIdx\n : this.tabs().findIndex(t => t.value() === this.activeValue());\n if (activeIdx >= 0 && activeIdx !== this.keyManager.activeItemIndex) {\n this.keyManager.setActiveItem(activeIdx);\n }\n\n // Enter / Space select the focused tab (we no longer get this for free\n // because the trigger is a div, not a button — see DOM restructure below).\n if (event.key === 'Enter' || event.key === ' ') {\n if (focusedIdx >= 0) {\n event.preventDefault();\n this.selectTab(this.tabs()[focusedIdx]);\n }\n return;\n }\n\n // Delete on a closable tab dismisses it (APG-recommended). This is the\n // ONLY keyboard path: the close control cannot be focusable without\n // failing axe's nested-interactive rule, so `aria-keyshortcuts=\"Delete\"`\n // on the trigger advertises this gesture to assistive tech.\n if (event.key === 'Delete' && focusedIdx >= 0) {\n const tab = this.tabs()[focusedIdx];\n if (tab.closable() && !tab.disabled()) {\n event.preventDefault();\n this.closeTab(tab, event);\n return;\n }\n }\n\n // Let the manager handle arrow/home/end navigation.\n const before = this.keyManager.activeItemIndex;\n this.keyManager.onKeydown(event);\n const after = this.keyManager.activeItemIndex;\n if (after !== null && after !== before && after >= 0) {\n // Automatic activation pattern (APG): selection follows focus.\n this.selectTab(this.tabs()[after]);\n }\n }\n\n // ── Scrolling ──\n\n /** Smoothly scrolls the tablist back toward its start by one step, along the current orientation's axis. */\n scrollStart(): void {\n const el = this.tablistInnerRef()?.nativeElement;\n if (!el) return;\n const isVertical = this.orientation() === 'vertical';\n if (isVertical) {\n el.scrollBy({ top: -120, behavior: 'smooth' });\n } else {\n el.scrollBy({ left: -120, behavior: 'smooth' });\n }\n }\n\n /** Smoothly scrolls the tablist forward toward its end by one step, along the current orientation's axis. */\n scrollEnd(): void {\n const el = this.tablistInnerRef()?.nativeElement;\n if (!el) return;\n const isVertical = this.orientation() === 'vertical';\n if (isVertical) {\n el.scrollBy({ top: 120, behavior: 'smooth' });\n } else {\n el.scrollBy({ left: 120, behavior: 'smooth' });\n }\n }\n\n private updateScrollState(): void {\n const el = this.tablistInnerRef()?.nativeElement;\n if (!el) return;\n\n const isVertical = this.orientation() === 'vertical';\n if (isVertical) {\n this.canScrollStart.set(el.scrollTop > 0);\n this.canScrollEnd.set(el.scrollTop + el.clientHeight < el.scrollHeight - 1);\n } else {\n this.canScrollStart.set(el.scrollLeft > 0);\n this.canScrollEnd.set(el.scrollLeft + el.clientWidth < el.scrollWidth - 1);\n }\n }\n\n ngAfterViewInit(): void {\n this.initializeActiveTab();\n }\n\n constructor() {\n afterNextRender(() => {\n this.setupScrollDetection();\n });\n\n // Rebuild FocusKeyManager whenever triggers, orientation or direction\n // change. `layoutDirection()` reads `Directionality.valueSignal` directly,\n // so an app that flips `dir` at runtime rebuilds the manager with the new\n // horizontal orientation without a subscription mirror.\n effect((onCleanup) => {\n const triggers = this.triggerElements();\n const orientation = this.orientation();\n if (triggers.length === 0) {\n this.keyManager = null;\n return;\n }\n const direction = this.layoutDirection();\n const manager = new FocusKeyManager(triggers)\n .withWrap()\n .withHomeAndEnd();\n if (orientation === 'vertical') {\n manager.withVerticalOrientation();\n } else {\n manager.withHorizontalOrientation(direction);\n }\n this.keyManager = manager;\n\n // Initialise the manager's active index to the active tab so the first\n // arrow press moves from the active item, not from -1.\n //\n // `updateActiveItem`, NOT `setActiveItem`: on a FocusKeyManager,\n // `setActiveItem` also moves DOM focus to the item. Calling it here —\n // during construction — makes merely MOUNTING a `<tw-tabs>` steal focus\n // from wherever the user was and scroll the tablist into view. On a page\n // where the tabs sit below the fold that silently jumps the viewport.\n // `updateActiveItem` seeds the index without touching focus, which is\n // all this needs; the keydown handler still uses `setActiveItem`, where\n // moving focus is the point.\n untracked(() => {\n // Seeded from the DOM tab stop, not from `activeValue()`: when `value`\n // matches no tab the tab stop falls back to the first enabled tab, and\n // seeding the manager with -1 there would desynchronise the two.\n const stopValue = this.focusStopValue();\n const tabs = this.tabs();\n const idx = tabs.findIndex(t => t.value() === stopValue);\n if (idx >= 0) {\n manager.updateActiveItem(idx);\n }\n });\n\n onCleanup(() => {\n manager.destroy();\n });\n });\n\n this.destroyRef.onDestroy(() => {\n this.resizeObserver?.disconnect();\n this.scrollCleanup?.();\n });\n }\n\n private initializeActiveTab(): void {\n // If no value was provided, default to the first enabled tab\n if (!this.activeValue()) {\n const first = this.tabs().find(t => !t.disabled());\n if (first) {\n this.activeValue.set(first.value());\n this.value.set(first.value());\n }\n }\n\n // Mark the initial active tab as activated (for lazy tracking)\n const val = this.activeValue();\n if (val) {\n this.activatedTabs.update(set => {\n const next = new Set(set);\n next.add(val);\n return next;\n });\n }\n }\n\n private setupScrollDetection(): void {\n const el = this.tablistInnerRef()?.nativeElement;\n if (!el) return;\n\n // Initial check\n this.updateScrollState();\n\n // ResizeObserver for container size changes\n if (typeof ResizeObserver !== 'undefined') {\n this.resizeObserver = new ResizeObserver(() => {\n this.updateScrollState();\n });\n this.resizeObserver.observe(el);\n }\n\n // Scroll event for scroll position changes\n const onScroll = () => this.updateScrollState();\n el.addEventListener('scroll', onScroll, { passive: true });\n this.scrollCleanup = () => el.removeEventListener('scroll', onScroll);\n }\n}\n","<!-- Tablist container. WAI-ARIA tablist owns roving focus on the tab elements\n inside; the container itself relays keydown but isn't tabbable. -->\n<!-- eslint-disable-next-line @angular-eslint/template/interactive-supports-focus -->\n<div\n [class]=\"tablistClasses()\"\n role=\"tablist\"\n [attr.aria-orientation]=\"orientation()\"\n (keydown)=\"onKeydown($event)\"\n>\n <!-- Scroll start button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollStart()\"\n (click)=\"scrollStart()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M9.78 4.22a.75.75 0 0 1 0 1.06L7.06 8l2.72 2.72a.75.75 0 1 1-1.06 1.06L5.47 8.53a.75.75 0 0 1 0-1.06l3.25-3.25a.75.75 0 0 1 1.06 0Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n\n <!-- Scrollable trigger strip -->\n <div #tablistInner [class]=\"tablistInnerClasses()\" style=\"scrollbar-width: none\">\n @for (tab of tabs(); track tab.value()) {\n <!-- Trigger is rendered as <div role=\"tab\">, not <button>: activation is\n wired explicitly via (click) and the parent tablist's keydown\n (Enter / Space), and the roving tab stop comes from\n twTabTriggerElement. -->\n <!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events, @angular-eslint/template/interactive-supports-focus -->\n <div\n role=\"tab\"\n twTabTriggerElement\n [isFocusStop]=\"isTabFocusStop(tab.value())\"\n [isDisabled]=\"tab.disabled()\"\n [id]=\"getTabId(tab.value())\"\n [attr.aria-selected]=\"isTabActive(tab.value())\"\n [attr.aria-controls]=\"getPanelId(tab.value())\"\n [attr.aria-disabled]=\"tab.disabled() || null\"\n [attr.aria-keyshortcuts]=\"tab.closable() && !tab.disabled() ? 'Delete' : null\"\n [class]=\"getTriggerClasses(tab.value(), isTabActive(tab.value()))\"\n [class.opacity-50]=\"tab.disabled()\"\n [class.pointer-events-none]=\"tab.disabled()\"\n (click)=\"selectTab(tab)\"\n >\n <!-- Custom trigger template or default label -->\n @if (tab.triggerTemplate(); as triggerDir) {\n <ng-container\n [ngTemplateOutlet]=\"triggerDir.templateRef\"\n [ngTemplateOutletContext]=\"{ $implicit: { active: isTabActive(tab.value()), disabled: tab.disabled(), value: tab.value() } }\"\n />\n } @else {\n {{ tab.label() }}\n }\n\n <!-- Close affordance — a pointer-only span, deliberately NOT a button.\n Anything focusable inside an element carrying an interactive role\n fails axe's nested-interactive rule, and hoisting a real button\n out to a sibling only trades that for aria-required-children\n (a tablist may own nothing but tabs — both measured). The\n keyboard path is the APG-recommended Delete key on the tab\n itself, handled in onKeydown and advertised to assistive tech\n through aria-keyshortcuts on the trigger above. -->\n @if (tab.closable() && !tab.disabled()) {\n <span\n data-tw-tab-close\n aria-hidden=\"true\"\n [class]=\"closeButtonClasses()\"\n (click)=\"closeTab(tab, $event)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path d=\"M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z\"/>\n </svg>\n </span>\n }\n </div>\n }\n </div>\n\n <!-- Scroll end button (horizontal only) -->\n @if (orientation() === 'horizontal' && (canScrollStart() || canScrollEnd())) {\n <button\n type=\"button\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [class]=\"scrollButtonClasses()\"\n [disabled]=\"!canScrollEnd()\"\n (click)=\"scrollEnd()\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 shrink-0\">\n <path fill-rule=\"evenodd\" d=\"M6.22 4.22a.75.75 0 0 1 1.06 0l3.25 3.25a.75.75 0 0 1 0 1.06l-3.25 3.25a.75.75 0 0 1-1.06-1.06L8.94 8 6.22 5.28a.75.75 0 0 1 0-1.06Z\" clip-rule=\"evenodd\" />\n </svg>\n </button>\n }\n</div>\n\n<!-- Tab panels -->\n@for (tab of tabs(); track tab.value()) {\n @if (shouldRenderPanel(tab)) {\n <div\n role=\"tabpanel\"\n [id]=\"getPanelId(tab.value())\"\n [attr.aria-labelledby]=\"getTabId(tab.value())\"\n [class]=\"panelClasses()\"\n [hidden]=\"!isTabActive(tab.value())\"\n tabindex=\"0\"\n >\n @if (tab.contentTemplate(); as contentDir) {\n <ng-container [ngTemplateOutlet]=\"contentDir.templateRef\" />\n } @else if (tab.implicitContentTemplate(); as implicitTpl) {\n <ng-container [ngTemplateOutlet]=\"implicitTpl\" />\n }\n </div>\n }\n}\n\n<!-- Hidden projection slot for tw-tab children -->\n<div style=\"display: none\">\n <ng-content />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}