@kouji-ui/core 0.1.1 → 0.1.3

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 +15 -7
  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/form/form.ts DELETED
@@ -1,326 +0,0 @@
1
- import {
2
- Directive,
3
- ElementRef,
4
- Injector,
5
- afterNextRender,
6
- booleanAttribute,
7
- computed,
8
- inject,
9
- input,
10
- model,
11
- output,
12
- signal,
13
- } from '@angular/core';
14
- import { AbstractControl, FormArray, FormGroup, FormGroupDirective, NgForm } from '@angular/forms';
15
- import { Observable } from 'rxjs';
16
- import {
17
- InvalidControlInfo,
18
- KJ_FORM,
19
- KjFormContext,
20
- KjFormControlRegistration,
21
- } from './form.context';
22
-
23
- /**
24
- * Async submit handler signature accepted by `[kjAsyncSubmit]`. The directive
25
- * awaits the returned promise/observable and toggles `submitting` for its
26
- * lifetime.
27
- */
28
- export type KjAsyncSubmitHandler<T = unknown> = (
29
- value: T,
30
- ) => void | Promise<unknown> | Observable<unknown>;
31
-
32
- /**
33
- * Coordinator directive applied to a `<form>` element. Owns the submit
34
- * pipeline (intercept, validity check, focus-on-first-error, scroll-into-view,
35
- * async submitting state, mark-all-as-touched, optional error summary). Defers
36
- * to Angular Forms (`FormGroup` / `NgForm`) for validation; this directive is
37
- * a coordinator, not a state holder.
38
- *
39
- * - Emits `(kjSubmit)` only when the form is valid (replaces hand-rolled
40
- * `(ngSubmit)` + `if (form.invalid) return` patterns).
41
- * - Emits `(kjInvalidSubmit)` when the user submitted but validity failed,
42
- * useful for analytics.
43
- * - When `[kjAsyncSubmit]` is set, awaits its returned `Promise`/`Observable`
44
- * and reflects `aria-busy="true"` / `data-submitting=""` for the lifetime.
45
- *
46
- * @example
47
- * ```html
48
- * <form kjForm [formGroup]="form" (kjSubmit)="onSubmit($event)">
49
- * <input formControlName="email" kjInput />
50
- * <button type="submit">Sign in</button>
51
- * </form>
52
- * ```
53
- * @doc-category Core/Inputs
54
- * @doc
55
- * @doc-name form
56
- * @doc-description Coordinates form submit with validation, first-error focus, and async submitting state.
57
- * @doc-is-main
58
- */
59
- @Directive({
60
- selector: 'form[kjForm]',
61
- standalone: true,
62
- exportAs: 'kjForm',
63
- providers: [{ provide: KJ_FORM, useExisting: KjForm }],
64
- host: {
65
- '[attr.aria-busy]': 'submitting() ? "true" : null',
66
- '[attr.aria-describedby]': 'errorSummaryId() ?? null',
67
- '[attr.data-submitting]': 'submitting() ? "" : null',
68
- '[attr.data-invalid]': 'invalid() ? "" : null',
69
- '(submit)': 'onNativeSubmit($event)',
70
- },
71
- })
72
- export class KjForm implements KjFormContext {
73
- private readonly el = inject<ElementRef<HTMLFormElement>>(ElementRef);
74
- private readonly injector = inject(Injector);
75
- private readonly ngForm = inject(NgForm, { optional: true, self: true });
76
- private readonly formGroupDir = inject(FormGroupDirective, { optional: true, self: true });
77
-
78
- // ── Inputs ───────────────────────────────────────────────────────────
79
- /** When `false`, skips moving focus to the first invalid control on invalid submit. */
80
- readonly kjFocusOnError = input(true, { transform: booleanAttribute });
81
- /** When `false`, does not call `scrollIntoView` on the focused control. */
82
- readonly kjScrollOnError = input(true, { transform: booleanAttribute });
83
- /** Forwarded to `scrollIntoView({ behavior })`. Auto-downgrades to `'auto'` under `prefers-reduced-motion`. */
84
- readonly kjScrollBehavior = input<ScrollBehavior>('smooth');
85
- /** Forwarded to `scrollIntoView({ block })`. */
86
- readonly kjScrollBlock = input<ScrollLogicalPosition>('center');
87
- /** When `true` (default), calls `markAllAsTouched()` before validity check so all errors show together. */
88
- readonly kjMarkAllAsTouchedOnSubmit = input(true, { transform: booleanAttribute });
89
- /** When `true`, calls `form.reset()` after a successful async submit resolves. */
90
- readonly kjResetOnSuccess = input(false, { transform: booleanAttribute });
91
- /** Optional async submit handler. When set, the directive awaits its result and toggles `submitting`. */
92
- readonly kjAsyncSubmit = input<KjAsyncSubmitHandler | undefined>(undefined);
93
-
94
- // ── Outputs ──────────────────────────────────────────────────────────
95
- /** Emits the form value when the user submits and the form is valid. */
96
- readonly kjSubmit = output<unknown>();
97
- /** Emits the FormGroup when the user submits but validity fails. */
98
- readonly kjInvalidSubmit = output<FormGroup>();
99
-
100
- // ── Models / state ───────────────────────────────────────────────────
101
- /** Two-way bindable submitting flag. When unbound, the directive owns it internally. */
102
- readonly kjSubmitting = model(false);
103
-
104
- private readonly _submitted = signal(false);
105
- private readonly _invalid = signal(false);
106
- private readonly _invalidControls = signal<readonly InvalidControlInfo[]>([]);
107
- private readonly _errorSummaryId = signal<string | null>(null);
108
- private readonly registry = new Map<string, KjFormControlRegistration>();
109
- private prefersReducedMotion = false;
110
-
111
- // ── Public surface (KjFormContext) ───────────────────────────────────
112
- readonly form = computed<FormGroup | null>(() => {
113
- if (this.formGroupDir) return this.formGroupDir.form;
114
- if (this.ngForm) return this.ngForm.form;
115
- return null;
116
- });
117
- readonly submitting = computed(() => this.kjSubmitting());
118
- readonly submitted = this._submitted.asReadonly();
119
- readonly invalid = this._invalid.asReadonly();
120
- readonly invalidControls = this._invalidControls.asReadonly();
121
- readonly errorSummaryId = this._errorSummaryId.asReadonly();
122
-
123
- constructor() {
124
- afterNextRender(() => {
125
- try {
126
- this.prefersReducedMotion = matchMedia('(prefers-reduced-motion: reduce)').matches;
127
- } catch {
128
- this.prefersReducedMotion = false;
129
- }
130
- });
131
- }
132
-
133
- registerControl(reg: KjFormControlRegistration): () => void {
134
- this.registry.set(reg.path, reg);
135
- return () => {
136
- const cur = this.registry.get(reg.path);
137
- if (cur === reg) this.registry.delete(reg.path);
138
- };
139
- }
140
-
141
- /** Internal: called by `KjFormErrorSummary` to advertise its `id` to the form. */
142
- setErrorSummaryId(id: string | null): void {
143
- this._errorSummaryId.set(id);
144
- }
145
-
146
- /** Imperative submit — equivalent to dispatching a `submit` event on the host. */
147
- submit(): void {
148
- this.el.nativeElement.requestSubmit();
149
- }
150
-
151
- /** @internal — host listener target. */
152
- onNativeSubmit(event: Event): void {
153
- event.preventDefault();
154
- // Drop submit attempts while a previous submission is still in flight.
155
- if (this.submitting()) return;
156
-
157
- const form = this.form();
158
- this._submitted.set(true);
159
-
160
- if (!form) {
161
- // No Angular forms binding — log a dev-mode warning and bail out.
162
- if (typeof ngDevMode !== 'undefined' && ngDevMode) {
163
- console.warn(
164
- '[KjForm] <form kjForm> has no `[formGroup]` or `ngForm` binding. The directive is a coordinator over Angular Forms and needs one to function.',
165
- );
166
- }
167
- return;
168
- }
169
-
170
- if (this.kjMarkAllAsTouchedOnSubmit()) {
171
- form.markAllAsTouched();
172
- }
173
-
174
- if (form.invalid) {
175
- this._invalid.set(true);
176
- const invalidControls = collectInvalidControls(form);
177
- this._invalidControls.set(this.attachLabels(invalidControls));
178
- this.kjInvalidSubmit.emit(form);
179
- this.handleInvalidSubmit(invalidControls);
180
- return;
181
- }
182
-
183
- this._invalid.set(false);
184
- this._invalidControls.set([]);
185
-
186
- const handler = this.kjAsyncSubmit();
187
- if (handler) {
188
- this.runAsyncSubmit(handler, form);
189
- } else {
190
- this.kjSubmit.emit(form.value);
191
- }
192
- }
193
-
194
- // ── Internals ────────────────────────────────────────────────────────
195
-
196
- private attachLabels(invalid: ReadonlyArray<{ path: string; control: AbstractControl }>): InvalidControlInfo[] {
197
- return invalid.map((entry) => {
198
- const reg = this.registry.get(entry.path);
199
- return { ...entry, label: reg?.label ?? humanizePath(entry.path) };
200
- });
201
- }
202
-
203
- private handleInvalidSubmit(invalid: ReadonlyArray<{ path: string }>): void {
204
- if (!this.kjFocusOnError() || invalid.length === 0) return;
205
- const first = invalid[0];
206
- const reg = this.registry.get(first.path);
207
- const target = reg?.element ?? this.fallbackQuery(first.path);
208
- if (!target) return;
209
- try {
210
- target.focus({ preventScroll: !this.kjScrollOnError() });
211
- } catch {
212
- // Some hosts (SSR/jsdom) may not implement focus options — ignore.
213
- target.focus?.();
214
- }
215
- if (this.kjScrollOnError()) {
216
- const behavior = this.prefersReducedMotion ? 'auto' : this.kjScrollBehavior();
217
- target.scrollIntoView?.({ block: this.kjScrollBlock(), behavior });
218
- }
219
- }
220
-
221
- private fallbackQuery(path: string): HTMLElement | null {
222
- const root = this.el.nativeElement;
223
- const escaped = cssEscape(path);
224
- return (
225
- root.querySelector<HTMLElement>(`[formcontrolname="${escaped}"]`) ??
226
- root.querySelector<HTMLElement>(`[ng-reflect-name="${escaped}"]`) ??
227
- null
228
- );
229
- }
230
-
231
- private runAsyncSubmit(handler: KjAsyncSubmitHandler, form: FormGroup): void {
232
- let result: ReturnType<KjAsyncSubmitHandler>;
233
- this.kjSubmitting.set(true);
234
- try {
235
- result = handler(form.value);
236
- } catch (err) {
237
- this.kjSubmitting.set(false);
238
- throw err;
239
- }
240
- if (result instanceof Promise) {
241
- result.then(
242
- () => this.afterAsync(form, true),
243
- () => this.afterAsync(form, false),
244
- );
245
- // Also emit the synchronous (kjSubmit) for consumers that use both shapes.
246
- this.kjSubmit.emit(form.value);
247
- return;
248
- }
249
- if (isObservable(result)) {
250
- const sub = result.subscribe({
251
- complete: () => this.afterAsync(form, true),
252
- error: () => this.afterAsync(form, false),
253
- });
254
- // Defensive: if the observable completes synchronously, the subscribe
255
- // call already cleaned us up. Otherwise this no-op preserves cleanup
256
- // behaviour (we don't track for unsubscription beyond completion).
257
- void sub;
258
- this.kjSubmit.emit(form.value);
259
- return;
260
- }
261
- // Sync handler — release the flag immediately and emit.
262
- this.kjSubmitting.set(false);
263
- this.kjSubmit.emit(form.value);
264
- }
265
-
266
- private afterAsync(form: FormGroup, success: boolean): void {
267
- this.kjSubmitting.set(false);
268
- if (success && this.kjResetOnSuccess()) {
269
- form.reset();
270
- this._submitted.set(false);
271
- this._invalid.set(false);
272
- this._invalidControls.set([]);
273
- }
274
- }
275
- }
276
-
277
- // ─── Helpers ──────────────────────────────────────────────────────────
278
-
279
- /** Walks a `FormGroup` / `FormArray` tree depth-first, returning invalid leaves. */
280
- function collectInvalidControls(
281
- root: AbstractControl,
282
- ): ReadonlyArray<{ path: string; control: AbstractControl }> {
283
- const out: { path: string; control: AbstractControl }[] = [];
284
- const walk = (ctrl: AbstractControl, path: string): void => {
285
- if (ctrl instanceof FormGroup) {
286
- for (const [name, child] of Object.entries(ctrl.controls)) {
287
- walk(child, path ? `${path}.${name}` : name);
288
- }
289
- return;
290
- }
291
- if (ctrl instanceof FormArray) {
292
- ctrl.controls.forEach((child, i) => walk(child, `${path}.${i}`));
293
- return;
294
- }
295
- if (ctrl.invalid) {
296
- out.push({ path, control: ctrl });
297
- }
298
- };
299
- walk(root, '');
300
- return out;
301
- }
302
-
303
- /** Converts `'address.street'` → `'Address street'` for fallback labels. */
304
- function humanizePath(path: string): string {
305
- if (!path) return '';
306
- const last = path.split('.').pop() ?? path;
307
- const words = last.replace(/([A-Z])/g, ' $1').replace(/[_-]+/g, ' ').trim();
308
- return words.charAt(0).toUpperCase() + words.slice(1);
309
- }
310
-
311
- /** Type guard for RxJS observable. Avoids a hard dep on `isObservable` in tests. */
312
- function isObservable(value: unknown): value is Observable<unknown> {
313
- return (
314
- !!value &&
315
- typeof value === 'object' &&
316
- typeof (value as { subscribe?: unknown }).subscribe === 'function'
317
- );
318
- }
319
-
320
- /** Minimal CSS.escape polyfill for `formcontrolname` attribute selectors. */
321
- function cssEscape(value: string): string {
322
- if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') {
323
- return CSS.escape(value);
324
- }
325
- return value.replace(/[^a-zA-Z0-9_-]/g, (ch) => `\\${ch}`);
326
- }
package/src/form/index.ts DELETED
@@ -1,11 +0,0 @@
1
- export { KjFormField, KjFormLabel, KjFormError } from './form-field';
2
- export { KJ_FORM_FIELD, type KjFormFieldContext } from './form-field.context';
3
-
4
- export { KjForm, type KjAsyncSubmitHandler } from './form';
5
- export { KjFormErrorSummary } from './form-error-summary';
6
- export {
7
- KJ_FORM,
8
- type KjFormContext,
9
- type KjFormControlRegistration,
10
- type InvalidControlInfo,
11
- } from './form.context';
package/src/icon/E2E.md DELETED
@@ -1,14 +0,0 @@
1
- # Icon — E2E coverage notes
2
-
3
- The core icon layer has no consumer-visible UI in this session (no Lucide
4
- adapter, no example refactor). The directive-level integration tests in
5
- `icon.directive.spec.ts` cover the end-to-end path through DI:
6
-
7
- - Eager registration via `provideIcons` → directive renders the registered value.
8
- - Async loader path → directive renders nothing while pending, then re-renders on success.
9
- - Decorative vs meaningful a11y modes → axe-clean.
10
- - Mode switching (svg vs font) → correct CSS variable wrapping and `data-kj-icon-mode`.
11
- - Selector restriction → directive only attaches to `span` and `i` hosts; ignores other tags.
12
-
13
- Browser-level E2E lands with the Lucide adapter follow-up, when there's a
14
- visible component to drive.
@@ -1,198 +0,0 @@
1
- import { render } from '@testing-library/angular';
2
- import { axe, toHaveNoViolations } from 'jest-axe';
3
- import { describe, expect, it } from 'vitest';
4
- import { KjIconDirective } from './icon.directive';
5
- import { provideIcons, provideIconLoader } from './icon.providers';
6
-
7
- expect.extend(toHaveNoViolations);
8
-
9
- describe('KjIconDirective — selector', () => {
10
- it('attaches to <i> hosts', async () => {
11
- const { container } = await render(`<i [kjIcon]="'settings'"></i>`, {
12
- imports: [KjIconDirective],
13
- providers: [provideIcons({ settings: 'url("a")' })],
14
- });
15
- const host = container.querySelector('i')!;
16
- expect(host.classList.contains('kj-icon')).toBe(true);
17
- expect(host.getAttribute('data-kj-icon-mode')).toBe('svg');
18
- });
19
-
20
- it('does NOT attach to disallowed hosts (e.g. <div>)', async () => {
21
- // Static `kjIcon` attribute (no binding) — Angular only matches the
22
- // directive against the host element's tag, not the attribute binding.
23
- const { container } = await render(`<div kjIcon="settings"></div>`, {
24
- imports: [KjIconDirective],
25
- providers: [provideIcons({ settings: 'url("a")' })],
26
- });
27
- const host = container.querySelector('div')!;
28
- expect(host.classList.contains('kj-icon')).toBe(false);
29
- expect(host.hasAttribute('data-kj-icon-mode')).toBe(false);
30
- });
31
- });
32
-
33
- describe('KjIconDirective — svg mode (decorative default)', () => {
34
- it('writes --kj-icon and data-kj-icon-mode="svg"', async () => {
35
- const { container } = await render(`<span [kjIcon]="'settings'"></span>`, {
36
- imports: [KjIconDirective],
37
- providers: [provideIcons({ settings: 'url("a")' })],
38
- });
39
- const host = container.querySelector('span')!;
40
- expect(host.getAttribute('data-kj-icon-mode')).toBe('svg');
41
- expect(host.style.getPropertyValue('--kj-icon')).toBe('url("a")');
42
- });
43
-
44
- it('applies the .kj-icon class', async () => {
45
- const { container } = await render(`<span [kjIcon]="'settings'"></span>`, {
46
- imports: [KjIconDirective],
47
- providers: [provideIcons({ settings: 'url("a")' })],
48
- });
49
- expect(container.querySelector('span')!.classList.contains('kj-icon')).toBe(true);
50
- });
51
-
52
- it('default = decorative: aria-hidden="true", no role, no aria-label', async () => {
53
- const { container } = await render(`<span [kjIcon]="'settings'"></span>`, {
54
- imports: [KjIconDirective],
55
- providers: [provideIcons({ settings: 'url("a")' })],
56
- });
57
- const host = container.querySelector('span')!;
58
- expect(host.getAttribute('aria-hidden')).toBe('true');
59
- expect(host.hasAttribute('role')).toBe(false);
60
- expect(host.hasAttribute('aria-label')).toBe(false);
61
- });
62
- });
63
-
64
- describe('KjIconDirective — meaningful mode (kjIconLabel)', () => {
65
- it('removes aria-hidden, sets role="img" and aria-label', async () => {
66
- const { container } = await render(
67
- `<span [kjIcon]="'alert'" [kjIconLabel]="'Warning'"></span>`,
68
- {
69
- imports: [KjIconDirective],
70
- providers: [provideIcons({ alert: 'url("a")' })],
71
- },
72
- );
73
- const host = container.querySelector('span')!;
74
- expect(host.hasAttribute('aria-hidden')).toBe(false);
75
- expect(host.getAttribute('role')).toBe('img');
76
- expect(host.getAttribute('aria-label')).toBe('Warning');
77
- });
78
- });
79
-
80
- describe('KjIconDirective — color tokens', () => {
81
- it('inherits color by default (no inline color style)', async () => {
82
- const { container } = await render(`<span [kjIcon]="'x'"></span>`, {
83
- imports: [KjIconDirective],
84
- providers: [provideIcons({ x: 'url("a")' })],
85
- });
86
- expect(container.querySelector('span')!.getAttribute('style') ?? '').not.toContain('color:');
87
- });
88
-
89
- it('writes color: var(--kj-color-icon-{token}) for non-inherit', async () => {
90
- const { container } = await render(
91
- `<span [kjIcon]="'x'" [kjIconColor]="'danger'"></span>`,
92
- {
93
- imports: [KjIconDirective],
94
- providers: [provideIcons({ x: 'url("a")' })],
95
- },
96
- );
97
- const styleAttr = container.querySelector('span')!.getAttribute('style') ?? '';
98
- expect(styleAttr).toContain('color: var(--kj-color-icon-danger)');
99
- });
100
-
101
- it('"inherit" color writes no inline color', async () => {
102
- const { container } = await render(
103
- `<span [kjIcon]="'x'" [kjIconColor]="'inherit'"></span>`,
104
- {
105
- imports: [KjIconDirective],
106
- providers: [provideIcons({ x: 'url("a")' })],
107
- },
108
- );
109
- expect(container.querySelector('span')!.getAttribute('style') ?? '').not.toContain('color:');
110
- });
111
- });
112
-
113
- describe('KjIconDirective — size tokens', () => {
114
- it('writes font-size: var(--kj-icon-size-{token})', async () => {
115
- const { container } = await render(
116
- `<span [kjIcon]="'x'" [kjIconSize]="'lg'"></span>`,
117
- {
118
- imports: [KjIconDirective],
119
- providers: [provideIcons({ x: 'url("a")' })],
120
- },
121
- );
122
- const styleAttr = container.querySelector('span')!.getAttribute('style') ?? '';
123
- expect(styleAttr).toContain('font-size: var(--kj-icon-size-lg)');
124
- });
125
- });
126
-
127
- describe('KjIconDirective — font mode', () => {
128
- it('reflects data-kj-icon-mode="font" for @font.* names', async () => {
129
- const { container } = await render(
130
- `<span [kjIcon]="'@font.fa-cog'"></span>`,
131
- {
132
- imports: [KjIconDirective],
133
- providers: [provideIcons({ '@font.fa-cog': '"\\f013"' })],
134
- },
135
- );
136
- const host = container.querySelector('span')!;
137
- expect(host.getAttribute('data-kj-icon-mode')).toBe('font');
138
- expect(host.style.getPropertyValue('--kj-icon')).toBe('"\\f013"');
139
- });
140
- });
141
-
142
- describe('KjIconDirective — loader pending', () => {
143
- it('renders no --kj-icon value while async load is pending', async () => {
144
- const neverResolves = () =>
145
- new Promise<string>(() => {/* hangs forever */});
146
- const { container } = await render(`<span [kjIcon]="'missing'"></span>`, {
147
- imports: [KjIconDirective],
148
- providers: [provideIconLoader(neverResolves)],
149
- });
150
- const host = container.querySelector('span')!;
151
- expect(host.style.getPropertyValue('--kj-icon')).toBe('');
152
- });
153
-
154
- it('updates --kj-icon once loader resolves', async () => {
155
- let resolveLoad!: (v: string) => void;
156
- const loader = (_n: string) =>
157
- new Promise<string>((res) => {
158
- resolveLoad = res;
159
- });
160
- const { container, fixture } = await render(
161
- `<span [kjIcon]="'settings'"></span>`,
162
- {
163
- imports: [KjIconDirective],
164
- providers: [provideIconLoader(loader)],
165
- },
166
- );
167
- const host = container.querySelector('span')!;
168
- expect(host.style.getPropertyValue('--kj-icon')).toBe('');
169
-
170
- resolveLoad('url("loaded")');
171
- await Promise.resolve();
172
- await Promise.resolve();
173
- fixture.detectChanges();
174
-
175
- expect(host.style.getPropertyValue('--kj-icon')).toBe('url("loaded")');
176
- });
177
- });
178
-
179
- describe('KjIconDirective — a11y audits', () => {
180
- it('decorative icon passes axe', async () => {
181
- const { container } = await render(`<span [kjIcon]="'settings'"></span>`, {
182
- imports: [KjIconDirective],
183
- providers: [provideIcons({ settings: 'url("a")' })],
184
- });
185
- expect(await axe(container)).toHaveNoViolations();
186
- });
187
-
188
- it('meaningful icon passes axe', async () => {
189
- const { container } = await render(
190
- `<span [kjIcon]="'alert'" [kjIconLabel]="'Warning'"></span>`,
191
- {
192
- imports: [KjIconDirective],
193
- providers: [provideIcons({ alert: 'url("a")' })],
194
- },
195
- );
196
- expect(await axe(container)).toHaveNoViolations();
197
- });
198
- });
@@ -1,113 +0,0 @@
1
- import { Directive, computed, input } from '@angular/core';
2
- import { getIconMode } from './icon.mode';
3
- import { injectKjIconResolver } from './icon.resolver';
4
- import type { KjIconColor, KjIconSize } from './icon.types';
5
-
6
- /**
7
- * Renders an icon on its host element via CSS custom properties. Owns icon
8
- * accessibility (decorative by default; meaningful when `kjIconLabel` is set).
9
- *
10
- * @example
11
- * ```html
12
- * <span [kjIcon]="'settings'"></span>
13
- * <span [kjIcon]="'alert-triangle'" [kjIconLabel]="'Warning'"></span>
14
- * <span [kjIcon]="'check'" [kjIconColor]="'success'" [kjIconSize]="'lg'"></span>
15
- * ```
16
- *
17
- * @doc-example Gallery
18
- * Browseable Lucide icon grid with a substring filter. Click any tile to
19
- * copy its `<i kjIcon="…">` snippet.
20
- * @doc-file ../../../components/src/icon/icon.gallery.example.ts
21
- * @doc-example Usage
22
- * Common icon shapes — decorative inline, meaningful with a label, sized
23
- * variants, and semantic color tokens.
24
- * @doc-file ../../../components/src/icon/icon.usage.example.ts
25
- *
26
- * @doc-keyboard
27
- * None — the icon directive is non-interactive. Place inside a focusable parent (button/link) for activation semantics.
28
- *
29
- * @doc-aria
30
- * aria-hidden — Set to "true" by default (decorative). Removed when [kjIconLabel] is provided
31
- * role="img" — Set when [kjIconLabel] is provided (meaningful icon)
32
- * aria-label — Bound to [kjIconLabel] when provided
33
- * data-kj-icon-mode — Mirrors the resolved mode ("svg" | "font") for theme CSS
34
- *
35
- * @doc-css-var
36
- * --kj-icon — CSS-ready resolved icon value (a url() for svg mode or a quoted glyph for font mode). Set by the directive.
37
- * --kj-icon-font — Font family used in font mode. Consumers set this on a parent when shipping icon fonts.
38
- * --kj-color-icon-* — Foreground color tokens for [kjIconColor] (muted/primary/success/warning/danger/info).
39
- * --kj-icon-size-* — Em-relative size tokens for [kjIconSize] (xs/sm/md/lg/xl).
40
- *
41
- * @doc-touch
42
- * The icon is layout-only and does not require a 44×44 target on its own.
43
- * When the icon is the sole label of an interactive control, the parent
44
- * (`kj-button kjSize="icon"`, `<a>`, etc.) must meet WCAG 2.5.5.
45
- *
46
- * @doc-a11y
47
- * Decorative by default — `aria-hidden="true"` keeps the icon silent for
48
- * AT. Pass `[kjIconLabel]` only when the icon conveys meaning that is not
49
- * duplicated in adjacent text; this swaps in `role="img"` and the label.
50
- * Color tokens map to `--kj-color-icon-{token}` so theme palettes can
51
- * retarget per-mode without API churn.
52
- *
53
- * @doc-related button,link,badge
54
- *
55
- * @doc-category Core/Icon
56
- * @doc
57
- * @doc-name icon
58
- * @doc-description Renders an accessible icon on its host element by name with color and size tokens.
59
- * @doc-is-main
60
- */
61
- @Directive({
62
- selector: 'span[kjIcon], i[kjIcon]',
63
- standalone: true,
64
- host: {
65
- class: 'kj-icon',
66
- '[style.--kj-icon]': 'iconValue()',
67
- '[style.color]': 'colorVar()',
68
- '[style.font-size]': 'sizeVar()',
69
- '[attr.data-kj-icon-mode]': 'mode()',
70
- '[attr.aria-hidden]': 'ariaHidden()',
71
- '[attr.role]': 'roleAttr()',
72
- '[attr.aria-label]': 'ariaLabelAttr()',
73
- },
74
- })
75
- export class KjIconDirective {
76
- private readonly resolve = injectKjIconResolver();
77
-
78
- /** Icon name. Names starting with `@font.` use font mode. */
79
- readonly kjIcon = input.required<string>();
80
-
81
- /**
82
- * Accessible name. When set, the icon is treated as meaningful:
83
- * `role="img"`, `aria-label` set, `aria-hidden` removed. When unset
84
- * (the default), the icon is decorative and `aria-hidden="true"`.
85
- */
86
- readonly kjIconLabel = input<string | null>(null);
87
-
88
- /** Semantic color token. Default `null` means inherit (CSS `currentColor`). */
89
- readonly kjIconColor = input<KjIconColor | null>(null);
90
-
91
- /** Size token. Default `null` means inherit from surrounding text. */
92
- readonly kjIconSize = input<KjIconSize | null>(null);
93
-
94
- protected readonly mode = computed(() => getIconMode(this.kjIcon()));
95
- protected readonly iconValue = computed(() => this.resolve(this.kjIcon()));
96
-
97
- protected readonly ariaHidden = computed(() =>
98
- this.kjIconLabel() ? null : 'true',
99
- );
100
- protected readonly roleAttr = computed(() =>
101
- this.kjIconLabel() ? 'img' : null,
102
- );
103
- protected readonly ariaLabelAttr = computed(() => this.kjIconLabel());
104
-
105
- protected readonly colorVar = computed(() => {
106
- const c = this.kjIconColor();
107
- return c && c !== 'inherit' ? `var(--kj-color-icon-${c})` : null;
108
- });
109
- protected readonly sizeVar = computed(() => {
110
- const s = this.kjIconSize();
111
- return s ? `var(--kj-icon-size-${s})` : null;
112
- });
113
- }