@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,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { input, model, output, inject, ElementRef, DestroyRef, signal, computed, afterNextRender, isDevMode, linkedSignal, forwardRef, ChangeDetectionStrategy, Component } from '@angular/core';
3
- import { NgControl, NgForm, FormGroupDirective, Validators } from '@angular/forms';
3
+ import { NgControl, Validators } from '@angular/forms';
4
4
  import { FocusMonitor } from '@angular/cdk/a11y';
5
5
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
- import { isObservable, merge } from 'rxjs';
6
+ import { isObservable } from 'rxjs';
7
7
  import { tv } from 'tailwind-variants';
8
- import { TW_ERROR_STATE_MATCHER } from '@cdevhub/ngx-tw/core';
8
+ import { wireErrorState } from '@cdevhub/ngx-tw/core';
9
9
  import { FormFieldControl, TW_FORM_FIELD_CONTROL } from '@cdevhub/ngx-tw/form-field';
10
10
 
11
11
  // ── tv() config ──────────────────────────────────────────────────
@@ -14,6 +14,27 @@ const checkboxVariants = tv({
14
14
  // `items-start` aligns the boxWrap with the top of the label container; combined with
15
15
  // a `min-h-N` matching the label's first-line line-height on boxWrap, the box stays
16
16
  // centered on the first line of the label whether it spans one line or many.
17
+ //
18
+ // ── Row-height scale (selection cohort) ──────────────────────────────
19
+ // The rendered row is `max(boxWrap, label first line)`, and the host itself is the
20
+ // click target (`role="checkbox"` + `tabindex` + `(click)` all sit on the root), so
21
+ // the row IS the interactive target. It runs 16 / 20 / 24 / 28 / 32 px — five distinct
22
+ // steps, every one on the 4px baseline of docs/vertical-rhythm.md, and identical to
23
+ // `switch`, the sibling selection control. Selection controls are glyph-scale and
24
+ // deliberately do NOT take the pinned 24/32/36/44/48 form-row scale (vertical-rhythm.md
25
+ // section 4).
26
+ //
27
+ // The row is driven by `boxWrap` min-h, NOT by the box glyph, which stays at its own
28
+ // well-proportioned 14 / 16 / 20 / 24 / 28 scale (4px of slack inside the row at every
29
+ // size; 2px at xs, where the codified size-3.5 half-step applies). Driving it from
30
+ // boxWrap is what makes the five steps survive when no label is projected.
31
+ //
32
+ // Because centering demands `boxWrap height == label first-line leading`, the label
33
+ // leading carries the same 4 / 5 / 6 / 7 / 8 progression. That is forced, not chosen:
34
+ // the label font scale has only three steps (text-xs, text-sm, text-base), so leading
35
+ // is the only lever that can break the sm/md and lg/xl ties. Before this, sm and md
36
+ // both rendered a 20px row — a dead step. Accepted cost: `text-base leading-8` at xl is
37
+ // a 2.0 line ratio, looser than typographic ideal on a wrapped multi-line label.
17
38
  root: 'relative inline-flex items-start gap-3 cursor-pointer select-none rounded-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500',
18
39
  boxWrap: 'relative inline-flex items-center justify-center shrink-0',
19
40
  box: 'inline-flex items-center justify-center rounded-md border transition-colors duration-normal motion-reduce:transition-none',
@@ -45,24 +66,27 @@ const checkboxVariants = tv({
45
66
  // size-5 (20px) box; the half-step is the only size that fills the
46
67
  // checkmark without crowding the box edges.
47
68
  icon: '[&_svg]:size-3.5',
48
- boxWrap: 'min-h-5',
49
- label: 'text-sm leading-5',
69
+ // 24px row. `text-sm` is shared with sm by the documented font scale, so the
70
+ // leading breaks the tie: leading-6 lifts the row off sm's 20px.
71
+ boxWrap: 'min-h-6',
72
+ label: 'text-sm leading-6',
50
73
  description: 'text-xs leading-4',
51
74
  },
52
75
  lg: {
53
76
  box: 'size-6',
54
77
  icon: '[&_svg]:size-4',
55
- boxWrap: 'min-h-6',
56
- label: 'text-base leading-6',
78
+ // 28px row — leading-7 keeps the first label line the same height as boxWrap.
79
+ boxWrap: 'min-h-7',
80
+ label: 'text-base leading-7',
57
81
  description: 'text-sm leading-5',
58
82
  },
59
83
  xl: {
60
84
  box: 'size-7',
61
85
  icon: '[&_svg]:size-5',
62
- // xl box (28px) > default text-base line-height (24px); bump leading to leading-7
63
- // so the first line height matches the box and they align cleanly.
64
- boxWrap: 'min-h-7',
65
- label: 'text-base leading-7',
86
+ // 32px row. `text-base` is shared with lg, so leading-8 breaks that tie the same
87
+ // way leading-6 breaks sm/md. A 2.0 ratio on a wrapped label is the accepted cost.
88
+ boxWrap: 'min-h-8',
89
+ label: 'text-base leading-8',
66
90
  description: 'text-sm leading-5',
67
91
  },
68
92
  },
@@ -156,44 +180,72 @@ class CheckboxComponent extends FormFieldControl {
156
180
  /** Optional name attribute, applied to the hidden native `<input type="checkbox">` so native form submission includes the control. */
157
181
  name = input(undefined, /* @ts-ignore */
158
182
  ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
159
- /** Id on the host element. Auto-generated as `tw-checkbox-N` when not provided. Used by the form-field's `<label for>` attribute. */
183
+ /** Id on the host element. Auto-generated as `tw-checkbox-N` when not provided. Anchors the derived label/description ids; the accessible name inside a `<tw-form-field>` comes from `aria-labelledby`, not from the field's `<label for>` (the host is a custom element, which `for` cannot target). */
160
184
  idInput = input(undefined, { ...(ngDevMode ? { debugName: "idInput" } : /* istanbul ignore next */ {}), alias: 'id' });
161
- /** Accessible name when no visible label is provided. Mirrored to `aria-label`. */
185
+ /** Accessible name when no visible label is provided. Mirrored to `aria-label`. Defaults to `undefined`. */
162
186
  ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'aria-label' });
163
- /** ID of an external element that labels the checkbox. Mirrored to `aria-labelledby`. */
187
+ /** ID of an external element that labels the checkbox. Mirrored to `aria-labelledby`. Defaults to `undefined`. */
164
188
  ariaLabelledby = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabelledby" } : /* istanbul ignore next */ {}), alias: 'aria-labelledby' });
165
- /** ID of an external element that describes the checkbox. Mirrored to `aria-describedby`. Form-field merges its hint/error ids alongside. */
189
+ /** ID of an external element that describes the checkbox. Mirrored to `aria-describedby`. Form-field merges its hint/error ids alongside. Defaults to `undefined`. */
166
190
  ariaDescribedby = input(undefined, { ...(ngDevMode ? { debugName: "ariaDescribedby" } : /* istanbul ignore next */ {}), alias: 'aria-describedby' });
167
191
  /** Per-instance override of the {@link ErrorStateMatcher}. When omitted, the directive uses the `TW_ERROR_STATE_MATCHER` token's value. */
168
192
  errorStateMatcher = input(undefined, /* @ts-ignore */
169
193
  ...(ngDevMode ? [{ debugName: "errorStateMatcher" }] : /* istanbul ignore next */ []));
170
- /** Two-way bound checked state. Updates when the user toggles via click or Space. */
194
+ /**
195
+ * Two-way bound checked state. Updates when the user toggles via click or
196
+ * Space, **and** when a bound form writes into the control
197
+ * (`FormControl.setValue`, `ngModel`, `writeValue`). Defaults to `false`.
198
+ *
199
+ * The two-way binding mints a `checkedChange` output. That output is the
200
+ * *any-change* channel: it fires on programmatic writes as well as user
201
+ * gestures. `(change)` is the *user-gesture-only* channel. Bind
202
+ * `(checkedChange)` to mirror state; bind `(change)` for analytics or a
203
+ * confirmation prompt, where a programmatic write must not count as a click.
204
+ * Writing back into the same form from a `(checkedChange)` handler will echo.
205
+ */
171
206
  checked = model(false, /* @ts-ignore */
172
207
  ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
173
- /** Two-way bound indeterminate state. When true, the box shows a dash and the host exposes `aria-checked="mixed"`. Any user toggle clears indeterminate and sets `checked` to `true`. */
208
+ /**
209
+ * Two-way bound indeterminate state. When true, the box shows a dash and the
210
+ * host exposes `aria-checked="mixed"`. Any user toggle clears indeterminate
211
+ * and sets `checked` to `true`. Defaults to `false`.
212
+ *
213
+ * Its minted `indeterminateChange` output follows the same rule as
214
+ * `checkedChange`: it also fires when `writeValue` clears the state, so it is
215
+ * an any-change channel, not a gesture channel.
216
+ */
174
217
  indeterminate = model(false, /* @ts-ignore */
175
218
  ...(ngDevMode ? [{ debugName: "indeterminate" }] : /* istanbul ignore next */ []));
176
- /** Fires after the checked state changes from a user interaction. Does not fire when the value is updated programmatically via `writeValue`. */
219
+ /**
220
+ * Fires after the checked state changes from a user interaction (click or
221
+ * Space). Does **not** fire when the value is updated programmatically via
222
+ * `writeValue` / `FormControl.setValue` / `ngModel` — for those, bind the
223
+ * two-way binding's `(checkedChange)` instead, which fires on any change.
224
+ */
177
225
  change = output();
178
226
  focusMonitor = inject(FocusMonitor);
179
227
  elementRef = inject((ElementRef));
180
228
  destroyRef = inject(DestroyRef);
181
229
  ngControl = inject(NgControl, { optional: true, self: true });
182
- parentForm = inject(NgForm, { optional: true });
183
- parentFormGroup = inject(FormGroupDirective, { optional: true });
184
- defaultMatcher = inject(TW_ERROR_STATE_MATCHER);
185
230
  onChange = () => { };
186
231
  onTouched = () => { };
187
232
  cvaDisabled = signal(false, /* @ts-ignore */
188
233
  ...(ngDevMode ? [{ debugName: "cvaDisabled" }] : /* istanbul ignore next */ []));
189
234
  _focused = signal(false, /* @ts-ignore */
190
235
  ...(ngDevMode ? [{ debugName: "_focused" }] : /* istanbul ignore next */ []));
191
- _ngControlRev = signal(0, /* @ts-ignore */
192
- ...(ngDevMode ? [{ debugName: "_ngControlRev" }] : /* istanbul ignore next */ []));
193
- _formSubmitRev = signal(0, /* @ts-ignore */
194
- ...(ngDevMode ? [{ debugName: "_formSubmitRev" }] : /* istanbul ignore next */ []));
236
+ /** @internal Shared `errorState` / `required` / `errors` derivation — see `wireErrorState`. */
237
+ errorWiring = wireErrorState({
238
+ ngControl: () => this.ngControl,
239
+ matcher: () => this.errorStateMatcher(),
240
+ required: () => this.requiredInput(),
241
+ // A checkbox bound with `Validators.requiredTrue` is required too.
242
+ requiredValidators: [Validators.required, Validators.requiredTrue],
243
+ track: [() => this._focused()],
244
+ });
195
245
  describedByIdsSignal = signal([], /* @ts-ignore */
196
246
  ...(ngDevMode ? [{ debugName: "describedByIdsSignal" }] : /* istanbul ignore next */ []));
247
+ labelledByIdsSignal = signal([], /* @ts-ignore */
248
+ ...(ngDevMode ? [{ debugName: "labelledByIdsSignal" }] : /* istanbul ignore next */ []));
197
249
  uid = nextId++;
198
250
  /** @internal Fallback id used when the consumer does not set `[id]`. */
199
251
  hostId = `tw-checkbox-${this.uid}`;
@@ -249,6 +301,16 @@ class CheckboxComponent extends FormFieldControl {
249
301
  }, /* @ts-ignore */
250
302
  ...(ngDevMode ? [{ debugName: "ariaCheckedValue" }] : /* istanbul ignore next */ []));
251
303
  effectiveAriaLabelledby = computed(() => {
304
+ // A wrapping `<tw-form-field>` pushes the projected `<label twLabel>` id (plus
305
+ // any consumer `aria-labelledby`) through `setLabelledByIds`. Those ids win:
306
+ // the host is `<tw-checkbox role="checkbox">`, a custom element that is not a
307
+ // labelable form control, so the field's `<label for>` resolves to nothing and
308
+ // this attribute is the ONLY route from the visible label to the control.
309
+ // Without it the checkbox's own label span is empty in that arrangement — the
310
+ // visible text lives in the form-field — and the control has no name at all.
311
+ const pushed = this.labelledByIdsSignal();
312
+ if (pushed.length)
313
+ return pushed.join(' ');
252
314
  const external = this.ariaLabelledby();
253
315
  if (external)
254
316
  return external;
@@ -286,32 +348,19 @@ class CheckboxComponent extends FormFieldControl {
286
348
  empty = computed(() => false, /* @ts-ignore */
287
349
  ...(ngDevMode ? [{ debugName: "empty" }] : /* istanbul ignore next */ []));
288
350
  /** @internal */
289
- required = computed(() => {
290
- this._ngControlRev();
291
- if (this.requiredInput())
292
- return true;
293
- const ctrl = this.ngControl?.control;
294
- if (!ctrl)
295
- return false;
296
- return ctrl.hasValidator(Validators.required) || ctrl.hasValidator(Validators.requiredTrue);
297
- }, /* @ts-ignore */
298
- ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
351
+ required = this.errorWiring.required;
299
352
  /** @internal */
300
- errorState = computed(() => {
301
- this._ngControlRev();
302
- this._formSubmitRev();
303
- this._focused();
304
- const matcher = this.errorStateMatcher() ?? this.defaultMatcher;
305
- const form = this.parentFormGroup ??
306
- this.parentForm;
307
- return matcher.isErrorState(this.ngControl?.control ?? null, form);
308
- }, /* @ts-ignore */
309
- ...(ngDevMode ? [{ debugName: "errorState" }] : /* istanbul ignore next */ []));
353
+ errorState = this.errorWiring.errorState;
354
+ /** @internal Active validation errors map from the bound `NgControl`. Drives `[twError match="…"]` inside a wrapping `tw-form-field`; without it the form-field's key set is permanently empty and every `match`ed error stays hidden. */
355
+ errors = this.errorWiring.errors;
310
356
  /** @internal */
311
357
  controlType = 'checkbox';
312
358
  /** @internal */
313
359
  userAriaDescribedBy = computed(() => this.ariaDescribedby(), /* @ts-ignore */
314
360
  ...(ngDevMode ? [{ debugName: "userAriaDescribedBy" }] : /* istanbul ignore next */ []));
361
+ /** @internal Consumer-supplied `aria-labelledby`, surfaced so the wrapping form-field merges it into the ids it pushes back rather than replacing it. */
362
+ userAriaLabelledby = computed(() => this.ariaLabelledby(), /* @ts-ignore */
363
+ ...(ngDevMode ? [{ debugName: "userAriaLabelledby" }] : /* istanbul ignore next */ []));
315
364
  variantResult = computed(() => checkboxVariants({
316
365
  size: this.size(),
317
366
  labelPosition: this.labelPosition(),
@@ -366,7 +415,12 @@ class CheckboxComponent extends FormFieldControl {
366
415
  this.indeterminate.set(false);
367
416
  }
368
417
  this.onChange(next);
369
- this.onTouched();
418
+ // Deliberately NOT `onTouched()`. Angular's CVA contract registers
419
+ // `onTouched` as the BLUR notification; calling it here flipped `touched`
420
+ // the instant the value changed, so a consumer staging error display on
421
+ // `touched` ("only once they leave the field") got different behaviour from
422
+ // `tw-checkbox` than from `tw-slider` / `tw-input`. `onBlur()` below is the
423
+ // only place that fires it.
370
424
  this.change.emit(next);
371
425
  }
372
426
  /** Handles keyboard activation. Only Space toggles — matches native checkbox semantics. */
@@ -381,7 +435,7 @@ class CheckboxComponent extends FormFieldControl {
381
435
  /** @internal Called on host blur to notify forms the control has been touched and recompute errorState. */
382
436
  onBlur() {
383
437
  this.onTouched();
384
- this._ngControlRev.update((n) => n + 1);
438
+ this.errorWiring.bump();
385
439
  }
386
440
  // ── ControlValueAccessor ──────────────────────────────────
387
441
  writeValue(value) {
@@ -405,6 +459,10 @@ class CheckboxComponent extends FormFieldControl {
405
459
  setDescribedByIds(ids) {
406
460
  this.describedByIdsSignal.set([...ids]);
407
461
  }
462
+ /** @internal Receives the merged `aria-labelledby` ids from the wrapping form-field. Required because the host is a custom element rather than a labelable control, so the field's `<label for>` never reaches it. */
463
+ setLabelledByIds(ids) {
464
+ this.labelledByIdsSignal.set([...ids]);
465
+ }
408
466
  /** @internal Called when the form-field container is clicked — focus the host without toggling. */
409
467
  onContainerClick(event) {
410
468
  if (this.isDisabled())
@@ -429,7 +487,7 @@ class CheckboxComponent extends FormFieldControl {
429
487
  // Blur often flips `touched` on the bound `NgControl`; notify forms
430
488
  // and bump the revision so `errorState` recomputes.
431
489
  this.onTouched();
432
- this._ngControlRev.update((n) => n + 1);
490
+ this.errorWiring.bump();
433
491
  }
434
492
  });
435
493
  }
@@ -437,23 +495,9 @@ class CheckboxComponent extends FormFieldControl {
437
495
  this.focusMonitor.stopMonitoring(this.elementRef);
438
496
  });
439
497
  // NgControl's `control` is set by the parent FormControl* directive before
440
- // children's `ngOnInit`. Subscribe here so errorState reacts to status/value
498
+ // children's `ngOnInit`. Connect here so errorState reacts to status/value
441
499
  // changes on the bound control.
442
- const ctrl = this.ngControl?.control;
443
- if (ctrl) {
444
- const streams = [ctrl.statusChanges, ctrl.valueChanges].filter((s) => !!s);
445
- if (streams.length) {
446
- merge(...streams)
447
- .pipe(takeUntilDestroyed(this.destroyRef))
448
- .subscribe(() => this._ngControlRev.update((n) => n + 1));
449
- }
450
- }
451
- const submit = this.parentFormGroup?.ngSubmit ?? this.parentForm?.ngSubmit;
452
- if (submit) {
453
- submit
454
- .pipe(takeUntilDestroyed(this.destroyRef))
455
- .subscribe(() => this._formSubmitRev.update((n) => n + 1));
456
- }
500
+ this.errorWiring.connect();
457
501
  }
458
502
  hasAccessibleNameHint() {
459
503
  if (this.label() || this.ariaLabel() || this.ariaLabelledby())
@@ -1 +1 @@
1
- {"version":3,"file":"cdevhub-ngx-tw-checkbox.mjs","sources":["../../../projects/ngx-tw/checkbox/checkbox.ts","../../../projects/ngx-tw/checkbox/cdevhub-ngx-tw-checkbox.ts"],"sourcesContent":["import {\n afterNextRender,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n ElementRef,\n forwardRef,\n inject,\n input,\n isDevMode,\n linkedSignal,\n model,\n type OnInit,\n output,\n signal,\n type Signal,\n} from '@angular/core';\nimport {\n type ControlValueAccessor,\n FormGroupDirective,\n NgControl,\n NgForm,\n Validators,\n} from '@angular/forms';\nimport { FocusMonitor } from '@angular/cdk/a11y';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { isObservable, merge } from 'rxjs';\nimport { tv } from 'tailwind-variants';\nimport {\n type ErrorStateMatcher,\n TW_ERROR_STATE_MATCHER,\n type TwColor,\n type TwFormSubmitted,\n type TwSize,\n} from '@cdevhub/ngx-tw/core';\nimport { FormFieldControl, TW_FORM_FIELD_CONTROL } from '@cdevhub/ngx-tw/form-field';\n\n/** Visual style of the checkbox when checked or indeterminate. */\nexport type CheckboxVariant = 'solid' | 'outline';\n\n/** Position of the label relative to the checkbox control. */\nexport type CheckboxLabelPosition = 'before' | 'after';\n\n// ── tv() config ──────────────────────────────────────────────────\n\nconst checkboxVariants = tv(\n {\n slots: {\n // `items-start` aligns the boxWrap with the top of the label container; combined with\n // a `min-h-N` matching the label's first-line line-height on boxWrap, the box stays\n // centered on the first line of the label whether it spans one line or many.\n root: 'relative inline-flex items-start gap-3 cursor-pointer select-none rounded-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500',\n boxWrap: 'relative inline-flex items-center justify-center shrink-0',\n box: 'inline-flex items-center justify-center rounded-md border transition-colors duration-normal motion-reduce:transition-none',\n icon: 'absolute inset-0 flex items-center justify-center pointer-events-none empty:hidden',\n labelWrap: 'flex flex-col min-w-0 empty:hidden',\n label: 'font-medium text-fg empty:hidden',\n description: 'text-fg-muted empty:hidden',\n },\n variants: {\n size: {\n xs: {\n // `size-3.5` half-step: aligns with text-xs/leading-4. Codified per CLAUDE.md.\n box: 'size-3.5',\n icon: '[&_svg]:size-3',\n boxWrap: 'min-h-4',\n label: 'text-xs leading-4',\n description: 'text-2xs leading-4',\n },\n sm: {\n box: 'size-4',\n icon: '[&_svg]:size-3',\n boxWrap: 'min-h-5',\n label: 'text-sm leading-5',\n description: 'text-xs leading-4',\n },\n md: {\n box: 'size-5',\n // md icon uses `size-3.5` (14px) — proportional inset (70%) of the\n // size-5 (20px) box; the half-step is the only size that fills the\n // checkmark without crowding the box edges.\n icon: '[&_svg]:size-3.5',\n boxWrap: 'min-h-5',\n label: 'text-sm leading-5',\n description: 'text-xs leading-4',\n },\n lg: {\n box: 'size-6',\n icon: '[&_svg]:size-4',\n boxWrap: 'min-h-6',\n label: 'text-base leading-6',\n description: 'text-sm leading-5',\n },\n xl: {\n box: 'size-7',\n icon: '[&_svg]:size-5',\n // xl box (28px) > default text-base line-height (24px); bump leading to leading-7\n // so the first line height matches the box and they align cleanly.\n boxWrap: 'min-h-7',\n label: 'text-base leading-7',\n description: 'text-sm leading-5',\n },\n },\n labelPosition: {\n before: { root: 'flex-row-reverse' },\n after: { root: 'flex-row' },\n },\n active: {\n true: { box: '' },\n false: { box: 'bg-surface border-border hover:border-border-strong' },\n },\n disabled: {\n true: { root: 'opacity-50 pointer-events-none cursor-not-allowed' },\n false: { root: '' },\n },\n },\n defaultVariants: {\n size: 'md',\n labelPosition: 'after',\n active: false,\n disabled: false,\n },\n },\n { twMerge: true },\n);\n\n// ── Static active-state color lookups (statically written for Tailwind v4 scanning) ──\n\nconst SOLID_BOX: Record<TwColor, string> = {\n primary: 'bg-primary-600 border-primary-600',\n secondary: 'bg-secondary-600 border-secondary-600',\n accent: 'bg-accent-600 border-accent-600',\n neutral: 'bg-fg border-fg',\n info: 'bg-info-600 border-info-600',\n success: 'bg-success-600 border-success-600',\n warning: 'bg-warning-500 border-warning-500',\n error: 'bg-error-600 border-error-600',\n};\n\nconst SOLID_ICON: Record<TwColor, string> = {\n primary: 'text-on-primary',\n secondary: 'text-on-secondary',\n accent: 'text-on-accent',\n neutral: 'text-on-neutral',\n info: 'text-on-info',\n success: 'text-on-success',\n warning: 'text-on-warning',\n error: 'text-on-error',\n};\n\nconst OUTLINE_BOX: Record<TwColor, string> = {\n primary: 'bg-surface border-primary-600',\n secondary: 'bg-surface border-secondary-600',\n accent: 'bg-surface border-accent-600',\n neutral: 'bg-surface border-fg',\n info: 'bg-surface border-info-600',\n success: 'bg-surface border-success-600',\n warning: 'bg-surface border-warning-500',\n error: 'bg-surface border-error-600',\n};\n\nconst OUTLINE_ICON: Record<TwColor, string> = {\n primary: 'text-primary-600',\n secondary: 'text-secondary-600',\n accent: 'text-accent-600',\n neutral: 'text-fg',\n info: 'text-info-600',\n success: 'text-success-600',\n warning: 'text-warning-600',\n error: 'text-error-600',\n};\n\nlet nextId = 0;\n\n// ── CheckboxComponent ────────────────────────────────────────────\n\n@Component({\n selector: 'tw-checkbox',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: TW_FORM_FIELD_CONTROL,\n useExisting: forwardRef(() => CheckboxComponent),\n },\n ],\n template: `\n <!--\n Hidden form-submission proxy. Uses \\`hidden\\` (display:none), not \\`sr-only\\`:\n a display:none control is excluded from focus order so axe's\n \\`nested-interactive\\` rule doesn't flag it inside the \\`role=\"checkbox\"\\`\n host, yet it still participates in native (non-Angular) form submission —\n the entry-list algorithm excludes only \\`disabled\\` controls, not hidden ones.\n -->\n <input\n type=\"checkbox\"\n hidden\n aria-hidden=\"true\"\n [name]=\"name() || null\"\n [checked]=\"internalChecked()\"\n [disabled]=\"isDisabled()\"\n />\n\n <span [class]=\"boxWrapClasses()\">\n <span [class]=\"boxClasses()\">\n <span [class]=\"iconClasses()\">\n @if (internalIndeterminate()) {\n <span [class]=\"iconColorClasses()\" animate.enter=\"check-in\">\n <ng-content select=\"[slot='indeterminate-icon']\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M5 12 h14\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </ng-content>\n </span>\n } @else if (internalChecked()) {\n <span [class]=\"iconColorClasses()\" animate.enter=\"check-in\">\n <ng-content select=\"[slot='check-icon']\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M5 12 l5 5 l9 -11\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </ng-content>\n </span>\n }\n </span>\n </span>\n </span>\n\n <span [class]=\"labelWrapClasses()\">\n <span [id]=\"labelElementId()\" [class]=\"labelClasses()\">\n <ng-content>\n @if (label()) {\n {{ label() }}\n }\n </ng-content>\n </span>\n <span [id]=\"descriptionElementId()\" [class]=\"descriptionClasses()\">\n <ng-content select=\"[slot='description']\">\n @if (description()) {\n {{ description() }}\n }\n </ng-content>\n </span>\n </span>\n `,\n host: {\n 'role': 'checkbox',\n '[id]': 'id()',\n '[class]': 'rootClasses()',\n '[attr.data-checked]': 'internalChecked()',\n '[attr.data-indeterminate]': 'internalIndeterminate()',\n '[attr.aria-checked]': 'ariaCheckedValue()',\n '[attr.aria-disabled]': 'isDisabled() || null',\n '[attr.aria-required]': 'required() || null',\n '[attr.aria-invalid]': 'errorState() || null',\n '[attr.aria-label]': 'ariaLabel() || null',\n '[attr.aria-labelledby]': 'effectiveAriaLabelledby() || null',\n '[attr.aria-describedby]': 'effectiveAriaDescribedby() || null',\n '[attr.tabindex]': 'isDisabled() ? -1 : 0',\n '[attr.name]': 'name() || null',\n '(click)': 'toggle()',\n '(keydown)': 'onKeydown($event)',\n '(blur)': 'onBlur()',\n },\n})\nexport class CheckboxComponent\n extends FormFieldControl<boolean>\n implements ControlValueAccessor, OnInit\n{\n /** Sets the semantic color for the checked and indeterminate box fill/border. Defaults to `'primary'`. */\n readonly color = input<TwColor>('primary');\n\n /** Controls the overall scale of the box, check icon, and label typography. Defaults to `'md'`. */\n readonly size = input<TwSize>('md');\n\n /** Visual style when checked or indeterminate. `'solid'` fills the box with the color; `'outline'` keeps a transparent fill with a colored border and check. Defaults to `'solid'`. */\n readonly variant = input<CheckboxVariant>('solid');\n\n /** When true, prevents interaction and applies muted styling. Defaults to `false`. */\n readonly disabled = input(false);\n\n /** When true, sets `aria-required=\"true\"` so assistive tech announces the control as required. Defaults to `false`. */\n readonly requiredInput = input(false, { alias: 'required' });\n\n /** Optional inline label rendered next to the checkbox. Use default content projection for rich label content instead. Projection takes precedence. */\n readonly label = input<string | undefined>(undefined);\n\n /** Optional secondary description rendered under the label. Use `[slot=\"description\"]` content projection for rich content instead. Projection takes precedence. */\n readonly description = input<string | undefined>(undefined);\n\n /** Position of the label/description relative to the checkbox. Defaults to `'after'`. */\n readonly labelPosition = input<CheckboxLabelPosition>('after');\n\n /** Optional name attribute, applied to the hidden native `<input type=\"checkbox\">` so native form submission includes the control. */\n readonly name = input<string | undefined>(undefined);\n\n /** Id on the host element. Auto-generated as `tw-checkbox-N` when not provided. Used by the form-field's `<label for>` attribute. */\n readonly idInput = input<string | undefined>(undefined, { alias: 'id' });\n\n /** Accessible name when no visible label is provided. Mirrored to `aria-label`. */\n readonly ariaLabel = input<string | undefined>(undefined, { alias: 'aria-label' });\n\n /** ID of an external element that labels the checkbox. Mirrored to `aria-labelledby`. */\n readonly ariaLabelledby = input<string | undefined>(undefined, { alias: 'aria-labelledby' });\n\n /** ID of an external element that describes the checkbox. Mirrored to `aria-describedby`. Form-field merges its hint/error ids alongside. */\n readonly ariaDescribedby = input<string | undefined>(undefined, { alias: 'aria-describedby' });\n\n /** Per-instance override of the {@link ErrorStateMatcher}. When omitted, the directive uses the `TW_ERROR_STATE_MATCHER` token's value. */\n readonly errorStateMatcher = input<ErrorStateMatcher | undefined>(undefined);\n\n /** Two-way bound checked state. Updates when the user toggles via click or Space. */\n readonly checked = model(false);\n\n /** Two-way bound indeterminate state. When true, the box shows a dash and the host exposes `aria-checked=\"mixed\"`. Any user toggle clears indeterminate and sets `checked` to `true`. */\n readonly indeterminate = model(false);\n\n /** Fires after the checked state changes from a user interaction. Does not fire when the value is updated programmatically via `writeValue`. */\n readonly change = output<boolean>();\n\n private readonly focusMonitor = inject(FocusMonitor);\n private readonly elementRef = inject(ElementRef<HTMLElement>);\n private readonly destroyRef = inject(DestroyRef);\n private readonly ngControl = inject(NgControl, { optional: true, self: true });\n private readonly parentForm = inject(NgForm, { optional: true });\n private readonly parentFormGroup = inject(FormGroupDirective, { optional: true });\n private readonly defaultMatcher = inject(TW_ERROR_STATE_MATCHER);\n\n private onChange: (value: boolean) => void = () => {};\n private onTouched: () => void = () => {};\n private readonly cvaDisabled = signal(false);\n\n private readonly _focused = signal(false);\n private readonly _ngControlRev = signal(0);\n private readonly _formSubmitRev = signal(0);\n private readonly describedByIdsSignal = signal<readonly string[]>([]);\n\n private readonly uid = nextId++;\n /** @internal Fallback id used when the consumer does not set `[id]`. */\n readonly hostId = `tw-checkbox-${this.uid}`;\n\n /** @internal Resolved id on the host element. */\n readonly id: Signal<string> = computed(() => this.idInput() ?? this.hostId);\n\n /** @internal Id of the internal label `<span>`, derived from the resolved host id. */\n readonly labelElementId = computed(() => `${this.id()}-label`);\n\n /** @internal Id of the internal description `<span>`, derived from the resolved host id. */\n readonly descriptionElementId = computed(() => `${this.id()}-description`);\n\n constructor() {\n super();\n // Material-style CVA wiring: declare ourselves as the value accessor on any\n // host-level `NgControl` (FormControlDirective, NgModel, etc.). This avoids\n // the circular-DI that a static `NG_VALUE_ACCESSOR` provider would create\n // because `NgControl` is injected with `self: true` on the same element.\n if (this.ngControl) {\n this.ngControl.valueAccessor = this;\n }\n\n afterNextRender(() => {\n if (isDevMode() && !this.hasAccessibleNameHint()) {\n console.warn(\n '[tw-checkbox] The checkbox has no accessible name. Provide a `label` input, project label content, or set `aria-label` / `aria-labelledby`.',\n );\n }\n });\n }\n\n /** @internal */\n readonly isDisabled = computed(() => this.disabled() || this.cvaDisabled());\n\n /**\n * @internal Visible-state mirror of the `checked` model. `linkedSignal` keeps it\n * synced with parent updates (including `writeValue` from reactive forms), while\n * also accepting explicit `set()` calls from `toggle()` / `writeValue()` so the\n * DOM reflects the new state synchronously — before `checkedChange` propagates\n * through the host binding round-trip. Reading this signal in host bindings\n * (`aria-checked`, `data-checked`, box classes) decouples render from the\n * model's notification cadence.\n */\n readonly internalChecked = linkedSignal(() => this.checked());\n\n /**\n * @internal Visible-state mirror of the `indeterminate` model. Same rationale as\n * `internalChecked` — `toggle()` and `writeValue()` clear it synchronously so\n * `aria-checked=\"mixed\"` flips off in the same microtask as `aria-checked=\"true\"`.\n */\n readonly internalIndeterminate = linkedSignal(() => this.indeterminate());\n\n readonly ariaCheckedValue = computed(() => {\n if (this.internalIndeterminate()) return 'mixed';\n return this.internalChecked() ? 'true' : 'false';\n });\n\n readonly effectiveAriaLabelledby = computed(() => {\n const external = this.ariaLabelledby();\n if (external) return external;\n if (this.ariaLabel()) return undefined;\n return this.labelElementId();\n });\n\n readonly effectiveAriaDescribedby = computed(() => {\n const merged: string[] = [];\n const extra = this.describedByIdsSignal();\n for (const id of extra) merged.push(id);\n const external = this.ariaDescribedby();\n if (external) {\n for (const id of external.split(/\\s+/).filter(Boolean)) merged.push(id);\n } else if (extra.length === 0) {\n // Only fall back to the internal description id when no external sources are wired.\n merged.push(this.descriptionElementId());\n }\n return merged.length ? merged.join(' ') : undefined;\n });\n\n private readonly isActive = computed(() => this.internalChecked() || this.internalIndeterminate());\n\n // ── FormFieldControl signals ──\n\n /** @internal */\n readonly value: Signal<boolean | null> = computed(() => this.internalChecked());\n\n /** @internal */\n readonly focused: Signal<boolean> = this._focused.asReadonly();\n\n /** @internal Checkboxes are never empty in the form-field sense — they always have a boolean value. */\n readonly empty: Signal<boolean> = computed(() => false);\n\n /** @internal */\n readonly required: Signal<boolean> = computed(() => {\n this._ngControlRev();\n if (this.requiredInput()) return true;\n const ctrl = this.ngControl?.control;\n if (!ctrl) return false;\n return ctrl.hasValidator(Validators.required) || ctrl.hasValidator(Validators.requiredTrue);\n });\n\n /** @internal */\n readonly errorState: Signal<boolean> = computed(() => {\n this._ngControlRev();\n this._formSubmitRev();\n this._focused();\n const matcher = this.errorStateMatcher() ?? this.defaultMatcher;\n const form: TwFormSubmitted | null =\n (this.parentFormGroup as TwFormSubmitted | null) ??\n (this.parentForm as TwFormSubmitted | null);\n return matcher.isErrorState(this.ngControl?.control ?? null, form);\n });\n\n /** @internal */\n readonly controlType = 'checkbox';\n\n /** @internal */\n readonly userAriaDescribedBy: Signal<string | undefined> = computed(() => this.ariaDescribedby());\n\n private readonly variantResult = computed(() =>\n checkboxVariants({\n size: this.size(),\n labelPosition: this.labelPosition(),\n active: this.isActive(),\n disabled: this.isDisabled(),\n }),\n );\n\n readonly rootClasses = computed(() => this.variantResult().root());\n readonly boxWrapClasses = computed(() => this.variantResult().boxWrap());\n readonly iconClasses = computed(() => this.variantResult().icon());\n readonly labelWrapClasses = computed(() => this.variantResult().labelWrap());\n readonly labelClasses = computed(() => this.variantResult().label());\n readonly descriptionClasses = computed(() => this.variantResult().description());\n\n readonly boxClasses = computed(() => {\n const base = this.variantResult().box();\n const active = this.isActive();\n const error = this.errorState();\n const variant = this.variant();\n const effectiveColor: TwColor = error ? 'error' : this.color();\n if (!active) {\n if (error) return `${base} border-error-500`;\n return base;\n }\n const lookup = variant === 'solid' ? SOLID_BOX : OUTLINE_BOX;\n return `${base} ${lookup[effectiveColor]}`;\n });\n\n readonly iconColorClasses = computed(() => {\n const lookup = this.variant() === 'solid' ? SOLID_ICON : OUTLINE_ICON;\n const effectiveColor: TwColor = this.errorState() ? 'error' : this.color();\n return `inline-flex items-center justify-center ${lookup[effectiveColor]}`;\n });\n\n // ── Interactions ──────────────────────────────────────────\n\n /** Toggles the checked state. Clears indeterminate if set. No-op when disabled. */\n toggle(): void {\n if (this.isDisabled()) return;\n const wasIndeterminate = this.internalIndeterminate();\n const next = wasIndeterminate ? true : !this.internalChecked();\n this.internalChecked.set(next);\n this.checked.set(next);\n if (wasIndeterminate) {\n this.internalIndeterminate.set(false);\n this.indeterminate.set(false);\n }\n this.onChange(next);\n this.onTouched();\n this.change.emit(next);\n }\n\n /** Handles keyboard activation. Only Space toggles — matches native checkbox semantics. */\n onKeydown(event: KeyboardEvent): void {\n if (this.isDisabled()) return;\n if (event.key === ' ' || event.key === 'Spacebar') {\n event.preventDefault();\n this.toggle();\n }\n }\n\n /** @internal Called on host blur to notify forms the control has been touched and recompute errorState. */\n onBlur(): void {\n this.onTouched();\n this._ngControlRev.update((n) => n + 1);\n }\n\n // ── ControlValueAccessor ──────────────────────────────────\n\n writeValue(value: boolean | null | undefined): void {\n const next = !!value;\n this.internalChecked.set(next);\n this.checked.set(next);\n this.internalIndeterminate.set(false);\n this.indeterminate.set(false);\n }\n\n registerOnChange(fn: (value: boolean) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.cvaDisabled.set(isDisabled);\n }\n\n // ── FormFieldControl methods ──\n\n /** @internal Called by the form-field once it has computed the merged describedby ids. */\n setDescribedByIds(ids: string[]): void {\n this.describedByIdsSignal.set([...ids]);\n }\n\n /** @internal Called when the form-field container is clicked — focus the host without toggling. */\n onContainerClick(event: MouseEvent): void {\n if (this.isDisabled()) return;\n if (event.defaultPrevented) return;\n const host = this.elementRef.nativeElement;\n if (event.target === host || host.contains(event.target as Node)) return;\n host.focus();\n }\n\n // ── Lifecycle ─────────────────────────────────────────────\n\n ngOnInit(): void {\n const monitor$ = this.focusMonitor.monitor(this.elementRef);\n if (isObservable(monitor$)) {\n monitor$\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((origin) => {\n const wasFocused = this._focused();\n this._focused.set(!!origin);\n if (wasFocused && !origin) {\n // Blur often flips `touched` on the bound `NgControl`; notify forms\n // and bump the revision so `errorState` recomputes.\n this.onTouched();\n this._ngControlRev.update((n) => n + 1);\n }\n });\n }\n this.destroyRef.onDestroy(() => {\n this.focusMonitor.stopMonitoring(this.elementRef);\n });\n\n // NgControl's `control` is set by the parent FormControl* directive before\n // children's `ngOnInit`. Subscribe here so errorState reacts to status/value\n // changes on the bound control.\n const ctrl = this.ngControl?.control;\n if (ctrl) {\n const streams = [ctrl.statusChanges, ctrl.valueChanges].filter(\n (s): s is NonNullable<typeof s> => !!s,\n );\n if (streams.length) {\n merge(...streams)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this._ngControlRev.update((n) => n + 1));\n }\n }\n\n const submit = this.parentFormGroup?.ngSubmit ?? this.parentForm?.ngSubmit;\n if (submit) {\n submit\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => this._formSubmitRev.update((n) => n + 1));\n }\n }\n\n private hasAccessibleNameHint(): boolean {\n if (this.label() || this.ariaLabel() || this.ariaLabelledby()) return true;\n const host = this.elementRef.nativeElement;\n return host.textContent !== null && host.textContent.trim().length > 0;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cdevhub-ngx-tw-checkbox.mjs","sources":["../../../projects/ngx-tw/checkbox/checkbox.ts","../../../projects/ngx-tw/checkbox/cdevhub-ngx-tw-checkbox.ts"],"sourcesContent":["import {\n afterNextRender,\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n ElementRef,\n forwardRef,\n inject,\n input,\n isDevMode,\n linkedSignal,\n model,\n type OnInit,\n output,\n signal,\n type Signal,\n} from '@angular/core';\nimport {\n type ControlValueAccessor,\n NgControl,\n Validators,\n} from '@angular/forms';\nimport { FocusMonitor } from '@angular/cdk/a11y';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { isObservable } from 'rxjs';\nimport { tv } from 'tailwind-variants';\nimport {\n type ErrorStateMatcher,\n type TwColor,\n type TwSize,\n wireErrorState,\n} from '@cdevhub/ngx-tw/core';\nimport { FormFieldControl, TW_FORM_FIELD_CONTROL } from '@cdevhub/ngx-tw/form-field';\n\n/** Visual style of the checkbox when checked or indeterminate. */\nexport type CheckboxVariant = 'solid' | 'outline';\n\n/** Position of the label relative to the checkbox control. */\nexport type CheckboxLabelPosition = 'before' | 'after';\n\n// ── tv() config ──────────────────────────────────────────────────\n\nconst checkboxVariants = tv(\n {\n slots: {\n // `items-start` aligns the boxWrap with the top of the label container; combined with\n // a `min-h-N` matching the label's first-line line-height on boxWrap, the box stays\n // centered on the first line of the label whether it spans one line or many.\n //\n // ── Row-height scale (selection cohort) ──────────────────────────────\n // The rendered row is `max(boxWrap, label first line)`, and the host itself is the\n // click target (`role=\"checkbox\"` + `tabindex` + `(click)` all sit on the root), so\n // the row IS the interactive target. It runs 16 / 20 / 24 / 28 / 32 px — five distinct\n // steps, every one on the 4px baseline of docs/vertical-rhythm.md, and identical to\n // `switch`, the sibling selection control. Selection controls are glyph-scale and\n // deliberately do NOT take the pinned 24/32/36/44/48 form-row scale (vertical-rhythm.md\n // section 4).\n //\n // The row is driven by `boxWrap` min-h, NOT by the box glyph, which stays at its own\n // well-proportioned 14 / 16 / 20 / 24 / 28 scale (4px of slack inside the row at every\n // size; 2px at xs, where the codified size-3.5 half-step applies). Driving it from\n // boxWrap is what makes the five steps survive when no label is projected.\n //\n // Because centering demands `boxWrap height == label first-line leading`, the label\n // leading carries the same 4 / 5 / 6 / 7 / 8 progression. That is forced, not chosen:\n // the label font scale has only three steps (text-xs, text-sm, text-base), so leading\n // is the only lever that can break the sm/md and lg/xl ties. Before this, sm and md\n // both rendered a 20px row — a dead step. Accepted cost: `text-base leading-8` at xl is\n // a 2.0 line ratio, looser than typographic ideal on a wrapped multi-line label.\n root: 'relative inline-flex items-start gap-3 cursor-pointer select-none rounded-md focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500',\n boxWrap: 'relative inline-flex items-center justify-center shrink-0',\n box: 'inline-flex items-center justify-center rounded-md border transition-colors duration-normal motion-reduce:transition-none',\n icon: 'absolute inset-0 flex items-center justify-center pointer-events-none empty:hidden',\n labelWrap: 'flex flex-col min-w-0 empty:hidden',\n label: 'font-medium text-fg empty:hidden',\n description: 'text-fg-muted empty:hidden',\n },\n variants: {\n size: {\n xs: {\n // `size-3.5` half-step: aligns with text-xs/leading-4. Codified per CLAUDE.md.\n box: 'size-3.5',\n icon: '[&_svg]:size-3',\n boxWrap: 'min-h-4',\n label: 'text-xs leading-4',\n description: 'text-2xs leading-4',\n },\n sm: {\n box: 'size-4',\n icon: '[&_svg]:size-3',\n boxWrap: 'min-h-5',\n label: 'text-sm leading-5',\n description: 'text-xs leading-4',\n },\n md: {\n box: 'size-5',\n // md icon uses `size-3.5` (14px) — proportional inset (70%) of the\n // size-5 (20px) box; the half-step is the only size that fills the\n // checkmark without crowding the box edges.\n icon: '[&_svg]:size-3.5',\n // 24px row. `text-sm` is shared with sm by the documented font scale, so the\n // leading breaks the tie: leading-6 lifts the row off sm's 20px.\n boxWrap: 'min-h-6',\n label: 'text-sm leading-6',\n description: 'text-xs leading-4',\n },\n lg: {\n box: 'size-6',\n icon: '[&_svg]:size-4',\n // 28px row — leading-7 keeps the first label line the same height as boxWrap.\n boxWrap: 'min-h-7',\n label: 'text-base leading-7',\n description: 'text-sm leading-5',\n },\n xl: {\n box: 'size-7',\n icon: '[&_svg]:size-5',\n // 32px row. `text-base` is shared with lg, so leading-8 breaks that tie the same\n // way leading-6 breaks sm/md. A 2.0 ratio on a wrapped label is the accepted cost.\n boxWrap: 'min-h-8',\n label: 'text-base leading-8',\n description: 'text-sm leading-5',\n },\n },\n labelPosition: {\n before: { root: 'flex-row-reverse' },\n after: { root: 'flex-row' },\n },\n active: {\n true: { box: '' },\n false: { box: 'bg-surface border-border hover:border-border-strong' },\n },\n disabled: {\n true: { root: 'opacity-50 pointer-events-none cursor-not-allowed' },\n false: { root: '' },\n },\n },\n defaultVariants: {\n size: 'md',\n labelPosition: 'after',\n active: false,\n disabled: false,\n },\n },\n { twMerge: true },\n);\n\n// ── Static active-state color lookups (statically written for Tailwind v4 scanning) ──\n\nconst SOLID_BOX: Record<TwColor, string> = {\n primary: 'bg-primary-600 border-primary-600',\n secondary: 'bg-secondary-600 border-secondary-600',\n accent: 'bg-accent-600 border-accent-600',\n neutral: 'bg-fg border-fg',\n info: 'bg-info-600 border-info-600',\n success: 'bg-success-600 border-success-600',\n warning: 'bg-warning-500 border-warning-500',\n error: 'bg-error-600 border-error-600',\n};\n\nconst SOLID_ICON: Record<TwColor, string> = {\n primary: 'text-on-primary',\n secondary: 'text-on-secondary',\n accent: 'text-on-accent',\n neutral: 'text-on-neutral',\n info: 'text-on-info',\n success: 'text-on-success',\n warning: 'text-on-warning',\n error: 'text-on-error',\n};\n\nconst OUTLINE_BOX: Record<TwColor, string> = {\n primary: 'bg-surface border-primary-600',\n secondary: 'bg-surface border-secondary-600',\n accent: 'bg-surface border-accent-600',\n neutral: 'bg-surface border-fg',\n info: 'bg-surface border-info-600',\n success: 'bg-surface border-success-600',\n warning: 'bg-surface border-warning-500',\n error: 'bg-surface border-error-600',\n};\n\nconst OUTLINE_ICON: Record<TwColor, string> = {\n primary: 'text-primary-600',\n secondary: 'text-secondary-600',\n accent: 'text-accent-600',\n neutral: 'text-fg',\n info: 'text-info-600',\n success: 'text-success-600',\n warning: 'text-warning-600',\n error: 'text-error-600',\n};\n\nlet nextId = 0;\n\n// ── CheckboxComponent ────────────────────────────────────────────\n\n@Component({\n selector: 'tw-checkbox',\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: TW_FORM_FIELD_CONTROL,\n useExisting: forwardRef(() => CheckboxComponent),\n },\n ],\n template: `\n <!--\n Hidden form-submission proxy. Uses \\`hidden\\` (display:none), not \\`sr-only\\`:\n a display:none control is excluded from focus order so axe's\n \\`nested-interactive\\` rule doesn't flag it inside the \\`role=\"checkbox\"\\`\n host, yet it still participates in native (non-Angular) form submission —\n the entry-list algorithm excludes only \\`disabled\\` controls, not hidden ones.\n -->\n <input\n type=\"checkbox\"\n hidden\n aria-hidden=\"true\"\n [name]=\"name() || null\"\n [checked]=\"internalChecked()\"\n [disabled]=\"isDisabled()\"\n />\n\n <span [class]=\"boxWrapClasses()\">\n <span [class]=\"boxClasses()\">\n <span [class]=\"iconClasses()\">\n @if (internalIndeterminate()) {\n <span [class]=\"iconColorClasses()\" animate.enter=\"check-in\">\n <ng-content select=\"[slot='indeterminate-icon']\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M5 12 h14\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </ng-content>\n </span>\n } @else if (internalChecked()) {\n <span [class]=\"iconColorClasses()\" animate.enter=\"check-in\">\n <ng-content select=\"[slot='check-icon']\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M5 12 l5 5 l9 -11\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </ng-content>\n </span>\n }\n </span>\n </span>\n </span>\n\n <span [class]=\"labelWrapClasses()\">\n <span [id]=\"labelElementId()\" [class]=\"labelClasses()\">\n <ng-content>\n @if (label()) {\n {{ label() }}\n }\n </ng-content>\n </span>\n <span [id]=\"descriptionElementId()\" [class]=\"descriptionClasses()\">\n <ng-content select=\"[slot='description']\">\n @if (description()) {\n {{ description() }}\n }\n </ng-content>\n </span>\n </span>\n `,\n host: {\n 'role': 'checkbox',\n '[id]': 'id()',\n '[class]': 'rootClasses()',\n '[attr.data-checked]': 'internalChecked()',\n '[attr.data-indeterminate]': 'internalIndeterminate()',\n '[attr.aria-checked]': 'ariaCheckedValue()',\n '[attr.aria-disabled]': 'isDisabled() || null',\n '[attr.aria-required]': 'required() || null',\n '[attr.aria-invalid]': 'errorState() || null',\n '[attr.aria-label]': 'ariaLabel() || null',\n '[attr.aria-labelledby]': 'effectiveAriaLabelledby() || null',\n '[attr.aria-describedby]': 'effectiveAriaDescribedby() || null',\n '[attr.tabindex]': 'isDisabled() ? -1 : 0',\n '[attr.name]': 'name() || null',\n '(click)': 'toggle()',\n '(keydown)': 'onKeydown($event)',\n '(blur)': 'onBlur()',\n },\n})\nexport class CheckboxComponent\n extends FormFieldControl<boolean>\n implements ControlValueAccessor, OnInit\n{\n /** Sets the semantic color for the checked and indeterminate box fill/border. Defaults to `'primary'`. */\n readonly color = input<TwColor>('primary');\n\n /** Controls the overall scale of the box, check icon, and label typography. Defaults to `'md'`. */\n readonly size = input<TwSize>('md');\n\n /** Visual style when checked or indeterminate. `'solid'` fills the box with the color; `'outline'` keeps a transparent fill with a colored border and check. Defaults to `'solid'`. */\n readonly variant = input<CheckboxVariant>('solid');\n\n /** When true, prevents interaction and applies muted styling. Defaults to `false`. */\n readonly disabled = input(false);\n\n /** When true, sets `aria-required=\"true\"` so assistive tech announces the control as required. Defaults to `false`. */\n readonly requiredInput = input(false, { alias: 'required' });\n\n /** Optional inline label rendered next to the checkbox. Use default content projection for rich label content instead. Projection takes precedence. */\n readonly label = input<string | undefined>(undefined);\n\n /** Optional secondary description rendered under the label. Use `[slot=\"description\"]` content projection for rich content instead. Projection takes precedence. */\n readonly description = input<string | undefined>(undefined);\n\n /** Position of the label/description relative to the checkbox. Defaults to `'after'`. */\n readonly labelPosition = input<CheckboxLabelPosition>('after');\n\n /** Optional name attribute, applied to the hidden native `<input type=\"checkbox\">` so native form submission includes the control. */\n readonly name = input<string | undefined>(undefined);\n\n /** Id on the host element. Auto-generated as `tw-checkbox-N` when not provided. Anchors the derived label/description ids; the accessible name inside a `<tw-form-field>` comes from `aria-labelledby`, not from the field's `<label for>` (the host is a custom element, which `for` cannot target). */\n readonly idInput = input<string | undefined>(undefined, { alias: 'id' });\n\n /** Accessible name when no visible label is provided. Mirrored to `aria-label`. Defaults to `undefined`. */\n readonly ariaLabel = input<string | undefined>(undefined, { alias: 'aria-label' });\n\n /** ID of an external element that labels the checkbox. Mirrored to `aria-labelledby`. Defaults to `undefined`. */\n readonly ariaLabelledby = input<string | undefined>(undefined, { alias: 'aria-labelledby' });\n\n /** ID of an external element that describes the checkbox. Mirrored to `aria-describedby`. Form-field merges its hint/error ids alongside. Defaults to `undefined`. */\n readonly ariaDescribedby = input<string | undefined>(undefined, { alias: 'aria-describedby' });\n\n /** Per-instance override of the {@link ErrorStateMatcher}. When omitted, the directive uses the `TW_ERROR_STATE_MATCHER` token's value. */\n readonly errorStateMatcher = input<ErrorStateMatcher | undefined>(undefined);\n\n /**\n * Two-way bound checked state. Updates when the user toggles via click or\n * Space, **and** when a bound form writes into the control\n * (`FormControl.setValue`, `ngModel`, `writeValue`). Defaults to `false`.\n *\n * The two-way binding mints a `checkedChange` output. That output is the\n * *any-change* channel: it fires on programmatic writes as well as user\n * gestures. `(change)` is the *user-gesture-only* channel. Bind\n * `(checkedChange)` to mirror state; bind `(change)` for analytics or a\n * confirmation prompt, where a programmatic write must not count as a click.\n * Writing back into the same form from a `(checkedChange)` handler will echo.\n */\n readonly checked = model(false);\n\n /**\n * Two-way bound indeterminate state. When true, the box shows a dash and the\n * host exposes `aria-checked=\"mixed\"`. Any user toggle clears indeterminate\n * and sets `checked` to `true`. Defaults to `false`.\n *\n * Its minted `indeterminateChange` output follows the same rule as\n * `checkedChange`: it also fires when `writeValue` clears the state, so it is\n * an any-change channel, not a gesture channel.\n */\n readonly indeterminate = model(false);\n\n /**\n * Fires after the checked state changes from a user interaction (click or\n * Space). Does **not** fire when the value is updated programmatically via\n * `writeValue` / `FormControl.setValue` / `ngModel` — for those, bind the\n * two-way binding's `(checkedChange)` instead, which fires on any change.\n */\n readonly change = output<boolean>();\n\n private readonly focusMonitor = inject(FocusMonitor);\n private readonly elementRef = inject(ElementRef<HTMLElement>);\n private readonly destroyRef = inject(DestroyRef);\n private readonly ngControl = inject(NgControl, { optional: true, self: true });\n\n private onChange: (value: boolean) => void = () => {};\n private onTouched: () => void = () => {};\n private readonly cvaDisabled = signal(false);\n\n private readonly _focused = signal(false);\n\n /** @internal Shared `errorState` / `required` / `errors` derivation — see `wireErrorState`. */\n private readonly errorWiring = wireErrorState({\n ngControl: () => this.ngControl,\n matcher: () => this.errorStateMatcher(),\n required: () => this.requiredInput(),\n // A checkbox bound with `Validators.requiredTrue` is required too.\n requiredValidators: [Validators.required, Validators.requiredTrue],\n track: [() => this._focused()],\n });\n private readonly describedByIdsSignal = signal<readonly string[]>([]);\n private readonly labelledByIdsSignal = signal<readonly string[]>([]);\n\n private readonly uid = nextId++;\n /** @internal Fallback id used when the consumer does not set `[id]`. */\n readonly hostId = `tw-checkbox-${this.uid}`;\n\n /** @internal Resolved id on the host element. */\n readonly id: Signal<string> = computed(() => this.idInput() ?? this.hostId);\n\n /** @internal Id of the internal label `<span>`, derived from the resolved host id. */\n readonly labelElementId = computed(() => `${this.id()}-label`);\n\n /** @internal Id of the internal description `<span>`, derived from the resolved host id. */\n readonly descriptionElementId = computed(() => `${this.id()}-description`);\n\n constructor() {\n super();\n // Material-style CVA wiring: declare ourselves as the value accessor on any\n // host-level `NgControl` (FormControlDirective, NgModel, etc.). This avoids\n // the circular-DI that a static `NG_VALUE_ACCESSOR` provider would create\n // because `NgControl` is injected with `self: true` on the same element.\n if (this.ngControl) {\n this.ngControl.valueAccessor = this;\n }\n\n afterNextRender(() => {\n if (isDevMode() && !this.hasAccessibleNameHint()) {\n console.warn(\n '[tw-checkbox] The checkbox has no accessible name. Provide a `label` input, project label content, or set `aria-label` / `aria-labelledby`.',\n );\n }\n });\n }\n\n /** @internal */\n readonly isDisabled = computed(() => this.disabled() || this.cvaDisabled());\n\n /**\n * @internal Visible-state mirror of the `checked` model. `linkedSignal` keeps it\n * synced with parent updates (including `writeValue` from reactive forms), while\n * also accepting explicit `set()` calls from `toggle()` / `writeValue()` so the\n * DOM reflects the new state synchronously — before `checkedChange` propagates\n * through the host binding round-trip. Reading this signal in host bindings\n * (`aria-checked`, `data-checked`, box classes) decouples render from the\n * model's notification cadence.\n */\n readonly internalChecked = linkedSignal(() => this.checked());\n\n /**\n * @internal Visible-state mirror of the `indeterminate` model. Same rationale as\n * `internalChecked` — `toggle()` and `writeValue()` clear it synchronously so\n * `aria-checked=\"mixed\"` flips off in the same microtask as `aria-checked=\"true\"`.\n */\n readonly internalIndeterminate = linkedSignal(() => this.indeterminate());\n\n readonly ariaCheckedValue = computed(() => {\n if (this.internalIndeterminate()) return 'mixed';\n return this.internalChecked() ? 'true' : 'false';\n });\n\n readonly effectiveAriaLabelledby = computed(() => {\n // A wrapping `<tw-form-field>` pushes the projected `<label twLabel>` id (plus\n // any consumer `aria-labelledby`) through `setLabelledByIds`. Those ids win:\n // the host is `<tw-checkbox role=\"checkbox\">`, a custom element that is not a\n // labelable form control, so the field's `<label for>` resolves to nothing and\n // this attribute is the ONLY route from the visible label to the control.\n // Without it the checkbox's own label span is empty in that arrangement — the\n // visible text lives in the form-field — and the control has no name at all.\n const pushed = this.labelledByIdsSignal();\n if (pushed.length) return pushed.join(' ');\n const external = this.ariaLabelledby();\n if (external) return external;\n if (this.ariaLabel()) return undefined;\n return this.labelElementId();\n });\n\n readonly effectiveAriaDescribedby = computed(() => {\n const merged: string[] = [];\n const extra = this.describedByIdsSignal();\n for (const id of extra) merged.push(id);\n const external = this.ariaDescribedby();\n if (external) {\n for (const id of external.split(/\\s+/).filter(Boolean)) merged.push(id);\n } else if (extra.length === 0) {\n // Only fall back to the internal description id when no external sources are wired.\n merged.push(this.descriptionElementId());\n }\n return merged.length ? merged.join(' ') : undefined;\n });\n\n private readonly isActive = computed(() => this.internalChecked() || this.internalIndeterminate());\n\n // ── FormFieldControl signals ──\n\n /** @internal */\n readonly value: Signal<boolean | null> = computed(() => this.internalChecked());\n\n /** @internal */\n readonly focused: Signal<boolean> = this._focused.asReadonly();\n\n /** @internal Checkboxes are never empty in the form-field sense — they always have a boolean value. */\n readonly empty: Signal<boolean> = computed(() => false);\n\n /** @internal */\n readonly required: Signal<boolean> = this.errorWiring.required;\n\n /** @internal */\n readonly errorState: Signal<boolean> = this.errorWiring.errorState;\n\n /** @internal Active validation errors map from the bound `NgControl`. Drives `[twError match=\"…\"]` inside a wrapping `tw-form-field`; without it the form-field's key set is permanently empty and every `match`ed error stays hidden. */\n override readonly errors: Signal<Record<string, unknown> | null> = this.errorWiring.errors;\n\n /** @internal */\n readonly controlType = 'checkbox';\n\n /** @internal */\n readonly userAriaDescribedBy: Signal<string | undefined> = computed(() => this.ariaDescribedby());\n\n /** @internal Consumer-supplied `aria-labelledby`, surfaced so the wrapping form-field merges it into the ids it pushes back rather than replacing it. */\n override readonly userAriaLabelledby: Signal<string | undefined> = computed(() =>\n this.ariaLabelledby(),\n );\n\n private readonly variantResult = computed(() =>\n checkboxVariants({\n size: this.size(),\n labelPosition: this.labelPosition(),\n active: this.isActive(),\n disabled: this.isDisabled(),\n }),\n );\n\n readonly rootClasses = computed(() => this.variantResult().root());\n readonly boxWrapClasses = computed(() => this.variantResult().boxWrap());\n readonly iconClasses = computed(() => this.variantResult().icon());\n readonly labelWrapClasses = computed(() => this.variantResult().labelWrap());\n readonly labelClasses = computed(() => this.variantResult().label());\n readonly descriptionClasses = computed(() => this.variantResult().description());\n\n readonly boxClasses = computed(() => {\n const base = this.variantResult().box();\n const active = this.isActive();\n const error = this.errorState();\n const variant = this.variant();\n const effectiveColor: TwColor = error ? 'error' : this.color();\n if (!active) {\n if (error) return `${base} border-error-500`;\n return base;\n }\n const lookup = variant === 'solid' ? SOLID_BOX : OUTLINE_BOX;\n return `${base} ${lookup[effectiveColor]}`;\n });\n\n readonly iconColorClasses = computed(() => {\n const lookup = this.variant() === 'solid' ? SOLID_ICON : OUTLINE_ICON;\n const effectiveColor: TwColor = this.errorState() ? 'error' : this.color();\n return `inline-flex items-center justify-center ${lookup[effectiveColor]}`;\n });\n\n // ── Interactions ──────────────────────────────────────────\n\n /** Toggles the checked state. Clears indeterminate if set. No-op when disabled. */\n toggle(): void {\n if (this.isDisabled()) return;\n const wasIndeterminate = this.internalIndeterminate();\n const next = wasIndeterminate ? true : !this.internalChecked();\n this.internalChecked.set(next);\n this.checked.set(next);\n if (wasIndeterminate) {\n this.internalIndeterminate.set(false);\n this.indeterminate.set(false);\n }\n this.onChange(next);\n // Deliberately NOT `onTouched()`. Angular's CVA contract registers\n // `onTouched` as the BLUR notification; calling it here flipped `touched`\n // the instant the value changed, so a consumer staging error display on\n // `touched` (\"only once they leave the field\") got different behaviour from\n // `tw-checkbox` than from `tw-slider` / `tw-input`. `onBlur()` below is the\n // only place that fires it.\n this.change.emit(next);\n }\n\n /** Handles keyboard activation. Only Space toggles — matches native checkbox semantics. */\n onKeydown(event: KeyboardEvent): void {\n if (this.isDisabled()) return;\n if (event.key === ' ' || event.key === 'Spacebar') {\n event.preventDefault();\n this.toggle();\n }\n }\n\n /** @internal Called on host blur to notify forms the control has been touched and recompute errorState. */\n onBlur(): void {\n this.onTouched();\n this.errorWiring.bump();\n }\n\n // ── ControlValueAccessor ──────────────────────────────────\n\n writeValue(value: boolean | null | undefined): void {\n const next = !!value;\n this.internalChecked.set(next);\n this.checked.set(next);\n this.internalIndeterminate.set(false);\n this.indeterminate.set(false);\n }\n\n registerOnChange(fn: (value: boolean) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.cvaDisabled.set(isDisabled);\n }\n\n // ── FormFieldControl methods ──\n\n /** @internal Called by the form-field once it has computed the merged describedby ids. */\n setDescribedByIds(ids: string[]): void {\n this.describedByIdsSignal.set([...ids]);\n }\n\n /** @internal Receives the merged `aria-labelledby` ids from the wrapping form-field. Required because the host is a custom element rather than a labelable control, so the field's `<label for>` never reaches it. */\n override setLabelledByIds(ids: string[]): void {\n this.labelledByIdsSignal.set([...ids]);\n }\n\n /** @internal Called when the form-field container is clicked — focus the host without toggling. */\n onContainerClick(event: MouseEvent): void {\n if (this.isDisabled()) return;\n if (event.defaultPrevented) return;\n const host = this.elementRef.nativeElement;\n if (event.target === host || host.contains(event.target as Node)) return;\n host.focus();\n }\n\n // ── Lifecycle ─────────────────────────────────────────────\n\n ngOnInit(): void {\n const monitor$ = this.focusMonitor.monitor(this.elementRef);\n if (isObservable(monitor$)) {\n monitor$\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((origin) => {\n const wasFocused = this._focused();\n this._focused.set(!!origin);\n if (wasFocused && !origin) {\n // Blur often flips `touched` on the bound `NgControl`; notify forms\n // and bump the revision so `errorState` recomputes.\n this.onTouched();\n this.errorWiring.bump();\n }\n });\n }\n this.destroyRef.onDestroy(() => {\n this.focusMonitor.stopMonitoring(this.elementRef);\n });\n\n // NgControl's `control` is set by the parent FormControl* directive before\n // children's `ngOnInit`. Connect here so errorState reacts to status/value\n // changes on the bound control.\n this.errorWiring.connect();\n }\n\n private hasAccessibleNameHint(): boolean {\n if (this.label() || this.ariaLabel() || this.ariaLabelledby()) return true;\n const host = this.elementRef.nativeElement;\n return host.textContent !== null && host.textContent.trim().length > 0;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -4,6 +4,11 @@ import { Clipboard } from '@angular/cdk/clipboard';
4
4
  import { LiveAnnouncer } from '@angular/cdk/a11y';
5
5
  import { tv } from 'tailwind-variants';
6
6
 
7
+ /** Maps every legacy spelling onto its canonical replacement. */
8
+ const VARIANT_ALIASES = {
9
+ filled: 'solid',
10
+ outlined: 'outline',
11
+ };
7
12
  /**
8
13
  * Marker directive for projected header content (e.g. filename, secondary
9
14
  * actions). Sits alongside the language label inside the code block's
@@ -42,8 +47,8 @@ const codeBlockVariants = tv({
42
47
  },
43
48
  variants: {
44
49
  variant: {
45
- filled: { root: 'bg-surface-sunken border border-border-strong' },
46
- outlined: { root: 'bg-transparent border border-border' },
50
+ solid: { root: 'bg-surface-sunken border border-border-strong' },
51
+ outline: { root: 'bg-transparent border border-border' },
47
52
  },
48
53
  copied: {
49
54
  true: { copyButton: 'text-success-500 hover:text-success-500' },
@@ -51,7 +56,7 @@ const codeBlockVariants = tv({
51
56
  },
52
57
  },
53
58
  defaultVariants: {
54
- variant: 'filled',
59
+ variant: 'solid',
55
60
  copied: false,
56
61
  },
57
62
  }, {
@@ -78,8 +83,8 @@ class CodeBlockComponent {
78
83
  /** Optional language label displayed in the header (e.g. `'TypeScript'`, `'HTML'`). */
79
84
  language = input(/* @ts-ignore */
80
85
  ...(ngDevMode ? [undefined, { debugName: "language" }] : /* istanbul ignore next */ []));
81
- /** Visual style of the container. Defaults to `'filled'`. */
82
- variant = input('filled', /* @ts-ignore */
86
+ /** Visual style of the container. Defaults to `'solid'`. `'filled'` and `'outlined'` are deprecated aliases for `'solid'` and `'outline'` and render identically. */
87
+ variant = input('solid', /* @ts-ignore */
83
88
  ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
84
89
  /** When true, wraps long lines instead of horizontal scrolling. Defaults to `false`. */
85
90
  wrap = input(false, { ...(ngDevMode ? { debugName: "wrap" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
@@ -110,7 +115,14 @@ class CodeBlockComponent {
110
115
  };
111
116
  }, /* @ts-ignore */
112
117
  ...(ngDevMode ? [{ debugName: "resolvedLabels" }] : /* istanbul ignore next */ []));
113
- variantResult = computed(() => codeBlockVariants({ variant: this.variant(), copied: this.isCopied() }), /* @ts-ignore */
118
+ /** @internal Canonical variant with legacy spellings folded in. */
119
+ resolvedVariant = computed(() => {
120
+ const v = this.variant();
121
+ return (VARIANT_ALIASES[v] ??
122
+ v);
123
+ }, /* @ts-ignore */
124
+ ...(ngDevMode ? [{ debugName: "resolvedVariant" }] : /* istanbul ignore next */ []));
125
+ variantResult = computed(() => codeBlockVariants({ variant: this.resolvedVariant(), copied: this.isCopied() }), /* @ts-ignore */
114
126
  ...(ngDevMode ? [{ debugName: "variantResult" }] : /* istanbul ignore next */ []));
115
127
  rootClasses = computed(() => this.variantResult().root(), /* @ts-ignore */
116
128
  ...(ngDevMode ? [{ debugName: "rootClasses" }] : /* istanbul ignore next */ []));