@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
@@ -1,339 +0,0 @@
1
- // packages/core/src/primitives/list/selection.ts
2
- import { Injectable, computed, effect, signal, type Signal, type WritableSignal } from '@angular/core';
3
- import type { KjListItem } from './item';
4
- import type {
5
- KjCompareFn,
6
- KjListSelectionMode,
7
- KjTreeShape,
8
- } from './tokens';
9
-
10
- /**
11
- * Selection state shared by a list-style consumer (KjSelect, KjCombobox,
12
- * KjTreeSelect, KjCascadeSelect). The consumer root calls {@link bind}
13
- * from its constructor to wire in its canonical signals — the model
14
- * reads/writes through those signals, so there is no second source of
15
- * truth and no cyclic DI dependency (the model does not inject the
16
- * root; the root injects the model).
17
- *
18
- * **Tree topology is first-class.** When the consumer supplies a
19
- * `treeShape` signal, the model uses it. Otherwise the model
20
- * **auto-derives** a shape from the registered `KjListItem` parent
21
- * pointers (each item injects its nearest ancestor `KjListItem` via the
22
- * element injector). That makes DOM-nested clusters (cascade-select,
23
- * sub-menus) tree-aware out of the box; flat data-driven clusters
24
- * (tree-select) keep using the explicit shape.
25
- *
26
- * Modes:
27
- * - `'single'` — replace + close. With a shape, branch toggles no-op
28
- * (only leaves enter `value`).
29
- * - `'multi'` — flat toggle in array
30
- * - `'leaf'` — tree-aware multi where only leaves enter `value`
31
- * - `'cascade'` — tri-state tree selection
32
- *
33
- * @doc-category Core/Primitives
34
- */
35
- @Injectable()
36
- export class KjSelectionModel<T = unknown> {
37
- /**
38
- * Source signals. Replaced wholesale by {@link bind} so the
39
- * consumer's reactive inputs become the canonical state. `bind` MUST
40
- * be called from the consumer's constructor, before any descendant
41
- * `KjListItem._activate` fires.
42
- */
43
- private _value: WritableSignal<T | readonly T[] | null> =
44
- signal<T | readonly T[] | null>(null);
45
- private _items: Signal<readonly KjListItem<unknown>[] | null> = signal(null);
46
- private _modeSig: Signal<KjListSelectionMode> = signal<KjListSelectionMode>('single');
47
- private _cmpSig: Signal<KjCompareFn<T>> = signal(Object.is as KjCompareFn<T>);
48
- private _shapeSig: Signal<KjTreeShape<T> | null> = signal(null);
49
-
50
- private readonly _mode = signal<KjListSelectionMode>('single');
51
- private _compareBy: KjCompareFn<T> = Object.is as KjCompareFn<T>;
52
- private readonly _consumerShape = signal<KjTreeShape<T> | null>(null);
53
-
54
- constructor() {
55
- // Effects always re-evaluate the bound signals so the model stays
56
- // in sync whether the consumer rebinds during construction or
57
- // mutates the underlying signals later. Reading inside an effect
58
- // (rather than at construction time) means the model is robust to
59
- // property-initializer ordering on consumer roots.
60
- effect(() => this._mode.set(this._modeSig()));
61
- effect(() => { this._compareBy = this._cmpSig(); });
62
- effect(() => this._consumerShape.set(this._shapeSig()));
63
- }
64
-
65
- /**
66
- * Bind consumer-owned source signals. Each is optional; unbound keys
67
- * keep their previous source (defaulting to constants on first
68
- * construct). Call once in the consumer's constructor before any
69
- * descendant `KjListItem` activation fires.
70
- */
71
- bind(sources: {
72
- readonly value?: WritableSignal<T | readonly T[] | null>;
73
- readonly items?: Signal<readonly KjListItem<unknown>[]>;
74
- readonly mode?: Signal<KjListSelectionMode>;
75
- readonly compareBy?: Signal<KjCompareFn<T>>;
76
- readonly treeShape?: Signal<KjTreeShape<T> | null>;
77
- }): void {
78
- if (sources.value) this._value = sources.value;
79
- if (sources.items) this._items = sources.items as Signal<readonly KjListItem<unknown>[] | null>;
80
- if (sources.mode) this._modeSig = sources.mode;
81
- if (sources.compareBy) this._cmpSig = sources.compareBy;
82
- if (sources.treeShape) this._shapeSig = sources.treeShape;
83
- }
84
-
85
- /** Current mode. */
86
- readonly mode = this._mode.asReadonly();
87
-
88
- /**
89
- * Effective tree topology — consumer-supplied (`bind({ treeShape })`)
90
- * when present, otherwise auto-derived from registered `KjListItem`
91
- * parent pointers. Returns `null` when neither is available.
92
- */
93
- readonly shape: Signal<KjTreeShape<T> | null> = computed(() => {
94
- const explicit = this._consumerShape();
95
- if (explicit) return explicit;
96
- return this._autoShape();
97
- });
98
-
99
- /**
100
- * Auto-derived tree shape: a map of every registered item's value to
101
- * its parent value (and inverse children list), built from each
102
- * `KjListItem`'s injected `parent` reference. Only useful for
103
- * DOM-nested clusters (cascade-select, sub-menus); flat clusters
104
- * (tree-select) bind their own shape.
105
- */
106
- private readonly _autoShape: Signal<KjTreeShape<T> | null> = computed(() => {
107
- const items = this._items();
108
- if (!items || items.length === 0) return null;
109
- const parentOf = new Map<T, T | null>();
110
- const childrenOf = new Map<T, T[]>();
111
- const valueByItem = new Map<KjListItem<unknown>, T>();
112
- for (const it of items) {
113
- const v = it.value();
114
- if (v === undefined) continue;
115
- valueByItem.set(it, v as T);
116
- }
117
- for (const it of items) {
118
- const v = valueByItem.get(it);
119
- if (v === undefined) continue;
120
- const parentItem = it.parent;
121
- const parentV = parentItem ? valueByItem.get(parentItem) ?? null : null;
122
- parentOf.set(v, parentV);
123
- if (parentV !== null) {
124
- const arr = childrenOf.get(parentV) ?? [];
125
- arr.push(v);
126
- childrenOf.set(parentV, arr);
127
- }
128
- }
129
- const eq = this._compareBy;
130
- const findKey = (n: T): T | undefined => {
131
- for (const k of parentOf.keys()) {
132
- if (eq(k, n)) return k;
133
- }
134
- return undefined;
135
- };
136
- return {
137
- getParent: (n: T) => {
138
- const key = findKey(n);
139
- return key !== undefined ? (parentOf.get(key) ?? null) : null;
140
- },
141
- getChildren: (n: T) => {
142
- const key = findKey(n);
143
- return key !== undefined ? (childrenOf.get(key) ?? []) : [];
144
- },
145
- isLeaf: (n: T) => {
146
- const key = findKey(n);
147
- if (key === undefined) return true;
148
- return (childrenOf.get(key)?.length ?? 0) === 0;
149
- },
150
- };
151
- });
152
-
153
- /** Switch mode imperatively (consumers should prefer binding a signal). */
154
- setMode(mode: KjListSelectionMode): void {
155
- this._mode.set(mode);
156
- }
157
-
158
- /** Replace the current selection value (writes through the bound signal). */
159
- setValue(v: T | readonly T[] | null): void {
160
- this._value.set(v);
161
- }
162
-
163
- /** Override the equality function. Defaults to `Object.is`. */
164
- setCompareBy(fn: KjCompareFn<T>): void {
165
- this._compareBy = fn;
166
- }
167
-
168
- /**
169
- * Provide the tree topology imperatively. Pass `null` to clear and
170
- * fall back to the auto-derived shape.
171
- */
172
- setTreeShape(shape: KjTreeShape<T> | null): void {
173
- this._consumerShape.set(shape);
174
- }
175
-
176
- /**
177
- * Whether `target` is a leaf in the effective shape. Returns `true`
178
- * when no shape is available (flat lists — everything is a "leaf").
179
- */
180
- isLeaf(target: T): boolean {
181
- const s = this.shape();
182
- return s ? s.isLeaf(target) : true;
183
- }
184
-
185
- /**
186
- * Root → target value chain via the effective shape. Returns
187
- * `[target]` when the target has no parent in the shape, and an
188
- * empty array when no shape is available.
189
- */
190
- pathTo(target: T): readonly T[] {
191
- const s = this.shape();
192
- if (!s) return [];
193
- const reverse: T[] = [target];
194
- let cur: T | null = s.getParent(target);
195
- while (cur !== null) {
196
- reverse.unshift(cur);
197
- cur = s.getParent(cur);
198
- }
199
- return reverse;
200
- }
201
-
202
- /**
203
- * Activation gate. Returns `true` when committing `target` is
204
- * meaningful in the current mode + shape:
205
- * - `'single'` with a shape → only leaves activate. Branches are
206
- * blocked so they can serve as pure disclosure controls (open a
207
- * sub-panel) without leaking a branch value into `value`.
208
- * - `'single'` without a shape → any value activates.
209
- * - `'multi'` → any value activates.
210
- * - `'leaf'` → only leaves activate (mirrors `toggle`'s no-op).
211
- * - `'cascade'` → any value activates (tri-state toggle applies).
212
- */
213
- canActivate(target: T): boolean {
214
- const mode = this._mode();
215
- if (mode === 'multi' || mode === 'cascade') return true;
216
- const s = this.shape();
217
- if (!s) return true;
218
- return s.isLeaf(target);
219
- }
220
-
221
- /** Whether `target` is currently in the selection (membership check). */
222
- isSelected(target: T): boolean {
223
- const v = this._value();
224
- if (v === null) return false;
225
- const mode = this._mode();
226
- if (mode === 'multi' || mode === 'leaf' || mode === 'cascade') {
227
- return Array.isArray(v) && v.some(x => this._compareBy(x, target));
228
- }
229
- return this._compareBy(v as T, target);
230
- }
231
-
232
- /**
233
- * Tri-state for `'cascade'` mode. Walks descendants via the effective
234
- * tree shape:
235
- * - `'true'` — node and all leaf descendants are selected
236
- * - `'mixed'` — some but not all descendants are selected
237
- * - `'false'` — no descendants are selected
238
- *
239
- * In any other mode (or when no tree shape is set), returns `'true'`
240
- * / `'false'` based on `isSelected()`.
241
- */
242
- cascadeState(target: T): 'true' | 'false' | 'mixed' {
243
- const shape = this.shape();
244
- if (this._mode() !== 'cascade' || !shape) {
245
- return this.isSelected(target) ? 'true' : 'false';
246
- }
247
- return this._cascadeState(target, shape);
248
- }
249
-
250
- private _cascadeState(node: T, shape: KjTreeShape<T>): 'true' | 'false' | 'mixed' {
251
- if (shape.isLeaf(node)) {
252
- return this.isSelected(node) ? 'true' : 'false';
253
- }
254
- const children = shape.getChildren(node);
255
- if (children.length === 0) {
256
- return this.isSelected(node) ? 'true' : 'false';
257
- }
258
- let allTrue = true;
259
- let anyTrueOrMixed = false;
260
- for (const c of children) {
261
- const s = this._cascadeState(c, shape);
262
- if (s !== 'true') allTrue = false;
263
- if (s !== 'false') anyTrueOrMixed = true;
264
- }
265
- if (allTrue) return 'true';
266
- if (anyTrueOrMixed) return 'mixed';
267
- return 'false';
268
- }
269
-
270
- /**
271
- * Toggle `target` per the current mode:
272
- * - `'single'` — with a shape, branch targets no-op
273
- * (`closeRequested: false`); leaves replace value and return
274
- * `closeRequested: true`. Without a shape, replaces unconditionally.
275
- * - `'multi'` — flat toggle in array; `closeRequested: false`
276
- * - `'leaf'` — toggle only when `target` is a leaf; branches are no-ops
277
- * - `'cascade'` — toggle target + all leaf descendants based on current
278
- * tri-state (`'true'` deselects, `'false'`/`'mixed'` selects)
279
- */
280
- toggle(target: T): { closeRequested: boolean } {
281
- const mode = this._mode();
282
- const shape = this.shape();
283
- if (mode === 'cascade' && shape) {
284
- return this._cascadeToggle(target, shape);
285
- }
286
- if (mode === 'leaf' && shape) {
287
- if (!shape.isLeaf(target)) return { closeRequested: false };
288
- return this._multiToggle(target);
289
- }
290
- if (mode === 'multi' || mode === 'leaf' || mode === 'cascade') {
291
- return this._multiToggle(target);
292
- }
293
- // Single mode — gate branches when a shape is available.
294
- if (shape && !shape.isLeaf(target)) return { closeRequested: false };
295
- this._value.set(target);
296
- return { closeRequested: true };
297
- }
298
-
299
- private _multiToggle(target: T): { closeRequested: boolean } {
300
- const current = this._value();
301
- const arr = Array.isArray(current) ? [...current] : [];
302
- const idx = arr.findIndex(x => this._compareBy(x, target));
303
- if (idx >= 0) arr.splice(idx, 1);
304
- else arr.push(target);
305
- this._value.set(arr);
306
- return { closeRequested: false };
307
- }
308
-
309
- private _cascadeToggle(target: T, shape: KjTreeShape<T>): { closeRequested: boolean } {
310
- const currentState = this._cascadeState(target, shape);
311
- const shouldSelect = currentState !== 'true';
312
-
313
- const collectLeaves = (node: T): T[] => {
314
- if (shape.isLeaf(node)) return [node];
315
- const out: T[] = [];
316
- for (const c of shape.getChildren(node)) out.push(...collectLeaves(c));
317
- return out;
318
- };
319
-
320
- const leaves = collectLeaves(target);
321
- const current = this._value();
322
- const arr = Array.isArray(current) ? [...current] : [];
323
-
324
- for (const leaf of leaves) {
325
- const idx = arr.findIndex(x => this._compareBy(x, leaf));
326
- if (shouldSelect && idx < 0) arr.push(leaf);
327
- else if (!shouldSelect && idx >= 0) arr.splice(idx, 1);
328
- }
329
-
330
- this._value.set(arr);
331
- return { closeRequested: false };
332
- }
333
-
334
- /** Clear the selection. `single` → `null`; multi-style → `[]`. */
335
- clear(): void {
336
- const mode = this._mode();
337
- this._value.set(mode === 'single' ? null : []);
338
- }
339
- }
@@ -1,106 +0,0 @@
1
- import { InjectionToken, Signal, WritableSignal } from '@angular/core';
2
- import type { KjListItem } from './item';
3
-
4
- /**
5
- * The single contract a consumer root directive (KjSelect, KjCombobox,
6
- * KjCommandPalette, …) implements + provides via
7
- * `useExisting: forwardRef(() => Self)`. Primitives read whichever
8
- * fields they need from this one object — items for the navigator,
9
- * `value` for the selection model, `visibleItems` for filter-aware nav.
10
- */
11
- export interface KjListNavigatorConfig {
12
- /** All registered items in DOM order. Source of truth for nav + filter. */
13
- readonly items: Signal<readonly KjListItem<unknown>[]>;
14
- /** Filter-aware visible subset. Falls back to `items` when not provided. */
15
- readonly visibleItems?: Signal<readonly KjListItem<unknown>[]>;
16
- /**
17
- * Writable signal holding the canonical selection value (typically the
18
- * consumer's `model()` input). When the consumer provides
19
- * `KjSelectionModel`, it reads / writes through this signal — one
20
- * source of truth, no bridging effects. Optional: consumers without
21
- * selection state (e.g. KjCommandPalette) omit it.
22
- */
23
- readonly value?: WritableSignal<unknown | readonly unknown[] | null>;
24
- /**
25
- * Selection mode signal. When provided, `KjSelectionModel` follows it
26
- * reactively — consumers don't need to inject the model just to call
27
- * `setMode()`. Default `'single'`.
28
- */
29
- readonly mode?: Signal<KjListSelectionMode>;
30
- /**
31
- * Equality fn signal. When provided, `KjSelectionModel` follows it
32
- * reactively. Default `Object.is`.
33
- */
34
- readonly compareBy?: Signal<KjCompareFn<unknown>>;
35
- /**
36
- * Tree topology signal. When provided, `KjSelectionModel` follows it
37
- * reactively, so the consumer never needs to inject the model just
38
- * to call `setTreeShape()`. Required for `'leaf'` / `'cascade'`
39
- * selection modes; optional otherwise.
40
- */
41
- readonly treeShape?: Signal<KjTreeShape<unknown> | null>;
42
- /**
43
- * Consumer-side hook invoked by `KjListItem` immediately after it
44
- * toggles the shared `KjSelectionModel`. Lets the consumer do its
45
- * post-selection work (close an overlay, set an input query, emit a
46
- * commit event) without subscribing to every option's `activate`
47
- * output — pushing the repeat pattern down into one place.
48
- *
49
- * `closeRequested` mirrors `KjSelectionModel.toggle()`'s return value:
50
- * `true` in single mode, `false` in multi / leaf / cascade modes.
51
- */
52
- afterSelect?(value: unknown, closeRequested: boolean): void;
53
- }
54
-
55
- export const KJ_LIST_NAVIGATOR_CONFIG =
56
- new InjectionToken<KjListNavigatorConfig>('KJ_LIST_NAVIGATOR_CONFIG');
57
-
58
- /**
59
- * Focus model for a list-style cluster:
60
- *
61
- * - `'activedescendant'` — host element keeps DOM focus; the active
62
- * option is signalled via `aria-activedescendant`. Default for
63
- * listbox / combobox / command-palette.
64
- * - `'roving'` — the active option *is* the focused element; focus
65
- * moves between options via roving `tabindex`. Used by menus,
66
- * menubars, tree-select.
67
- */
68
- export type KjListFocusMode = 'activedescendant' | 'roving';
69
-
70
- /**
71
- * Provided by `KjListNavigator` so child `KjListItem`s can read the
72
- * current focus mode reactively and bind their own `tabindex`. Items
73
- * inject this `{ optional: true }` — when absent (no navigator on the
74
- * host) they fall back to `'activedescendant'` behavior.
75
- */
76
- export const KJ_LIST_FOCUS_MODE =
77
- new InjectionToken<Signal<KjListFocusMode>>('KJ_LIST_FOCUS_MODE');
78
-
79
- export type KjListOrientation = 'vertical' | 'horizontal' | 'both';
80
-
81
- /**
82
- * Selection modes supported by `KjSelectionModel`:
83
- *
84
- * - `'single'` — exactly one value (or `null`). Aria: `aria-selected="true"` on the chosen item.
85
- * - `'multi'` — any combination from a flat list. Aria: `aria-selected="true|false"` per item, container `aria-multiselectable="true"`.
86
- * - `'leaf'` — multi over a tree, but only leaf nodes go into `value`. Branch clicks are no-ops. Requires `setTreeShape()`. Aria: `aria-selected`.
87
- * - `'cascade'` — tri-state tree selection. Toggling a branch selects/deselects all leaf descendants; the parent's state is computed from descendants (`true` / `false` / `mixed`). Requires `setTreeShape()`. Aria: `aria-checked="true|false|mixed"` per WAI-ARIA tree checkbox pattern.
88
- */
89
- export type KjListSelectionMode = 'single' | 'multi' | 'leaf' | 'cascade';
90
-
91
- export type KjFilterFn = (query: string, haystacks: readonly string[]) => number;
92
- export type KjCompareFn<T> = (a: T, b: T) => boolean;
93
-
94
- /**
95
- * Tree topology contract used by `KjSelectionModel` in `'leaf'` and
96
- * `'cascade'` modes. The consumer's root directive (typically
97
- * `KjTreeSelect`) implements + provides this via `setTreeShape()`.
98
- */
99
- export interface KjTreeShape<T> {
100
- /** Parent of `node`, or `null` at the root. */
101
- getParent(node: T): T | null;
102
- /** Immediate children of `node`. Empty for leaves. */
103
- getChildren(node: T): readonly T[];
104
- /** `true` when `node` has no children. */
105
- isLeaf(node: T): boolean;
106
- }
@@ -1,58 +0,0 @@
1
- // packages/core/src/primitives/list/type-ahead.spec.ts
2
- import { TestBed } from '@angular/core/testing';
3
- import { describe, it, expect, beforeEach } from 'vitest';
4
- import { KjTypeAhead } from './type-ahead';
5
- import type { KjListItem } from './item';
6
-
7
- function item(id: string, label: string, disabled = false): KjListItem<unknown> {
8
- return {
9
- id,
10
- label: () => label,
11
- disabled: () => disabled,
12
- } as unknown as KjListItem<unknown>;
13
- }
14
-
15
- describe('KjTypeAhead', () => {
16
- let ta: KjTypeAhead;
17
- beforeEach(() => {
18
- TestBed.configureTestingModule({ providers: [KjTypeAhead] });
19
- ta = TestBed.inject(KjTypeAhead);
20
- });
21
-
22
- it('returns the first item whose label starts with the typed char', () => {
23
- const items = [item('1', 'Apple'), item('2', 'Banana')];
24
- expect(ta.match('b', items)).toBe('2');
25
- });
26
-
27
- it('buffers consecutive chars within the debounce window', () => {
28
- const items = [item('1', 'Apple'), item('2', 'Apricot'), item('3', 'Avocado')];
29
- expect(ta.match('a', items)).toBe('1');
30
- expect(ta.match('p', items)).toBe('1');
31
- expect(ta.match('r', items)).toBe('2');
32
- });
33
-
34
- it('resets the buffer after the debounce window', async () => {
35
- const items = [item('1', 'Apple'), item('2', 'Banana')];
36
- ta.debounceMs.set(10);
37
- expect(ta.match('a', items)).toBe('1');
38
- await new Promise(r => setTimeout(r, 20));
39
- expect(ta.match('b', items)).toBe('2');
40
- });
41
-
42
- it('skips disabled items', () => {
43
- const items = [item('1', 'Apple', true), item('2', 'Apricot')];
44
- expect(ta.match('a', items)).toBe('2');
45
- });
46
-
47
- it('returns null when nothing matches', () => {
48
- const items = [item('1', 'Apple')];
49
- expect(ta.match('z', items)).toBeNull();
50
- });
51
-
52
- it('reset() clears the buffer', () => {
53
- const items = [item('1', 'Apple'), item('2', 'Banana')];
54
- ta.match('a', items);
55
- ta.reset();
56
- expect(ta.match('b', items)).toBe('2');
57
- });
58
- });
@@ -1,46 +0,0 @@
1
- // packages/core/src/primitives/list/type-ahead.ts
2
- import { Injectable, signal } from '@angular/core';
3
- import type { KjListItem } from './item';
4
-
5
- /**
6
- * Char-buffered type-ahead matcher used by `KjListNavigator` on
7
- * single-character key presses. Buffers characters within a debounce
8
- * window so users can type "ap" to jump to "Apricot" instead of just
9
- * "Apple". Matches case-insensitive prefix against `KjListItem.label()`.
10
- * Skips disabled items.
11
- *
12
- * @doc-category Core/Primitives
13
- */
14
- @Injectable()
15
- export class KjTypeAhead {
16
- /** Debounce window (ms) that resets the buffer between key presses. */
17
- readonly debounceMs = signal(500);
18
-
19
- private _buffer = '';
20
- private _lastKeyAt = 0;
21
-
22
- /**
23
- * Append `key` to the buffer (reset if outside debounce window), then
24
- * return the id of the first non-disabled item whose label starts with
25
- * the buffered prefix. Returns `null` if no item matches.
26
- */
27
- match(key: string, items: readonly KjListItem<unknown>[]): string | null {
28
- if (key.length !== 1) return null;
29
- const now = performance.now();
30
- if (now - this._lastKeyAt > this.debounceMs()) this._buffer = '';
31
- this._buffer += key.toLowerCase();
32
- this._lastKeyAt = now;
33
-
34
- const needle = this._buffer;
35
- const hit = items.find(
36
- i => !i.disabled() && i.label().toLowerCase().startsWith(needle),
37
- );
38
- return hit?.id ?? null;
39
- }
40
-
41
- /** Clear the buffer and last-key timestamp. */
42
- reset(): void {
43
- this._buffer = '';
44
- this._lastKeyAt = 0;
45
- }
46
- }
@@ -1,54 +0,0 @@
1
- import { Component, inject } from '@angular/core';
2
- import { render } from '@testing-library/angular';
3
- import { describe, it, expect, vi } from 'vitest';
4
- import { KjBackdrop } from './backdrop';
5
- import { KjOverlayController } from './controller';
6
- import { KJ_OVERLAY_BACKDROP_STRATEGY } from './tokens';
7
-
8
- describe('KjBackdrop', () => {
9
- it('clicking host invokes controller.close when closeOnClick=true', async () => {
10
- @Component({
11
- standalone: true,
12
- imports: [KjBackdrop],
13
- providers: [
14
- KjOverlayController,
15
- { provide: KJ_OVERLAY_BACKDROP_STRATEGY, useValue: {
16
- inertSiblings: true, closeOnClick: true, className: 'kj-backdrop',
17
- attach() {}, onOpen() {}, onClose() {}, detach() {},
18
- }},
19
- ],
20
- template: '<kj-backdrop></kj-backdrop>',
21
- })
22
- class Host {
23
- readonly ctrl = inject(KjOverlayController);
24
- }
25
- const { fixture, container } = await render(Host);
26
- const closeSpy = vi.spyOn(fixture.componentInstance.ctrl, 'close');
27
- const el = container.querySelector('kj-backdrop') as HTMLElement;
28
- el.click();
29
- expect(closeSpy).toHaveBeenCalledWith('outside');
30
- });
31
-
32
- it('does not close when closeOnClick=false', async () => {
33
- @Component({
34
- standalone: true,
35
- imports: [KjBackdrop],
36
- providers: [
37
- KjOverlayController,
38
- { provide: KJ_OVERLAY_BACKDROP_STRATEGY, useValue: {
39
- inertSiblings: false, closeOnClick: false, className: 'kj-backdrop',
40
- attach() {}, onOpen() {}, onClose() {}, detach() {},
41
- }},
42
- ],
43
- template: '<kj-backdrop></kj-backdrop>',
44
- })
45
- class Host {
46
- readonly ctrl = inject(KjOverlayController);
47
- }
48
- const { fixture, container } = await render(Host);
49
- const closeSpy = vi.spyOn(fixture.componentInstance.ctrl, 'close');
50
- const el = container.querySelector('kj-backdrop') as HTMLElement;
51
- el.click();
52
- expect(closeSpy).not.toHaveBeenCalled();
53
- });
54
- });
@@ -1,31 +0,0 @@
1
- import { Component, ChangeDetectionStrategy, computed, inject } from '@angular/core';
2
- import { KjOverlayController } from './controller';
3
- import { KJ_OVERLAY_BACKDROP_STRATEGY } from './tokens';
4
-
5
- /**
6
- * Renders the backdrop scrim for an overlay. Reads the backdrop strategy
7
- * (className, closeOnClick) and the controller from the per-overlay
8
- * injector so neither needs to be passed in. Mounted by `KjOverlayBuilder`
9
- * as a sibling preceding the panel inside the per-overlay wrapper.
10
- */
11
- @Component({
12
- selector: 'kj-backdrop',
13
- standalone: true,
14
- template: '',
15
- host: {
16
- '[class]': 'klass()',
17
- '[attr.data-state]': 'state()',
18
- '(click)': 'onClick($event)',
19
- },
20
- changeDetection: ChangeDetectionStrategy.OnPush,
21
- })
22
- export class KjBackdrop {
23
- private readonly controller = inject(KjOverlayController, { optional: true });
24
- private readonly strategy = inject(KJ_OVERLAY_BACKDROP_STRATEGY)!;
25
- readonly state = computed(() => this.controller?.state() ?? 'closed');
26
- readonly klass = computed(() => (this.strategy as { className?: string }).className ?? 'kj-backdrop');
27
-
28
- onClick(_e: MouseEvent): void {
29
- if (this.strategy.closeOnClick) this.controller?.close('outside');
30
- }
31
- }
@@ -1,38 +0,0 @@
1
- import { Component, inject } from '@angular/core';
2
- import { TestBed } from '@angular/core/testing';
3
- import { describe, it, expect } from 'vitest';
4
- import { KjOverlayBuilder } from './builder';
5
- import type { KjOverlayStrategies } from './controller';
6
- import { bodyPortal } from './strategies/mount/body-portal';
7
- import { viewportCentered } from './strategies/position/viewport-centered';
8
- import { programmatic } from './strategies/trigger-event/programmatic';
9
-
10
- function makeStrategies(): KjOverlayStrategies {
11
- return {
12
- mount: bodyPortal(),
13
- position: viewportCentered(),
14
- trigger: programmatic(),
15
- };
16
- }
17
-
18
- describe('KjOverlayBuilder', () => {
19
- it('create returns a controller with strategies attached', () => {
20
- const builder = TestBed.inject(KjOverlayBuilder);
21
- const ctrl = builder.create({ ...makeStrategies(), panelRole: 'dialog' });
22
- expect(ctrl.state()).toBe('closed');
23
- });
24
-
25
- it('attachComponent injects custom providers', () => {
26
- @Component({ standalone: true, template: '' })
27
- class Cmp {
28
- readonly value = inject('TOKEN' as never);
29
- }
30
- const builder = TestBed.inject(KjOverlayBuilder);
31
- const ctrl = builder.create({ ...makeStrategies(), panelRole: 'dialog' });
32
- const ref = builder.attachComponent(ctrl, Cmp, {
33
- providers: [{ provide: 'TOKEN' as never, useValue: 'hello' }],
34
- });
35
- expect((ref.instance as Cmp).value).toBe('hello');
36
- ref.destroy();
37
- });
38
- });