@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
package/src/kbd/kbd.ts DELETED
@@ -1,132 +0,0 @@
1
- import {
2
- Directive,
3
- ElementRef,
4
- afterNextRender,
5
- inject,
6
- isDevMode,
7
- } from '@angular/core';
8
- import { KjSize, type KjSizePreset } from '../presets';
9
-
10
- /**
11
- * Default size preset used by Kbd consumers (`xs / sm / md / lg`, default `md`).
12
- *
13
- * Re-exported so core-package consumers applying `[kjKbd]` directly to their
14
- * own `<kbd>` elements can opt into the same size scale the eventual styled
15
- * wrapper will provide, via:
16
- *
17
- * ```ts
18
- * providers: [{ provide: KJ_SIZE_PRESET, useValue: KJ_KBD_SIZE_PRESET }]
19
- * ```
20
- *
21
- * Avoids the silent-drift case where a consumer picks `'huge'` and the
22
- * directive's dev-mode validator passes (because the consumer's preset didn't
23
- * list it) but the CSS doesn't recognise the value. See
24
- * `docs/component-analyses/data-display/kbd.md` (Open question 13).
25
- */
26
- export const KJ_KBD_SIZE_PRESET: KjSizePreset = {
27
- values: ['xs', 'sm', 'md', 'lg'],
28
- default: 'md',
29
- };
30
-
31
- /**
32
- * Marks an element as a kouji keyboard-key visual (`<kbd>`). The directive is
33
- * a pure visual primitive: it composes `KjSize` (the only configurable axis)
34
- * and otherwise relies on the native `<kbd>` element's a11y semantics.
35
- *
36
- * The host element is consumer-supplied. The recommended host is `<kbd>`
37
- * (native semantic — implicit `role="generic"` per HTML AAM, but commonly
38
- * announced with a "key" prefix in verbose AT modes); applying `[kjKbd]` to
39
- * any other element is dev-mode warned but not enforced (consumers wanting a
40
- * `<span>` host for inline-baseline reasons get an escape hatch).
41
- *
42
- * **No variant.** Kbd is tonally neutral — there is no "destructive kbd" or
43
- * "primary kbd". A future design language wanting e.g. a "deprecated shortcut"
44
- * tone can fold in via a CSS-only `[data-deprecated="true"]` attribute without
45
- * API churn.
46
- *
47
- * **No keyboard contract.** Kbd is non-focusable, non-clickable. Consumers
48
- * wanting a clickable shortcut chip wrap a `<button kjButton>` around the
49
- * `<kbd kjKbd>` and the button owns the click / focus / a11y story. Embedding
50
- * a focusable descendant inside `[kjKbd]` is dev-mode warned because most AT
51
- * will re-parent or strip the interactive child out of the kbd's accessible
52
- * name.
53
- *
54
- * **No `aria-label` injection.** When the visible text is a unicode glyph
55
- * (`⌘`, `⌥`, `↵`) the consumer sets `aria-label` directly on the host —
56
- * exactly the same idiom as setting `aria-label` on any HTML element. The
57
- * directive does not declare a duplicate input for it. (The eventual
58
- * `<kj-kbd>` wrapper exposes a template-driven `kjKbdAriaLabel` input that
59
- * forwards to `[attr.aria-label]`; that is the wrapper's call, not the
60
- * directive's.)
61
- *
62
- * @example
63
- * ```html
64
- * <kbd kjKbd>Enter</kbd>
65
- * <kbd kjKbd kjSize="xs">⌘</kbd>
66
- * <kbd kjKbd aria-label="Command">⌘</kbd>
67
- * ```
68
- * @doc-category Core/Data display
69
- * @doc
70
- * @doc-name kbd
71
- * @doc-description Marks a kbd element as a keyboard-key visual with a configurable size.
72
- * @doc-is-main
73
- */
74
- @Directive({
75
- selector: '[kjKbd]',
76
- standalone: true,
77
- hostDirectives: [{ directive: KjSize, inputs: ['kjSize'] }],
78
- })
79
- export class KjKbd {
80
- private readonly el = inject<ElementRef<HTMLElement>>(ElementRef);
81
-
82
- constructor() {
83
- if (isDevMode()) {
84
- afterNextRender(() => {
85
- const host = this.el.nativeElement;
86
-
87
- if (host.tagName?.toLowerCase() !== 'kbd') {
88
- console.warn(
89
- `[kj] kjKbd applied to <${host.tagName?.toLowerCase()}>. ` +
90
- `Recommended host element is <kbd> for native semantics ` +
91
- `(WCAG 1.3.1 / 4.1.2). Apply only to non-kbd elements when ` +
92
- `you have a specific styling reason.`,
93
- );
94
- }
95
-
96
- if (hasFocusableDescendant(host)) {
97
- console.warn(
98
- `[kj] kjKbd contains a focusable descendant. Kbd is a ` +
99
- `non-interactive visual primitive; most AT will re-parent or ` +
100
- `strip interactive children out of the kbd's accessible name. ` +
101
- `Wrap the <kbd kjKbd> inside a <button kjButton> instead of ` +
102
- `nesting an interactive element inside it.`,
103
- );
104
- }
105
- });
106
- }
107
- }
108
- }
109
-
110
- /**
111
- * Selector matching elements that are focusable by default. Intentionally
112
- * narrow: this is a dev-mode advisory, not an a11y enforcement gate, so we
113
- * accept the small risk of missing exotic focusable descendants
114
- * (`contenteditable`, embedded `<object>` with focusable controls, etc.) in
115
- * favour of a fast first-pass check.
116
- */
117
- const FOCUSABLE_SELECTOR = [
118
- 'a[href]',
119
- 'button',
120
- 'input',
121
- 'select',
122
- 'textarea',
123
- 'audio[controls]',
124
- 'video[controls]',
125
- '[tabindex]',
126
- '[contenteditable=""]',
127
- '[contenteditable="true"]',
128
- ].join(',');
129
-
130
- function hasFocusableDescendant(host: HTMLElement): boolean {
131
- return host.querySelector(FOCUSABLE_SELECTOR) !== null;
132
- }
@@ -1,44 +0,0 @@
1
- import { InjectionToken, Provider } from '@angular/core';
2
-
3
- export interface KjLinkConfig {
4
- variants: string[];
5
- sizes: string[];
6
- defaults: { variant: string; size: string };
7
- }
8
-
9
- /**
10
- * Default Link presets shipped by kouji-ui. Exported so consumers can spread
11
- * them when extending: `[...KJ_LINK_DEFAULTS.variants, 'brand']`.
12
- */
13
- export const KJ_LINK_DEFAULTS: KjLinkConfig = {
14
- variants: ['primary', 'secondary', 'muted', 'destructive'],
15
- sizes: ['sm', 'md', 'lg', 'inherit'],
16
- defaults: { variant: 'primary', size: 'inherit' },
17
- };
18
-
19
- /**
20
- * DI token for the active Link presets. Default factory yields
21
- * `KJ_LINK_DEFAULTS`. Override via `provideKjLink(…)` at the application
22
- * scope (e.g. `bootstrapApplication`'s `providers` or a route's `providers`)
23
- * or at the component scope (a component's own `providers: […]`).
24
- */
25
- export const KJ_LINK_CONFIG = new InjectionToken<KjLinkConfig>('kj.link.config', {
26
- factory: () => KJ_LINK_DEFAULTS,
27
- });
28
-
29
- /**
30
- * Configures the Link presets for the enclosing injector. Replaces (does not
31
- * merge) `variants` and `sizes`; spread `KJ_LINK_DEFAULTS.variants` to extend.
32
- *
33
- * Returns a `Provider[]` so it can be spread into either an environment
34
- * `providers` (`bootstrapApplication`, route config) or a component-level
35
- * `providers` array.
36
- */
37
- export function provideKjLink(config: Partial<KjLinkConfig>): Provider[] {
38
- return [
39
- {
40
- provide: KJ_LINK_CONFIG,
41
- useValue: { ...KJ_LINK_DEFAULTS, ...config },
42
- },
43
- ];
44
- }
package/src/link/index.ts DELETED
@@ -1,2 +0,0 @@
1
- export * from './link';
2
- export * from './config';
@@ -1,246 +0,0 @@
1
- import { Component, ChangeDetectionStrategy } from '@angular/core';
2
- import { TestBed } from '@angular/core/testing';
3
- import { render } from '@testing-library/angular';
4
- import { describe, expect, it } from 'vitest';
5
- import { KjLink } from './link';
6
-
7
- @Component({
8
- standalone: true,
9
- imports: [KjLink],
10
- changeDetection: ChangeDetectionStrategy.Eager,
11
- template: `<a kjLink href="/x" [kjDisabled]="d" (click)="onClick()">x</a>`,
12
- })
13
- class DisabledClickHost {
14
- d = true;
15
- fired = 0;
16
- onClick() {
17
- this.fired++;
18
- }
19
- }
20
-
21
- @Component({
22
- standalone: true,
23
- imports: [KjLink],
24
- changeDetection: ChangeDetectionStrategy.Eager,
25
- template: `<a kjLink href="/x" [kjDisabled]="d" (keydown)="onKeydown($event)">x</a>`,
26
- })
27
- class DisabledKeydownHost {
28
- d = true;
29
- navigated = 0;
30
- onKeydown(_event: KeyboardEvent) {
31
- this.navigated++;
32
- }
33
- }
34
-
35
- describe('KjLink', () => {
36
- it('renders an anchor with role=link via native <a>', async () => {
37
- const { getByRole } = await render(`<a kjLink href="/foo">Foo</a>`, { imports: [KjLink] });
38
- expect(getByRole('link')).toBeInTheDocument();
39
- });
40
-
41
- it('default variant comes from KJ_LINK_DEFAULTS', async () => {
42
- const { getByRole } = await render(`<a kjLink href="/x">x</a>`, { imports: [KjLink] });
43
- expect(getByRole('link')).toHaveAttribute('data-variant', 'primary');
44
- });
45
-
46
- it('default size comes from KJ_LINK_DEFAULTS', async () => {
47
- const { getByRole } = await render(`<a kjLink href="/x">x</a>`, { imports: [KjLink] });
48
- expect(getByRole('link')).toHaveAttribute('data-size', 'inherit');
49
- });
50
-
51
- it('reflects kjVariant to data-variant', async () => {
52
- const { getByRole } = await render(`<a kjLink href="/x" [kjVariant]="'destructive'">x</a>`, {
53
- imports: [KjLink],
54
- });
55
- expect(getByRole('link')).toHaveAttribute('data-variant', 'destructive');
56
- });
57
-
58
- it('reflects kjSize to data-size', async () => {
59
- const { getByRole } = await render(`<a kjLink href="/x" [kjSize]="'sm'">x</a>`, {
60
- imports: [KjLink],
61
- });
62
- expect(getByRole('link')).toHaveAttribute('data-size', 'sm');
63
- });
64
-
65
- it('reflects kjUnderline to data-underline (default hover)', async () => {
66
- const { getByRole } = await render(`<a kjLink href="/x">x</a>`, { imports: [KjLink] });
67
- expect(getByRole('link')).toHaveAttribute('data-underline', 'hover');
68
- });
69
-
70
- it('reflects kjUnderline=always', async () => {
71
- const { getByRole } = await render(`<a kjLink href="/x" [kjUnderline]="'always'">x</a>`, {
72
- imports: [KjLink],
73
- });
74
- expect(getByRole('link')).toHaveAttribute('data-underline', 'always');
75
- });
76
-
77
- it('reflects kjUnderline=none', async () => {
78
- const { getByRole } = await render(`<a kjLink href="/x" [kjUnderline]="'none'">x</a>`, {
79
- imports: [KjLink],
80
- });
81
- expect(getByRole('link')).toHaveAttribute('data-underline', 'none');
82
- });
83
-
84
- it('auto-detects external from target="_blank" and reflects data-external', async () => {
85
- const { getByRole } = await render(
86
- `<a kjLink href="https://example.com" target="_blank">Docs</a>`,
87
- { imports: [KjLink] },
88
- );
89
- expect(getByRole('link')).toHaveAttribute('data-external', 'true');
90
- });
91
-
92
- it('does not mark as external when no target="_blank" and kjExternal unset', async () => {
93
- const { getByRole } = await render(`<a kjLink href="https://example.com">Docs</a>`, {
94
- imports: [KjLink],
95
- });
96
- expect(getByRole('link')).not.toHaveAttribute('data-external');
97
- });
98
-
99
- it('explicit kjExternal=true overrides target detection', async () => {
100
- const { getByRole } = await render(`<a kjLink href="/internal" [kjExternal]="true">Docs</a>`, {
101
- imports: [KjLink],
102
- });
103
- expect(getByRole('link')).toHaveAttribute('data-external', 'true');
104
- });
105
-
106
- it('explicit kjExternal=false suppresses external treatment even with target=_blank', async () => {
107
- const { getByRole } = await render(
108
- `<a kjLink href="/x" target="_blank" [kjExternal]="false">x</a>`,
109
- { imports: [KjLink] },
110
- );
111
- expect(getByRole('link')).not.toHaveAttribute('data-external');
112
- });
113
-
114
- it('injects rel="noopener noreferrer" when external', async () => {
115
- const { getByRole } = await render(
116
- `<a kjLink href="https://example.com" target="_blank">Docs</a>`,
117
- { imports: [KjLink] },
118
- );
119
- const rel = getByRole('link').getAttribute('rel') ?? '';
120
- const tokens = rel.split(/\s+/u).filter(Boolean);
121
- expect(tokens).toContain('noopener');
122
- expect(tokens).toContain('noreferrer');
123
- });
124
-
125
- it('rel injection is additive — preserves consumer-supplied tokens', async () => {
126
- const { getByRole } = await render(
127
- `<a kjLink href="https://example.com" target="_blank" rel="nofollow me">Docs</a>`,
128
- { imports: [KjLink] },
129
- );
130
- const rel = getByRole('link').getAttribute('rel') ?? '';
131
- const tokens = rel.split(/\s+/u).filter(Boolean);
132
- expect(tokens).toContain('nofollow');
133
- expect(tokens).toContain('me');
134
- expect(tokens).toContain('noopener');
135
- expect(tokens).toContain('noreferrer');
136
- });
137
-
138
- it('does not add noopener/noreferrer when not external', async () => {
139
- const { getByRole } = await render(`<a kjLink href="/internal" rel="nofollow">x</a>`, {
140
- imports: [KjLink],
141
- });
142
- const rel = getByRole('link').getAttribute('rel') ?? '';
143
- expect(rel.split(/\s+/u)).not.toContain('noopener');
144
- expect(rel.split(/\s+/u)).toContain('nofollow');
145
- });
146
-
147
- it('appends visually-hidden "(opens in new tab)" suffix span when external', async () => {
148
- const { getByRole } = await render(
149
- `<a kjLink href="https://example.com" target="_blank">Docs</a>`,
150
- { imports: [KjLink] },
151
- );
152
- const link = getByRole('link');
153
- const suffix = link.querySelector('.kj-link-external-suffix');
154
- expect(suffix).not.toBeNull();
155
- expect(suffix!.textContent).toContain('opens in new tab');
156
- // Visually hidden inline style applied.
157
- const style = (suffix as HTMLElement).getAttribute('style') ?? '';
158
- expect(style).toContain('width:1px');
159
- expect(style).toContain('height:1px');
160
- });
161
-
162
- it('does not inject AT suffix when consumer supplies aria-label', async () => {
163
- const { getByRole } = await render(
164
- `<a kjLink href="https://example.com" target="_blank" aria-label="Docs (new window)">Docs</a>`,
165
- { imports: [KjLink] },
166
- );
167
- const link = getByRole('link');
168
- expect(link.querySelector('.kj-link-external-suffix')).toBeNull();
169
- });
170
-
171
- it('does not inject AT suffix for non-external links', async () => {
172
- const { getByRole } = await render(`<a kjLink href="/x">x</a>`, { imports: [KjLink] });
173
- expect(getByRole('link').querySelector('.kj-link-external-suffix')).toBeNull();
174
- });
175
-
176
- it('disabled bundle: aria-disabled, data-disabled, tabindex=-1', async () => {
177
- const { getByRole } = await render(`<a kjLink href="/x" [kjDisabled]="true">x</a>`, {
178
- imports: [KjLink],
179
- });
180
- const link = getByRole('link');
181
- expect(link).toHaveAttribute('aria-disabled', 'true');
182
- expect(link).toHaveAttribute('data-disabled', '');
183
- expect(link).toHaveAttribute('tabindex', '-1');
184
- });
185
-
186
- it('omits aria-disabled / tabindex when not disabled', async () => {
187
- const { getByRole } = await render(`<a kjLink href="/x">x</a>`, { imports: [KjLink] });
188
- const link = getByRole('link');
189
- expect(link).not.toHaveAttribute('aria-disabled');
190
- expect(link).not.toHaveAttribute('tabindex');
191
- });
192
-
193
- it('suppresses click events when disabled (capture-phase)', () => {
194
- TestBed.configureTestingModule({ imports: [DisabledClickHost] });
195
- const fixture = TestBed.createComponent(DisabledClickHost);
196
- fixture.detectChanges();
197
- const link = fixture.nativeElement.querySelector('a') as HTMLAnchorElement;
198
- link.click();
199
- expect(fixture.componentInstance.fired).toBe(0);
200
- });
201
-
202
- it('allows click events when not disabled', () => {
203
- TestBed.configureTestingModule({ imports: [DisabledClickHost] });
204
- const fixture = TestBed.createComponent(DisabledClickHost);
205
- fixture.componentInstance.d = false;
206
- fixture.detectChanges();
207
- const link = fixture.nativeElement.querySelector('a') as HTMLAnchorElement;
208
- link.addEventListener('click', (e) => e.preventDefault(), { once: true });
209
- link.click();
210
- expect(fixture.componentInstance.fired).toBe(1);
211
- });
212
-
213
- it('suppresses Enter keydown events when disabled', () => {
214
- TestBed.configureTestingModule({ imports: [DisabledKeydownHost] });
215
- const fixture = TestBed.createComponent(DisabledKeydownHost);
216
- fixture.detectChanges();
217
- const link = fixture.nativeElement.querySelector('a') as HTMLAnchorElement;
218
- const event = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true });
219
- link.dispatchEvent(event);
220
- expect(event.defaultPrevented).toBe(true);
221
- expect(fixture.componentInstance.navigated).toBe(0);
222
- });
223
-
224
- it('does not suppress non-Enter keydown when disabled', () => {
225
- TestBed.configureTestingModule({ imports: [DisabledKeydownHost] });
226
- const fixture = TestBed.createComponent(DisabledKeydownHost);
227
- fixture.detectChanges();
228
- const link = fixture.nativeElement.querySelector('a') as HTMLAnchorElement;
229
- const event = new KeyboardEvent('keydown', { key: 'Tab', bubbles: true, cancelable: true });
230
- link.dispatchEvent(event);
231
- expect(event.defaultPrevented).toBe(false);
232
- expect(fixture.componentInstance.navigated).toBe(1);
233
- });
234
-
235
- it('does not suppress Enter when not disabled', () => {
236
- TestBed.configureTestingModule({ imports: [DisabledKeydownHost] });
237
- const fixture = TestBed.createComponent(DisabledKeydownHost);
238
- fixture.componentInstance.d = false;
239
- fixture.detectChanges();
240
- const link = fixture.nativeElement.querySelector('a') as HTMLAnchorElement;
241
- const event = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true });
242
- link.dispatchEvent(event);
243
- expect(event.defaultPrevented).toBe(false);
244
- expect(fixture.componentInstance.navigated).toBe(1);
245
- });
246
- });
package/src/link/link.ts DELETED
@@ -1,226 +0,0 @@
1
- import { DOCUMENT } from '@angular/common';
2
- import {
3
- Directive,
4
- ElementRef,
5
- afterNextRender,
6
- computed,
7
- effect,
8
- inject,
9
- input,
10
- } from '@angular/core';
11
- import { KjFocusRing, KjDisabled } from '../primitives';
12
- import { KjVariant, KjSize, bindPresets } from '../presets';
13
- import { KJ_LINK_CONFIG } from './config';
14
-
15
- /** CSS class applied to the visually-hidden "(opens in new tab)" suffix span. */
16
- const KJ_LINK_EXTERNAL_SUFFIX_CLASS = 'kj-link-external-suffix';
17
-
18
- /** AT suffix copy. English-only for v1; i18n is a v1.1 concern (see analysis §15). */
19
- const KJ_LINK_EXTERNAL_SUFFIX_TEXT = '(opens in new tab)';
20
-
21
- /** Inline style string equivalent to `KjVisuallyHidden` — applied to the AT suffix span. */
22
- const KJ_LINK_VISUALLY_HIDDEN_STYLE =
23
- 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0';
24
-
25
- /**
26
- * Enhances a native `<a>` (or any element used as a link) with kouji-ui
27
- * presets, focus-ring and disabled-link plumbing, and external-link
28
- * `rel` + AT suffix discipline.
29
- *
30
- * Composes `KjVariant`, `KjSize`, `KjFocusRing`, and `KjDisabled` via
31
- * `hostDirectives`. Variants and sizes are configurable via
32
- * `provideKjLink(…)`.
33
- *
34
- * Owns three behaviours that a CSS-only solution cannot deliver:
35
- *
36
- * 1. **External-link plumbing.** When `kjExternal` is `true` (or `undefined`
37
- * and the host carries `target="_blank"`), the directive ensures `rel`
38
- * contains both `noopener` and `noreferrer` (additive — preserves any
39
- * consumer-supplied `rel` tokens like `nofollow`, `me`, `bookmark`) and
40
- * appends a visually-hidden `(opens in new tab)` `<span>` to the host's
41
- * accessible name. The suffix is suppressed when the consumer has set
42
- * their own `aria-label` (the consumer is presumed to have authored the
43
- * complete accessible name).
44
- *
45
- * 2. **Disabled-link bundle.** When `kjDisabled` is `true`, the directive
46
- * sets `aria-disabled="true"`, `tabindex="-1"`, and capture-phase
47
- * intercepts both `click` and `keydown.enter` to call `preventDefault()`
48
- * and `stopImmediatePropagation()`. Capture phase ensures the suppression
49
- * runs before any consumer-bound `(click)` handler and before Angular
50
- * Router's bubble-phase click handler — so `<a kjLink routerLink="/foo"
51
- * [kjDisabled]="true">` does not navigate either.
52
- *
53
- * 3. **Underline-mode reflection.** `kjUnderline: 'always' | 'hover' |
54
- * 'none'` reflects to `[attr.data-underline]` for the components-package
55
- * CSS to key off. The `kj-prose a` selector overrides only when the
56
- * directive's input is left at its default — explicit consumer values
57
- * win over the prose container's defaults.
58
- *
59
- * @example
60
- * ```html
61
- * <a kjLink href="/about">Inline link</a>
62
- * <a kjLink href="https://example.com" target="_blank">External</a>
63
- * <a kjLink [kjDisabled]="!ready()" routerLink="/billing">Manage billing</a>
64
- * ```
65
- *
66
- * @doc-category Core/Navigation
67
- * @doc
68
- * @doc-name link
69
- * @doc-description Adds disabled-link, external-link, and underline-mode handling to a native anchor.
70
- * @doc-is-main
71
- */
72
- @Directive({
73
- selector: 'a[kjLink], [kjLink]',
74
- standalone: true,
75
- hostDirectives: [
76
- { directive: KjVariant, inputs: ['kjVariant'] },
77
- { directive: KjSize, inputs: ['kjSize'] },
78
- KjFocusRing,
79
- { directive: KjDisabled, inputs: ['kjDisabled'] },
80
- ],
81
- providers: [...bindPresets(KJ_LINK_CONFIG)],
82
- host: {
83
- '[attr.data-underline]': 'kjUnderline()',
84
- '[attr.data-external]': 'isExternal() ? "true" : null',
85
- '[attr.tabindex]': 'kjDisabled() ? "-1" : null',
86
- '[attr.rel]': 'relAttr()',
87
- },
88
- })
89
- export class KjLink {
90
- private readonly el = inject<ElementRef<HTMLElement>>(ElementRef);
91
- private readonly document = inject(DOCUMENT);
92
-
93
- /**
94
- * Disables the link. Forwarded to `KjDisabled` (which reflects
95
- * `aria-disabled` and `data-disabled`); the directive additionally sets
96
- * `tabindex="-1"` and intercepts `click` + `keydown.enter` in the capture
97
- * phase.
98
- */
99
- readonly kjDisabled = input(false);
100
-
101
- /**
102
- * Underline policy. `'always'` for in-content links (WCAG 1.4.1 — colour
103
- * is not the only means); `'hover'` for standalone links sitting in a
104
- * group of links that already signals "this is a link" via layout;
105
- * `'none'` for the rare cases where the consumer wants to suppress the
106
- * underline entirely (e.g. icon-text links inside breadcrumb separators).
107
- * Reflects `[attr.data-underline]`.
108
- */
109
- readonly kjUnderline = input<'always' | 'hover' | 'none'>('hover');
110
-
111
- /**
112
- * External-link tri-state. `undefined` (default) auto-detects from the
113
- * host's `target` attribute (`target="_blank"` → external). `true` forces
114
- * external treatment regardless of `target` (e.g. for cross-origin URLs
115
- * served through the app's router that still warrant the indicator).
116
- * `false` forces internal treatment even when `target="_blank"` is
117
- * present (suppresses the icon and AT suffix).
118
- */
119
- readonly kjExternal = input<boolean | undefined>(undefined);
120
-
121
- /** Whether the host element currently carries `target="_blank"`. */
122
- protected readonly hasBlankTarget = computed(() => this.targetSignal() === '_blank');
123
-
124
- /** Computed external state — explicit input wins, else target-based auto-detect. */
125
- protected readonly isExternal = computed(() => {
126
- const explicit = this.kjExternal();
127
- if (explicit !== undefined) return explicit;
128
- return this.hasBlankTarget();
129
- });
130
-
131
- /**
132
- * `rel` attribute computation. Additive: existing tokens (`nofollow`,
133
- * `me`, `bookmark`, …) are preserved; the directive only adds the missing
134
- * `noopener` / `noreferrer` security tokens when external. When not
135
- * external, the directive returns `null` so the consumer's literal `rel`
136
- * attribute (read at construction) is preserved as-is.
137
- */
138
- protected readonly relAttr = computed(() => {
139
- if (!this.isExternal()) return this.initialRel || null;
140
- const tokens = new Set<string>();
141
- if (this.initialRel) {
142
- for (const token of this.initialRel.split(/\s+/u)) {
143
- if (token) tokens.add(token);
144
- }
145
- }
146
- tokens.add('noopener');
147
- tokens.add('noreferrer');
148
- return [...tokens].join(' ');
149
- });
150
-
151
- /**
152
- * Snapshot of the host's `target` attribute. Re-read after the host
153
- * renders — host bindings are evaluated synchronously on creation, so
154
- * the SSR HTML carries the right `[data-external]` / `[rel]` values
155
- * provided the consumer's `target` is set declaratively in the template
156
- * (the common case).
157
- */
158
- private readonly targetSignal = (() => {
159
- const initial = this.el.nativeElement.getAttribute('target');
160
- return computed(() => initial);
161
- })();
162
-
163
- /** Snapshot of the host's `rel` attribute at construction time. */
164
- private readonly initialRel: string | null = this.el.nativeElement.getAttribute('rel');
165
-
166
- /** Reference to the injected AT suffix span, if any. Cleaned up on toggle. */
167
- private suffixSpan: HTMLSpanElement | null = null;
168
-
169
- constructor() {
170
- // Capture-phase native listeners: fire BEFORE Angular's template-bound
171
- // bubble-phase (click) handlers and before Angular Router's bubble-phase
172
- // click handler on `<a routerLink>`, so `stopImmediatePropagation()`
173
- // actually prevents both navigation and any consumer (click) handlers.
174
- afterNextRender(() => {
175
- const node = this.el.nativeElement;
176
-
177
- const onClick = (event: Event) => {
178
- if (this.kjDisabled()) {
179
- event.preventDefault();
180
- event.stopImmediatePropagation();
181
- }
182
- };
183
-
184
- const onKeydown = (event: KeyboardEvent) => {
185
- if (this.kjDisabled() && event.key === 'Enter') {
186
- event.preventDefault();
187
- event.stopImmediatePropagation();
188
- }
189
- };
190
-
191
- node.addEventListener('click', onClick, { capture: true });
192
- node.addEventListener('keydown', onKeydown, { capture: true });
193
- });
194
-
195
- // External-link AT suffix injection. Runs reactively so the suffix
196
- // appears / disappears as `kjExternal` (or the host's `target`) changes.
197
- // The effect itself is created in injection context (constructor); its
198
- // first run happens after the first change-detection pass, by which
199
- // point the host element has been attached to the DOM in browser
200
- // contexts. Use injected DOCUMENT — prerender VMs may have no global `document`.
201
- effect(() => {
202
- const external = this.isExternal();
203
- const doc = this.document;
204
- if (!doc.createElement) return;
205
-
206
- const node = this.el.nativeElement;
207
- const consumerOwnsName = node.hasAttribute('aria-label');
208
-
209
- if (external && !consumerOwnsName) {
210
- if (!this.suffixSpan) {
211
- const span = doc.createElement('span');
212
- span.className = KJ_LINK_EXTERNAL_SUFFIX_CLASS;
213
- span.setAttribute('style', KJ_LINK_VISUALLY_HIDDEN_STYLE);
214
- // Leading space so AT reads "Documentation (opens in new tab)"
215
- // not "Documentation(opens in new tab)".
216
- span.textContent = ` ${KJ_LINK_EXTERNAL_SUFFIX_TEXT}`;
217
- node.appendChild(span);
218
- this.suffixSpan = span;
219
- }
220
- } else if (this.suffixSpan) {
221
- this.suffixSpan.remove();
222
- this.suffixSpan = null;
223
- }
224
- });
225
- }
226
- }
package/src/list/index.ts DELETED
@@ -1,11 +0,0 @@
1
- export {
2
- KjList,
3
- KjListRow,
4
- KJ_LIST,
5
- KJ_LIST_ROW,
6
- } from './list';
7
- export type {
8
- KjListAs,
9
- KjListContext,
10
- KjListRowContext,
11
- } from './list';