@kouji-ui/core 0.0.3 → 0.1.1

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 (534) hide show
  1. package/.turbo/turbo-build.log +6 -3
  2. package/CHANGELOG.md +177 -0
  3. package/ng-package.json +5 -1
  4. package/package.json +18 -6
  5. package/src/a11y/aria-describedby.ts +7 -3
  6. package/src/a11y/aria-labelledby.spec.ts +55 -0
  7. package/src/a11y/aria-labelledby.ts +38 -0
  8. package/src/a11y/focus-trap.ts +4 -2
  9. package/src/a11y/index.ts +1 -0
  10. package/src/a11y/live-region.ts +4 -2
  11. package/src/a11y/roving-tabindex.spec.ts +139 -0
  12. package/src/a11y/roving-tabindex.ts +56 -7
  13. package/src/a11y/visually-hidden.ts +4 -2
  14. package/src/accordion/accordion.context.ts +22 -0
  15. package/src/accordion/accordion.spec.ts +233 -23
  16. package/src/accordion/accordion.ts +311 -39
  17. package/src/accordion/index.ts +8 -2
  18. package/src/alert/alert.context.ts +28 -0
  19. package/src/alert/alert.spec.ts +217 -0
  20. package/src/alert/alert.ts +417 -0
  21. package/src/alert/config.ts +46 -0
  22. package/src/alert/index.ts +19 -0
  23. package/src/avatar/avatar-group.context.ts +45 -0
  24. package/src/avatar/avatar-group.spec.ts +358 -0
  25. package/src/avatar/avatar-group.ts +259 -0
  26. package/src/avatar/avatar.ts +17 -4
  27. package/src/avatar/index.ts +11 -1
  28. package/src/badge/badge.spec.ts +8 -0
  29. package/src/badge/badge.ts +24 -3
  30. package/src/breadcrumb/breadcrumb-current.ts +38 -0
  31. package/src/breadcrumb/breadcrumb-ellipsis.ts +71 -0
  32. package/src/breadcrumb/breadcrumb-item.ts +41 -0
  33. package/src/breadcrumb/breadcrumb-link.ts +44 -0
  34. package/src/breadcrumb/breadcrumb-list.ts +42 -0
  35. package/src/breadcrumb/breadcrumb-separator.ts +45 -0
  36. package/src/breadcrumb/breadcrumb.context.ts +45 -0
  37. package/src/breadcrumb/breadcrumb.spec.ts +354 -0
  38. package/src/breadcrumb/breadcrumb.ts +239 -0
  39. package/src/breadcrumb/config.ts +84 -0
  40. package/src/breadcrumb/index.ts +18 -0
  41. package/src/button/_examples/button.example.ts +71 -0
  42. package/src/button/_examples/button.finance.example.ts +83 -0
  43. package/src/button/_examples/button.retro.example.ts +91 -0
  44. package/src/button/_examples/button.sizes.example.ts +60 -0
  45. package/src/button/_examples/index.ts +6 -0
  46. package/src/button/button.spec.ts +139 -8
  47. package/src/button/button.ts +114 -16
  48. package/src/button/config.spec.ts +33 -0
  49. package/src/button/config.ts +45 -0
  50. package/src/button/index.ts +2 -1
  51. package/src/button-group/button-group.context.ts +28 -0
  52. package/src/button-group/button-group.spec.ts +99 -0
  53. package/src/button-group/button-group.ts +99 -0
  54. package/src/button-group/index.ts +2 -0
  55. package/src/calendar/calendar-day.ts +102 -0
  56. package/src/calendar/calendar-grid.ts +90 -0
  57. package/src/calendar/calendar-header.ts +65 -0
  58. package/src/calendar/calendar.context.ts +53 -0
  59. package/src/calendar/calendar.spec.ts +225 -0
  60. package/src/calendar/calendar.ts +233 -0
  61. package/src/calendar/date-utils.ts +225 -0
  62. package/src/calendar/index.ts +28 -0
  63. package/src/carousel/carousel.context.ts +81 -0
  64. package/src/carousel/carousel.spec.ts +337 -0
  65. package/src/carousel/carousel.ts +919 -0
  66. package/src/carousel/index.ts +22 -0
  67. package/src/cascade-select/cascade-select-option.ts +205 -0
  68. package/src/cascade-select/cascade-select-panel.ts +106 -0
  69. package/src/cascade-select/cascade-select-root.ts +265 -0
  70. package/src/cascade-select/cascade-select-sub-panel.ts +168 -0
  71. package/src/cascade-select/cascade-select-trigger.ts +44 -0
  72. package/src/cascade-select/cascade-select.context.ts +71 -0
  73. package/src/cascade-select/cascade-select.spec.ts +241 -0
  74. package/src/cascade-select/cascade-select.ts +5 -0
  75. package/src/cascade-select/index.ts +11 -0
  76. package/src/chart/chart.ts +6 -2
  77. package/src/chat/chat-avatar.ts +31 -0
  78. package/src/chat/chat-bubble.ts +49 -0
  79. package/src/chat/chat-footer.ts +67 -0
  80. package/src/chat/chat-header.ts +41 -0
  81. package/src/chat/chat-log.ts +43 -0
  82. package/src/chat/chat.context.ts +64 -0
  83. package/src/chat/chat.spec.ts +341 -0
  84. package/src/chat/chat.ts +191 -0
  85. package/src/chat/config.ts +53 -0
  86. package/src/chat/index.ts +21 -0
  87. package/src/checkbox/checkbox.ts +9 -2
  88. package/src/color-picker/color-picker.context.ts +74 -0
  89. package/src/color-picker/color-picker.spec.ts +241 -0
  90. package/src/color-picker/color-picker.ts +698 -0
  91. package/src/color-picker/color-picker.utils.ts +140 -0
  92. package/src/color-picker/index.ts +28 -0
  93. package/src/combobox/combobox-input.ts +143 -0
  94. package/src/combobox/combobox-listbox.ts +49 -0
  95. package/src/combobox/combobox-option.ts +43 -0
  96. package/src/combobox/combobox-root.ts +281 -0
  97. package/src/combobox/combobox.spec.ts +75 -0
  98. package/src/combobox/combobox.ts +4 -0
  99. package/src/combobox/index.ts +4 -0
  100. package/src/command-palette/command-empty.ts +36 -0
  101. package/src/command-palette/command-group.ts +21 -0
  102. package/src/command-palette/command-input.ts +70 -0
  103. package/src/command-palette/command-item.ts +60 -0
  104. package/src/command-palette/command-list.ts +25 -0
  105. package/src/command-palette/command-palette-dialog.ts +74 -0
  106. package/src/command-palette/command-palette-trigger.ts +64 -0
  107. package/src/command-palette/command-palette.filters.ts +53 -0
  108. package/src/command-palette/command-palette.spec.ts +349 -0
  109. package/src/command-palette/command-palette.ts +204 -0
  110. package/src/command-palette/command-separator.ts +18 -0
  111. package/src/command-palette/index.ts +15 -0
  112. package/src/confirm-popup/confirm-popup-action.ts +39 -0
  113. package/src/confirm-popup/confirm-popup-cancel.ts +38 -0
  114. package/src/confirm-popup/confirm-popup-content.ts +113 -0
  115. package/src/confirm-popup/confirm-popup-message.ts +36 -0
  116. package/src/confirm-popup/confirm-popup-trigger.ts +31 -0
  117. package/src/confirm-popup/confirm-popup.context.ts +41 -0
  118. package/src/confirm-popup/confirm-popup.spec.ts +337 -0
  119. package/src/confirm-popup/confirm-popup.ts +109 -0
  120. package/src/confirm-popup/index.ts +12 -0
  121. package/src/date-picker/date-picker-calendar.ts +65 -0
  122. package/src/date-picker/date-picker-trigger.ts +215 -0
  123. package/src/date-picker/date-picker.context.ts +50 -0
  124. package/src/date-picker/date-picker.spec.ts +117 -0
  125. package/src/date-picker/date-picker.ts +127 -0
  126. package/src/date-picker/index.ts +7 -0
  127. package/src/dialog/_examples/dialog.confirm.example.ts +145 -0
  128. package/src/dialog/_examples/dialog.example.ts +106 -0
  129. package/src/dialog/_examples/dialog.finance.example.ts +121 -0
  130. package/src/dialog/_examples/dialog.retro.example.ts +126 -0
  131. package/src/dialog/_examples/index.ts +6 -0
  132. package/src/dialog/dialog.ref.ts +42 -0
  133. package/src/dialog/dialog.service.ts +57 -167
  134. package/src/dialog/dialog.spec.ts +35 -120
  135. package/src/dialog/dialog.ts +17 -192
  136. package/src/dialog/index.ts +3 -9
  137. package/src/divider/divider.spec.ts +223 -0
  138. package/src/divider/divider.ts +137 -0
  139. package/src/divider/index.ts +5 -0
  140. package/src/drawer/drawer.ref.ts +63 -0
  141. package/src/drawer/drawer.service.ts +106 -0
  142. package/src/drawer/drawer.spec.ts +117 -0
  143. package/src/drawer/drawer.ts +122 -0
  144. package/src/drawer/index.ts +10 -0
  145. package/src/dropdown-menu/dropdown-menu-content.ts +258 -0
  146. package/src/dropdown-menu/dropdown-menu-group.ts +31 -0
  147. package/src/dropdown-menu/dropdown-menu-item.ts +51 -0
  148. package/src/dropdown-menu/dropdown-menu-label.ts +41 -0
  149. package/src/dropdown-menu/dropdown-menu-separator.ts +27 -0
  150. package/src/dropdown-menu/dropdown-menu-trigger.ts +140 -0
  151. package/src/dropdown-menu/dropdown-menu.spec.ts +265 -0
  152. package/src/dropdown-menu/dropdown-menu.ts +60 -0
  153. package/src/dropdown-menu/index.ts +15 -0
  154. package/src/example-components.ts +39 -30
  155. package/src/field/field-error.ts +49 -0
  156. package/src/field/field-group.ts +39 -0
  157. package/src/field/field-help.ts +47 -0
  158. package/src/field/field-label.ts +30 -0
  159. package/src/field/field.context.ts +28 -0
  160. package/src/field/field.spec.ts +179 -0
  161. package/src/field/field.ts +121 -0
  162. package/src/field/index.ts +6 -0
  163. package/src/file-upload/file-upload.context.ts +89 -0
  164. package/src/file-upload/file-upload.spec.ts +290 -0
  165. package/src/file-upload/file-upload.ts +639 -0
  166. package/src/file-upload/file-upload.types.ts +59 -0
  167. package/src/file-upload/index.ts +23 -0
  168. package/src/form/form-error-summary.ts +87 -0
  169. package/src/form/form-field.context.ts +3 -0
  170. package/src/form/form-field.spec.ts +25 -0
  171. package/src/form/form-field.ts +52 -0
  172. package/src/form/form.context.ts +52 -2
  173. package/src/form/form.spec.ts +155 -18
  174. package/src/form/form.ts +315 -35
  175. package/src/form/index.ts +11 -2
  176. package/src/icon/E2E.md +14 -0
  177. package/src/icon/icon.css +40 -0
  178. package/src/icon/icon.directive.spec.ts +198 -0
  179. package/src/icon/icon.directive.ts +113 -0
  180. package/src/icon/icon.mode.spec.ts +29 -0
  181. package/src/icon/icon.mode.ts +23 -0
  182. package/src/icon/icon.providers.spec.ts +63 -0
  183. package/src/icon/icon.providers.ts +47 -0
  184. package/src/icon/icon.resolver.spec.ts +96 -0
  185. package/src/icon/icon.resolver.ts +49 -0
  186. package/src/icon/icon.tokens.ts +88 -0
  187. package/src/icon/icon.types.ts +48 -0
  188. package/src/icon/index.ts +21 -0
  189. package/src/input/input.ts +12 -3
  190. package/src/input-group/index.ts +3 -0
  191. package/src/input-group/input-group-addon.ts +92 -0
  192. package/src/input-group/input-group.context.ts +27 -0
  193. package/src/input-group/input-group.spec.ts +186 -0
  194. package/src/input-group/input-group.ts +136 -0
  195. package/src/input-mask/index.ts +11 -0
  196. package/src/input-mask/input-mask.compile.ts +69 -0
  197. package/src/input-mask/input-mask.engine.ts +376 -0
  198. package/src/input-mask/input-mask.presets.ts +24 -0
  199. package/src/input-mask/input-mask.spec.ts +304 -0
  200. package/src/input-mask/input-mask.tokens.ts +49 -0
  201. package/src/input-mask/input-mask.ts +280 -0
  202. package/src/input-otp/index.ts +2 -0
  203. package/src/input-otp/input-otp.context.ts +41 -0
  204. package/src/input-otp/input-otp.spec.ts +308 -0
  205. package/src/input-otp/input-otp.ts +470 -0
  206. package/src/kbd/index.ts +1 -0
  207. package/src/kbd/kbd.spec.ts +127 -0
  208. package/src/kbd/kbd.ts +132 -0
  209. package/src/link/config.ts +44 -0
  210. package/src/link/index.ts +2 -0
  211. package/src/link/link.spec.ts +246 -0
  212. package/src/link/link.ts +226 -0
  213. package/src/list/index.ts +11 -0
  214. package/src/list/list.spec.ts +237 -0
  215. package/src/list/list.ts +277 -0
  216. package/src/menubar/index.ts +7 -0
  217. package/src/menubar/menubar-item.ts +204 -0
  218. package/src/menubar/menubar.context.ts +43 -0
  219. package/src/menubar/menubar.spec.ts +433 -0
  220. package/src/menubar/menubar.ts +309 -0
  221. package/src/number-input/index.ts +4 -0
  222. package/src/number-input/number-input-group.ts +64 -0
  223. package/src/number-input/number-input.context.ts +31 -0
  224. package/src/number-input/number-input.format.ts +148 -0
  225. package/src/number-input/number-input.spec.ts +170 -0
  226. package/src/number-input/number-input.ts +457 -0
  227. package/src/number-input/number-stepper.ts +193 -0
  228. package/src/overlay-badge/index.ts +7 -0
  229. package/src/overlay-badge/overlay-badge-content.ts +73 -0
  230. package/src/overlay-badge/overlay-badge.context.ts +37 -0
  231. package/src/overlay-badge/overlay-badge.spec.ts +220 -0
  232. package/src/overlay-badge/overlay-badge.ts +128 -0
  233. package/src/pagination/config.ts +82 -0
  234. package/src/pagination/index.ts +19 -0
  235. package/src/pagination/page-tokens.ts +78 -0
  236. package/src/pagination/pagination-ellipsis.ts +69 -0
  237. package/src/pagination/pagination-first.ts +84 -0
  238. package/src/pagination/pagination-info.ts +70 -0
  239. package/src/pagination/pagination-item.ts +81 -0
  240. package/src/pagination/pagination-last.ts +85 -0
  241. package/src/pagination/pagination-next.ts +86 -0
  242. package/src/pagination/pagination-previous.ts +90 -0
  243. package/src/pagination/pagination.context.ts +52 -0
  244. package/src/pagination/pagination.spec.ts +388 -0
  245. package/src/pagination/pagination.ts +288 -0
  246. package/src/password-input/index.ts +15 -0
  247. package/src/password-input/password-input.context.ts +65 -0
  248. package/src/password-input/password-input.scorer.ts +34 -0
  249. package/src/password-input/password-input.spec.ts +274 -0
  250. package/src/password-input/password-input.ts +488 -0
  251. package/src/popover/_examples/index.ts +5 -0
  252. package/src/popover/_examples/popover.example.ts +92 -0
  253. package/src/popover/_examples/popover.finance.example.ts +106 -0
  254. package/src/popover/_examples/popover.retro.example.ts +103 -0
  255. package/src/popover/index.ts +5 -12
  256. package/src/popover/popover-arrow.ts +30 -0
  257. package/src/popover/popover-close.ts +36 -0
  258. package/src/popover/popover-content.ts +41 -0
  259. package/src/popover/popover-title.ts +39 -0
  260. package/src/popover/popover-trigger.ts +40 -0
  261. package/src/popover/popover.spec.ts +51 -44
  262. package/src/popover/popover.ts +5 -124
  263. package/src/presets/bind-presets.spec.ts +50 -0
  264. package/src/presets/bind-presets.ts +43 -0
  265. package/src/presets/index.ts +3 -0
  266. package/src/presets/size.spec.ts +67 -0
  267. package/src/presets/size.ts +59 -0
  268. package/src/presets/variant.spec.ts +72 -0
  269. package/src/presets/variant.ts +62 -0
  270. package/src/primitives/directionality/directionality.spec.ts +112 -0
  271. package/src/primitives/directionality/directionality.ts +89 -0
  272. package/src/primitives/directionality/index.ts +1 -0
  273. package/src/primitives/forms/form-control.spec.ts +14 -6
  274. package/src/primitives/forms/form-control.ts +6 -2
  275. package/src/primitives/index.ts +3 -0
  276. package/src/primitives/interaction/disabled.ts +12 -5
  277. package/src/primitives/interaction/focus-ring.ts +4 -2
  278. package/src/primitives/list/filterable-list.spec.ts +114 -0
  279. package/src/primitives/list/filterable-list.ts +126 -0
  280. package/src/primitives/list/group.spec.ts +99 -0
  281. package/src/primitives/list/group.ts +139 -0
  282. package/src/primitives/list/index.ts +8 -0
  283. package/src/primitives/list/inject-helpers.ts +8 -0
  284. package/src/primitives/list/item.spec.ts +173 -0
  285. package/src/primitives/list/item.ts +222 -0
  286. package/src/primitives/list/navigator.spec.ts +286 -0
  287. package/src/primitives/list/navigator.ts +238 -0
  288. package/src/primitives/list/selection.spec.ts +214 -0
  289. package/src/primitives/list/selection.ts +339 -0
  290. package/src/primitives/list/tokens.ts +106 -0
  291. package/src/primitives/list/type-ahead.spec.ts +58 -0
  292. package/src/primitives/list/type-ahead.ts +46 -0
  293. package/src/primitives/overlay/backdrop.spec.ts +54 -0
  294. package/src/primitives/overlay/backdrop.ts +31 -0
  295. package/src/primitives/overlay/builder.spec.ts +38 -0
  296. package/src/primitives/overlay/builder.ts +151 -0
  297. package/src/primitives/overlay/container.ts +42 -0
  298. package/src/primitives/overlay/context.ts +14 -0
  299. package/src/primitives/overlay/controller.spec.ts +86 -0
  300. package/src/primitives/overlay/controller.ts +190 -0
  301. package/src/primitives/overlay/id.spec.ts +24 -0
  302. package/src/primitives/overlay/id.ts +17 -0
  303. package/src/primitives/overlay/index.ts +18 -1
  304. package/src/primitives/overlay/overlay.css +42 -0
  305. package/src/primitives/overlay/panel.spec.ts +52 -0
  306. package/src/primitives/overlay/panel.ts +102 -0
  307. package/src/primitives/overlay/stack.spec.ts +55 -0
  308. package/src/primitives/overlay/stack.ts +113 -0
  309. package/src/primitives/overlay/strategies/backdrop/blurred.spec.ts +11 -0
  310. package/src/primitives/overlay/strategies/backdrop/blurred.ts +5 -0
  311. package/src/primitives/overlay/strategies/backdrop/none.spec.ts +10 -0
  312. package/src/primitives/overlay/strategies/backdrop/none.ts +9 -0
  313. package/src/primitives/overlay/strategies/backdrop/solid.spec.ts +18 -0
  314. package/src/primitives/overlay/strategies/backdrop/solid.ts +23 -0
  315. package/src/primitives/overlay/strategies/focus-trap/inert-based.spec.ts +28 -0
  316. package/src/primitives/overlay/strategies/focus-trap/inert-based.ts +38 -0
  317. package/src/primitives/overlay/strategies/focus-trap/no-trap.spec.ts +9 -0
  318. package/src/primitives/overlay/strategies/focus-trap/no-trap.ts +8 -0
  319. package/src/primitives/overlay/strategies/focus-trap/tab-cycle.spec.ts +49 -0
  320. package/src/primitives/overlay/strategies/focus-trap/tab-cycle.ts +85 -0
  321. package/src/primitives/overlay/strategies/index.ts +34 -0
  322. package/src/primitives/overlay/strategies/live-announcer/_announce.ts +35 -0
  323. package/src/primitives/overlay/strategies/live-announcer/assertive.spec.ts +21 -0
  324. package/src/primitives/overlay/strategies/live-announcer/assertive.ts +11 -0
  325. package/src/primitives/overlay/strategies/live-announcer/polite.spec.ts +21 -0
  326. package/src/primitives/overlay/strategies/live-announcer/polite.ts +11 -0
  327. package/src/primitives/overlay/strategies/live-announcer/silent.spec.ts +12 -0
  328. package/src/primitives/overlay/strategies/live-announcer/silent.ts +5 -0
  329. package/src/primitives/overlay/strategies/mount/body-portal.spec.ts +40 -0
  330. package/src/primitives/overlay/strategies/mount/body-portal.ts +91 -0
  331. package/src/primitives/overlay/strategies/mount/in-container.spec.ts +43 -0
  332. package/src/primitives/overlay/strategies/mount/in-container.ts +39 -0
  333. package/src/primitives/overlay/strategies/mount/in-place.spec.ts +40 -0
  334. package/src/primitives/overlay/strategies/mount/in-place.ts +20 -0
  335. package/src/primitives/overlay/strategies/position/anchored-to.spec.ts +56 -0
  336. package/src/primitives/overlay/strategies/position/anchored-to.ts +248 -0
  337. package/src/primitives/overlay/strategies/position/corner.spec.ts +36 -0
  338. package/src/primitives/overlay/strategies/position/corner.ts +33 -0
  339. package/src/primitives/overlay/strategies/position/edge-sheet.spec.ts +32 -0
  340. package/src/primitives/overlay/strategies/position/edge-sheet.ts +36 -0
  341. package/src/primitives/overlay/strategies/position/in-place-sibling.spec.ts +25 -0
  342. package/src/primitives/overlay/strategies/position/in-place-sibling.ts +13 -0
  343. package/src/primitives/overlay/strategies/position/point-at.spec.ts +40 -0
  344. package/src/primitives/overlay/strategies/position/point-at.ts +34 -0
  345. package/src/primitives/overlay/strategies/position/viewport-centered.spec.ts +31 -0
  346. package/src/primitives/overlay/strategies/position/viewport-centered.ts +31 -0
  347. package/src/primitives/overlay/strategies/scroll-lock/css-clip.spec.ts +15 -0
  348. package/src/primitives/overlay/strategies/scroll-lock/css-clip.ts +39 -0
  349. package/src/primitives/overlay/strategies/scroll-lock/html-overflow.spec.ts +21 -0
  350. package/src/primitives/overlay/strategies/scroll-lock/html-overflow.ts +44 -0
  351. package/src/primitives/overlay/strategies/scroll-lock/none.spec.ts +9 -0
  352. package/src/primitives/overlay/strategies/scroll-lock/none.ts +5 -0
  353. package/src/primitives/overlay/strategies/trigger-event/on-click.spec.ts +32 -0
  354. package/src/primitives/overlay/strategies/trigger-event/on-click.ts +28 -0
  355. package/src/primitives/overlay/strategies/trigger-event/on-context-menu.spec.ts +45 -0
  356. package/src/primitives/overlay/strategies/trigger-event/on-context-menu.ts +70 -0
  357. package/src/primitives/overlay/strategies/trigger-event/on-focus-or-input.spec.ts +35 -0
  358. package/src/primitives/overlay/strategies/trigger-event/on-focus-or-input.ts +34 -0
  359. package/src/primitives/overlay/strategies/trigger-event/on-focus.spec.ts +64 -0
  360. package/src/primitives/overlay/strategies/trigger-event/on-focus.ts +37 -0
  361. package/src/primitives/overlay/strategies/trigger-event/on-hotkey.spec.ts +37 -0
  362. package/src/primitives/overlay/strategies/trigger-event/on-hotkey.ts +59 -0
  363. package/src/primitives/overlay/strategies/trigger-event/on-hover.spec.ts +34 -0
  364. package/src/primitives/overlay/strategies/trigger-event/on-hover.ts +86 -0
  365. package/src/primitives/overlay/strategies/trigger-event/programmatic.spec.ts +16 -0
  366. package/src/primitives/overlay/strategies/trigger-event/programmatic.ts +12 -0
  367. package/src/primitives/overlay/tokens.ts +54 -0
  368. package/src/primitives/overlay/trigger.spec.ts +103 -0
  369. package/src/primitives/overlay/trigger.ts +75 -0
  370. package/src/primitives/overlay/types.ts +24 -0
  371. package/src/primitives/overlay/wrapper.ts +50 -0
  372. package/src/primitives/signals/deep-signal.ts +109 -0
  373. package/src/primitives/signals/index.ts +1 -0
  374. package/src/progress-bar/config.ts +48 -0
  375. package/src/progress-bar/index.ts +12 -0
  376. package/src/progress-bar/progress-bar-fill.ts +37 -0
  377. package/src/progress-bar/progress-bar.context.ts +34 -0
  378. package/src/progress-bar/progress-bar.spec.ts +423 -0
  379. package/src/progress-bar/progress-bar.ts +217 -0
  380. package/src/public-api.ts +58 -9
  381. package/src/radio/radio.ts +14 -3
  382. package/src/select/index.ts +4 -2
  383. package/src/select/select-content.ts +69 -0
  384. package/src/select/select-option.ts +35 -0
  385. package/src/select/select-root.ts +129 -0
  386. package/src/select/select-trigger.ts +93 -0
  387. package/src/select/select.spec.ts +133 -140
  388. package/src/select/select.ts +4 -250
  389. package/src/skeleton/index.ts +5 -0
  390. package/src/skeleton/skeleton.spec.ts +115 -0
  391. package/src/skeleton/skeleton.ts +56 -0
  392. package/src/slider/index.ts +10 -0
  393. package/src/slider/slider-range.ts +49 -0
  394. package/src/slider/slider-thumb.ts +335 -0
  395. package/src/slider/slider-track.ts +70 -0
  396. package/src/slider/slider.context.ts +79 -0
  397. package/src/slider/slider.geometry.ts +73 -0
  398. package/src/slider/slider.spec.ts +216 -0
  399. package/src/slider/slider.ts +443 -0
  400. package/src/speed-dial/index.ts +10 -0
  401. package/src/speed-dial/speed-dial-action.ts +40 -0
  402. package/src/speed-dial/speed-dial-actions.ts +31 -0
  403. package/src/speed-dial/speed-dial-trigger.ts +55 -0
  404. package/src/speed-dial/speed-dial.context.ts +36 -0
  405. package/src/speed-dial/speed-dial.spec.ts +143 -0
  406. package/src/speed-dial/speed-dial.ts +127 -0
  407. package/src/spinner/config.ts +48 -0
  408. package/src/spinner/index.ts +8 -0
  409. package/src/spinner/spinner.spec.ts +262 -0
  410. package/src/spinner/spinner.ts +129 -0
  411. package/src/stepper/index.ts +15 -0
  412. package/src/stepper/stepper.context.ts +63 -0
  413. package/src/stepper/stepper.spec.ts +403 -0
  414. package/src/stepper/stepper.ts +544 -0
  415. package/src/styles.css +17 -0
  416. package/src/table/column-helpers.spec.ts +74 -0
  417. package/src/table/column-helpers.ts +68 -0
  418. package/src/table/filter-fns.ts +230 -0
  419. package/src/table/filter-models.spec.ts +240 -0
  420. package/src/table/filter-models.ts +124 -0
  421. package/src/table/filter-params.ts +90 -0
  422. package/src/table/grid-api-impl.ts +321 -0
  423. package/src/table/grid-api.spec.ts +178 -0
  424. package/src/table/grid-api.ts +285 -0
  425. package/src/table/index.ts +73 -1
  426. package/src/table/table-cell.spec.ts +43 -0
  427. package/src/table/table-cell.ts +38 -0
  428. package/src/table/table-filter-outlet.ts +120 -0
  429. package/src/table/table-header.spec.ts +54 -0
  430. package/src/table/table-header.ts +63 -0
  431. package/src/table/table-keyboard.spec.ts +68 -0
  432. package/src/table/table-keyboard.ts +107 -0
  433. package/src/table/table-resource.spec.ts +37 -0
  434. package/src/table/table-resource.ts +36 -0
  435. package/src/table/table-row.spec.ts +54 -0
  436. package/src/table/table-row.ts +31 -0
  437. package/src/table/table-storage.spec.ts +67 -0
  438. package/src/table/table-storage.ts +76 -0
  439. package/src/table/table.spec.ts +102 -43
  440. package/src/table/table.ts +228 -73
  441. package/src/table/table.types.ts +83 -0
  442. package/src/tabs/index.ts +7 -2
  443. package/src/tabs/tabs.context.ts +27 -4
  444. package/src/tabs/tabs.spec.ts +336 -24
  445. package/src/tabs/tabs.ts +313 -79
  446. package/src/tag/config.ts +53 -0
  447. package/src/tag/index.ts +7 -0
  448. package/src/tag/tag-list.ts +76 -0
  449. package/src/tag/tag-remove.ts +61 -0
  450. package/src/tag/tag.context.ts +36 -0
  451. package/src/tag/tag.spec.ts +240 -0
  452. package/src/tag/tag.ts +203 -0
  453. package/src/textarea/config.ts +42 -0
  454. package/src/textarea/index.ts +8 -0
  455. package/src/textarea/textarea.spec.ts +176 -0
  456. package/src/textarea/textarea.ts +235 -0
  457. package/src/time-picker/index.ts +15 -0
  458. package/src/time-picker/time-picker-meridiem.ts +123 -0
  459. package/src/time-picker/time-picker-segment.ts +318 -0
  460. package/src/time-picker/time-picker.context.ts +38 -0
  461. package/src/time-picker/time-picker.format.ts +181 -0
  462. package/src/time-picker/time-picker.spec.ts +189 -0
  463. package/src/time-picker/time-picker.ts +274 -0
  464. package/src/toast/_examples/index.ts +5 -0
  465. package/src/toast/_examples/toast.example.ts +282 -0
  466. package/src/toast/_examples/toast.finance.example.ts +180 -0
  467. package/src/toast/_examples/toast.retro.example.ts +161 -0
  468. package/src/toast/index.ts +8 -1
  469. package/src/toast/toast.ref.ts +26 -0
  470. package/src/toast/toast.service.ts +227 -41
  471. package/src/toast/toast.spec.ts +178 -25
  472. package/src/toast/toast.strategy.ts +10 -0
  473. package/src/toast/toast.ts +178 -22
  474. package/src/toggle/toggle.ts +10 -2
  475. package/src/tooltip/_examples/index.ts +6 -0
  476. package/src/tooltip/_examples/tooltip.example.ts +82 -0
  477. package/src/tooltip/_examples/tooltip.finance.example.ts +97 -0
  478. package/src/tooltip/_examples/tooltip.placements.example.ts +83 -0
  479. package/src/tooltip/_examples/tooltip.retro.example.ts +107 -0
  480. package/src/tooltip/index.ts +4 -5
  481. package/src/tooltip/tooltip-arrow.ts +31 -0
  482. package/src/tooltip/tooltip-content.ts +38 -0
  483. package/src/tooltip/tooltip-group.ts +32 -0
  484. package/src/tooltip/tooltip-trigger.ts +47 -0
  485. package/src/tooltip/tooltip.spec.ts +38 -102
  486. package/src/tooltip/tooltip.ts +5 -129
  487. package/src/tree-select/index.ts +12 -0
  488. package/src/tree-select/tree-select-content.ts +199 -0
  489. package/src/tree-select/tree-select-node.ts +132 -0
  490. package/src/tree-select/tree-select-root.ts +272 -0
  491. package/src/tree-select/tree-select-trigger.ts +90 -0
  492. package/src/tree-select/tree-select.context.ts +63 -0
  493. package/src/tree-select/tree-select.spec.ts +433 -0
  494. package/src/tree-select/tree-select.ts +2 -0
  495. package/src/typography/blockquote.ts +57 -0
  496. package/src/typography/code.ts +53 -0
  497. package/src/typography/index.ts +22 -0
  498. package/src/typography/lead.ts +49 -0
  499. package/src/typography/muted.ts +29 -0
  500. package/src/typography/prose.css +312 -0
  501. package/src/typography/truncate.ts +99 -0
  502. package/src/typography/typography.spec.ts +203 -0
  503. package/tsconfig.lib.json +9 -1
  504. package/tsconfig.lib.prod.json +7 -1
  505. package/tsconfig.spec.json +9 -1
  506. package/vite.config.ts +8 -0
  507. package/src/button/button.example.ts +0 -30
  508. package/src/button/button.finance.example.ts +0 -37
  509. package/src/button/button.retro.example.ts +0 -47
  510. package/src/button/button.sizes.example.ts +0 -25
  511. package/src/dialog/dialog.confirm.example.ts +0 -57
  512. package/src/dialog/dialog.context.ts +0 -11
  513. package/src/dialog/dialog.example.ts +0 -40
  514. package/src/dialog/dialog.finance.example.ts +0 -47
  515. package/src/dialog/dialog.retro.example.ts +0 -46
  516. package/src/menu/index.ts +0 -2
  517. package/src/menu/menu.context.ts +0 -10
  518. package/src/menu/menu.example.ts +0 -39
  519. package/src/menu/menu.spec.ts +0 -168
  520. package/src/menu/menu.ts +0 -176
  521. package/src/popover/popover.context.ts +0 -18
  522. package/src/popover/popover.example.ts +0 -50
  523. package/src/popover/popover.finance.example.ts +0 -52
  524. package/src/popover/popover.retro.example.ts +0 -53
  525. package/src/primitives/overlay/overlay.spec.ts +0 -90
  526. package/src/primitives/overlay/overlay.ts +0 -102
  527. package/src/select/select.context.ts +0 -3
  528. package/src/toast/toast.example.ts +0 -134
  529. package/src/toast/toast.finance.example.ts +0 -68
  530. package/src/toast/toast.retro.example.ts +0 -69
  531. package/src/tooltip/tooltip.example.ts +0 -46
  532. package/src/tooltip/tooltip.finance.example.ts +0 -54
  533. package/src/tooltip/tooltip.placements.example.ts +0 -56
  534. package/src/tooltip/tooltip.retro.example.ts +0 -65
@@ -1,23 +1,56 @@
1
- import {
2
- ColumnDef,
3
- RowData,
4
- SortingState,
5
- createAngularTable,
6
- getCoreRowModel,
7
- getSortedRowModel,
1
+ import {
2
+ ColumnDef, RowData,
3
+ createAngularTable, getCoreRowModel, getSortedRowModel, getFilteredRowModel,
4
+ getPaginationRowModel, getExpandedRowModel, getGroupedRowModel,
5
+ type ColumnSizingInfoState,
8
6
  type Table,
9
7
  } from '@tanstack/angular-table';
10
- import { Directive, InjectionToken, computed, input, signal } from '@angular/core';
8
+ import { Directive, InjectionToken, computed, input, model, signal } from '@angular/core';
9
+ import { toDeepSignal, type DeepSignal } from '../primitives/signals/deep-signal';
10
+ import { createGridApi } from './grid-api-impl';
11
+ import type { KjColumnApi, KjGridApi } from './grid-api';
12
+ import type { KjTableState } from './table.types';
11
13
 
12
14
  /** Injection token providing the TanStack table instance to child directives. */
13
15
  export const KJ_TABLE = new InjectionToken<KjTable<unknown>>('KjTable');
14
16
 
17
+ const DEFAULT_STATE: KjTableState = {
18
+ sorting: [],
19
+ columnFilters: [],
20
+ globalFilter: '',
21
+ pagination: { pageIndex: 0, pageSize: 25 },
22
+ rowSelection: {},
23
+ columnSizing: {},
24
+ columnVisibility: {},
25
+ columnOrder: [],
26
+ columnPinning: { left: [], right: [] },
27
+ expanded: {},
28
+ grouping: [],
29
+ density: 'standard',
30
+ };
31
+
32
+ const DEFAULT_RESIZE_INFO: ColumnSizingInfoState = {
33
+ startOffset: null,
34
+ startSize: null,
35
+ deltaOffset: null,
36
+ deltaPercentage: null,
37
+ isResizingColumn: false,
38
+ columnSizingStart: [],
39
+ };
40
+
15
41
  /**
16
42
  * Wraps TanStack Angular Table. Accepts `kjTable` (columns) and `kjTableData` signal inputs and
17
43
  * exposes the table instance (rows, headers, sorting) via the `KJ_TABLE` context token.
18
44
  *
19
45
  * Use `table` to access the full TanStack `Table<T>` instance in templates via `exportAs: 'kjTable'`.
20
46
  *
47
+ * State is exposed as a single `DeepSignal<KjTableState>`:
48
+ *
49
+ * - `state()` — full snapshot (also used by `kjTableResource`).
50
+ * - `state.sorting()`, `state.pagination()`, … — per-slice readonly signals,
51
+ * lazily memoised by the deep-signal proxy. Reading one only re-runs your
52
+ * consumer when that specific slice changes.
53
+ *
21
54
  * @example
22
55
  * ```html
23
56
  * <table [kjTable]="columns" [kjTableData]="rows" #tbl="kjTable">
@@ -34,7 +67,6 @@ export const KJ_TABLE = new InjectionToken<KjTable<unknown>>('KjTable');
34
67
  * </thead>
35
68
  * </table>
36
69
  * ```
37
- * @category Core/Data
38
70
  */
39
71
  @Directive({
40
72
  selector: '[kjTable]',
@@ -46,81 +78,204 @@ export class KjTable<TData extends RowData = unknown> {
46
78
  /** Column definitions for the table. */
47
79
  kjTable = input.required<ColumnDef<TData>[]>();
48
80
 
49
- /** Data rows for the table. */
50
- kjTableData = input<TData[]>([]);
81
+ /**
82
+ * Data rows for the table. A `model()` so the styled wrapper can write
83
+ * resource-resolved rows back into the directive when the user uses
84
+ * `[kjResource]` instead of `[kjData]`. The model defaults to `[]`, and
85
+ * a one-way external binding (`[kjTableData]="rows"`) keeps working.
86
+ */
87
+ kjTableData = model<TData[]>([]);
88
+
89
+ /**
90
+ * Optional accessor that returns a stable id for each row. When set, TanStack
91
+ * keys row state (selection, expansion, pinning) by this id rather than by
92
+ * row index. Mirrors TanStack's `getRowId` option.
93
+ */
94
+ kjGetRowId = input<((row: TData, index: number) => string) | undefined>(undefined);
95
+
96
+ private readonly _state = signal<KjTableState>(DEFAULT_STATE);
97
+
98
+ /**
99
+ * The full table state as a single deep signal. Call `state()` for the
100
+ * whole snapshot, or read any slice (`state.sorting()`, `state.pagination()`,
101
+ * `state.density()`…) as an individual `Signal<T>` — child signals are
102
+ * lazily memoised so each only invalidates on its own slice's change.
103
+ */
104
+ readonly state: DeepSignal<KjTableState> = toDeepSignal(this._state.asReadonly());
51
105
 
52
- private readonly _sorting = signal<SortingState>([]);
106
+ /**
107
+ * Transient column-resize tracker. Updated continuously by TanStack while
108
+ * the user drags a resize handle and read by the styled wrapper to render
109
+ * a preview guide line. Excluded from `state` so it never gets persisted
110
+ * or echoed through `(stateChange)`.
111
+ */
112
+ private readonly _columnSizingInfo = signal<ColumnSizingInfoState>(DEFAULT_RESIZE_INFO);
113
+ readonly columnSizingInfo = this._columnSizingInfo.asReadonly();
114
+
115
+ /**
116
+ * Manual-pagination + total-row-count wiring for server-driven tables.
117
+ * When `rowCount` is set to a non-null value, the wrapper assumes the
118
+ * loader pages rows externally — TanStack stops paginating client-side
119
+ * and the pagination / status-bar slots derive their totals from the
120
+ * remote count. Set both via `setRowCount(total)` and read them through
121
+ * the public `rowCount` / `manualPagination` signals if you need them.
122
+ */
123
+ private readonly _rowCount = signal<number | null>(null);
124
+ readonly rowCount = this._rowCount.asReadonly();
125
+ readonly manualPagination = computed(() => this._rowCount() !== null);
126
+ setRowCount(n: number | null): void {
127
+ this._rowCount.set(n);
128
+ }
129
+
130
+ /**
131
+ * Apply a TanStack updater (value or function) to a single state slice.
132
+ *
133
+ * Dedupes content-equal updates: TanStack often calls `on*Change` with a
134
+ * fresh object literal that has identical fields (e.g. pagination emits
135
+ * `{pageIndex:0, pageSize:25}` on data ingestion). Without dedupe, the
136
+ * state signal invalidates on every such call, which cascades into
137
+ * `(stateChange)` consumers that drive `kjTableResource` — creating an
138
+ * infinite loader loop where the spinner never goes away.
139
+ */
140
+ private patch<K extends keyof KjTableState>(
141
+ key: K,
142
+ updater: KjTableState[K] | ((prev: KjTableState[K]) => KjTableState[K]),
143
+ ): void {
144
+ this._state.update(s => {
145
+ const next = typeof updater === 'function'
146
+ ? (updater as (p: KjTableState[K]) => KjTableState[K])(s[key])
147
+ : updater;
148
+ if (sliceEqual(s[key], next)) return s;
149
+ return { ...s, [key]: next };
150
+ });
151
+ }
53
152
 
54
153
  /** The TanStack table instance. Access rows, headers, and state here. */
55
154
  readonly table: () => Table<TData> = createAngularTable<TData>(() => ({
56
155
  data: this.kjTableData(),
57
156
  columns: this.kjTable(),
58
- state: { sorting: this._sorting() },
59
- onSortingChange: (updater) => {
60
- const next = typeof updater === 'function' ? updater(this._sorting()) : updater;
61
- this._sorting.set(next);
62
- },
63
- getCoreRowModel: getCoreRowModel(),
64
- getSortedRowModel: getSortedRowModel(),
157
+ getRowId: this.kjGetRowId()
158
+ ? (row, index) => this.kjGetRowId()!(row, index)
159
+ : undefined,
160
+ // `columnResizeMode: 'onEnd'` defers the actual column width write until
161
+ // the user releases the resize handle. While dragging, the wrapper reads
162
+ // `state.columnSizingInfo().deltaOffset` to render a vertical preview
163
+ // guide so the user sees where the new edge will land before reflow.
164
+ columnResizeMode: 'onEnd',
165
+ // Server-mode wiring: when a total `rowCount` is registered, switch
166
+ // TanStack to manual pagination so the loader-page becomes the
167
+ // visible page (no client-side slicing) and pagination controls
168
+ // derive their totals from the remote count.
169
+ manualPagination: this._rowCount() !== null,
170
+ rowCount: this._rowCount() ?? undefined,
171
+ state: { ...this._state(), columnSizingInfo: this._columnSizingInfo() },
172
+ onSortingChange: u => this.patch('sorting', u),
173
+ onColumnFiltersChange: u => this.patch('columnFilters', u),
174
+ onGlobalFilterChange: u => this.patch('globalFilter', u),
175
+ onPaginationChange: u => this.patch('pagination', u),
176
+ onRowSelectionChange: u => this.patch('rowSelection', u),
177
+ onColumnSizingChange: u => this.patch('columnSizing', u),
178
+ onColumnSizingInfoChange: u => this._columnSizingInfo.update(p => typeof u === 'function' ? (u as (prev: ColumnSizingInfoState) => ColumnSizingInfoState)(p) : u),
179
+ onColumnVisibilityChange: u => this.patch('columnVisibility', u),
180
+ onColumnOrderChange: u => this.patch('columnOrder', u),
181
+ onColumnPinningChange: u => this.patch('columnPinning', u),
182
+ onExpandedChange: u => this.patch('expanded', u),
183
+ onGroupingChange: u => this.patch('grouping', u),
184
+ getCoreRowModel: getCoreRowModel(),
185
+ getSortedRowModel: getSortedRowModel(),
186
+ getFilteredRowModel: getFilteredRowModel(),
187
+ getPaginationRowModel: getPaginationRowModel(),
188
+ getExpandedRowModel: getExpandedRowModel(),
189
+ getGroupedRowModel: getGroupedRowModel(),
190
+ // Selection is enabled by default in TanStack, but be explicit so a
191
+ // future opts-passthrough doesn't accidentally turn it off and break
192
+ // the styled wrapper's row-click toggle.
193
+ enableRowSelection: true,
194
+ enableMultiRowSelection: true,
65
195
  }));
66
196
 
67
- /** Current sorting state as a signal. */
68
- readonly sorting = this._sorting.asReadonly();
69
- }
197
+ /** Merge a partial state. Unspecified slices are left untouched. */
198
+ setState(partial: Partial<KjTableState>): void {
199
+ this._state.update(s => ({ ...s, ...partial }));
200
+ }
201
+
202
+ /** Reset every slice back to the directive's default state. */
203
+ resetState(): void { this._state.set(DEFAULT_STATE); }
70
204
 
71
- /** Sort direction for table columns. */
72
- export type KjSortDirection = 'asc' | 'desc';
205
+ // ── Public API surface (AG-Grid-style) ─────────────────────────────────
206
+ // Built lazily on first read so the TanStack table getter and the state
207
+ // signal are already wired when callers touch the api.
208
+
209
+ private _api?: { gridApi: KjGridApi<TData>; columnApi: KjColumnApi<TData> };
210
+ private buildApi(): { gridApi: KjGridApi<TData>; columnApi: KjColumnApi<TData> } {
211
+ return this._api ??= createGridApi<TData>({
212
+ state: this._state.asReadonly(),
213
+ table: this.table,
214
+ patch: (key, updater) => this.patch(key, updater),
215
+ setStateInternal: this._state.update.bind(this._state),
216
+ resetState: () => this.resetState(),
217
+ defaultState: DEFAULT_STATE,
218
+ });
219
+ }
220
+
221
+ /**
222
+ * Grid-wide imperative API — selection, sorting, filtering, pagination,
223
+ * expansion, grouping, density, bulk state. Stable across grid lifetime.
224
+ * Passed to custom filter/editor components via their params object so
225
+ * user code never has to reach into TanStack or the directive directly.
226
+ */
227
+ get gridApi(): KjGridApi<TData> { return this.buildApi().gridApi; }
228
+
229
+ /**
230
+ * Per-column imperative API — visibility, width, pinning, order, grouping.
231
+ * Mirrors AG-Grid's `ColumnApi`. Passed alongside `gridApi` to custom
232
+ * filter/editor components.
233
+ */
234
+ get columnApi(): KjColumnApi<TData> { return this.buildApi().columnApi; }
235
+ }
73
236
 
74
237
  /**
75
- * Marks a `<th>` as a sortable column header. Sets `aria-sort` based on TanStack sort state.
76
- * Clicking toggles sort direction only when the column has sorting enabled.
77
- * If `enableSorting: false` is set on the column def, the header renders as plain text.
78
- *
79
- * @example
80
- * ```html
81
- * <th kjTableHeader [kjHeader]="header" scope="col">Name</th>
82
- * ```
83
- * @category Core/Data
238
+ * Shallow-equality check tuned for `KjTableState` slices plain objects,
239
+ * primitive arrays, and primitives. Returns `true` when `a` and `b` are
240
+ * structurally identical at one level (object keys + values compared with
241
+ * `Object.is`; arrays element-wise the same way). Falls back to `Object.is`
242
+ * for non-object types. Cheap enough to run on every `patch()`.
84
243
  */
85
- @Directive({
86
- selector: '[kjTableHeader]',
87
- standalone: true,
88
- host: {
89
- '[style.cursor]': 'canSort() ? "pointer" : null',
90
- '[attr.tabindex]': 'canSort() ? "0" : null',
91
- '[attr.aria-sort]': 'canSort() ? ariaSort() : null',
92
- '[attr.data-sort]': 'canSort() ? sortDir() : null',
93
- '(click)': 'onHeaderClick()',
94
- '(keydown.enter)': 'onHeaderClick()',
95
- '(keydown.space)': '$event.preventDefault(); onHeaderClick()',
96
- },
97
- })
98
- export class KjTableHeader<TData extends RowData = unknown> {
99
- /** The TanStack header object for this column. Pass from the table's getHeaderGroups(). */
100
- kjHeader = input<ReturnType<Table<TData>['getHeaderGroups']>[0]['headers'][0] | undefined>(undefined);
101
-
102
- /** Whether this column supports sorting, derived from TanStack column state. */
103
- readonly canSort = computed(() => this.kjHeader()?.column.getCanSort() ?? false);
104
-
105
- /** Current sort direction, or null when unsorted. */
106
- readonly sortDir = computed((): KjSortDirection | null => {
107
- const h = this.kjHeader();
108
- if (!h) return null;
109
- const sorted = h.column.getIsSorted();
110
- if (sorted === 'asc') return 'asc';
111
- if (sorted === 'desc') return 'desc';
112
- return null;
113
- });
114
-
115
- /** ARIA sort attribute value derived from sort direction. */
116
- readonly ariaSort = computed(() => {
117
- const d = this.sortDir();
118
- if (d === 'asc') return 'ascending';
119
- if (d === 'desc') return 'descending';
120
- return 'none';
121
- });
122
-
123
- onHeaderClick(): void {
124
- if (this.canSort()) this.kjHeader()?.column.toggleSorting();
244
+ function sliceEqual(a: unknown, b: unknown): boolean {
245
+ if (Object.is(a, b)) return true;
246
+ if (a == null || b == null) return false;
247
+ if (typeof a !== 'object' || typeof b !== 'object') return false;
248
+ if (Array.isArray(a)) {
249
+ if (!Array.isArray(b) || a.length !== b.length) return false;
250
+ for (let i = 0; i < a.length; i++) {
251
+ const av = a[i];
252
+ const bv = b[i];
253
+ if (Object.is(av, bv)) continue;
254
+ // Sorting / column-filter entries are plain objects — one-level deep.
255
+ if (av && bv && typeof av === 'object' && typeof bv === 'object') {
256
+ if (!sliceEqual(av, bv)) return false;
257
+ } else {
258
+ return false;
259
+ }
260
+ }
261
+ return true;
262
+ }
263
+ if (Array.isArray(b)) return false;
264
+ const ao = a as Record<string, unknown>;
265
+ const bo = b as Record<string, unknown>;
266
+ const ak = Object.keys(ao);
267
+ const bk = Object.keys(bo);
268
+ if (ak.length !== bk.length) return false;
269
+ for (const k of ak) {
270
+ const av = ao[k];
271
+ const bv = bo[k];
272
+ if (Object.is(av, bv)) continue;
273
+ // columnPinning has `{ left: string[], right: string[] }` — recurse one level.
274
+ if (Array.isArray(av) || (av && typeof av === 'object')) {
275
+ if (!sliceEqual(av, bv)) return false;
276
+ } else {
277
+ return false;
278
+ }
125
279
  }
280
+ return true;
126
281
  }
@@ -0,0 +1,83 @@
1
+ import type { ColumnDef, RowData, Table, SortingState, ColumnFiltersState, PaginationState, RowSelectionState, ColumnSizingState, VisibilityState, ColumnOrderState, ColumnPinningState, ExpandedState, GroupingState } from '@tanstack/angular-table';
2
+ import type { TemplateRef, Type } from '@angular/core';
3
+
4
+ /** Built-in column types. Drives filter widget, editor widget, formatter, alignment. */
5
+ export type KjColumnType = 'text' | 'number' | 'date' | 'boolean' | 'select';
6
+
7
+ /** Pin slot for a column. */
8
+ export type KjColumnPin = 'left' | 'right' | null;
9
+
10
+ /** Built-in aggregation kinds; pass a function for custom. */
11
+ export type KjAggregationKind = 'sum' | 'avg' | 'min' | 'max' | 'count';
12
+ export type KjAggregationFn<T> = (rows: readonly T[]) => unknown;
13
+ export type KjAggregation<T> = KjAggregationKind | KjAggregationFn<T>;
14
+
15
+ /** Editor / filter UI override: a component class OR a template ref. */
16
+ export type KjEditorRef<TData = unknown, TValue = unknown> =
17
+ | Type<unknown>
18
+ | TemplateRef<{ row: TData; value: TValue; commit: (v: TValue) => void; cancel: () => void }>;
19
+
20
+ export type KjFilterUiRef<TData = unknown> =
21
+ | Type<unknown>
22
+ | TemplateRef<{ column: unknown; table: Table<TData> }>;
23
+
24
+ /** kj-specific meta stored on TanStack ColumnDef.meta.kj. */
25
+ export interface KjColumnMeta<TData extends RowData = RowData> {
26
+ type?: KjColumnType;
27
+ editable?: boolean;
28
+ filterable?: boolean;
29
+ pin?: KjColumnPin;
30
+ group?: boolean;
31
+ agg?: KjAggregation<TData>;
32
+ editor?: KjEditorRef<TData>;
33
+ filterUi?: KjFilterUiRef<TData>;
34
+ selectOptions?: ReadonlyArray<string | { value: unknown; label: string }>;
35
+ exportable?: boolean;
36
+ persist?: boolean;
37
+ }
38
+
39
+ /** kj column definition — TanStack ColumnDef extended with kj* top-level knobs. */
40
+ export type KjColumnDef<TData extends RowData = RowData> =
41
+ ColumnDef<TData> & {
42
+ kjType?: KjColumnType;
43
+ kjEditable?: boolean;
44
+ kjFilterable?: boolean;
45
+ kjPin?: KjColumnPin;
46
+ kjGroup?: boolean;
47
+ kjAgg?: KjAggregation<TData>;
48
+ kjEditor?: KjEditorRef<TData>;
49
+ kjFilterUi?: KjFilterUiRef<TData>;
50
+ kjSelectOptions?: ReadonlyArray<string | { value: unknown; label: string }>;
51
+ kjExportable?: boolean;
52
+ kjPersist?: boolean;
53
+ };
54
+
55
+ /** Density preset applied to the styled wrapper. */
56
+ export type KjTableDensity = 'compact' | 'standard' | 'comfortable';
57
+
58
+ /**
59
+ * Persistent table state — exposed as a single `DeepSignal<KjTableState>` and
60
+ * emitted via `(stateChange)`. Transient drag state (`columnSizingInfo`) is
61
+ * tracked separately on the directive and intentionally excluded here so it
62
+ * never round-trips through storage adapters or change-detection emissions.
63
+ */
64
+ export interface KjTableState {
65
+ readonly sorting: SortingState;
66
+ readonly columnFilters: ColumnFiltersState;
67
+ readonly globalFilter: string;
68
+ readonly pagination: PaginationState;
69
+ readonly rowSelection: RowSelectionState;
70
+ readonly columnSizing: ColumnSizingState;
71
+ readonly columnVisibility: VisibilityState;
72
+ readonly columnOrder: ColumnOrderState;
73
+ readonly columnPinning: ColumnPinningState;
74
+ readonly expanded: ExpandedState;
75
+ readonly grouping: GroupingState;
76
+ readonly density: KjTableDensity;
77
+ }
78
+
79
+ /** Loader return value for kjTableResource. Matches TanStack manualPagination + rowCount. */
80
+ export interface KjResourceResult<TData> {
81
+ readonly rows: readonly TData[];
82
+ readonly rowCount: number;
83
+ }
package/src/tabs/index.ts CHANGED
@@ -1,2 +1,7 @@
1
- export { KjTabs, KjTabList, KjTab, KjTabPanel } from './tabs';
2
- export { KJ_TABS, type KjTabsContext } from './tabs.context';
1
+ export { KjTabs, KjTabList, KjTab, KjTabPanel } from './tabs';
2
+ export {
3
+ KJ_TABS,
4
+ type KjTabsContext,
5
+ type KjTabsActivationMode,
6
+ type KjTabsOrientation,
7
+ } from './tabs.context';
@@ -1,9 +1,32 @@
1
- import { InjectionToken, Signal } from '@angular/core';
1
+ import { InjectionToken, Signal } from '@angular/core';
2
2
 
3
- /** Shared context passed from KjTabs to child tab/panel directives. */
3
+ /** Activation modes per WAI-ARIA APG Tabs pattern. */
4
+ export type KjTabsActivationMode = 'automatic' | 'manual';
5
+
6
+ /** Tabs orientation. Drives `aria-orientation` and the roving arrow-axis. */
7
+ export type KjTabsOrientation = 'horizontal' | 'vertical';
8
+
9
+ /**
10
+ * Context exposed by `KjTabs` to its child directives (`KjTabList`, `KjTab`,
11
+ * `KjTabPanel`). Holds the active value, orientation, activation mode, and
12
+ * id helpers for ARIA wiring.
13
+ */
4
14
  export interface KjTabsContext {
5
- value: Signal<string>;
6
- activate: (value: string) => void;
15
+ /** Currently active tab value. */
16
+ readonly value: Signal<string>;
17
+ /** Tabs orientation; drives `aria-orientation` and arrow-key axis. */
18
+ readonly orientation: Signal<KjTabsOrientation>;
19
+ /** Activation mode; `'automatic'` activates on focus, `'manual'` requires Enter/Space. */
20
+ readonly activationMode: Signal<KjTabsActivationMode>;
21
+ /** Unique id for the tab element associated with `value`. */
22
+ tabId(value: string): string;
23
+ /** Unique id for the panel element associated with `value`. */
24
+ panelId(value: string): string;
25
+ /** Whether the tab/panel pair for `value` is currently active. */
26
+ isActive(value: string): boolean;
27
+ /** Activates the tab/panel pair for `value`. No-op when the tab is disabled. */
28
+ select(value: string): void;
7
29
  }
8
30
 
31
+ /** Injection token for the root `KjTabs` directive context. */
9
32
  export const KJ_TABS = new InjectionToken<KjTabsContext>('KjTabs');