@kouji-ui/core 0.1.1 → 0.1.2

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 (535) hide show
  1. package/fesm2022/kouji-ui-core.mjs +26789 -0
  2. package/fesm2022/kouji-ui-core.mjs.map +1 -0
  3. package/package.json +5 -6
  4. package/types/kouji-ui-core.d.ts +13545 -0
  5. package/.turbo/turbo-build.log +0 -30
  6. package/CHANGELOG.md +0 -190
  7. package/ng-package.json +0 -11
  8. package/src/a11y/.gitkeep +0 -0
  9. package/src/a11y/aria-describedby.spec.ts +0 -55
  10. package/src/a11y/aria-describedby.ts +0 -37
  11. package/src/a11y/aria-labelledby.spec.ts +0 -55
  12. package/src/a11y/aria-labelledby.ts +0 -38
  13. package/src/a11y/focus-trap.spec.ts +0 -86
  14. package/src/a11y/focus-trap.ts +0 -72
  15. package/src/a11y/index.ts +0 -10
  16. package/src/a11y/live-region.spec.ts +0 -58
  17. package/src/a11y/live-region.ts +0 -50
  18. package/src/a11y/roving-tabindex.spec.ts +0 -201
  19. package/src/a11y/roving-tabindex.ts +0 -153
  20. package/src/a11y/visually-hidden.spec.ts +0 -34
  21. package/src/a11y/visually-hidden.ts +0 -26
  22. package/src/accordion/accordion.context.ts +0 -44
  23. package/src/accordion/accordion.spec.ts +0 -242
  24. package/src/accordion/accordion.ts +0 -401
  25. package/src/accordion/index.ts +0 -8
  26. package/src/alert/alert.context.ts +0 -28
  27. package/src/alert/alert.spec.ts +0 -217
  28. package/src/alert/alert.ts +0 -417
  29. package/src/alert/config.ts +0 -46
  30. package/src/alert/index.ts +0 -19
  31. package/src/avatar/avatar-group.context.ts +0 -45
  32. package/src/avatar/avatar-group.spec.ts +0 -358
  33. package/src/avatar/avatar-group.ts +0 -259
  34. package/src/avatar/avatar.spec.ts +0 -18
  35. package/src/avatar/avatar.ts +0 -39
  36. package/src/avatar/index.ts +0 -11
  37. package/src/badge/badge.spec.ts +0 -28
  38. package/src/badge/badge.ts +0 -35
  39. package/src/badge/index.ts +0 -1
  40. package/src/breadcrumb/breadcrumb-current.ts +0 -38
  41. package/src/breadcrumb/breadcrumb-ellipsis.ts +0 -71
  42. package/src/breadcrumb/breadcrumb-item.ts +0 -41
  43. package/src/breadcrumb/breadcrumb-link.ts +0 -44
  44. package/src/breadcrumb/breadcrumb-list.ts +0 -42
  45. package/src/breadcrumb/breadcrumb-separator.ts +0 -45
  46. package/src/breadcrumb/breadcrumb.context.ts +0 -45
  47. package/src/breadcrumb/breadcrumb.spec.ts +0 -354
  48. package/src/breadcrumb/breadcrumb.ts +0 -239
  49. package/src/breadcrumb/config.ts +0 -84
  50. package/src/breadcrumb/index.ts +0 -18
  51. package/src/button/_examples/button.example.ts +0 -71
  52. package/src/button/_examples/button.finance.example.ts +0 -83
  53. package/src/button/_examples/button.retro.example.ts +0 -91
  54. package/src/button/_examples/button.sizes.example.ts +0 -60
  55. package/src/button/_examples/index.ts +0 -6
  56. package/src/button/button.spec.ts +0 -163
  57. package/src/button/button.ts +0 -142
  58. package/src/button/config.spec.ts +0 -33
  59. package/src/button/config.ts +0 -45
  60. package/src/button/index.ts +0 -2
  61. package/src/button-group/button-group.context.ts +0 -28
  62. package/src/button-group/button-group.spec.ts +0 -99
  63. package/src/button-group/button-group.ts +0 -99
  64. package/src/button-group/index.ts +0 -2
  65. package/src/calendar/calendar-day.ts +0 -102
  66. package/src/calendar/calendar-grid.ts +0 -90
  67. package/src/calendar/calendar-header.ts +0 -65
  68. package/src/calendar/calendar.context.ts +0 -53
  69. package/src/calendar/calendar.spec.ts +0 -225
  70. package/src/calendar/calendar.ts +0 -233
  71. package/src/calendar/date-utils.ts +0 -225
  72. package/src/calendar/index.ts +0 -28
  73. package/src/carousel/carousel.context.ts +0 -81
  74. package/src/carousel/carousel.spec.ts +0 -337
  75. package/src/carousel/carousel.ts +0 -919
  76. package/src/carousel/index.ts +0 -22
  77. package/src/cascade-select/cascade-select-option.ts +0 -205
  78. package/src/cascade-select/cascade-select-panel.ts +0 -106
  79. package/src/cascade-select/cascade-select-root.ts +0 -265
  80. package/src/cascade-select/cascade-select-sub-panel.ts +0 -168
  81. package/src/cascade-select/cascade-select-trigger.ts +0 -44
  82. package/src/cascade-select/cascade-select.context.ts +0 -71
  83. package/src/cascade-select/cascade-select.spec.ts +0 -241
  84. package/src/cascade-select/cascade-select.ts +0 -5
  85. package/src/cascade-select/index.ts +0 -11
  86. package/src/chart/chart.spec.ts +0 -27
  87. package/src/chart/chart.ts +0 -52
  88. package/src/chart/index.ts +0 -1
  89. package/src/chat/chat-avatar.ts +0 -31
  90. package/src/chat/chat-bubble.ts +0 -49
  91. package/src/chat/chat-footer.ts +0 -67
  92. package/src/chat/chat-header.ts +0 -41
  93. package/src/chat/chat-log.ts +0 -43
  94. package/src/chat/chat.context.ts +0 -64
  95. package/src/chat/chat.spec.ts +0 -341
  96. package/src/chat/chat.ts +0 -191
  97. package/src/chat/config.ts +0 -53
  98. package/src/chat/index.ts +0 -21
  99. package/src/checkbox/checkbox.spec.ts +0 -35
  100. package/src/checkbox/checkbox.ts +0 -89
  101. package/src/checkbox/index.ts +0 -1
  102. package/src/color-picker/color-picker.context.ts +0 -74
  103. package/src/color-picker/color-picker.spec.ts +0 -241
  104. package/src/color-picker/color-picker.ts +0 -698
  105. package/src/color-picker/color-picker.utils.ts +0 -140
  106. package/src/color-picker/index.ts +0 -28
  107. package/src/combobox/combobox-input.ts +0 -143
  108. package/src/combobox/combobox-listbox.ts +0 -49
  109. package/src/combobox/combobox-option.ts +0 -43
  110. package/src/combobox/combobox-root.ts +0 -281
  111. package/src/combobox/combobox.spec.ts +0 -75
  112. package/src/combobox/combobox.ts +0 -4
  113. package/src/combobox/index.ts +0 -4
  114. package/src/command-palette/command-empty.ts +0 -36
  115. package/src/command-palette/command-group.ts +0 -21
  116. package/src/command-palette/command-input.ts +0 -70
  117. package/src/command-palette/command-item.ts +0 -60
  118. package/src/command-palette/command-list.ts +0 -25
  119. package/src/command-palette/command-palette-dialog.ts +0 -74
  120. package/src/command-palette/command-palette-trigger.ts +0 -64
  121. package/src/command-palette/command-palette.filters.ts +0 -53
  122. package/src/command-palette/command-palette.spec.ts +0 -349
  123. package/src/command-palette/command-palette.ts +0 -204
  124. package/src/command-palette/command-separator.ts +0 -18
  125. package/src/command-palette/index.ts +0 -15
  126. package/src/confirm-popup/confirm-popup-action.ts +0 -39
  127. package/src/confirm-popup/confirm-popup-cancel.ts +0 -38
  128. package/src/confirm-popup/confirm-popup-content.ts +0 -113
  129. package/src/confirm-popup/confirm-popup-message.ts +0 -36
  130. package/src/confirm-popup/confirm-popup-trigger.ts +0 -31
  131. package/src/confirm-popup/confirm-popup.context.ts +0 -41
  132. package/src/confirm-popup/confirm-popup.spec.ts +0 -337
  133. package/src/confirm-popup/confirm-popup.ts +0 -109
  134. package/src/confirm-popup/index.ts +0 -12
  135. package/src/date-picker/date-picker-calendar.ts +0 -65
  136. package/src/date-picker/date-picker-trigger.ts +0 -215
  137. package/src/date-picker/date-picker.context.ts +0 -50
  138. package/src/date-picker/date-picker.spec.ts +0 -117
  139. package/src/date-picker/date-picker.ts +0 -127
  140. package/src/date-picker/index.ts +0 -7
  141. package/src/dialog/_examples/dialog.confirm.example.ts +0 -145
  142. package/src/dialog/_examples/dialog.example.ts +0 -106
  143. package/src/dialog/_examples/dialog.finance.example.ts +0 -121
  144. package/src/dialog/_examples/dialog.retro.example.ts +0 -126
  145. package/src/dialog/_examples/index.ts +0 -6
  146. package/src/dialog/dialog.ref.ts +0 -42
  147. package/src/dialog/dialog.service.ts +0 -66
  148. package/src/dialog/dialog.spec.ts +0 -37
  149. package/src/dialog/dialog.ts +0 -26
  150. package/src/dialog/index.ts +0 -3
  151. package/src/divider/divider.spec.ts +0 -223
  152. package/src/divider/divider.ts +0 -137
  153. package/src/divider/index.ts +0 -5
  154. package/src/drawer/drawer.ref.ts +0 -63
  155. package/src/drawer/drawer.service.ts +0 -106
  156. package/src/drawer/drawer.spec.ts +0 -117
  157. package/src/drawer/drawer.ts +0 -122
  158. package/src/drawer/index.ts +0 -10
  159. package/src/dropdown-menu/dropdown-menu-content.ts +0 -258
  160. package/src/dropdown-menu/dropdown-menu-group.ts +0 -31
  161. package/src/dropdown-menu/dropdown-menu-item.ts +0 -51
  162. package/src/dropdown-menu/dropdown-menu-label.ts +0 -41
  163. package/src/dropdown-menu/dropdown-menu-separator.ts +0 -27
  164. package/src/dropdown-menu/dropdown-menu-trigger.ts +0 -140
  165. package/src/dropdown-menu/dropdown-menu.spec.ts +0 -265
  166. package/src/dropdown-menu/dropdown-menu.ts +0 -60
  167. package/src/dropdown-menu/index.ts +0 -15
  168. package/src/example-components.ts +0 -42
  169. package/src/field/field-error.ts +0 -49
  170. package/src/field/field-group.ts +0 -39
  171. package/src/field/field-help.ts +0 -47
  172. package/src/field/field-label.ts +0 -30
  173. package/src/field/field.context.ts +0 -28
  174. package/src/field/field.spec.ts +0 -179
  175. package/src/field/field.ts +0 -121
  176. package/src/field/index.ts +0 -6
  177. package/src/file-upload/file-upload.context.ts +0 -89
  178. package/src/file-upload/file-upload.spec.ts +0 -290
  179. package/src/file-upload/file-upload.ts +0 -639
  180. package/src/file-upload/file-upload.types.ts +0 -59
  181. package/src/file-upload/index.ts +0 -23
  182. package/src/form/form-error-summary.ts +0 -87
  183. package/src/form/form-field.context.ts +0 -3
  184. package/src/form/form-field.spec.ts +0 -25
  185. package/src/form/form-field.ts +0 -52
  186. package/src/form/form.context.ts +0 -53
  187. package/src/form/form.spec.ts +0 -162
  188. package/src/form/form.ts +0 -326
  189. package/src/form/index.ts +0 -11
  190. package/src/icon/E2E.md +0 -14
  191. package/src/icon/icon.directive.spec.ts +0 -198
  192. package/src/icon/icon.directive.ts +0 -113
  193. package/src/icon/icon.mode.spec.ts +0 -29
  194. package/src/icon/icon.mode.ts +0 -23
  195. package/src/icon/icon.providers.spec.ts +0 -63
  196. package/src/icon/icon.providers.ts +0 -47
  197. package/src/icon/icon.resolver.spec.ts +0 -96
  198. package/src/icon/icon.resolver.ts +0 -49
  199. package/src/icon/icon.tokens.ts +0 -88
  200. package/src/icon/icon.types.ts +0 -48
  201. package/src/icon/index.ts +0 -21
  202. package/src/input/index.ts +0 -1
  203. package/src/input/input.spec.ts +0 -43
  204. package/src/input/input.ts +0 -89
  205. package/src/input-group/index.ts +0 -3
  206. package/src/input-group/input-group-addon.ts +0 -92
  207. package/src/input-group/input-group.context.ts +0 -27
  208. package/src/input-group/input-group.spec.ts +0 -186
  209. package/src/input-group/input-group.ts +0 -136
  210. package/src/input-mask/index.ts +0 -11
  211. package/src/input-mask/input-mask.compile.ts +0 -69
  212. package/src/input-mask/input-mask.engine.ts +0 -376
  213. package/src/input-mask/input-mask.presets.ts +0 -24
  214. package/src/input-mask/input-mask.spec.ts +0 -304
  215. package/src/input-mask/input-mask.tokens.ts +0 -49
  216. package/src/input-mask/input-mask.ts +0 -280
  217. package/src/input-otp/index.ts +0 -2
  218. package/src/input-otp/input-otp.context.ts +0 -41
  219. package/src/input-otp/input-otp.spec.ts +0 -308
  220. package/src/input-otp/input-otp.ts +0 -470
  221. package/src/kbd/index.ts +0 -1
  222. package/src/kbd/kbd.spec.ts +0 -127
  223. package/src/kbd/kbd.ts +0 -132
  224. package/src/link/config.ts +0 -44
  225. package/src/link/index.ts +0 -2
  226. package/src/link/link.spec.ts +0 -246
  227. package/src/link/link.ts +0 -226
  228. package/src/list/index.ts +0 -11
  229. package/src/list/list.spec.ts +0 -237
  230. package/src/list/list.ts +0 -277
  231. package/src/menubar/index.ts +0 -7
  232. package/src/menubar/menubar-item.ts +0 -204
  233. package/src/menubar/menubar.context.ts +0 -43
  234. package/src/menubar/menubar.spec.ts +0 -433
  235. package/src/menubar/menubar.ts +0 -309
  236. package/src/number-input/index.ts +0 -4
  237. package/src/number-input/number-input-group.ts +0 -64
  238. package/src/number-input/number-input.context.ts +0 -31
  239. package/src/number-input/number-input.format.ts +0 -148
  240. package/src/number-input/number-input.spec.ts +0 -170
  241. package/src/number-input/number-input.ts +0 -457
  242. package/src/number-input/number-stepper.ts +0 -193
  243. package/src/overlay-badge/index.ts +0 -7
  244. package/src/overlay-badge/overlay-badge-content.ts +0 -73
  245. package/src/overlay-badge/overlay-badge.context.ts +0 -37
  246. package/src/overlay-badge/overlay-badge.spec.ts +0 -220
  247. package/src/overlay-badge/overlay-badge.ts +0 -128
  248. package/src/pagination/config.ts +0 -82
  249. package/src/pagination/index.ts +0 -19
  250. package/src/pagination/page-tokens.ts +0 -78
  251. package/src/pagination/pagination-ellipsis.ts +0 -69
  252. package/src/pagination/pagination-first.ts +0 -84
  253. package/src/pagination/pagination-info.ts +0 -70
  254. package/src/pagination/pagination-item.ts +0 -81
  255. package/src/pagination/pagination-last.ts +0 -85
  256. package/src/pagination/pagination-next.ts +0 -86
  257. package/src/pagination/pagination-previous.ts +0 -90
  258. package/src/pagination/pagination.context.ts +0 -52
  259. package/src/pagination/pagination.spec.ts +0 -388
  260. package/src/pagination/pagination.ts +0 -288
  261. package/src/password-input/index.ts +0 -15
  262. package/src/password-input/password-input.context.ts +0 -65
  263. package/src/password-input/password-input.scorer.ts +0 -34
  264. package/src/password-input/password-input.spec.ts +0 -274
  265. package/src/password-input/password-input.ts +0 -488
  266. package/src/popover/_examples/index.ts +0 -5
  267. package/src/popover/_examples/popover.example.ts +0 -92
  268. package/src/popover/_examples/popover.finance.example.ts +0 -106
  269. package/src/popover/_examples/popover.retro.example.ts +0 -103
  270. package/src/popover/index.ts +0 -5
  271. package/src/popover/popover-arrow.ts +0 -30
  272. package/src/popover/popover-close.ts +0 -36
  273. package/src/popover/popover-content.ts +0 -41
  274. package/src/popover/popover-title.ts +0 -39
  275. package/src/popover/popover-trigger.ts +0 -40
  276. package/src/popover/popover.spec.ts +0 -59
  277. package/src/popover/popover.ts +0 -5
  278. package/src/presets/bind-presets.spec.ts +0 -50
  279. package/src/presets/bind-presets.ts +0 -43
  280. package/src/presets/index.ts +0 -3
  281. package/src/presets/size.spec.ts +0 -67
  282. package/src/presets/size.ts +0 -59
  283. package/src/presets/variant.spec.ts +0 -72
  284. package/src/presets/variant.ts +0 -62
  285. package/src/primitives/.gitkeep +0 -0
  286. package/src/primitives/directionality/directionality.spec.ts +0 -112
  287. package/src/primitives/directionality/directionality.ts +0 -89
  288. package/src/primitives/directionality/index.ts +0 -1
  289. package/src/primitives/forms/form-control.spec.ts +0 -67
  290. package/src/primitives/forms/form-control.ts +0 -94
  291. package/src/primitives/forms/index.ts +0 -1
  292. package/src/primitives/index.ts +0 -6
  293. package/src/primitives/interaction/disabled.spec.ts +0 -47
  294. package/src/primitives/interaction/disabled.ts +0 -31
  295. package/src/primitives/interaction/focus-ring.spec.ts +0 -62
  296. package/src/primitives/interaction/focus-ring.ts +0 -59
  297. package/src/primitives/interaction/index.ts +0 -2
  298. package/src/primitives/list/filterable-list.spec.ts +0 -114
  299. package/src/primitives/list/filterable-list.ts +0 -126
  300. package/src/primitives/list/group.spec.ts +0 -99
  301. package/src/primitives/list/group.ts +0 -139
  302. package/src/primitives/list/index.ts +0 -8
  303. package/src/primitives/list/inject-helpers.ts +0 -8
  304. package/src/primitives/list/item.spec.ts +0 -173
  305. package/src/primitives/list/item.ts +0 -222
  306. package/src/primitives/list/navigator.spec.ts +0 -286
  307. package/src/primitives/list/navigator.ts +0 -238
  308. package/src/primitives/list/selection.spec.ts +0 -214
  309. package/src/primitives/list/selection.ts +0 -339
  310. package/src/primitives/list/tokens.ts +0 -106
  311. package/src/primitives/list/type-ahead.spec.ts +0 -58
  312. package/src/primitives/list/type-ahead.ts +0 -46
  313. package/src/primitives/overlay/backdrop.spec.ts +0 -54
  314. package/src/primitives/overlay/backdrop.ts +0 -31
  315. package/src/primitives/overlay/builder.spec.ts +0 -38
  316. package/src/primitives/overlay/builder.ts +0 -151
  317. package/src/primitives/overlay/container.ts +0 -42
  318. package/src/primitives/overlay/context.ts +0 -14
  319. package/src/primitives/overlay/controller.spec.ts +0 -86
  320. package/src/primitives/overlay/controller.ts +0 -190
  321. package/src/primitives/overlay/id.spec.ts +0 -24
  322. package/src/primitives/overlay/id.ts +0 -17
  323. package/src/primitives/overlay/index.ts +0 -18
  324. package/src/primitives/overlay/overlay.css +0 -42
  325. package/src/primitives/overlay/panel.spec.ts +0 -52
  326. package/src/primitives/overlay/panel.ts +0 -102
  327. package/src/primitives/overlay/stack.spec.ts +0 -55
  328. package/src/primitives/overlay/stack.ts +0 -113
  329. package/src/primitives/overlay/strategies/backdrop/blurred.spec.ts +0 -11
  330. package/src/primitives/overlay/strategies/backdrop/blurred.ts +0 -5
  331. package/src/primitives/overlay/strategies/backdrop/none.spec.ts +0 -10
  332. package/src/primitives/overlay/strategies/backdrop/none.ts +0 -9
  333. package/src/primitives/overlay/strategies/backdrop/solid.spec.ts +0 -18
  334. package/src/primitives/overlay/strategies/backdrop/solid.ts +0 -23
  335. package/src/primitives/overlay/strategies/focus-trap/inert-based.spec.ts +0 -28
  336. package/src/primitives/overlay/strategies/focus-trap/inert-based.ts +0 -38
  337. package/src/primitives/overlay/strategies/focus-trap/no-trap.spec.ts +0 -9
  338. package/src/primitives/overlay/strategies/focus-trap/no-trap.ts +0 -8
  339. package/src/primitives/overlay/strategies/focus-trap/tab-cycle.spec.ts +0 -49
  340. package/src/primitives/overlay/strategies/focus-trap/tab-cycle.ts +0 -85
  341. package/src/primitives/overlay/strategies/index.ts +0 -34
  342. package/src/primitives/overlay/strategies/live-announcer/_announce.ts +0 -35
  343. package/src/primitives/overlay/strategies/live-announcer/assertive.spec.ts +0 -21
  344. package/src/primitives/overlay/strategies/live-announcer/assertive.ts +0 -11
  345. package/src/primitives/overlay/strategies/live-announcer/polite.spec.ts +0 -21
  346. package/src/primitives/overlay/strategies/live-announcer/polite.ts +0 -11
  347. package/src/primitives/overlay/strategies/live-announcer/silent.spec.ts +0 -12
  348. package/src/primitives/overlay/strategies/live-announcer/silent.ts +0 -5
  349. package/src/primitives/overlay/strategies/mount/body-portal.spec.ts +0 -40
  350. package/src/primitives/overlay/strategies/mount/body-portal.ts +0 -91
  351. package/src/primitives/overlay/strategies/mount/in-container.spec.ts +0 -43
  352. package/src/primitives/overlay/strategies/mount/in-container.ts +0 -39
  353. package/src/primitives/overlay/strategies/mount/in-place.spec.ts +0 -40
  354. package/src/primitives/overlay/strategies/mount/in-place.ts +0 -20
  355. package/src/primitives/overlay/strategies/position/anchored-to.spec.ts +0 -56
  356. package/src/primitives/overlay/strategies/position/anchored-to.ts +0 -248
  357. package/src/primitives/overlay/strategies/position/corner.spec.ts +0 -36
  358. package/src/primitives/overlay/strategies/position/corner.ts +0 -33
  359. package/src/primitives/overlay/strategies/position/edge-sheet.spec.ts +0 -32
  360. package/src/primitives/overlay/strategies/position/edge-sheet.ts +0 -36
  361. package/src/primitives/overlay/strategies/position/in-place-sibling.spec.ts +0 -25
  362. package/src/primitives/overlay/strategies/position/in-place-sibling.ts +0 -13
  363. package/src/primitives/overlay/strategies/position/point-at.spec.ts +0 -40
  364. package/src/primitives/overlay/strategies/position/point-at.ts +0 -34
  365. package/src/primitives/overlay/strategies/position/viewport-centered.spec.ts +0 -31
  366. package/src/primitives/overlay/strategies/position/viewport-centered.ts +0 -31
  367. package/src/primitives/overlay/strategies/scroll-lock/css-clip.spec.ts +0 -15
  368. package/src/primitives/overlay/strategies/scroll-lock/css-clip.ts +0 -39
  369. package/src/primitives/overlay/strategies/scroll-lock/html-overflow.spec.ts +0 -21
  370. package/src/primitives/overlay/strategies/scroll-lock/html-overflow.ts +0 -44
  371. package/src/primitives/overlay/strategies/scroll-lock/none.spec.ts +0 -9
  372. package/src/primitives/overlay/strategies/scroll-lock/none.ts +0 -5
  373. package/src/primitives/overlay/strategies/trigger-event/on-click.spec.ts +0 -32
  374. package/src/primitives/overlay/strategies/trigger-event/on-click.ts +0 -28
  375. package/src/primitives/overlay/strategies/trigger-event/on-context-menu.spec.ts +0 -45
  376. package/src/primitives/overlay/strategies/trigger-event/on-context-menu.ts +0 -70
  377. package/src/primitives/overlay/strategies/trigger-event/on-focus-or-input.spec.ts +0 -35
  378. package/src/primitives/overlay/strategies/trigger-event/on-focus-or-input.ts +0 -34
  379. package/src/primitives/overlay/strategies/trigger-event/on-focus.spec.ts +0 -64
  380. package/src/primitives/overlay/strategies/trigger-event/on-focus.ts +0 -37
  381. package/src/primitives/overlay/strategies/trigger-event/on-hotkey.spec.ts +0 -37
  382. package/src/primitives/overlay/strategies/trigger-event/on-hotkey.ts +0 -59
  383. package/src/primitives/overlay/strategies/trigger-event/on-hover.spec.ts +0 -34
  384. package/src/primitives/overlay/strategies/trigger-event/on-hover.ts +0 -86
  385. package/src/primitives/overlay/strategies/trigger-event/programmatic.spec.ts +0 -16
  386. package/src/primitives/overlay/strategies/trigger-event/programmatic.ts +0 -12
  387. package/src/primitives/overlay/tokens.ts +0 -54
  388. package/src/primitives/overlay/trigger.spec.ts +0 -103
  389. package/src/primitives/overlay/trigger.ts +0 -75
  390. package/src/primitives/overlay/types.ts +0 -24
  391. package/src/primitives/overlay/wrapper.ts +0 -50
  392. package/src/primitives/signals/deep-signal.ts +0 -109
  393. package/src/primitives/signals/index.ts +0 -1
  394. package/src/progress-bar/config.ts +0 -48
  395. package/src/progress-bar/index.ts +0 -12
  396. package/src/progress-bar/progress-bar-fill.ts +0 -37
  397. package/src/progress-bar/progress-bar.context.ts +0 -34
  398. package/src/progress-bar/progress-bar.spec.ts +0 -423
  399. package/src/progress-bar/progress-bar.ts +0 -217
  400. package/src/public-api.ts +0 -84
  401. package/src/radio/index.ts +0 -2
  402. package/src/radio/radio.context.ts +0 -3
  403. package/src/radio/radio.spec.ts +0 -36
  404. package/src/radio/radio.ts +0 -66
  405. package/src/select/index.ts +0 -4
  406. package/src/select/select-content.ts +0 -69
  407. package/src/select/select-option.ts +0 -35
  408. package/src/select/select-root.ts +0 -129
  409. package/src/select/select-trigger.ts +0 -93
  410. package/src/select/select.spec.ts +0 -138
  411. package/src/select/select.ts +0 -4
  412. package/src/skeleton/index.ts +0 -5
  413. package/src/skeleton/skeleton.spec.ts +0 -115
  414. package/src/skeleton/skeleton.ts +0 -56
  415. package/src/slider/index.ts +0 -10
  416. package/src/slider/slider-range.ts +0 -49
  417. package/src/slider/slider-thumb.ts +0 -335
  418. package/src/slider/slider-track.ts +0 -70
  419. package/src/slider/slider.context.ts +0 -79
  420. package/src/slider/slider.geometry.ts +0 -73
  421. package/src/slider/slider.spec.ts +0 -216
  422. package/src/slider/slider.ts +0 -443
  423. package/src/speed-dial/index.ts +0 -10
  424. package/src/speed-dial/speed-dial-action.ts +0 -40
  425. package/src/speed-dial/speed-dial-actions.ts +0 -31
  426. package/src/speed-dial/speed-dial-trigger.ts +0 -55
  427. package/src/speed-dial/speed-dial.context.ts +0 -36
  428. package/src/speed-dial/speed-dial.spec.ts +0 -143
  429. package/src/speed-dial/speed-dial.ts +0 -127
  430. package/src/spinner/config.ts +0 -48
  431. package/src/spinner/index.ts +0 -8
  432. package/src/spinner/spinner.spec.ts +0 -262
  433. package/src/spinner/spinner.ts +0 -129
  434. package/src/stepper/index.ts +0 -15
  435. package/src/stepper/stepper.context.ts +0 -63
  436. package/src/stepper/stepper.spec.ts +0 -403
  437. package/src/stepper/stepper.ts +0 -544
  438. package/src/styles/docs-themes.css +0 -82
  439. package/src/styles.css +0 -17
  440. package/src/table/column-helpers.spec.ts +0 -74
  441. package/src/table/column-helpers.ts +0 -68
  442. package/src/table/filter-fns.ts +0 -230
  443. package/src/table/filter-models.spec.ts +0 -240
  444. package/src/table/filter-models.ts +0 -124
  445. package/src/table/filter-params.ts +0 -90
  446. package/src/table/grid-api-impl.ts +0 -321
  447. package/src/table/grid-api.spec.ts +0 -178
  448. package/src/table/grid-api.ts +0 -285
  449. package/src/table/index.ts +0 -73
  450. package/src/table/table-cell.spec.ts +0 -43
  451. package/src/table/table-cell.ts +0 -38
  452. package/src/table/table-filter-outlet.ts +0 -120
  453. package/src/table/table-header.spec.ts +0 -54
  454. package/src/table/table-header.ts +0 -63
  455. package/src/table/table-keyboard.spec.ts +0 -68
  456. package/src/table/table-keyboard.ts +0 -107
  457. package/src/table/table-resource.spec.ts +0 -37
  458. package/src/table/table-resource.ts +0 -36
  459. package/src/table/table-row.spec.ts +0 -54
  460. package/src/table/table-row.ts +0 -31
  461. package/src/table/table-storage.spec.ts +0 -67
  462. package/src/table/table-storage.ts +0 -76
  463. package/src/table/table.spec.ts +0 -172
  464. package/src/table/table.ts +0 -281
  465. package/src/table/table.types.ts +0 -83
  466. package/src/tabs/index.ts +0 -7
  467. package/src/tabs/tabs.context.ts +0 -32
  468. package/src/tabs/tabs.spec.ts +0 -352
  469. package/src/tabs/tabs.ts +0 -364
  470. package/src/tag/config.ts +0 -53
  471. package/src/tag/index.ts +0 -7
  472. package/src/tag/tag-list.ts +0 -76
  473. package/src/tag/tag-remove.ts +0 -61
  474. package/src/tag/tag.context.ts +0 -36
  475. package/src/tag/tag.spec.ts +0 -240
  476. package/src/tag/tag.ts +0 -203
  477. package/src/test-setup.ts +0 -5
  478. package/src/textarea/config.ts +0 -42
  479. package/src/textarea/index.ts +0 -8
  480. package/src/textarea/textarea.spec.ts +0 -176
  481. package/src/textarea/textarea.ts +0 -235
  482. package/src/time-picker/index.ts +0 -15
  483. package/src/time-picker/time-picker-meridiem.ts +0 -123
  484. package/src/time-picker/time-picker-segment.ts +0 -318
  485. package/src/time-picker/time-picker.context.ts +0 -38
  486. package/src/time-picker/time-picker.format.ts +0 -181
  487. package/src/time-picker/time-picker.spec.ts +0 -189
  488. package/src/time-picker/time-picker.ts +0 -274
  489. package/src/toast/_examples/index.ts +0 -5
  490. package/src/toast/_examples/toast.example.ts +0 -282
  491. package/src/toast/_examples/toast.finance.example.ts +0 -180
  492. package/src/toast/_examples/toast.retro.example.ts +0 -161
  493. package/src/toast/index.ts +0 -28
  494. package/src/toast/toast.ref.ts +0 -26
  495. package/src/toast/toast.service.ts +0 -339
  496. package/src/toast/toast.spec.ts +0 -247
  497. package/src/toast/toast.strategy.ts +0 -112
  498. package/src/toast/toast.ts +0 -463
  499. package/src/toast/toast.types.ts +0 -5
  500. package/src/toggle/index.ts +0 -1
  501. package/src/toggle/toggle.spec.ts +0 -24
  502. package/src/toggle/toggle.ts +0 -48
  503. package/src/tooltip/_examples/index.ts +0 -6
  504. package/src/tooltip/_examples/tooltip.example.ts +0 -82
  505. package/src/tooltip/_examples/tooltip.finance.example.ts +0 -97
  506. package/src/tooltip/_examples/tooltip.placements.example.ts +0 -83
  507. package/src/tooltip/_examples/tooltip.retro.example.ts +0 -107
  508. package/src/tooltip/index.ts +0 -4
  509. package/src/tooltip/tooltip-arrow.ts +0 -31
  510. package/src/tooltip/tooltip-content.ts +0 -38
  511. package/src/tooltip/tooltip-group.ts +0 -32
  512. package/src/tooltip/tooltip-trigger.ts +0 -47
  513. package/src/tooltip/tooltip.spec.ts +0 -40
  514. package/src/tooltip/tooltip.ts +0 -5
  515. package/src/tree-select/index.ts +0 -12
  516. package/src/tree-select/tree-select-content.ts +0 -199
  517. package/src/tree-select/tree-select-node.ts +0 -132
  518. package/src/tree-select/tree-select-root.ts +0 -272
  519. package/src/tree-select/tree-select-trigger.ts +0 -90
  520. package/src/tree-select/tree-select.context.ts +0 -63
  521. package/src/tree-select/tree-select.spec.ts +0 -433
  522. package/src/tree-select/tree-select.ts +0 -2
  523. package/src/typography/blockquote.ts +0 -57
  524. package/src/typography/code.ts +0 -53
  525. package/src/typography/index.ts +0 -22
  526. package/src/typography/lead.ts +0 -49
  527. package/src/typography/muted.ts +0 -29
  528. package/src/typography/truncate.ts +0 -99
  529. package/src/typography/typography.spec.ts +0 -203
  530. package/tsconfig.lib.json +0 -21
  531. package/tsconfig.lib.prod.json +0 -17
  532. package/tsconfig.spec.json +0 -18
  533. package/vite.config.ts +0 -27
  534. /package/{src/icon → icon}/icon.css +0 -0
  535. /package/{src/typography → typography}/prose.css +0 -0
@@ -1,45 +0,0 @@
1
- import { InjectionToken, Signal } from '@angular/core';
2
-
3
- /** Logical text direction surfaced by the group to its CSS / wrapper. */
4
- export type KjAvatarGroupDirection = 'ltr' | 'rtl';
5
-
6
- /**
7
- * Shape forwarded from the group to its child avatars as a default.
8
- * Per-child overrides win.
9
- */
10
- export type KjAvatarShape = 'circle' | 'rounded';
11
-
12
- /**
13
- * Shared state surfaced by `KjAvatarGroup` for child avatars (in the wrapper
14
- * package) and the wrapper template to read.
15
- *
16
- * - `size` / `shape` are *defaults* — children may override per-instance.
17
- * - `direction` mirrors the group's resolved logical direction.
18
- * - `visibleCount`, `overflowCount`, `total` drive the count-aware
19
- * `aria-label` and the wrapper's overflow chip.
20
- */
21
- export interface KjAvatarGroupContext {
22
- /** Size token forwarded from the group as a default for children. */
23
- readonly size: Signal<string | undefined>;
24
- /** Shape forwarded from the group as a default for children. */
25
- readonly shape: Signal<KjAvatarShape | undefined>;
26
- /** Logical text direction observed by the group. */
27
- readonly direction: Signal<KjAvatarGroupDirection>;
28
- /**
29
- * Number of avatars rendered visibly, including the overflow chip when
30
- * present.
31
- */
32
- readonly visibleCount: Signal<number>;
33
- /** Number of avatars hidden behind the chip. `0` when no overflow. */
34
- readonly overflowCount: Signal<number>;
35
- /**
36
- * Effective total: `kjTotal` if provided (and not less than the projected
37
- * count), otherwise the projected child count.
38
- */
39
- readonly total: Signal<number>;
40
- }
41
-
42
- /** Injection token for `KjAvatarGroupContext`. */
43
- export const KJ_AVATAR_GROUP = new InjectionToken<KjAvatarGroupContext>(
44
- 'KjAvatarGroup',
45
- );
@@ -1,358 +0,0 @@
1
- import { Component, PLATFORM_ID, inject } from '@angular/core';
2
- import { render } from '@testing-library/angular';
3
- import { axe, toHaveNoViolations } from 'jest-axe';
4
-
5
- import { KjAvatar, KjAvatarFallback } from './avatar';
6
- import { KjAvatarGroup } from './avatar-group';
7
- import { KJ_AVATAR_GROUP } from './avatar-group.context';
8
-
9
- expect.extend(toHaveNoViolations);
10
-
11
- const imports = [KjAvatar, KjAvatarFallback, KjAvatarGroup];
12
-
13
- /**
14
- * Allow Angular's signal-driven `effect()` to run after a query update —
15
- * tests need a microtask + a macrotask for content-children + writes to
16
- * settle before asserting on host attributes.
17
- */
18
- async function flush(): Promise<void> {
19
- await new Promise<void>((resolve) => setTimeout(resolve, 0));
20
- await Promise.resolve();
21
- await Promise.resolve();
22
- }
23
-
24
- function setHtmlDir(value: 'ltr' | 'rtl' | null): void {
25
- if (value === null) {
26
- document.documentElement.removeAttribute('dir');
27
- } else {
28
- document.documentElement.setAttribute('dir', value);
29
- }
30
- }
31
-
32
- describe('KjAvatarGroup', () => {
33
- afterEach(() => setHtmlDir(null));
34
-
35
- it('enumerates projected children', async () => {
36
- const { container } = await render(
37
- `<span kjAvatarGroup>
38
- <span kjAvatar>A</span>
39
- <span kjAvatar>B</span>
40
- <span kjAvatar>C</span>
41
- </span>`,
42
- { imports },
43
- );
44
- await flush();
45
-
46
- expect(container.querySelectorAll('[kjAvatar]')).toHaveLength(3);
47
- });
48
-
49
- it('hides children past kjMax via [hidden] and data-overflow', async () => {
50
- const { container } = await render(
51
- `<span kjAvatarGroup [kjMax]="2">
52
- <span kjAvatar id="a">A</span>
53
- <span kjAvatar id="b">B</span>
54
- <span kjAvatar id="c">C</span>
55
- <span kjAvatar id="d">D</span>
56
- </span>`,
57
- { imports },
58
- );
59
- await flush();
60
-
61
- const a = container.querySelector('#a') as HTMLElement;
62
- const b = container.querySelector('#b') as HTMLElement;
63
- const c = container.querySelector('#c') as HTMLElement;
64
- const d = container.querySelector('#d') as HTMLElement;
65
-
66
- expect(a.hasAttribute('hidden')).toBe(false);
67
- expect(b.hasAttribute('hidden')).toBe(false);
68
- expect(c.hasAttribute('hidden')).toBe(true);
69
- expect(c.getAttribute('data-overflow')).toBe('true');
70
- expect(d.hasAttribute('hidden')).toBe(true);
71
- expect(d.getAttribute('data-overflow')).toBe('true');
72
- });
73
-
74
- it('exposes visible / overflow / total signals correctly', async () => {
75
- @Component({
76
- standalone: true,
77
- imports,
78
- template: `
79
- <span kjAvatarGroup [kjMax]="2">
80
- @for (i of items; track i) {
81
- <span kjAvatar></span>
82
- }
83
- </span>`,
84
- })
85
- class Host {
86
- items = [1, 2, 3, 4, 5];
87
- }
88
-
89
- const { fixture } = await render(Host);
90
- await flush();
91
-
92
- const el = fixture.nativeElement.querySelector(
93
- '[kjAvatarGroup]',
94
- ) as HTMLElement;
95
- expect(el).toBeTruthy();
96
-
97
- // Visible count = min(5, 2) = 2; overflow = 5 - 2 = 3; total = 5.
98
- // Verify via the count-aware aria-label and CSS variable as public surfaces.
99
- expect(el.getAttribute('aria-label')).toBe('2 of 5 avatars');
100
- expect(el.getAttribute('role')).toBe('group');
101
- expect(el.style.getPropertyValue('--kj-avatar-group-count')).toBe('2');
102
- });
103
-
104
- it('default count-aware aria-label uses "avatars"', async () => {
105
- const { container } = await render(
106
- `<span kjAvatarGroup [kjMax]="3">
107
- <span kjAvatar></span>
108
- <span kjAvatar></span>
109
- <span kjAvatar></span>
110
- <span kjAvatar></span>
111
- <span kjAvatar></span>
112
- </span>`,
113
- { imports },
114
- );
115
- await flush();
116
-
117
- const el = container.querySelector('[kjAvatarGroup]') as HTMLElement;
118
- expect(el.getAttribute('aria-label')).toBe('3 of 5 avatars');
119
- });
120
-
121
- it('aria-label uses kjAriaLabel noun and kjTotal override', async () => {
122
- const { container } = await render(
123
- `<span kjAvatarGroup [kjMax]="3" kjAriaLabel="collaborators" [kjTotal]="42">
124
- <span kjAvatar></span>
125
- <span kjAvatar></span>
126
- <span kjAvatar></span>
127
- </span>`,
128
- { imports },
129
- );
130
- await flush();
131
-
132
- const el = container.querySelector('[kjAvatarGroup]') as HTMLElement;
133
- expect(el.getAttribute('aria-label')).toBe('3 of 42 collaborators');
134
- });
135
-
136
- it('clamps kjTotal upward when smaller than projected child count', async () => {
137
- const { container } = await render(
138
- `<span kjAvatarGroup [kjMax]="2" [kjTotal]="1">
139
- <span kjAvatar></span>
140
- <span kjAvatar></span>
141
- <span kjAvatar></span>
142
- </span>`,
143
- { imports },
144
- );
145
- await flush();
146
-
147
- const el = container.querySelector('[kjAvatarGroup]') as HTMLElement;
148
- // Clamped to 3 (the projected count); never reads "2 of 1".
149
- expect(el.getAttribute('aria-label')).toBe('2 of 3 avatars');
150
- });
151
-
152
- it('omits aria-label entirely when total === 0', async () => {
153
- const { container } = await render(
154
- `<span kjAvatarGroup [kjMax]="3"></span>`,
155
- { imports },
156
- );
157
- await flush();
158
-
159
- const el = container.querySelector('[kjAvatarGroup]') as HTMLElement;
160
- expect(el.hasAttribute('aria-label')).toBe(false);
161
- });
162
-
163
- it('aria-label override (kjAriaLabelOverride) wins over count-aware default', async () => {
164
- const { container } = await render(
165
- `<span kjAvatarGroup [kjMax]="2" kjAriaLabelOverride="Project team">
166
- <span kjAvatar></span>
167
- <span kjAvatar></span>
168
- <span kjAvatar></span>
169
- </span>`,
170
- { imports },
171
- );
172
- await flush();
173
-
174
- const el = container.querySelector('[kjAvatarGroup]') as HTMLElement;
175
- expect(el.getAttribute('aria-label')).toBe('Project team');
176
- });
177
-
178
- it('honours custom kjAriaLabelFormat for i18n', async () => {
179
- @Component({
180
- standalone: true,
181
- imports,
182
- template: `
183
- <span kjAvatarGroup [kjMax]="2" [kjAriaLabelFormat]="format">
184
- <span kjAvatar></span>
185
- <span kjAvatar></span>
186
- <span kjAvatar></span>
187
- <span kjAvatar></span>
188
- </span>`,
189
- })
190
- class Host {
191
- format = (v: number, t: number, l: string) =>
192
- `${v}/${t} ${l} (FR)`;
193
- }
194
-
195
- const { fixture } = await render(Host);
196
- await flush();
197
-
198
- const el = fixture.nativeElement.querySelector(
199
- '[kjAvatarGroup]',
200
- ) as HTMLElement;
201
- expect(el.getAttribute('aria-label')).toBe('2/4 avatars (FR)');
202
- });
203
-
204
- it('size and shape propagate via KJ_AVATAR_GROUP context', async () => {
205
- @Component({
206
- selector: 'kj-test-child',
207
- standalone: true,
208
- template: `<span data-test-child [attr.data-size]="ctx?.size()" [attr.data-shape]="ctx?.shape()"></span>`,
209
- })
210
- class Child {
211
- readonly ctx = inject(KJ_AVATAR_GROUP, { optional: true });
212
- }
213
-
214
- @Component({
215
- standalone: true,
216
- imports: [...imports, Child],
217
- template: `
218
- <span kjAvatarGroup kjSize="lg" kjShape="rounded">
219
- <span kjAvatar><kj-test-child /></span>
220
- <span kjAvatar><kj-test-child /></span>
221
- </span>`,
222
- })
223
- class Host {}
224
-
225
- const { container } = await render(Host);
226
- await flush();
227
-
228
- const probes = container.querySelectorAll('[data-test-child]');
229
- expect(probes.length).toBe(2);
230
- probes.forEach((p) => {
231
- expect(p.getAttribute('data-size')).toBe('lg');
232
- expect(p.getAttribute('data-shape')).toBe('rounded');
233
- });
234
- });
235
-
236
- it('kjRole controls host role (group / list)', async () => {
237
- const { container } = await render(
238
- `<span kjAvatarGroup kjRole="list">
239
- <span kjAvatar></span>
240
- <span kjAvatar></span>
241
- </span>`,
242
- { imports },
243
- );
244
- await flush();
245
-
246
- const el = container.querySelector('[kjAvatarGroup]') as HTMLElement;
247
- expect(el.getAttribute('role')).toBe('list');
248
- });
249
-
250
- it('kjRole=null opts out of the host role attribute', async () => {
251
- @Component({
252
- standalone: true,
253
- imports,
254
- template: `
255
- <span kjAvatarGroup [kjRole]="null">
256
- <span kjAvatar></span>
257
- </span>`,
258
- })
259
- class Host {}
260
-
261
- const { container } = await render(Host);
262
- await flush();
263
-
264
- const el = container.querySelector('[kjAvatarGroup]') as HTMLElement;
265
- expect(el.hasAttribute('role')).toBe(false);
266
- });
267
-
268
- it('LTR stacking writes per-child --kj-avatar-group-stack-order with first child on top', async () => {
269
- setHtmlDir('ltr');
270
-
271
- const { container } = await render(
272
- `<span kjAvatarGroup [kjMax]="0">
273
- <span kjAvatar id="a"></span>
274
- <span kjAvatar id="b"></span>
275
- <span kjAvatar id="c"></span>
276
- </span>`,
277
- { imports },
278
- );
279
- await flush();
280
-
281
- const a = container.querySelector('#a') as HTMLElement;
282
- const b = container.querySelector('#b') as HTMLElement;
283
- const c = container.querySelector('#c') as HTMLElement;
284
-
285
- // First child highest stack-order in LTR.
286
- expect(a.style.getPropertyValue('--kj-avatar-group-stack-order')).toBe('2');
287
- expect(b.style.getPropertyValue('--kj-avatar-group-stack-order')).toBe('1');
288
- expect(c.style.getPropertyValue('--kj-avatar-group-stack-order')).toBe('0');
289
-
290
- const groupEl = container.querySelector('[kjAvatarGroup]') as HTMLElement;
291
- expect(groupEl.getAttribute('data-direction')).toBe('ltr');
292
- });
293
-
294
- it('RTL stacking flips so the last DOM child paints on top', async () => {
295
- setHtmlDir('rtl');
296
-
297
- const { container } = await render(
298
- `<span kjAvatarGroup [kjMax]="0">
299
- <span kjAvatar id="a"></span>
300
- <span kjAvatar id="b"></span>
301
- <span kjAvatar id="c"></span>
302
- </span>`,
303
- { imports },
304
- );
305
- await flush();
306
- // Direction signal updates after afterNextRender; allow another tick.
307
- await flush();
308
-
309
- const a = container.querySelector('#a') as HTMLElement;
310
- const c = container.querySelector('#c') as HTMLElement;
311
-
312
- const groupEl = container.querySelector('[kjAvatarGroup]') as HTMLElement;
313
- expect(groupEl.getAttribute('data-direction')).toBe('rtl');
314
-
315
- // In RTL the visually-leading face (last DOM child) should paint on
316
- // top — so its stack-order is the highest, while the first DOM child
317
- // is now visually trailing and paints behind.
318
- expect(c.style.getPropertyValue('--kj-avatar-group-stack-order')).toBe('2');
319
- expect(a.style.getPropertyValue('--kj-avatar-group-stack-order')).toBe('0');
320
- });
321
-
322
- it('SSR safe — no DOM mutations when PLATFORM_ID is "server"', async () => {
323
- const { container } = await render(
324
- `<span kjAvatarGroup [kjMax]="1">
325
- <span kjAvatar id="a"></span>
326
- <span kjAvatar id="b"></span>
327
- <span kjAvatar id="c"></span>
328
- </span>`,
329
- {
330
- imports,
331
- providers: [{ provide: PLATFORM_ID, useValue: 'server' }],
332
- },
333
- );
334
- await flush();
335
-
336
- // On the server we must not write [hidden] or stack-order CSS variables;
337
- // those belong to the hydration step.
338
- const b = container.querySelector('#b') as HTMLElement;
339
- const c = container.querySelector('#c') as HTMLElement;
340
- expect(b.hasAttribute('hidden')).toBe(false);
341
- expect(c.hasAttribute('hidden')).toBe(false);
342
- expect(b.style.getPropertyValue('--kj-avatar-group-stack-order')).toBe('');
343
- });
344
-
345
- it('passes axe accessibility audit (default group)', async () => {
346
- const { container } = await render(
347
- `<span kjAvatarGroup kjAriaLabel="collaborators" [kjMax]="2">
348
- <span kjAvatar><span kjAvatarFallback aria-hidden="true">JD</span></span>
349
- <span kjAvatar><span kjAvatarFallback aria-hidden="true">AB</span></span>
350
- <span kjAvatar><span kjAvatarFallback aria-hidden="true">CD</span></span>
351
- </span>`,
352
- { imports },
353
- );
354
- await flush();
355
-
356
- expect(await axe(container)).toHaveNoViolations();
357
- });
358
- });
@@ -1,259 +0,0 @@
1
- import {
2
- Directive,
3
- ElementRef,
4
- PLATFORM_ID,
5
- Signal,
6
- computed,
7
- contentChildren,
8
- effect,
9
- inject,
10
- input,
11
- } from '@angular/core';
12
- import { isPlatformBrowser } from '@angular/common';
13
-
14
- import { KjDirectionality } from '../primitives/directionality/directionality';
15
- import { KjAvatar } from './avatar';
16
- import {
17
- KJ_AVATAR_GROUP,
18
- KjAvatarGroupContext,
19
- KjAvatarGroupDirection,
20
- KjAvatarShape,
21
- } from './avatar-group.context';
22
-
23
- /** Format used to compose the count-aware `aria-label`. */
24
- export type KjAvatarGroupAriaLabelFormat = (
25
- visible: number,
26
- total: number,
27
- label: string,
28
- ) => string;
29
-
30
- const DEFAULT_ARIA_LABEL_FORMAT: KjAvatarGroupAriaLabelFormat = (v, t, l) =>
31
- `${v} of ${t} ${l}`;
32
-
33
- /**
34
- * Coordinates a horizontally stacked cluster of `KjAvatar` children.
35
- *
36
- * Owns:
37
- * - **Counting** — enumerates the projected `KjAvatar` directives via
38
- * `contentChildren` and exposes `visibleCount`, `overflowCount`, and `total`
39
- * signals for the wrapper template.
40
- * - **Overflow hiding (Plan C)** — writes `[hidden]` (and a
41
- * `data-overflow="true"` data attribute) on each child past `kjMax`.
42
- * Cleared automatically when the child re-enters the visible range.
43
- * - **ARIA** — applies `role="group"` (or `"list"` / none) and a count-aware
44
- * `aria-label` such as `"3 of 8 collaborators"`. Consumers may override the
45
- * noun (`kjAriaLabel`) and the entire format function (`kjAriaLabelFormat`),
46
- * or pass a static label via the standard `aria-label` attribute on the
47
- * host (the host binding only writes when the consumer hasn't).
48
- * - **RTL-aware stacking** — composes `KjDirectionality` and writes a
49
- * per-child `--kj-avatar-group-stack-order` CSS custom property (and the
50
- * group-wide `--kj-avatar-group-count` and `--kj-avatar-group-direction`)
51
- * so theme CSS can paint first-on-top in either direction without walking
52
- * ancestors.
53
- *
54
- * The directive renders nothing of its own (no template, no DOM mutations
55
- * beyond child host attributes / inline custom properties). The wrapper
56
- * component owns the chip element and the layout CSS.
57
- *
58
- * @example
59
- * ```html
60
- * <span kjAvatarGroup [kjMax]="3" kjAriaLabel="collaborators">
61
- * <span kjAvatar>...</span>
62
- * <span kjAvatar>...</span>
63
- * <span kjAvatar>...</span>
64
- * <span kjAvatar>...</span>
65
- * <span kjAvatar>...</span>
66
- * </span>
67
- * ```
68
- * @doc-category Core/Data display
69
- * @doc
70
- * @doc-name avatar
71
- */
72
- @Directive({
73
- selector: '[kjAvatarGroup]',
74
- standalone: true,
75
- exportAs: 'kjAvatarGroup',
76
- providers: [{ provide: KJ_AVATAR_GROUP, useExisting: KjAvatarGroup }],
77
- host: {
78
- '[attr.role]': 'kjRole()',
79
- '[attr.aria-label]': 'resolvedAriaLabel()',
80
- '[attr.data-direction]': 'direction()',
81
- '[style.--kj-avatar-group-count]': 'visibleCount()',
82
- '[style.--kj-avatar-group-direction]': 'direction()',
83
- },
84
- })
85
- export class KjAvatarGroup implements KjAvatarGroupContext {
86
- private readonly platformId = inject(PLATFORM_ID);
87
- private readonly directionality = inject(KjDirectionality);
88
-
89
- /**
90
- * Maximum number of avatars to show before the overflow chip. Children past
91
- * this index are hidden via `[hidden]` and counted toward
92
- * `overflowCount`. `0` disables the cap (always show all, no chip).
93
- * @default 4
94
- */
95
- readonly kjMax = input<number>(4);
96
-
97
- /**
98
- * Override of the effective total. When provided (and not less than the
99
- * projected child count) drives the count-aware `aria-label` and the
100
- * overflow count, so consumers can show a *page* of a larger collection
101
- * (e.g. server-side pagination).
102
- *
103
- * If the consumer passes a value smaller than the projected count, the
104
- * directive clamps to the projected count to avoid nonsense like `"5 of 3"`.
105
- */
106
- readonly kjTotal = input<number | undefined>(undefined);
107
-
108
- /**
109
- * Default size token forwarded to children via `KJ_AVATAR_GROUP`. Per-child
110
- * overrides win.
111
- */
112
- readonly kjSize = input<string | undefined>(undefined);
113
-
114
- /**
115
- * Default shape forwarded to children via `KJ_AVATAR_GROUP`. Per-child
116
- * overrides win.
117
- * @default 'circle'
118
- */
119
- readonly kjShape = input<KjAvatarShape | undefined>('circle');
120
-
121
- /** Noun used in the count-aware `aria-label`. */
122
- readonly kjAriaLabel = input<string>('avatars');
123
-
124
- /** Formatter for the count-aware `aria-label`. */
125
- readonly kjAriaLabelFormat = input<KjAvatarGroupAriaLabelFormat>(
126
- DEFAULT_ARIA_LABEL_FORMAT,
127
- );
128
-
129
- /**
130
- * Host role. `'group'` for a decorative cluster, `'list'` when each child
131
- * is wrapped in a `listitem` (e.g. interactive avatars as links), `null`
132
- * to opt out entirely.
133
- * @default 'group'
134
- */
135
- readonly kjRole = input<'group' | 'list' | null>('group');
136
-
137
- /**
138
- * Per-consumer override for the host `aria-label`. When set, takes
139
- * precedence over the count-aware label. `null` opts out of `aria-label`.
140
- */
141
- readonly kjAriaLabelOverride = input<string | null | undefined>(undefined);
142
-
143
- /**
144
- * All `KjAvatar` directives projected into the group, including those
145
- * composed via `hostDirectives` on a wrapper component.
146
- *
147
- * `descendants: true` so wrapping a `<kj-avatar>` in `<a>` (the "stack of
148
- * links" use case) still finds the child.
149
- */
150
- private readonly avatars = contentChildren(KjAvatar, { descendants: true });
151
-
152
- /**
153
- * Host elements for each projected `KjAvatar`, queried in parallel with
154
- * the directive query so we can write `[hidden]` and CSS variables onto
155
- * the right host node without having to expose `ElementRef` on `KjAvatar`.
156
- */
157
- private readonly avatarHosts = contentChildren(KjAvatar, {
158
- descendants: true,
159
- read: ElementRef,
160
- });
161
-
162
- /** Effective total: `kjTotal` (clamped) or the projected child count. */
163
- readonly total: Signal<number> = computed(() => {
164
- const childCount = this.avatars().length;
165
- const override = this.kjTotal();
166
- if (override === undefined) return childCount;
167
- return Math.max(override, childCount);
168
- });
169
-
170
- /** Number of children rendered visibly (the rest are `[hidden]`). */
171
- readonly visibleCount: Signal<number> = computed(() => {
172
- const max = this.kjMax();
173
- const childCount = this.avatars().length;
174
- if (max <= 0) return childCount;
175
- return Math.min(childCount, max);
176
- });
177
-
178
- /** Number of avatars hidden by the cap. `0` when nothing overflows. */
179
- readonly overflowCount: Signal<number> = computed(() => {
180
- const max = this.kjMax();
181
- if (max <= 0) return 0;
182
- return Math.max(0, this.total() - max);
183
- });
184
-
185
- /** Logical text direction observed at the document level. */
186
- readonly direction: Signal<KjAvatarGroupDirection> = computed(
187
- () => this.directionality.current() as KjAvatarGroupDirection,
188
- );
189
-
190
- /** Default `aria-label`, omitted when the group is empty. */
191
- private readonly countAwareAriaLabel = computed<string | null>(() => {
192
- const total = this.total();
193
- if (total === 0) return null;
194
- return this.kjAriaLabelFormat()(this.visibleCount(), total, this.kjAriaLabel());
195
- });
196
-
197
- /**
198
- * `aria-label` actually written to the host. Consumer override wins; `null`
199
- * opts out of the attribute entirely.
200
- */
201
- protected readonly resolvedAriaLabel = computed<string | null>(() => {
202
- const override = this.kjAriaLabelOverride();
203
- if (override !== undefined) return override ?? null;
204
- return this.countAwareAriaLabel();
205
- });
206
-
207
- /** Read-only signal — exposed for the wrapper / spec ergonomics. */
208
- get size(): Signal<string | undefined> {
209
- return this.kjSize;
210
- }
211
-
212
- /** Read-only signal — exposed for the wrapper / spec ergonomics. */
213
- get shape(): Signal<KjAvatarShape | undefined> {
214
- return this.kjShape;
215
- }
216
-
217
- constructor() {
218
- // Plan C from `avatar-group.md`: write `[hidden]` and a per-child stack
219
- // order onto each projected avatar's host element. Crosses the directive
220
- // boundary by design — the group owns visibility of its overflow items.
221
- effect(() => {
222
- const hosts = this.avatarHosts();
223
- const max = this.kjMax();
224
- const dir = this.direction();
225
- const visibleCount = this.visibleCount();
226
- const isBrowser = isPlatformBrowser(this.platformId);
227
- if (!isBrowser) return;
228
-
229
- const total = hosts.length;
230
- const cap = max <= 0 ? total : Math.min(max, total);
231
-
232
- hosts.forEach((ref, index) => {
233
- const el = ref.nativeElement as HTMLElement | null;
234
- if (!el) return;
235
-
236
- const overflow = max > 0 && index >= cap;
237
- if (overflow) {
238
- el.setAttribute('hidden', '');
239
- el.setAttribute('data-overflow', 'true');
240
- } else {
241
- el.removeAttribute('hidden');
242
- el.removeAttribute('data-overflow');
243
- }
244
-
245
- // First-on-top in LTR (highest z-index goes to index 0); flipped in
246
- // RTL so the visually-leading face — which is now on the right —
247
- // still paints on top.
248
- const visualIndex =
249
- dir === 'rtl' ? Math.max(0, visibleCount - 1 - index) : index;
250
- const stackOrder = Math.max(0, visibleCount - 1 - visualIndex);
251
- el.style.setProperty(
252
- '--kj-avatar-group-stack-order',
253
- String(stackOrder),
254
- );
255
- el.style.setProperty('--kj-avatar-group-index', String(index));
256
- });
257
- });
258
- }
259
- }
@@ -1,18 +0,0 @@
1
- import { render } from '@testing-library/angular';
2
- import { axe, toHaveNoViolations } from 'jest-axe';
3
- import { KjAvatar, KjAvatarImage, KjAvatarFallback } from './avatar';
4
-
5
- expect.extend(toHaveNoViolations);
6
-
7
- const imports = [KjAvatar, KjAvatarImage, KjAvatarFallback];
8
-
9
- describe('KjAvatar', () => {
10
- it('renders container', async () => {
11
- const { container } = await render(`<span kjAvatar><img kjAvatarImage src="" alt="JD" /><span kjAvatarFallback>JD</span></span>`, { imports });
12
- expect(container.querySelector('[kjAvatar]')).toBeInTheDocument();
13
- });
14
- it('passes axe audit', async () => {
15
- const { container } = await render(`<span kjAvatar><img kjAvatarImage src="/p.jpg" alt="Jane Doe" /><span kjAvatarFallback aria-hidden="true">JD</span></span>`, { imports });
16
- expect(await axe(container)).toHaveNoViolations();
17
- });
18
- });