@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,639 +0,0 @@
1
- import {
2
- Directive,
3
- ElementRef,
4
- EventEmitter,
5
- Output,
6
- Signal,
7
- afterNextRender,
8
- booleanAttribute,
9
- computed,
10
- inject,
11
- input,
12
- signal,
13
- } from '@angular/core';
14
- import {
15
- KJ_FILE_UPLOAD,
16
- KJ_FILE_UPLOAD_ITEM,
17
- KjFileUploadAggregateStatus,
18
- KjFileUploadContext,
19
- KjFileUploadItemContext,
20
- } from './file-upload.context';
21
- import {
22
- KJ_FILE_UPLOAD_DEFAULT_MESSAGES,
23
- KjFileRejection,
24
- KjFileStatus,
25
- KjFileUploadValidationMessages,
26
- KjUploadableFile,
27
- } from './file-upload.types';
28
-
29
- let kjFileUploadIdCounter = 0;
30
- function nextFileId(): string {
31
- const cryptoLike = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;
32
- if (cryptoLike?.randomUUID) return `kjf-${cryptoLike.randomUUID().slice(0, 8)}`;
33
- return `kjf-${(++kjFileUploadIdCounter).toString(36)}`;
34
- }
35
-
36
- /**
37
- * Validates a single `File` against the configured `accept` / `maxSize`
38
- * constraints. Returns the rejection reason, or `null` if the file passes.
39
- *
40
- * `accept` matching follows the WHATWG file picker rules: a comma-separated
41
- * list of MIME types (`image/*`, `application/pdf`) or extensions
42
- * (`.pdf`, `.heic`). When `file.type` is empty (browsers don't report a MIME
43
- * type for some extensions, e.g. `.heic`), we fall back to extension
44
- * matching against `file.name`.
45
- *
46
- * @internal
47
- */
48
- export function kjFileMatchesAccept(file: File, accept: string | undefined): boolean {
49
- if (!accept) return true;
50
- const tokens = accept
51
- .split(',')
52
- .map((t) => t.trim().toLowerCase())
53
- .filter(Boolean);
54
- if (!tokens.length) return true;
55
- const type = file.type.toLowerCase();
56
- const name = file.name.toLowerCase();
57
- for (const tok of tokens) {
58
- if (tok.startsWith('.')) {
59
- if (name.endsWith(tok)) return true;
60
- } else if (tok.endsWith('/*')) {
61
- const prefix = tok.slice(0, -1); // keep the trailing slash
62
- if (type.startsWith(prefix)) return true;
63
- } else if (type && tok === type) {
64
- return true;
65
- }
66
- }
67
- return false;
68
- }
69
-
70
- /**
71
- * Root file-upload directive. Owns the file list, drag state, and selection
72
- * validation (`accept` / `maxSize` / `maxFiles`). Provides `KJ_FILE_UPLOAD`
73
- * for child directives (trigger, drop-zone, list, item).
74
- *
75
- * The transport is the consumer's job — `KjFileUpload` ships the *state
76
- * machine* and emits structured events. Examples call `setFileStatus` from
77
- * a simulated upload to drive `KjProgressBar` per row.
78
- *
79
- * The directive owns a visually-hidden `aria-live="polite"` span (mounted
80
- * as a child of the host on first render) that announces file additions,
81
- * removals, completions, and errors to screen readers (WCAG 4.1.3). The
82
- * announcement node is intentionally NOT the host element itself — clearing
83
- * `host.textContent` to retrigger SR readout would also wipe out the
84
- * projected drop-zone / list children, so we keep the live region as a
85
- * dedicated sibling.
86
- *
87
- * @example
88
- * ```html
89
- * <div kjFileUpload kjAccept="image/*" [kjMaxSize]="5_000_000">
90
- * <button kjFileUploadTrigger>Choose files</button>
91
- * <div kjFileUploadDropzone>Drop files here</div>
92
- * <ul kjFileUploadList>
93
- * @for (f of upload.files(); track f.id) {
94
- * <li kjFileUploadItem [kjFile]="f">{{ f.file.name }}</li>
95
- * }
96
- * </ul>
97
- * </div>
98
- * ```
99
- * @doc-category Core/Data input
100
- * @doc
101
- * @doc-name file-upload
102
- * @doc-description Manages file selection, drag state, and validation while you control the upload transport.
103
- * @doc-is-main
104
- */
105
- @Directive({
106
- selector: '[kjFileUpload]',
107
- standalone: true,
108
- exportAs: 'kjFileUpload',
109
- providers: [{ provide: KJ_FILE_UPLOAD, useExisting: KjFileUpload }],
110
- host: {
111
- '[attr.data-disabled]': 'kjDisabled() ? "" : null',
112
- '[attr.data-drag-active]': 'dragActive() ? "" : null',
113
- '[attr.data-status]': 'aggregateStatus()',
114
- },
115
- })
116
- export class KjFileUpload implements KjFileUploadContext {
117
- private readonly hostEl = inject<ElementRef<HTMLElement>>(ElementRef);
118
- private liveRegionEl: HTMLElement | null = null;
119
-
120
- /** MIME / extension list for the file picker and drop validation. */
121
- readonly kjAccept = input<string | undefined>(undefined);
122
-
123
- /** Whether multiple files may be selected. Defaults to `true` (advanced flavour). */
124
- readonly kjMultiple = input(true, { transform: booleanAttribute });
125
-
126
- /** Maximum bytes per file. Files over the cap are rejected at selection. */
127
- readonly kjMaxSize = input<number | undefined>(undefined);
128
-
129
- /** Maximum total file count across the list. Excess files are rejected. */
130
- readonly kjMaxFiles = input<number | undefined>(undefined);
131
-
132
- /** Disables the upload — drop-zone is `aria-disabled`, the trigger is inert. */
133
- readonly kjDisabled = input(false, { transform: booleanAttribute });
134
-
135
- /** Per-rejection-reason override messages. */
136
- readonly kjValidationMessages = input<Partial<KjFileUploadValidationMessages>>({});
137
-
138
- /** Emits the survivors after validation each time the user adds files. */
139
- @Output() readonly kjSelect = new EventEmitter<File[]>();
140
-
141
- /** Emits the rejection list whenever validation filters files out. */
142
- @Output() readonly kjReject = new EventEmitter<KjFileRejection[]>();
143
-
144
- /** Emits the `KjUploadableFile` for each row the user removes. */
145
- @Output() readonly kjRemove = new EventEmitter<KjUploadableFile>();
146
-
147
- private readonly _files = signal<readonly KjUploadableFile[]>([]);
148
- /** Current file list (in selection order). */
149
- readonly files: Signal<readonly KjUploadableFile[]> = this._files.asReadonly();
150
-
151
- private readonly _dragActive = signal(false);
152
- /** True while at least one drag operation is currently over the drop-zone host. */
153
- readonly dragActive: Signal<boolean> = this._dragActive.asReadonly();
154
-
155
- /** Read-only mirror of the disabled flag for context consumers. */
156
- readonly disabled: Signal<boolean> = this.kjDisabled;
157
- readonly multiple: Signal<boolean> = this.kjMultiple;
158
- readonly accept: Signal<string | undefined> = this.kjAccept;
159
- readonly maxSize: Signal<number | undefined> = this.kjMaxSize;
160
- readonly maxFiles: Signal<number | undefined> = this.kjMaxFiles;
161
-
162
- /** Aggregate status across the file list. */
163
- readonly aggregateStatus = computed<KjFileUploadAggregateStatus>(() => {
164
- const list = this._files();
165
- if (!list.length) return 'idle';
166
- let hasUploading = false;
167
- let hasPending = false;
168
- let hasError = false;
169
- let allDone = true;
170
- for (const f of list) {
171
- if (f.status === 'uploading') hasUploading = true;
172
- if (f.status === 'pending' || f.status === 'preparing') hasPending = true;
173
- if (f.status === 'error') hasError = true;
174
- if (f.status !== 'done') allDone = false;
175
- }
176
- if (hasUploading) return 'uploading';
177
- if (allDone) return 'complete';
178
- if (hasError && !hasPending) return 'partial-error';
179
- return 'pending';
180
- });
181
-
182
- /** @internal Drag-enter / drag-leave counter — flips `_dragActive` cleanly across nested children. */
183
- private dragDepth = 0;
184
-
185
- /** @internal Set by the trigger / drop-zone so `openPicker()` can click the right input. */
186
- private pickerInput: HTMLInputElement | null = null;
187
-
188
- /** @internal Trigger / drop-zone register their hidden file input here. */
189
- registerPickerInput(el: HTMLInputElement): void {
190
- this.pickerInput = el;
191
- }
192
-
193
- /** Opens the native file picker by clicking the registered hidden input. */
194
- openPicker(): void {
195
- if (this.kjDisabled()) return;
196
- this.pickerInput?.click();
197
- }
198
-
199
- /**
200
- * Adds candidate files (from drop, programmatic add, or the picker's
201
- * `change` event). Validates each against `accept` / `maxSize`, then
202
- * applies the `kjMaxFiles` cap to the survivors. Mints ids, appends to
203
- * the list, fires `kjSelect` / `kjReject`, and announces.
204
- */
205
- addFiles(incoming: readonly File[] | FileList): void {
206
- if (this.kjDisabled()) return;
207
- const candidates: File[] = Array.from(incoming);
208
- if (!candidates.length) return;
209
-
210
- const accept = this.kjAccept();
211
- const maxSize = this.kjMaxSize();
212
- const maxFiles = this.kjMaxFiles();
213
- const messages = this.resolvedMessages();
214
-
215
- const survivors: File[] = [];
216
- const rejections: KjFileRejection[] = [];
217
-
218
- for (const file of candidates) {
219
- if (accept && !kjFileMatchesAccept(file, accept)) {
220
- rejections.push({ file, reason: 'type' });
221
- continue;
222
- }
223
- if (maxSize !== undefined && file.size > maxSize) {
224
- rejections.push({ file, reason: 'size' });
225
- continue;
226
- }
227
- survivors.push(file);
228
- }
229
-
230
- // In single mode, the most recent pick replaces any existing file. Cap
231
- // the survivors to 1 (rejecting any overflow with reason 'count'), then
232
- // clear the existing list so the survivor takes its place.
233
- if (!this.kjMultiple()) {
234
- if (survivors.length > 1) {
235
- const overflow = survivors.splice(1);
236
- for (const f of overflow) rejections.push({ file: f, reason: 'count' });
237
- }
238
- if (survivors.length) this._files.set([]);
239
- } else if (maxFiles !== undefined) {
240
- // Multi mode: the explicit `kjMaxFiles` cap applies to current + new.
241
- const current = this._files().length;
242
- if (current + survivors.length > maxFiles) {
243
- const allowed = Math.max(0, maxFiles - current);
244
- const overflow = survivors.splice(allowed);
245
- for (const f of overflow) rejections.push({ file: f, reason: 'count' });
246
- }
247
- }
248
-
249
- if (survivors.length) {
250
- const next: KjUploadableFile[] = survivors.map((f) => ({
251
- id: nextFileId(),
252
- file: f,
253
- status: 'pending' as const,
254
- progress: null,
255
- }));
256
- this._files.update((list) => [...list, ...next]);
257
- this.kjSelect.emit(survivors);
258
- this.announce(
259
- survivors.length === 1
260
- ? `${survivors[0].name} added`
261
- : `${survivors.length} files added`,
262
- );
263
- }
264
-
265
- if (rejections.length) {
266
- this.kjReject.emit(rejections);
267
- const reason = rejections[0].reason;
268
- const msg = messages[reason];
269
- this.announce(
270
- rejections.length === 1
271
- ? `${rejections[0].file.name} rejected: ${msg}`
272
- : `${rejections.length} files rejected: ${msg}`,
273
- );
274
- }
275
- }
276
-
277
- /** Remove a file by id. Cancels in-flight uploads, emits `kjRemove`. */
278
- remove(id: string): void {
279
- const target = this._files().find((f) => f.id === id);
280
- if (!target) return;
281
- this._files.update((list) => list.filter((f) => f.id !== id));
282
- this.kjRemove.emit(target);
283
- this.announce(`${target.file.name} removed`);
284
- }
285
-
286
- /** Clear the entire file list. */
287
- clear(): void {
288
- if (!this._files().length) return;
289
- this._files.set([]);
290
- this.announce('File list cleared');
291
- }
292
-
293
- /** Reset a row to `pending` so the consumer (or simulator) can re-run it. */
294
- retry(id: string): void {
295
- this.patchFile(id, { status: 'pending', progress: null, error: undefined });
296
- }
297
-
298
- /** Cancel an in-flight upload — sets `status: 'cancelled'`, clears progress. */
299
- cancel(id: string): void {
300
- this.patchFile(id, { status: 'cancelled', progress: null });
301
- }
302
-
303
- /**
304
- * Update a row's status / progress / error. Examples drive this from a
305
- * simulated upload; consumers wiring `HttpClient` call it from their
306
- * progress / success / error subscriptions.
307
- */
308
- setFileStatus(id: string, status: KjFileStatus, progress?: number | null, error?: string): void {
309
- this.patchFile(id, {
310
- status,
311
- progress: progress === undefined ? null : progress,
312
- error,
313
- });
314
- if (status === 'done') {
315
- const f = this._files().find((x) => x.id === id);
316
- if (f) this.announce(`${f.file.name} uploaded`);
317
- } else if (status === 'error') {
318
- const f = this._files().find((x) => x.id === id);
319
- if (f) this.announce(`${f.file.name} failed: ${error ?? 'upload error'}`);
320
- }
321
- }
322
-
323
- // ─── Drag state plumbing (called by KjFileUploadDropzone) ───
324
-
325
- /** @internal */
326
- onDragEnter(event: Event): void {
327
- if (this.kjDisabled()) return;
328
- if (!this.eventCarriesFiles(event)) return;
329
- event.preventDefault();
330
- this.dragDepth++;
331
- this._dragActive.set(true);
332
- }
333
-
334
- /** @internal */
335
- onDragOver(event: Event): void {
336
- if (this.kjDisabled()) return;
337
- if (!this.eventCarriesFiles(event)) return;
338
- event.preventDefault();
339
- }
340
-
341
- /** @internal */
342
- onDragLeave(event: Event): void {
343
- if (this.kjDisabled()) return;
344
- event.preventDefault();
345
- this.dragDepth = Math.max(0, this.dragDepth - 1);
346
- if (this.dragDepth === 0) this._dragActive.set(false);
347
- }
348
-
349
- /** @internal */
350
- onDrop(event: Event): void {
351
- event.preventDefault();
352
- this.dragDepth = 0;
353
- this._dragActive.set(false);
354
- if (this.kjDisabled()) return;
355
- const files = (event as DragEvent).dataTransfer?.files;
356
- if (!files || files.length === 0) return;
357
- this.addFiles(files);
358
- }
359
-
360
- /** @internal */
361
- onPickerChange(event: Event): void {
362
- const target = event.target as HTMLInputElement;
363
- if (target.files) this.addFiles(target.files);
364
- // Reset so picking the same file twice fires another change event.
365
- target.value = '';
366
- }
367
-
368
- private eventCarriesFiles(event: Event): boolean {
369
- const types = (event as DragEvent).dataTransfer?.types;
370
- if (!types) return false;
371
- for (let i = 0; i < types.length; i++) {
372
- if (types[i] === 'Files') return true;
373
- }
374
- return false;
375
- }
376
-
377
- private patchFile(id: string, patch: Partial<KjUploadableFile>): void {
378
- this._files.update((list) =>
379
- list.map((f) => (f.id === id ? { ...f, ...patch } : f)),
380
- );
381
- }
382
-
383
- private resolvedMessages(): KjFileUploadValidationMessages {
384
- return { ...KJ_FILE_UPLOAD_DEFAULT_MESSAGES, ...this.kjValidationMessages() };
385
- }
386
-
387
- private announce(message: string): void {
388
- const el = this.liveRegionEl;
389
- if (!el) return;
390
- // Clear-then-set with a microtask gap so screen readers detect the change
391
- // even when consecutive announcements share a prefix.
392
- el.textContent = '';
393
- setTimeout(() => {
394
- if (this.liveRegionEl) this.liveRegionEl.textContent = message;
395
- }, 50);
396
- }
397
-
398
- constructor() {
399
- afterNextRender(() => {
400
- if (typeof document === 'undefined') return;
401
- const span = document.createElement('span');
402
- span.setAttribute('aria-live', 'polite');
403
- span.setAttribute('aria-atomic', 'true');
404
- span.style.cssText =
405
- 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;';
406
- this.hostEl.nativeElement.appendChild(span);
407
- this.liveRegionEl = span;
408
- });
409
- }
410
- }
411
-
412
- /**
413
- * The "browse" button — when clicked, opens the native file picker. Owns the
414
- * hidden `<input type="file">` so consumers don't have to render one
415
- * themselves. Mirrors the `KjButton` keyboard contract (Enter / Space click
416
- * the host element).
417
- *
418
- * Use on a `<button>` (recommended, native keyboard semantics) or any
419
- * focusable element. The directive does **not** force `role="button"` — wrap
420
- * a real `<button>` and let the browser handle it.
421
- *
422
- * @example
423
- * ```html
424
- * <button kjFileUploadTrigger>Choose files</button>
425
- * ```
426
- * @doc-category Core/Data input
427
- * @doc
428
- * @doc-name file-upload
429
- */
430
- @Directive({
431
- selector: '[kjFileUploadTrigger]',
432
- standalone: true,
433
- host: {
434
- 'type': 'button',
435
- '[attr.aria-disabled]': 'ctx.disabled() ? "true" : null',
436
- '[attr.data-disabled]': 'ctx.disabled() ? "" : null',
437
- '(click)': 'onClick($event)',
438
- },
439
- })
440
- export class KjFileUploadTrigger {
441
- /** @internal */
442
- readonly ctx = inject(KJ_FILE_UPLOAD);
443
- private readonly el = inject<ElementRef<HTMLElement>>(ElementRef);
444
- private hidden!: HTMLInputElement;
445
-
446
- constructor() {
447
- // Mint and own a hidden `<input type="file">` parked in the trigger's
448
- // host element. Visually hidden (not [hidden] attribute) so it stays in
449
- // the a11y tree and programmatic .click() opens the picker reliably
450
- // across browsers (analysis open-question #2).
451
- if (typeof document !== 'undefined') {
452
- this.hidden = document.createElement('input');
453
- this.hidden.type = 'file';
454
- this.hidden.tabIndex = -1;
455
- this.hidden.setAttribute('aria-hidden', 'true');
456
- this.hidden.style.cssText =
457
- 'position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;';
458
- this.hidden.addEventListener('change', (event) => this.ctx.onPickerChange(event));
459
- this.syncAttrs();
460
- // Mirror dynamic accept / multiple onto the hidden input.
461
- // computed-via-effect would also work; for a deliberately small surface
462
- // we re-sync on every click (cheap).
463
- this.el.nativeElement.appendChild(this.hidden);
464
- this.ctx.registerPickerInput(this.hidden);
465
- }
466
- }
467
-
468
- /** @internal */
469
- onClick(event: Event): void {
470
- if (this.ctx.disabled()) {
471
- event.preventDefault();
472
- event.stopImmediatePropagation();
473
- return;
474
- }
475
- this.syncAttrs();
476
- this.hidden?.click();
477
- }
478
-
479
- private syncAttrs(): void {
480
- if (!this.hidden) return;
481
- const accept = this.ctx.accept();
482
- if (accept) this.hidden.setAttribute('accept', accept);
483
- else this.hidden.removeAttribute('accept');
484
- if (this.ctx.multiple()) this.hidden.setAttribute('multiple', '');
485
- else this.hidden.removeAttribute('multiple');
486
- }
487
- }
488
-
489
- /**
490
- * Drag-and-drop surface. `role="button"`, `tabindex="0"`, Enter/Space open
491
- * the picker. Reflects `data-drag-active` while files are over the host so
492
- * theme CSS can style the highlighted state.
493
- *
494
- * The drop-zone wires drag enter / over / leave / drop into the root's
495
- * counter (so nested children don't churn `data-drag-active`). The host is
496
- * a generic `<div>`-shaped element so consumers can project arbitrary
497
- * content (thumbnail grid, instructional text, etc.) — analysis decision
498
- * #3 in `file-upload.md`.
499
- *
500
- * @example
501
- * ```html
502
- * <div kjFileUploadDropzone>
503
- * Drag files here, or click to browse
504
- * </div>
505
- * ```
506
- * @doc-category Core/Data input
507
- * @doc
508
- * @doc-name file-upload
509
- */
510
- @Directive({
511
- selector: '[kjFileUploadDropzone]',
512
- standalone: true,
513
- host: {
514
- 'role': 'button',
515
- 'tabindex': '0',
516
- '[attr.aria-label]': 'kjLabel()',
517
- '[attr.aria-disabled]': 'ctx.disabled() ? "true" : null',
518
- '[attr.data-drag-active]': 'ctx.dragActive() ? "" : null',
519
- '[attr.data-disabled]': 'ctx.disabled() ? "" : null',
520
- '(dragenter)': 'ctx.onDragEnter($event)',
521
- '(dragover)': 'ctx.onDragOver($event)',
522
- '(dragleave)': 'ctx.onDragLeave($event)',
523
- '(drop)': 'ctx.onDrop($event)',
524
- '(click)': 'onClick($event)',
525
- '(keydown.enter)': 'onActivate($event)',
526
- '(keydown.space)': 'onActivate($event)',
527
- },
528
- })
529
- export class KjFileUploadDropzone {
530
- /** @internal */
531
- readonly ctx = inject(KJ_FILE_UPLOAD);
532
-
533
- /** Accessible name for the drop-zone. */
534
- readonly kjLabel = input<string>('Drag files here, or click to browse');
535
-
536
- /** @internal */
537
- onClick(event: Event): void {
538
- if (this.ctx.disabled()) {
539
- event.preventDefault();
540
- return;
541
- }
542
- this.ctx.openPicker();
543
- }
544
-
545
- /** @internal */
546
- onActivate(event: Event): void {
547
- event.preventDefault();
548
- if (this.ctx.disabled()) return;
549
- this.ctx.openPicker();
550
- }
551
- }
552
-
553
- /**
554
- * File list container. Sets `role="list"` (idempotent on a `<ul>`, required
555
- * on a `<div>`) so the per-row `role="listitem"` semantics chain correctly
556
- * for screen readers (WCAG 1.3.1).
557
- *
558
- * The directive is structural-light — the consumer iterates `ctx.files()`
559
- * with `@for` and renders rows via `[kjFileUploadItem]` — so list-shape
560
- * (table / definition list / virtualised) stays the consumer's call.
561
- *
562
- * @example
563
- * ```html
564
- * <ul kjFileUploadList>
565
- * @for (f of upload.files(); track f.id) {
566
- * <li kjFileUploadItem [kjFile]="f">{{ f.file.name }}</li>
567
- * }
568
- * </ul>
569
- * ```
570
- * @doc-category Core/Data input
571
- * @doc
572
- * @doc-name file-upload
573
- */
574
- @Directive({
575
- selector: '[kjFileUploadList]',
576
- standalone: true,
577
- host: {
578
- 'role': 'list',
579
- },
580
- })
581
- export class KjFileUploadList {
582
- /** @internal */
583
- readonly ctx = inject(KJ_FILE_UPLOAD);
584
- }
585
-
586
- /**
587
- * Per-file row directive. Provides `KJ_FILE_UPLOAD_ITEM` so per-row buttons
588
- * (retry / cancel / remove) and a per-row `KjProgressBar` can read
589
- * `file()` / `progress()` / `status()` from context.
590
- *
591
- * Reflects `data-status` so theme CSS can flip the row's tint (red border
592
- * for `error`, dimmed for `done`, etc.).
593
- *
594
- * @example
595
- * ```html
596
- * <li kjFileUploadItem [kjFile]="f">
597
- * <span>{{ f.file.name }}</span>
598
- * <button (click)="item.remove()">Remove</button>
599
- * </li>
600
- * ```
601
- * @doc-category Core/Data input
602
- * @doc
603
- * @doc-name file-upload
604
- */
605
- @Directive({
606
- selector: '[kjFileUploadItem]',
607
- standalone: true,
608
- exportAs: 'kjFileUploadItem',
609
- providers: [{ provide: KJ_FILE_UPLOAD_ITEM, useExisting: KjFileUploadItem }],
610
- host: {
611
- 'role': 'listitem',
612
- '[attr.data-status]': 'status()',
613
- },
614
- })
615
- export class KjFileUploadItem implements KjFileUploadItemContext {
616
- /** @internal */
617
- readonly ctx = inject(KJ_FILE_UPLOAD);
618
-
619
- /** The `KjUploadableFile` for this row. Required. */
620
- readonly kjFile = input.required<KjUploadableFile>();
621
-
622
- /** Read-only mirror for context consumers. */
623
- readonly file: Signal<KjUploadableFile> = this.kjFile;
624
-
625
- readonly status: Signal<KjFileStatus> = computed(() => this.kjFile().status);
626
- readonly progress: Signal<number | null> = computed(() => this.kjFile().progress);
627
-
628
- retry(): void {
629
- this.ctx.retry(this.kjFile().id);
630
- }
631
-
632
- cancel(): void {
633
- this.ctx.cancel(this.kjFile().id);
634
- }
635
-
636
- remove(): void {
637
- this.ctx.remove(this.kjFile().id);
638
- }
639
- }
@@ -1,59 +0,0 @@
1
- /**
2
- * Per-file lifecycle status. Set by the directive as files move through the
3
- * state machine; read by templates and per-row controls (retry / cancel /
4
- * remove gate on this).
5
- */
6
- export type KjFileStatus =
7
- | 'preparing'
8
- | 'pending'
9
- | 'uploading'
10
- | 'done'
11
- | 'error'
12
- | 'cancelled';
13
-
14
- /**
15
- * The kouji envelope around a native `File`. `KjFileUpload` mints `id` (a
16
- * stable string) on selection so consumers can `track` per-row by identity.
17
- *
18
- * `progress` is `null` when the file hasn't started yet *or* the upload is
19
- * indeterminate; once the consumer reports `progress` events the directive
20
- * fills in `0..100`.
21
- */
22
- export interface KjUploadableFile {
23
- /** Stable id, minted by `KjFileUpload`. Survives retry. */
24
- readonly id: string;
25
- /** The native `File`. */
26
- readonly file: File;
27
- /** Current per-file status. */
28
- readonly status: KjFileStatus;
29
- /** `0..100` once the upload reports progress; `null` otherwise. */
30
- readonly progress: number | null;
31
- /** Human-readable error message (set when `status === 'error'`). */
32
- readonly error?: string;
33
- }
34
-
35
- /**
36
- * Reason a candidate file was rejected at selection time. Drives both the
37
- * built-in validation messages and the structured `kjReject` output the
38
- * consumer can map to a hint / toast.
39
- */
40
- export type KjFileRejectReason = 'size' | 'type' | 'count';
41
-
42
- /** A file that was filtered out at selection. */
43
- export interface KjFileRejection {
44
- readonly file: File;
45
- readonly reason: KjFileRejectReason;
46
- }
47
-
48
- /** Built-in validation messages (English, locale-neutral). Override per-instance via `kjValidationMessages`. */
49
- export interface KjFileUploadValidationMessages {
50
- size: string;
51
- type: string;
52
- count: string;
53
- }
54
-
55
- export const KJ_FILE_UPLOAD_DEFAULT_MESSAGES: KjFileUploadValidationMessages = {
56
- size: 'File too large',
57
- type: 'File type not allowed',
58
- count: 'Too many files',
59
- };