@kouji-ui/components 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 (730) hide show
  1. package/.turbo/turbo-build.log +29 -0
  2. package/CHANGELOG.md +192 -0
  3. package/ng-package.json +7 -0
  4. package/package.json +43 -0
  5. package/src/accordion/_examples/accordion.default.example.ts +31 -0
  6. package/src/accordion/_examples/accordion.disabled.example.ts +38 -0
  7. package/src/accordion/_examples/accordion.multiple.example.ts +31 -0
  8. package/src/accordion/_examples/accordion.rich-content.example.ts +49 -0
  9. package/src/accordion/_examples/index.ts +6 -0
  10. package/src/accordion/accordion.arrow-nav.example.ts +39 -0
  11. package/src/accordion/accordion.css +68 -0
  12. package/src/accordion/accordion.playground.ts +119 -0
  13. package/src/accordion/accordion.spec.ts +117 -0
  14. package/src/accordion/accordion.ts +153 -0
  15. package/src/accordion/accordion.usage.example.ts +38 -0
  16. package/src/accordion/accordion.value.example.ts +60 -0
  17. package/src/accordion/index.ts +1 -0
  18. package/src/alert/_examples/alert.banner.example.ts +56 -0
  19. package/src/alert/_examples/alert.dismissible.example.ts +53 -0
  20. package/src/alert/_examples/alert.example.ts +40 -0
  21. package/src/alert/_examples/alert.variants.example.ts +66 -0
  22. package/src/alert/_examples/alert.with-actions.example.ts +57 -0
  23. package/src/alert/_examples/index.ts +7 -0
  24. package/src/alert/alert.css +133 -0
  25. package/src/alert/alert.playground.ts +111 -0
  26. package/src/alert/alert.spec.ts +167 -0
  27. package/src/alert/alert.ts +250 -0
  28. package/src/alert/alert.usage.example.ts +58 -0
  29. package/src/alert/index.ts +8 -0
  30. package/src/avatar/_examples/avatar-group.example.ts +31 -0
  31. package/src/avatar/_examples/avatar-group.list.example.ts +45 -0
  32. package/src/avatar/_examples/avatar-group.overflow.example.ts +33 -0
  33. package/src/avatar/_examples/avatar-group.shapes.example.ts +39 -0
  34. package/src/avatar/_examples/avatar-group.sizes.example.ts +44 -0
  35. package/src/avatar/_examples/avatar.default.example.ts +18 -0
  36. package/src/avatar/_examples/avatar.initials.example.ts +20 -0
  37. package/src/avatar/_examples/avatar.shapes.example.ts +22 -0
  38. package/src/avatar/_examples/avatar.sizes.example.ts +26 -0
  39. package/src/avatar/_examples/avatar.with-image.example.ts +20 -0
  40. package/src/avatar/_examples/index.ts +12 -0
  41. package/src/avatar/avatar-group.spec.ts +138 -0
  42. package/src/avatar/avatar-group.ts +127 -0
  43. package/src/avatar/avatar-group.usage.example.ts +30 -0
  44. package/src/avatar/avatar.css +58 -0
  45. package/src/avatar/avatar.playground.ts +95 -0
  46. package/src/avatar/avatar.ts +123 -0
  47. package/src/avatar/index.ts +2 -0
  48. package/src/badge/_examples/badge.default.example.ts +18 -0
  49. package/src/badge/_examples/badge.sizes.example.ts +25 -0
  50. package/src/badge/_examples/badge.variants.example.ts +24 -0
  51. package/src/badge/_examples/badge.with-dot.example.ts +31 -0
  52. package/src/badge/_examples/badge.with-icon.example.ts +23 -0
  53. package/src/badge/_examples/index.ts +7 -0
  54. package/src/badge/badge.css +59 -0
  55. package/src/badge/badge.playground.ts +49 -0
  56. package/src/badge/badge.ts +86 -0
  57. package/src/badge/badge.usage.example.ts +22 -0
  58. package/src/badge/index.ts +1 -0
  59. package/src/breadcrumb/_examples/breadcrumb.custom-separator.example.ts +53 -0
  60. package/src/breadcrumb/_examples/breadcrumb.example.ts +48 -0
  61. package/src/breadcrumb/_examples/breadcrumb.long-path.example.ts +58 -0
  62. package/src/breadcrumb/_examples/breadcrumb.truncated.example.ts +59 -0
  63. package/src/breadcrumb/_examples/breadcrumb.with-icons.example.ts +66 -0
  64. package/src/breadcrumb/_examples/index.ts +7 -0
  65. package/src/breadcrumb/breadcrumb.css +121 -0
  66. package/src/breadcrumb/breadcrumb.playground.ts +93 -0
  67. package/src/breadcrumb/breadcrumb.spec.ts +230 -0
  68. package/src/breadcrumb/breadcrumb.ts +272 -0
  69. package/src/breadcrumb/breadcrumb.usage.example.ts +45 -0
  70. package/src/breadcrumb/index.ts +1 -0
  71. package/src/button/_examples/button.anchor.example.ts +18 -0
  72. package/src/button/_examples/button.configured.example.ts +43 -0
  73. package/src/button/_examples/button.disabled.example.ts +25 -0
  74. package/src/button/_examples/button.example.ts +22 -0
  75. package/src/button/_examples/button.icon.example.ts +27 -0
  76. package/src/button/_examples/button.loading.example.ts +31 -0
  77. package/src/button/_examples/button.pressed.example.ts +24 -0
  78. package/src/button/_examples/button.sizes.example.ts +26 -0
  79. package/src/button/_examples/button.usage.example.ts +66 -0
  80. package/src/button/_examples/button.variants.example.ts +26 -0
  81. package/src/button/_examples/index.ts +12 -0
  82. package/src/button/button.css +263 -0
  83. package/src/button/button.playground.ts +79 -0
  84. package/src/button/button.spec.ts +100 -0
  85. package/src/button/button.ts +150 -0
  86. package/src/button/index.ts +1 -0
  87. package/src/button-group/_examples/button-group.example.ts +30 -0
  88. package/src/button-group/_examples/button-group.icon-only.example.ts +30 -0
  89. package/src/button-group/_examples/button-group.toggle.example.ts +36 -0
  90. package/src/button-group/_examples/button-group.variants.example.ts +40 -0
  91. package/src/button-group/_examples/button-group.vertical.example.ts +29 -0
  92. package/src/button-group/_examples/index.ts +7 -0
  93. package/src/button-group/button-group.css +80 -0
  94. package/src/button-group/button-group.playground.ts +94 -0
  95. package/src/button-group/button-group.spec.ts +119 -0
  96. package/src/button-group/button-group.ts +130 -0
  97. package/src/button-group/button-group.usage.example.ts +35 -0
  98. package/src/button-group/index.ts +1 -0
  99. package/src/calendar/_examples/calendar.example.ts +33 -0
  100. package/src/calendar/_examples/index.ts +3 -0
  101. package/src/calendar/calendar.css +129 -0
  102. package/src/calendar/calendar.playground.ts +84 -0
  103. package/src/calendar/calendar.spec.ts +50 -0
  104. package/src/calendar/calendar.ts +171 -0
  105. package/src/calendar/calendar.usage.example.ts +33 -0
  106. package/src/calendar/index.ts +1 -0
  107. package/src/card/_examples/card.cover.example.ts +53 -0
  108. package/src/card/_examples/card.example.ts +27 -0
  109. package/src/card/_examples/card.full.example.ts +51 -0
  110. package/src/card/_examples/index.ts +5 -0
  111. package/src/card/card.css +120 -0
  112. package/src/card/card.playground.ts +116 -0
  113. package/src/card/card.spec.ts +50 -0
  114. package/src/card/card.ts +194 -0
  115. package/src/card/card.usage.example.ts +46 -0
  116. package/src/card/index.ts +1 -0
  117. package/src/carousel/_examples/carousel.autoplay.example.ts +69 -0
  118. package/src/carousel/_examples/carousel.example.ts +60 -0
  119. package/src/carousel/_examples/carousel.indicators.example.ts +64 -0
  120. package/src/carousel/_examples/carousel.lazy-load.example.ts +85 -0
  121. package/src/carousel/_examples/carousel.tabs-pattern.example.ts +61 -0
  122. package/src/carousel/_examples/index.ts +7 -0
  123. package/src/carousel/carousel.css +181 -0
  124. package/src/carousel/carousel.playground.ts +135 -0
  125. package/src/carousel/carousel.spec.ts +211 -0
  126. package/src/carousel/carousel.ts +399 -0
  127. package/src/carousel/carousel.usage.example.ts +46 -0
  128. package/src/carousel/index.ts +1 -0
  129. package/src/cascade-select/_examples/cascade-select.data-driven.example.ts +119 -0
  130. package/src/cascade-select/_examples/cascade-select.disabled.example.ts +74 -0
  131. package/src/cascade-select/_examples/cascade-select.example.ts +80 -0
  132. package/src/cascade-select/_examples/cascade-select.field.example.ts +73 -0
  133. package/src/cascade-select/_examples/cascade-select.path.example.ts +85 -0
  134. package/src/cascade-select/_examples/index.ts +7 -0
  135. package/src/cascade-select/cascade-select.css +120 -0
  136. package/src/cascade-select/cascade-select.playground.ts +133 -0
  137. package/src/cascade-select/cascade-select.ts +201 -0
  138. package/src/cascade-select/cascade-select.usage.example.ts +44 -0
  139. package/src/cascade-select/index.ts +5 -0
  140. package/src/chat/_examples/chat-bubble.example.ts +71 -0
  141. package/src/chat/_examples/chat-bubble.grouped.example.ts +69 -0
  142. package/src/chat/_examples/chat-bubble.sides.example.ts +41 -0
  143. package/src/chat/_examples/chat-bubble.variants.example.ts +58 -0
  144. package/src/chat/_examples/chat-bubble.with-state.example.ts +57 -0
  145. package/src/chat/_examples/index.ts +7 -0
  146. package/src/chat/chat.css +231 -0
  147. package/src/chat/chat.playground.ts +171 -0
  148. package/src/chat/chat.spec.ts +343 -0
  149. package/src/chat/chat.ts +269 -0
  150. package/src/chat/chat.usage.example.ts +49 -0
  151. package/src/chat/index.ts +13 -0
  152. package/src/checkbox/_examples/checkbox.checked.example.ts +20 -0
  153. package/src/checkbox/_examples/checkbox.default.example.ts +20 -0
  154. package/src/checkbox/_examples/checkbox.disabled.example.ts +26 -0
  155. package/src/checkbox/_examples/checkbox.indeterminate.example.ts +20 -0
  156. package/src/checkbox/_examples/checkbox.usage.example.ts +62 -0
  157. package/src/checkbox/_examples/index.ts +7 -0
  158. package/src/checkbox/checkbox.css +74 -0
  159. package/src/checkbox/checkbox.playground.ts +68 -0
  160. package/src/checkbox/checkbox.ts +122 -0
  161. package/src/checkbox/index.ts +1 -0
  162. package/src/color-picker/_examples/color-picker.alpha.example.ts +36 -0
  163. package/src/color-picker/_examples/color-picker.example.ts +34 -0
  164. package/src/color-picker/_examples/color-picker.hex-input.example.ts +53 -0
  165. package/src/color-picker/_examples/color-picker.in-form.example.ts +60 -0
  166. package/src/color-picker/_examples/color-picker.usage.example.ts +58 -0
  167. package/src/color-picker/_examples/color-picker.with-presets.example.ts +45 -0
  168. package/src/color-picker/_examples/index.ts +8 -0
  169. package/src/color-picker/color-picker.css +183 -0
  170. package/src/color-picker/color-picker.playground.ts +83 -0
  171. package/src/color-picker/color-picker.spec.ts +94 -0
  172. package/src/color-picker/color-picker.ts +234 -0
  173. package/src/color-picker/index.ts +1 -0
  174. package/src/combobox/_examples/combobox.async.example.ts +85 -0
  175. package/src/combobox/_examples/combobox.empty-state.example.ts +36 -0
  176. package/src/combobox/_examples/combobox.example.ts +36 -0
  177. package/src/combobox/_examples/combobox.free-text.example.ts +42 -0
  178. package/src/combobox/_examples/combobox.usage.example.ts +51 -0
  179. package/src/combobox/_examples/combobox.with-icons.example.ts +49 -0
  180. package/src/combobox/_examples/index.ts +8 -0
  181. package/src/combobox/combobox.css +101 -0
  182. package/src/combobox/combobox.playground.ts +90 -0
  183. package/src/combobox/combobox.spec.ts +111 -0
  184. package/src/combobox/combobox.ts +219 -0
  185. package/src/combobox/index.ts +6 -0
  186. package/src/command-palette/_examples/command-palette.async.example.ts +99 -0
  187. package/src/command-palette/_examples/command-palette.dialog.example.ts +90 -0
  188. package/src/command-palette/_examples/command-palette.example.ts +40 -0
  189. package/src/command-palette/_examples/command-palette.fuzzy.example.ts +54 -0
  190. package/src/command-palette/_examples/command-palette.groups.example.ts +55 -0
  191. package/src/command-palette/_examples/command-palette.usage.example.ts +49 -0
  192. package/src/command-palette/_examples/index.ts +8 -0
  193. package/src/command-palette/command-palette.css +234 -0
  194. package/src/command-palette/command-palette.playground.ts +119 -0
  195. package/src/command-palette/command-palette.ts +448 -0
  196. package/src/command-palette/index.ts +10 -0
  197. package/src/confirm-popup/_examples/confirm-popup.destructive.example.ts +72 -0
  198. package/src/confirm-popup/_examples/confirm-popup.example.ts +82 -0
  199. package/src/confirm-popup/_examples/confirm-popup.placement.example.ts +97 -0
  200. package/src/confirm-popup/_examples/confirm-popup.usage.example.ts +94 -0
  201. package/src/confirm-popup/_examples/confirm-popup.with-message.example.ts +76 -0
  202. package/src/confirm-popup/_examples/index.ts +7 -0
  203. package/src/confirm-popup/confirm-popup.css +47 -0
  204. package/src/confirm-popup/confirm-popup.playground.ts +109 -0
  205. package/src/confirm-popup/confirm-popup.spec.ts +209 -0
  206. package/src/confirm-popup/confirm-popup.ts +279 -0
  207. package/src/confirm-popup/index.ts +1 -0
  208. package/src/date-picker/_examples/date-picker.disabled-dates.example.ts +44 -0
  209. package/src/date-picker/_examples/date-picker.example.ts +38 -0
  210. package/src/date-picker/_examples/date-picker.locale.example.ts +50 -0
  211. package/src/date-picker/_examples/date-picker.readonly.example.ts +32 -0
  212. package/src/date-picker/_examples/date-picker.usage.example.ts +60 -0
  213. package/src/date-picker/_examples/date-picker.with-min-max.example.ts +47 -0
  214. package/src/date-picker/_examples/index.ts +8 -0
  215. package/src/date-picker/date-picker.css +61 -0
  216. package/src/date-picker/date-picker.playground.ts +79 -0
  217. package/src/date-picker/date-picker.spec.ts +71 -0
  218. package/src/date-picker/date-picker.ts +185 -0
  219. package/src/date-picker/index.ts +1 -0
  220. package/src/dialog/_examples/dialog.confirmation.example.ts +30 -0
  221. package/src/dialog/_examples/dialog.default.example.ts +30 -0
  222. package/src/dialog/_examples/dialog.nested.example.ts +86 -0
  223. package/src/dialog/_examples/dialog.scrollable.example.ts +30 -0
  224. package/src/dialog/_examples/dialog.usage.example.ts +57 -0
  225. package/src/dialog/_examples/dialog.with-form.example.ts +48 -0
  226. package/src/dialog/_examples/index.ts +8 -0
  227. package/src/dialog/dialog.css +56 -0
  228. package/src/dialog/dialog.playground.ts +136 -0
  229. package/src/dialog/dialog.ts +82 -0
  230. package/src/dialog/index.ts +1 -0
  231. package/src/divider/_examples/divider.example.ts +27 -0
  232. package/src/divider/_examples/divider.sizes.example.ts +33 -0
  233. package/src/divider/_examples/divider.structural.example.ts +55 -0
  234. package/src/divider/_examples/divider.usage.example.ts +48 -0
  235. package/src/divider/_examples/divider.variants.example.ts +33 -0
  236. package/src/divider/_examples/divider.vertical.example.ts +38 -0
  237. package/src/divider/_examples/divider.with-content.example.ts +38 -0
  238. package/src/divider/_examples/index.ts +9 -0
  239. package/src/divider/divider.css +93 -0
  240. package/src/divider/divider.playground.ts +97 -0
  241. package/src/divider/divider.spec.ts +207 -0
  242. package/src/divider/divider.ts +220 -0
  243. package/src/divider/index.ts +1 -0
  244. package/src/drawer/_examples/drawer.example.ts +30 -0
  245. package/src/drawer/_examples/drawer.modal-vs-non-modal.example.ts +27 -0
  246. package/src/drawer/_examples/drawer.scrollable.example.ts +30 -0
  247. package/src/drawer/_examples/drawer.sides.example.ts +32 -0
  248. package/src/drawer/_examples/drawer.usage.example.ts +56 -0
  249. package/src/drawer/_examples/drawer.with-form.example.ts +48 -0
  250. package/src/drawer/_examples/index.ts +8 -0
  251. package/src/drawer/drawer.css +130 -0
  252. package/src/drawer/drawer.playground.ts +107 -0
  253. package/src/drawer/drawer.spec.ts +216 -0
  254. package/src/drawer/drawer.ts +85 -0
  255. package/src/drawer/index.ts +1 -0
  256. package/src/dropdown-menu/_examples/dropdown-menu.disabled.example.ts +19 -0
  257. package/src/dropdown-menu/_examples/dropdown-menu.example.ts +20 -0
  258. package/src/dropdown-menu/_examples/dropdown-menu.shortcuts.example.ts +31 -0
  259. package/src/dropdown-menu/_examples/dropdown-menu.sides.example.ts +18 -0
  260. package/src/dropdown-menu/_examples/dropdown-menu.usage.example.ts +56 -0
  261. package/src/dropdown-menu/_examples/dropdown-menu.with-icons.example.ts +31 -0
  262. package/src/dropdown-menu/_examples/dropdown-menu.with-separator.example.ts +41 -0
  263. package/src/dropdown-menu/_examples/index.ts +9 -0
  264. package/src/dropdown-menu/dropdown-menu.css +108 -0
  265. package/src/dropdown-menu/dropdown-menu.playground.ts +109 -0
  266. package/src/dropdown-menu/dropdown-menu.spec.ts +5 -0
  267. package/src/dropdown-menu/dropdown-menu.ts +128 -0
  268. package/src/dropdown-menu/index.ts +1 -0
  269. package/src/empty-state/_examples/empty-state.error.example.ts +63 -0
  270. package/src/empty-state/_examples/empty-state.example.ts +59 -0
  271. package/src/empty-state/_examples/empty-state.search.example.ts +82 -0
  272. package/src/empty-state/_examples/empty-state.sizes.example.ts +76 -0
  273. package/src/empty-state/_examples/empty-state.usage.example.ts +66 -0
  274. package/src/empty-state/_examples/empty-state.with-actions.example.ts +68 -0
  275. package/src/empty-state/_examples/index.ts +8 -0
  276. package/src/empty-state/empty-state.css +114 -0
  277. package/src/empty-state/empty-state.playground.ts +87 -0
  278. package/src/empty-state/empty-state.spec.ts +211 -0
  279. package/src/empty-state/empty-state.ts +276 -0
  280. package/src/empty-state/index.ts +1 -0
  281. package/src/example-components.ts +396 -0
  282. package/src/field/_examples/field.disabled.example.ts +49 -0
  283. package/src/field/_examples/field.example.ts +51 -0
  284. package/src/field/_examples/field.required.example.ts +46 -0
  285. package/src/field/_examples/field.with-error.example.ts +73 -0
  286. package/src/field/_examples/field.with-prefix-suffix.example.ts +63 -0
  287. package/src/field/_examples/index.ts +7 -0
  288. package/src/field/field.css +138 -0
  289. package/src/field/field.playground.ts +108 -0
  290. package/src/field/field.spec.ts +132 -0
  291. package/src/field/field.ts +232 -0
  292. package/src/field/field.usage.example.ts +63 -0
  293. package/src/field/index.ts +7 -0
  294. package/src/file-upload/_examples/file-upload.dropzone.example.ts +32 -0
  295. package/src/file-upload/_examples/file-upload.example.ts +29 -0
  296. package/src/file-upload/_examples/file-upload.image-preview.example.ts +31 -0
  297. package/src/file-upload/_examples/file-upload.multiple.example.ts +23 -0
  298. package/src/file-upload/_examples/file-upload.with-progress.example.ts +59 -0
  299. package/src/file-upload/_examples/index.ts +7 -0
  300. package/src/file-upload/file-upload.css +207 -0
  301. package/src/file-upload/file-upload.playground.ts +84 -0
  302. package/src/file-upload/file-upload.spec.ts +94 -0
  303. package/src/file-upload/file-upload.ts +301 -0
  304. package/src/file-upload/file-upload.usage.example.ts +45 -0
  305. package/src/file-upload/index.ts +1 -0
  306. package/src/form/_examples/form.async-submit.example.ts +72 -0
  307. package/src/form/_examples/form.compound.example.ts +93 -0
  308. package/src/form/_examples/form.example.ts +70 -0
  309. package/src/form/_examples/form.validation.example.ts +67 -0
  310. package/src/form/_examples/index.ts +6 -0
  311. package/src/form/form.css +63 -0
  312. package/src/form/form.playground.ts +145 -0
  313. package/src/form/form.spec.ts +96 -0
  314. package/src/form/form.ts +216 -0
  315. package/src/form/form.usage.example.ts +63 -0
  316. package/src/form/index.ts +5 -0
  317. package/src/icon/_examples/icon.gallery.example.ts +199 -0
  318. package/src/icon/_examples/icon.usage.example.ts +46 -0
  319. package/src/icon/_examples/index.ts +4 -0
  320. package/src/icon/icon.playground.ts +63 -0
  321. package/src/icon/index.ts +5 -0
  322. package/src/icon/lucide/icon-names.generated.ts +1708 -0
  323. package/src/icon/lucide/icon-names.ts +18 -0
  324. package/src/icon/lucide/index.ts +2 -0
  325. package/src/icon/lucide/provide-lucide-icons.ts +96 -0
  326. package/src/input/_examples/index.ts +4 -0
  327. package/src/input/_examples/input.color.example.ts +33 -0
  328. package/src/input/_examples/input.example.ts +22 -0
  329. package/src/input/index.ts +1 -0
  330. package/src/input/input.css +70 -0
  331. package/src/input/input.playground.ts +79 -0
  332. package/src/input/input.spec.ts +98 -0
  333. package/src/input/input.ts +158 -0
  334. package/src/input/input.usage.example.ts +40 -0
  335. package/src/input-group/_examples/index.ts +7 -0
  336. package/src/input-group/_examples/input-group.button.example.ts +43 -0
  337. package/src/input-group/_examples/input-group.example.ts +39 -0
  338. package/src/input-group/_examples/input-group.icon.example.ts +49 -0
  339. package/src/input-group/_examples/input-group.url.example.ts +36 -0
  340. package/src/input-group/_examples/input-group.variants.example.ts +39 -0
  341. package/src/input-group/index.ts +1 -0
  342. package/src/input-group/input-group.css +125 -0
  343. package/src/input-group/input-group.playground.ts +90 -0
  344. package/src/input-group/input-group.ts +142 -0
  345. package/src/input-group/input-group.usage.example.ts +47 -0
  346. package/src/input-mask/_examples/index.ts +8 -0
  347. package/src/input-mask/_examples/input-mask.credit-card.example.ts +90 -0
  348. package/src/input-mask/_examples/input-mask.custom-tokens.example.ts +87 -0
  349. package/src/input-mask/_examples/input-mask.date.example.ts +61 -0
  350. package/src/input-mask/_examples/input-mask.example.ts +61 -0
  351. package/src/input-mask/_examples/input-mask.usage.example.ts +44 -0
  352. package/src/input-mask/_examples/input-mask.validation.example.ts +80 -0
  353. package/src/input-mask/index.ts +9 -0
  354. package/src/input-mask/input-mask.css +39 -0
  355. package/src/input-mask/input-mask.playground.ts +79 -0
  356. package/src/input-mask/input-mask.ts +130 -0
  357. package/src/input-otp/_examples/index.ts +8 -0
  358. package/src/input-otp/_examples/input-otp.autosubmit.example.ts +71 -0
  359. package/src/input-otp/_examples/input-otp.example.ts +47 -0
  360. package/src/input-otp/_examples/input-otp.lengths.example.ts +67 -0
  361. package/src/input-otp/_examples/input-otp.masked.example.ts +46 -0
  362. package/src/input-otp/_examples/input-otp.reactive.example.ts +58 -0
  363. package/src/input-otp/_examples/input-otp.separator.example.ts +49 -0
  364. package/src/input-otp/index.ts +1 -0
  365. package/src/input-otp/input-otp.css +87 -0
  366. package/src/input-otp/input-otp.playground.ts +107 -0
  367. package/src/input-otp/input-otp.ts +244 -0
  368. package/src/input-otp/input-otp.usage.example.ts +45 -0
  369. package/src/kbd/_examples/index.ts +6 -0
  370. package/src/kbd/_examples/kbd.combo.example.ts +24 -0
  371. package/src/kbd/_examples/kbd.example.ts +22 -0
  372. package/src/kbd/_examples/kbd.in-tooltip.example.ts +43 -0
  373. package/src/kbd/_examples/kbd.sizes.example.ts +31 -0
  374. package/src/kbd/index.ts +1 -0
  375. package/src/kbd/kbd.css +67 -0
  376. package/src/kbd/kbd.playground.ts +51 -0
  377. package/src/kbd/kbd.spec.ts +123 -0
  378. package/src/kbd/kbd.ts +123 -0
  379. package/src/kbd/kbd.usage.example.ts +38 -0
  380. package/src/link/_examples/index.ts +8 -0
  381. package/src/link/_examples/link.disabled.example.ts +23 -0
  382. package/src/link/_examples/link.example.ts +26 -0
  383. package/src/link/_examples/link.external.example.ts +33 -0
  384. package/src/link/_examples/link.in-prose.example.ts +36 -0
  385. package/src/link/_examples/link.sizes.example.ts +28 -0
  386. package/src/link/_examples/link.variants.example.ts +25 -0
  387. package/src/link/index.ts +1 -0
  388. package/src/link/link.css +104 -0
  389. package/src/link/link.playground.ts +98 -0
  390. package/src/link/link.spec.ts +146 -0
  391. package/src/link/link.ts +133 -0
  392. package/src/link/link.usage.example.ts +37 -0
  393. package/src/list/_examples/index.ts +7 -0
  394. package/src/list/_examples/list.divided.example.ts +32 -0
  395. package/src/list/_examples/list.example.ts +31 -0
  396. package/src/list/_examples/list.interactive.example.ts +51 -0
  397. package/src/list/_examples/list.nav.example.ts +44 -0
  398. package/src/list/_examples/list.with-icons.example.ts +97 -0
  399. package/src/list/index.ts +1 -0
  400. package/src/list/list.css +166 -0
  401. package/src/list/list.playground.ts +90 -0
  402. package/src/list/list.spec.ts +121 -0
  403. package/src/list/list.ts +227 -0
  404. package/src/list/list.usage.example.ts +45 -0
  405. package/src/menubar/_examples/index.ts +6 -0
  406. package/src/menubar/_examples/menubar.disabled-item.example.ts +23 -0
  407. package/src/menubar/_examples/menubar.example.ts +22 -0
  408. package/src/menubar/_examples/menubar.with-shortcuts.example.ts +33 -0
  409. package/src/menubar/_examples/menubar.with-submenu.example.ts +76 -0
  410. package/src/menubar/index.ts +1 -0
  411. package/src/menubar/menubar.css +62 -0
  412. package/src/menubar/menubar.playground.ts +96 -0
  413. package/src/menubar/menubar.ts +160 -0
  414. package/src/menubar/menubar.usage.example.ts +33 -0
  415. package/src/number-input/_examples/index.ts +7 -0
  416. package/src/number-input/_examples/number-input.currency.example.ts +35 -0
  417. package/src/number-input/_examples/number-input.decimal.example.ts +34 -0
  418. package/src/number-input/_examples/number-input.example.ts +24 -0
  419. package/src/number-input/_examples/number-input.min-max.example.ts +33 -0
  420. package/src/number-input/_examples/number-input.with-stepper.example.ts +45 -0
  421. package/src/number-input/index.ts +1 -0
  422. package/src/number-input/number-input.css +115 -0
  423. package/src/number-input/number-input.playground.ts +92 -0
  424. package/src/number-input/number-input.spec.ts +102 -0
  425. package/src/number-input/number-input.ts +212 -0
  426. package/src/number-input/number-input.usage.example.ts +73 -0
  427. package/src/overlay/overlay.css +32 -0
  428. package/src/overlay-badge/_examples/index.ts +7 -0
  429. package/src/overlay-badge/_examples/overlay-badge.described.example.ts +36 -0
  430. package/src/overlay-badge/_examples/overlay-badge.dot.example.ts +28 -0
  431. package/src/overlay-badge/_examples/overlay-badge.example.ts +34 -0
  432. package/src/overlay-badge/_examples/overlay-badge.on-avatar.example.ts +38 -0
  433. package/src/overlay-badge/_examples/overlay-badge.positions.example.ts +39 -0
  434. package/src/overlay-badge/index.ts +1 -0
  435. package/src/overlay-badge/overlay-badge.css +118 -0
  436. package/src/overlay-badge/overlay-badge.playground.ts +92 -0
  437. package/src/overlay-badge/overlay-badge.spec.ts +174 -0
  438. package/src/overlay-badge/overlay-badge.ts +232 -0
  439. package/src/overlay-badge/overlay-badge.usage.example.ts +44 -0
  440. package/src/pagination/_examples/index.ts +7 -0
  441. package/src/pagination/_examples/pagination.boundaries.example.ts +56 -0
  442. package/src/pagination/_examples/pagination.compact.example.ts +42 -0
  443. package/src/pagination/_examples/pagination.example.ts +55 -0
  444. package/src/pagination/_examples/pagination.large.example.ts +54 -0
  445. package/src/pagination/_examples/pagination.with-info.example.ts +49 -0
  446. package/src/pagination/index.ts +1 -0
  447. package/src/pagination/pagination.css +146 -0
  448. package/src/pagination/pagination.playground.ts +107 -0
  449. package/src/pagination/pagination.spec.ts +202 -0
  450. package/src/pagination/pagination.ts +432 -0
  451. package/src/pagination/pagination.usage.example.ts +50 -0
  452. package/src/password-input/_examples/index.ts +6 -0
  453. package/src/password-input/_examples/password-input.example.ts +24 -0
  454. package/src/password-input/_examples/password-input.strength.example.ts +45 -0
  455. package/src/password-input/_examples/password-input.toggle.example.ts +43 -0
  456. package/src/password-input/_examples/password-input.with-rules.example.ts +78 -0
  457. package/src/password-input/index.ts +1 -0
  458. package/src/password-input/password-input.css +155 -0
  459. package/src/password-input/password-input.playground.ts +81 -0
  460. package/src/password-input/password-input.spec.ts +129 -0
  461. package/src/password-input/password-input.ts +254 -0
  462. package/src/password-input/password-input.usage.example.ts +55 -0
  463. package/src/playground-types.ts +47 -0
  464. package/src/popover/_examples/index.ts +7 -0
  465. package/src/popover/_examples/popover.cancellable.example.ts +20 -0
  466. package/src/popover/_examples/popover.example.ts +20 -0
  467. package/src/popover/_examples/popover.modal.example.ts +22 -0
  468. package/src/popover/_examples/popover.sides.example.ts +37 -0
  469. package/src/popover/_examples/popover.with-form.example.ts +38 -0
  470. package/src/popover/index.ts +1 -0
  471. package/src/popover/popover.css +71 -0
  472. package/src/popover/popover.playground.ts +86 -0
  473. package/src/popover/popover.spec.ts +5 -0
  474. package/src/popover/popover.ts +94 -0
  475. package/src/popover/popover.usage.example.ts +48 -0
  476. package/src/progress-bar/_examples/index.ts +7 -0
  477. package/src/progress-bar/_examples/progress-bar.example.ts +22 -0
  478. package/src/progress-bar/_examples/progress-bar.indeterminate.example.ts +23 -0
  479. package/src/progress-bar/_examples/progress-bar.sizes.example.ts +29 -0
  480. package/src/progress-bar/_examples/progress-bar.variants.example.ts +30 -0
  481. package/src/progress-bar/_examples/progress-bar.with-label.example.ts +30 -0
  482. package/src/progress-bar/index.ts +1 -0
  483. package/src/progress-bar/progress-bar.css +113 -0
  484. package/src/progress-bar/progress-bar.playground.ts +87 -0
  485. package/src/progress-bar/progress-bar.spec.ts +233 -0
  486. package/src/progress-bar/progress-bar.ts +155 -0
  487. package/src/progress-bar/progress-bar.usage.example.ts +52 -0
  488. package/src/public-api.ts +61 -0
  489. package/src/radio/_examples/index.ts +6 -0
  490. package/src/radio/_examples/radio.default.example.ts +26 -0
  491. package/src/radio/_examples/radio.disabled.example.ts +26 -0
  492. package/src/radio/_examples/radio.group.example.ts +27 -0
  493. package/src/radio/_examples/radio.inline.example.ts +26 -0
  494. package/src/radio/index.ts +1 -0
  495. package/src/radio/radio.css +58 -0
  496. package/src/radio/radio.playground.ts +90 -0
  497. package/src/radio/radio.ts +143 -0
  498. package/src/radio/radio.usage.example.ts +54 -0
  499. package/src/select/_examples/index.ts +6 -0
  500. package/src/select/_examples/select.default.example.ts +26 -0
  501. package/src/select/_examples/select.disabled.example.ts +24 -0
  502. package/src/select/_examples/select.grouped.example.ts +37 -0
  503. package/src/select/_examples/select.placeholder.example.ts +26 -0
  504. package/src/select/index.ts +1 -0
  505. package/src/select/select.css +65 -0
  506. package/src/select/select.playground.ts +81 -0
  507. package/src/select/select.ts +176 -0
  508. package/src/select/select.usage.example.ts +64 -0
  509. package/src/skeleton/_examples/index.ts +6 -0
  510. package/src/skeleton/_examples/skeleton.animations.example.ts +52 -0
  511. package/src/skeleton/_examples/skeleton.card.example.ts +68 -0
  512. package/src/skeleton/_examples/skeleton.example.ts +24 -0
  513. package/src/skeleton/_examples/skeleton.shapes.example.ts +55 -0
  514. package/src/skeleton/index.ts +1 -0
  515. package/src/skeleton/skeleton.css +111 -0
  516. package/src/skeleton/skeleton.playground.ts +80 -0
  517. package/src/skeleton/skeleton.spec.ts +126 -0
  518. package/src/skeleton/skeleton.ts +155 -0
  519. package/src/skeleton/skeleton.usage.example.ts +49 -0
  520. package/src/slider/_examples/index.ts +7 -0
  521. package/src/slider/_examples/slider.example.ts +41 -0
  522. package/src/slider/_examples/slider.formatted.example.ts +53 -0
  523. package/src/slider/_examples/slider.range.example.ts +48 -0
  524. package/src/slider/_examples/slider.vertical.example.ts +48 -0
  525. package/src/slider/_examples/slider.with-marks.example.ts +46 -0
  526. package/src/slider/index.ts +1 -0
  527. package/src/slider/slider.css +172 -0
  528. package/src/slider/slider.playground.ts +88 -0
  529. package/src/slider/slider.spec.ts +139 -0
  530. package/src/slider/slider.ts +246 -0
  531. package/src/slider/slider.usage.example.ts +68 -0
  532. package/src/speed-dial/_examples/index.ts +7 -0
  533. package/src/speed-dial/_examples/speed-dial.directions.example.ts +85 -0
  534. package/src/speed-dial/_examples/speed-dial.disabled.example.ts +71 -0
  535. package/src/speed-dial/_examples/speed-dial.example.ts +48 -0
  536. package/src/speed-dial/_examples/speed-dial.usage.example.ts +59 -0
  537. package/src/speed-dial/_examples/speed-dial.with-tooltips.example.ts +65 -0
  538. package/src/speed-dial/index.ts +1 -0
  539. package/src/speed-dial/speed-dial.css +137 -0
  540. package/src/speed-dial/speed-dial.playground.ts +137 -0
  541. package/src/speed-dial/speed-dial.spec.ts +191 -0
  542. package/src/speed-dial/speed-dial.ts +257 -0
  543. package/src/spinner/_examples/index.ts +8 -0
  544. package/src/spinner/_examples/spinner.animations.example.ts +54 -0
  545. package/src/spinner/_examples/spinner.example.ts +26 -0
  546. package/src/spinner/_examples/spinner.in-button.example.ts +51 -0
  547. package/src/spinner/_examples/spinner.sizes.example.ts +31 -0
  548. package/src/spinner/_examples/spinner.usage.example.ts +45 -0
  549. package/src/spinner/_examples/spinner.variants.example.ts +34 -0
  550. package/src/spinner/index.ts +1 -0
  551. package/src/spinner/spinner.css +161 -0
  552. package/src/spinner/spinner.playground.ts +68 -0
  553. package/src/spinner/spinner.spec.ts +184 -0
  554. package/src/spinner/spinner.ts +185 -0
  555. package/src/stepper/_examples/index.ts +8 -0
  556. package/src/stepper/_examples/stepper.example.ts +62 -0
  557. package/src/stepper/_examples/stepper.non-linear.example.ts +63 -0
  558. package/src/stepper/_examples/stepper.optional-step.example.ts +62 -0
  559. package/src/stepper/_examples/stepper.usage.example.ts +73 -0
  560. package/src/stepper/_examples/stepper.vertical.example.ts +66 -0
  561. package/src/stepper/_examples/stepper.with-error.example.ts +63 -0
  562. package/src/stepper/index.ts +1 -0
  563. package/src/stepper/stepper.css +147 -0
  564. package/src/stepper/stepper.playground.ts +88 -0
  565. package/src/stepper/stepper.spec.ts +200 -0
  566. package/src/stepper/stepper.ts +242 -0
  567. package/src/table/_examples/index.ts +23 -0
  568. package/src/table/_examples/table.column-pinning.example.ts +55 -0
  569. package/src/table/_examples/table.column-resize.example.ts +49 -0
  570. package/src/table/_examples/table.column-visibility.example.ts +52 -0
  571. package/src/table/_examples/table.density.example.ts +71 -0
  572. package/src/table/_examples/table.editable.example.ts +85 -0
  573. package/src/table/_examples/table.empty-and-error.example.ts +112 -0
  574. package/src/table/_examples/table.example.ts +45 -0
  575. package/src/table/_examples/table.export.example.ts +82 -0
  576. package/src/table/_examples/table.filterable.example.ts +67 -0
  577. package/src/table/_examples/table.grouping.example.ts +63 -0
  578. package/src/table/_examples/table.keyboard.example.ts +115 -0
  579. package/src/table/_examples/table.master-detail.example.ts +102 -0
  580. package/src/table/_examples/table.persistence.example.ts +85 -0
  581. package/src/table/_examples/table.playground.ts +154 -0
  582. package/src/table/_examples/table.row-pinning.example.ts +71 -0
  583. package/src/table/_examples/table.selection.example.ts +67 -0
  584. package/src/table/_examples/table.server-mode.example.ts +120 -0
  585. package/src/table/_examples/table.sortable.example.ts +49 -0
  586. package/src/table/_examples/table.theming.example.ts +64 -0
  587. package/src/table/_examples/table.usage.example.ts +90 -0
  588. package/src/table/_examples/table.virtualized.example.ts +122 -0
  589. package/src/table/index.ts +11 -0
  590. package/src/table/table-cell-editor-outlet.ts +111 -0
  591. package/src/table/table-editors/boolean-editor.ts +71 -0
  592. package/src/table/table-editors/date-editor.ts +117 -0
  593. package/src/table/table-editors/editors.spec.ts +147 -0
  594. package/src/table/table-editors/index.ts +41 -0
  595. package/src/table/table-editors/number-editor.ts +89 -0
  596. package/src/table/table-editors/select-editor.ts +107 -0
  597. package/src/table/table-editors/text-editor.ts +82 -0
  598. package/src/table/table-export.spec.ts +33 -0
  599. package/src/table/table-export.ts +53 -0
  600. package/src/table/table-filter-outlet.ts +137 -0
  601. package/src/table/table-filters/date-filter.ts +122 -0
  602. package/src/table/table-filters/filters.css +53 -0
  603. package/src/table/table-filters/filters.spec.ts +277 -0
  604. package/src/table/table-filters/index.ts +11 -0
  605. package/src/table/table-filters/number-filter.ts +232 -0
  606. package/src/table/table-filters/select-filter.ts +129 -0
  607. package/src/table/table-filters/text-filter.ts +110 -0
  608. package/src/table/table-pagination.spec.ts +118 -0
  609. package/src/table/table-pagination.ts +191 -0
  610. package/src/table/table-side-panel.spec.ts +170 -0
  611. package/src/table/table-side-panel.ts +263 -0
  612. package/src/table/table-status-bar.spec.ts +78 -0
  613. package/src/table/table-status-bar.ts +70 -0
  614. package/src/table/table-toolbar.spec.ts +180 -0
  615. package/src/table/table-toolbar.ts +244 -0
  616. package/src/table/table-virtual.spec.ts +103 -0
  617. package/src/table/table-virtual.ts +180 -0
  618. package/src/table/table.css +468 -0
  619. package/src/table/table.spec.ts +175 -0
  620. package/src/table/table.ts +1009 -0
  621. package/src/tabs/_examples/index.ts +8 -0
  622. package/src/tabs/_examples/tabs.controlled.example.ts +59 -0
  623. package/src/tabs/_examples/tabs.disabled.example.ts +34 -0
  624. package/src/tabs/_examples/tabs.example.ts +34 -0
  625. package/src/tabs/_examples/tabs.manual-activation.example.ts +34 -0
  626. package/src/tabs/_examples/tabs.usage.example.ts +43 -0
  627. package/src/tabs/_examples/tabs.vertical.example.ts +33 -0
  628. package/src/tabs/index.ts +1 -0
  629. package/src/tabs/tabs.css +80 -0
  630. package/src/tabs/tabs.playground.ts +88 -0
  631. package/src/tabs/tabs.spec.ts +135 -0
  632. package/src/tabs/tabs.ts +204 -0
  633. package/src/tag/_examples/index.ts +9 -0
  634. package/src/tag/_examples/tag.example.ts +22 -0
  635. package/src/tag/_examples/tag.list.example.ts +38 -0
  636. package/src/tag/_examples/tag.removable.example.ts +39 -0
  637. package/src/tag/_examples/tag.selectable.example.ts +33 -0
  638. package/src/tag/_examples/tag.sizes.example.ts +25 -0
  639. package/src/tag/_examples/tag.usage.example.ts +62 -0
  640. package/src/tag/_examples/tag.variants.example.ts +29 -0
  641. package/src/tag/index.ts +1 -0
  642. package/src/tag/tag.css +167 -0
  643. package/src/tag/tag.playground.ts +63 -0
  644. package/src/tag/tag.spec.ts +153 -0
  645. package/src/tag/tag.ts +186 -0
  646. package/src/test-setup.ts +5 -0
  647. package/src/textarea/_examples/index.ts +8 -0
  648. package/src/textarea/_examples/textarea.autoresize.example.ts +37 -0
  649. package/src/textarea/_examples/textarea.character-count.example.ts +34 -0
  650. package/src/textarea/_examples/textarea.example.ts +22 -0
  651. package/src/textarea/_examples/textarea.no-resize.example.ts +28 -0
  652. package/src/textarea/_examples/textarea.usage.example.ts +50 -0
  653. package/src/textarea/_examples/textarea.with-field.example.ts +66 -0
  654. package/src/textarea/index.ts +1 -0
  655. package/src/textarea/textarea.css +117 -0
  656. package/src/textarea/textarea.playground.ts +70 -0
  657. package/src/textarea/textarea.spec.ts +161 -0
  658. package/src/textarea/textarea.ts +339 -0
  659. package/src/time-picker/_examples/index.ts +8 -0
  660. package/src/time-picker/_examples/time-picker.12-hour.example.ts +24 -0
  661. package/src/time-picker/_examples/time-picker.example.ts +24 -0
  662. package/src/time-picker/_examples/time-picker.formatted.example.ts +32 -0
  663. package/src/time-picker/_examples/time-picker.range.example.ts +54 -0
  664. package/src/time-picker/_examples/time-picker.usage.example.ts +53 -0
  665. package/src/time-picker/_examples/time-picker.with-seconds.example.ts +24 -0
  666. package/src/time-picker/index.ts +1 -0
  667. package/src/time-picker/time-picker.css +126 -0
  668. package/src/time-picker/time-picker.playground.ts +72 -0
  669. package/src/time-picker/time-picker.spec.ts +77 -0
  670. package/src/time-picker/time-picker.ts +207 -0
  671. package/src/toast/_examples/index.ts +7 -0
  672. package/src/toast/_examples/toast.default.example.ts +37 -0
  673. package/src/toast/_examples/toast.dismissible.example.ts +38 -0
  674. package/src/toast/_examples/toast.usage.example.ts +57 -0
  675. package/src/toast/_examples/toast.variants.example.ts +43 -0
  676. package/src/toast/_examples/toast.with-action.example.ts +46 -0
  677. package/src/toast/index.ts +1 -0
  678. package/src/toast/toast.css +115 -0
  679. package/src/toast/toast.playground.ts +61 -0
  680. package/src/toast/toast.ts +168 -0
  681. package/src/toggle/_examples/index.ts +7 -0
  682. package/src/toggle/_examples/toggle.checked.example.ts +20 -0
  683. package/src/toggle/_examples/toggle.default.example.ts +20 -0
  684. package/src/toggle/_examples/toggle.disabled.example.ts +26 -0
  685. package/src/toggle/_examples/toggle.usage.example.ts +51 -0
  686. package/src/toggle/_examples/toggle.with-label.example.ts +30 -0
  687. package/src/toggle/index.ts +1 -0
  688. package/src/toggle/toggle.css +123 -0
  689. package/src/toggle/toggle.playground.ts +65 -0
  690. package/src/toggle/toggle.ts +113 -0
  691. package/src/tooltip/_examples/index.ts +9 -0
  692. package/src/tooltip/_examples/tooltip.delays.example.ts +16 -0
  693. package/src/tooltip/_examples/tooltip.disabled.example.ts +16 -0
  694. package/src/tooltip/_examples/tooltip.example.ts +16 -0
  695. package/src/tooltip/_examples/tooltip.group.example.ts +20 -0
  696. package/src/tooltip/_examples/tooltip.rich.example.ts +19 -0
  697. package/src/tooltip/_examples/tooltip.sides.example.ts +18 -0
  698. package/src/tooltip/_examples/tooltip.usage.example.ts +50 -0
  699. package/src/tooltip/index.ts +1 -0
  700. package/src/tooltip/tooltip.css +61 -0
  701. package/src/tooltip/tooltip.playground.ts +79 -0
  702. package/src/tooltip/tooltip.spec.ts +5 -0
  703. package/src/tooltip/tooltip.ts +102 -0
  704. package/src/tree-select/_examples/index.ts +8 -0
  705. package/src/tree-select/_examples/tree-select.disabled.example.ts +106 -0
  706. package/src/tree-select/_examples/tree-select.example.ts +65 -0
  707. package/src/tree-select/_examples/tree-select.expanded.example.ts +72 -0
  708. package/src/tree-select/_examples/tree-select.field.example.ts +77 -0
  709. package/src/tree-select/_examples/tree-select.multi.example.ts +73 -0
  710. package/src/tree-select/_examples/tree-select.usage.example.ts +85 -0
  711. package/src/tree-select/index.ts +1 -0
  712. package/src/tree-select/tree-select.css +220 -0
  713. package/src/tree-select/tree-select.playground.ts +83 -0
  714. package/src/tree-select/tree-select.ts +348 -0
  715. package/src/typography/_examples/index.ts +9 -0
  716. package/src/typography/_examples/typography.blockquote.example.ts +34 -0
  717. package/src/typography/_examples/typography.code.example.ts +32 -0
  718. package/src/typography/_examples/typography.example.ts +42 -0
  719. package/src/typography/_examples/typography.lead.example.ts +37 -0
  720. package/src/typography/_examples/typography.muted.example.ts +27 -0
  721. package/src/typography/_examples/typography.truncate.example.ts +41 -0
  722. package/src/typography/_examples/typography.usage.example.ts +44 -0
  723. package/src/typography/index.ts +8 -0
  724. package/src/typography/typography.playground.ts +101 -0
  725. package/src/typography/typography.spec.ts +70 -0
  726. package/src/typography/typography.ts +105 -0
  727. package/tsconfig.lib.json +25 -0
  728. package/tsconfig.lib.prod.json +17 -0
  729. package/tsconfig.spec.json +16 -0
  730. package/vite.config.ts +33 -0
@@ -0,0 +1,1009 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ TemplateRef,
5
+ Type,
6
+ ViewEncapsulation,
7
+ computed,
8
+ effect,
9
+ inject,
10
+ input,
11
+ model,
12
+ output,
13
+ signal,
14
+ untracked,
15
+ contentChild,
16
+ } from '@angular/core';
17
+ import { NgTemplateOutlet } from '@angular/common';
18
+ import type { ResourceRef } from '@angular/core';
19
+ import {
20
+ KjTable,
21
+ KjTableHeader,
22
+ KjTableRow,
23
+ KjTableCell,
24
+ KjTableKeyboardNav,
25
+ KjIconDirective,
26
+ KJ_TABLE_STORAGE,
27
+ type KjColumnMeta,
28
+ type KjResourceResult,
29
+ type KjStorageAdapter,
30
+ type KjTableState,
31
+ } from '@kouji-ui/core';
32
+ import type { Cell, Column, Header, Row, RowData } from '@tanstack/angular-table';
33
+ import { KjTableVirtual } from './table-virtual';
34
+ import { KjCheckboxComponent } from '../checkbox/checkbox';
35
+ import {
36
+ KjBooleanEditor,
37
+ KjDateEditor,
38
+ KjNumberEditor,
39
+ KjSelectEditor,
40
+ KjTextEditor,
41
+ } from './table-editors';
42
+ import {
43
+ KjDateFilter,
44
+ KjNumberFilter,
45
+ KjSelectFilter,
46
+ KjTextFilter,
47
+ } from './table-filters';
48
+ import { KjCellEditorOutlet } from './table-cell-editor-outlet';
49
+ import { KjFilterCellOutlet } from './table-filter-outlet';
50
+
51
+ /** Cell-edit payload emitted by `(cellEdit)`. */
52
+ export interface KjCellEditEvent<TData> {
53
+ readonly row: TData;
54
+ readonly columnId: string;
55
+ readonly oldValue: unknown;
56
+ readonly newValue: unknown;
57
+ }
58
+
59
+ /** Row click payload. */
60
+ export interface KjRowClickEvent<TData> {
61
+ readonly row: TData;
62
+ readonly event: MouseEvent;
63
+ }
64
+
65
+ const VIRTUAL_AUTO_THRESHOLD = 200;
66
+
67
+ /** Lookup of column type → built-in editor component. */
68
+ const BUILTIN_EDITORS: Readonly<Record<string, Type<unknown>>> = {
69
+ text: KjTextEditor,
70
+ number: KjNumberEditor,
71
+ date: KjDateEditor,
72
+ boolean: KjBooleanEditor,
73
+ select: KjSelectEditor,
74
+ };
75
+
76
+ /** Lookup of column type → built-in filter UI. */
77
+ const BUILTIN_FILTERS: Readonly<Record<string, Type<unknown>>> = {
78
+ text: KjTextFilter,
79
+ number: KjNumberFilter,
80
+ date: KjDateFilter,
81
+ select: KjSelectFilter,
82
+ };
83
+
84
+ /**
85
+ * Themed root data table built on top of the headless `@kouji-ui/core` table
86
+ * directives. Wires TanStack-backed `<table>` rendering, ARIA grid semantics,
87
+ * density / variant tokens, content projection slots (toolbar, side-panel,
88
+ * empty, error, loading, row-expansion), persistence, virtualization,
89
+ * resource-backed data, inline editing, and column resizing.
90
+ *
91
+ * Three data modes:
92
+ * - **Static**: pass `kjData` as a plain array.
93
+ * - **Signal**: pass a signal of rows via `kjData`.
94
+ * - **Resource**: pass a `ResourceRef<KjResourceResult<T>>` via `kjResource`;
95
+ * `kjData` is ignored and loading / error are derived from the resource.
96
+ *
97
+ * @example
98
+ * ```html
99
+ * <kj-table [kjData]="rows()" [kjColumns]="cols" kjDensity="compact" />
100
+ * ```
101
+ *
102
+ * @doc-example Default [full]
103
+ * The smallest possible `<kj-table>` — three columns, five rows.
104
+ * @doc-file table.example.ts
105
+ * @doc-example Usage [full]
106
+ * Full host API: density toggle, bordered variant, toolbar / pagination /
107
+ * status-bar slots projected.
108
+ * @doc-file table.usage.example.ts
109
+ * @doc-example Sortable [full]
110
+ * Click a header to sort; click again to flip direction; third click clears.
111
+ * Shift-click a second header to add a secondary sort.
112
+ * @doc-file table.sortable.example.ts
113
+ * @doc-example Filterable [full]
114
+ * `[kjEnableFilters]="true"` renders a filter row under each header. Built-in
115
+ * text / number / date / select filters pick by `kjType`.
116
+ * @doc-file table.filterable.example.ts
117
+ * @doc-example Selection [full]
118
+ * Multi-row selection with status-bar count + bulk-action slot.
119
+ * @doc-file table.selection.example.ts
120
+ * @doc-example Inline editing [full]
121
+ * Double-click a cell to mount the matching editor; Enter commits, Escape
122
+ * cancels. Listen to `(cellEdit)` and persist yourself.
123
+ * @doc-file table.editable.example.ts
124
+ * @doc-example Column visibility [full]
125
+ * Show / hide columns via the toolbar's visibility menu.
126
+ * @doc-file table.column-visibility.example.ts
127
+ * @doc-example Column resize [full]
128
+ * `[kjEnableResize]="true"` puts a grab handle on each `<th>` border.
129
+ * @doc-file table.column-resize.example.ts
130
+ * @doc-example Column pinning [full]
131
+ * `kjPin: 'left' | 'right'` on a column meta pins it. Unpinned columns
132
+ * scroll horizontally between the pinned edges.
133
+ * @doc-file table.column-pinning.example.ts
134
+ * @doc-example Row pinning [full]
135
+ * Pin rows top / bottom via TanStack's row-pinning state.
136
+ * @doc-file table.row-pinning.example.ts
137
+ * @doc-example Grouping [full]
138
+ * Group by a column; toggle group rows to collapse / expand.
139
+ * @doc-file table.grouping.example.ts
140
+ * @doc-example Master / detail [full]
141
+ * `<ng-template #kjRowExpansion let-row>` renders below the expanded row.
142
+ * @doc-file table.master-detail.example.ts
143
+ * @doc-example Virtualized [full]
144
+ * `[kjVirtual]="true"` (or `'auto'` past 200 rows) windows the body via
145
+ * `@tanstack/virtual-core`.
146
+ * @doc-file table.virtualized.example.ts
147
+ * @doc-example Density [full]
148
+ * `compact` / `standard` / `comfortable` adjust row padding.
149
+ * @doc-file table.density.example.ts
150
+ * @doc-example Theming [full]
151
+ * `bordered` / `striped` / `clean` variants for visual weight.
152
+ * @doc-file table.theming.example.ts
153
+ * @doc-example Server mode [full]
154
+ * `kjTableResource()` wires the table state into an async loader; pagination
155
+ * and filtering round-trip through your endpoint.
156
+ * @doc-file table.server-mode.example.ts
157
+ * @doc-example Persistence [full]
158
+ * `[kjStorageKey]` + a `KjStorageAdapter` round-trip sort / filter / pinning
159
+ * / visibility / density through reload.
160
+ * @doc-file table.persistence.example.ts
161
+ * @doc-example Export [full]
162
+ * CSV / JSON / clipboard export via `data-table-export` utilities, wired to
163
+ * the toolbar's export menu.
164
+ * @doc-file table.export.example.ts
165
+ * @doc-example Empty and error [full]
166
+ * Project `[kjEmpty]` / `[kjError]` slots to override the defaults.
167
+ * @doc-file table.empty-and-error.example.ts
168
+ * @doc-example Keyboard [full]
169
+ * Arrow / Home / End / Ctrl+Home/End / PageUp/Down / F2 / Enter / Esc /
170
+ * Space / Cmd+A — full WAI-ARIA Grid pattern.
171
+ * @doc-file table.keyboard.example.ts
172
+ *
173
+ * @doc-category Library/Data display
174
+ * @doc
175
+ * @doc-name table
176
+ * @doc-is-main
177
+ * @doc-description Themed data table built on TanStack — slots for toolbar, side panel, empty/error/loading; inline editing, filtering, resize, persistence, virtualization, resource-backed data.
178
+ */
179
+ @Component({
180
+ selector: 'kj-table',
181
+ standalone: true,
182
+ changeDetection: ChangeDetectionStrategy.OnPush,
183
+ // `hostDirectives: [KjTable]` hoists the core directive (and its
184
+ // `KJ_TABLE` provider) onto the `<kj-table>` host element so projected
185
+ // content — `<kj-table-toolbar>`, `<kj-table-status-bar>`,
186
+ // `<kj-table-pagination>` — can `inject(KJ_TABLE)` from its element
187
+ // injector. The aliased inputs expose the directive surface under
188
+ // wrapper-friendly names (`kjColumns`, `kjData`, `kjGetRowId`).
189
+ hostDirectives: [
190
+ {
191
+ directive: KjTable,
192
+ inputs: ['kjTable: kjColumns', 'kjTableData: kjData', 'kjGetRowId'],
193
+ },
194
+ ],
195
+ imports: [
196
+ KjTableHeader,
197
+ KjTableRow,
198
+ KjTableCell,
199
+ KjTableKeyboardNav,
200
+ KjTableVirtual,
201
+ KjIconDirective,
202
+ KjCheckboxComponent,
203
+ KjCellEditorOutlet,
204
+ KjFilterCellOutlet,
205
+ NgTemplateOutlet,
206
+ ],
207
+ host: {
208
+ // Read density from the hosted directive's signal — both the wrapper's
209
+ // `kjDensity` input AND the toolbar's density toggle write through to
210
+ // `KjTable.density` via `setState({ density })`, so a single source of
211
+ // truth drives the `data-density` host attribute.
212
+ '[attr.data-density]': 't.state.density()',
213
+ '[attr.data-variant]': 'kjVariant()',
214
+ '[attr.data-loading]': 'isLoading() ? "" : null',
215
+ '[attr.data-error]': 'hasError() ? "" : null',
216
+ },
217
+ template: `
218
+ <div class="kj-table-wrapper">
219
+ <!-- Toolbar projection: matches either an explicit [kjToolbar] marker
220
+ OR the styled <kj-table-toolbar> element directly, so users don't
221
+ have to remember the marker attribute. -->
222
+ <ng-content select="kj-table-toolbar, [kjToolbar]" />
223
+
224
+ <div class="kj-table-body">
225
+ <table kjTableKeyboardNav
226
+ role="grid"
227
+ [attr.aria-rowcount]="aria.rowCount()"
228
+ [attr.aria-colcount]="aria.colCount()"
229
+ >
230
+ <thead>
231
+ @for (g of t.table().getHeaderGroups(); track g.id) {
232
+ <tr role="row">
233
+ @if (showSelectionColumn()) {
234
+ <th scope="col" class="kj-table-select-cell">
235
+ @if (kjSelectionMode() === 'multi') {
236
+ <kj-checkbox
237
+ [checked]="t.table().getIsAllPageRowsSelected()"
238
+ [indeterminate]="t.table().getIsSomePageRowsSelected()"
239
+ (checkedChange)="onSelectAll($event)"
240
+ kjAriaLabel="Select all rows"
241
+ />
242
+ }
243
+ </th>
244
+ }
245
+ @for (h of g.headers; track h.id) {
246
+ <th kjTableHeader
247
+ [kjHeader]="h"
248
+ scope="col"
249
+ [style.width.px]="kjEnableResize() ? h.getSize() : null"
250
+ [attr.data-pin]="headerPin(h)"
251
+ [attr.data-resizing]="h.column.getIsResizing?.() ? '' : null"
252
+ [style.--kj-resize-delta.px]="t.columnSizingInfo().deltaOffset ?? 0"
253
+ >
254
+ {{ h.column.columnDef.header }}
255
+ @if (h.column.getCanSort?.()) {
256
+ <i
257
+ class="kj-table-sort-indicator"
258
+ kjIconSize="sm"
259
+ aria-hidden="true"
260
+ [kjIcon]="sortIcon(h)"
261
+ ></i>
262
+ }
263
+ @if (kjEnableResize() && h.column.getCanResize?.()) {
264
+ <span
265
+ class="kj-table-resize-handle"
266
+ role="separator"
267
+ aria-orientation="vertical"
268
+ aria-label="Resize column"
269
+ (mousedown)="h.getResizeHandler()($event)"
270
+ (touchstart)="h.getResizeHandler()($event)"
271
+ ></span>
272
+ }
273
+ </th>
274
+ }
275
+ </tr>
276
+ }
277
+ @if (kjEnableFilters()) {
278
+ <tr role="row" class="kj-table-filter-row">
279
+ @if (showSelectionColumn()) {
280
+ <th scope="col" class="kj-table-select-cell"></th>
281
+ }
282
+ @for (g of t.table().getHeaderGroups(); track g.id) {
283
+ @for (h of g.headers; track h.id) {
284
+ <th scope="col" class="kj-table-filter-cell">
285
+ @if (filterTypeFor(h.column); as ft) {
286
+ <span
287
+ kjFilterCell
288
+ class="kj-table-filter-anchor"
289
+ [kjColumn]="h.column"
290
+ [kjFilter]="filterRendererFor(h.column, ft)"
291
+ ></span>
292
+ }
293
+ </th>
294
+ }
295
+ }
296
+ </tr>
297
+ }
298
+ </thead>
299
+
300
+ @if (kjEnableRowPinning() && t.table().getTopRows().length > 0) {
301
+ <tbody class="kj-table-tbody-pinned" data-pin="top">
302
+ @for (r of t.table().getTopRows(); track r.id) {
303
+ <tr kjTableRow [kjRow]="r"
304
+ (click)="onRowClick(r, $event)"
305
+ (dblclick)="onRowDblClick(r, $event)">
306
+ @if (showSelectionColumn()) {
307
+ <td class="kj-table-select-cell"
308
+ (mousedown)="rememberClickModifiers($event)"
309
+ (click)="$event.stopPropagation()">
310
+ <kj-checkbox
311
+ [checked]="r.getIsSelected()"
312
+ (checkedChange)="onRowCheckboxToggle(r)"
313
+ kjAriaLabel="Select row"
314
+ />
315
+ </td>
316
+ }
317
+ @for (c of r.getVisibleCells(); track c.id) {
318
+ <td kjTableCell [kjCell]="c" tabindex="-1"
319
+ [class.kj-table-cell--editing]="isEditing(c)"
320
+ (click)="onCellClick(c, $event)"
321
+ (dblclick)="onCellDblClick(c, $event)"
322
+ (keydown)="onCellKeydown(c, $event)">
323
+ @if (isEditing(c)) {
324
+ <span class="kj-table-cell-ghost" aria-hidden="true">{{ c.getValue() }}</span>
325
+ <span
326
+ kjCellEditorOutlet
327
+ class="kj-table-editor-anchor"
328
+ [kjEditor]="editorTypeFor(c)"
329
+ [kjValue]="c.getValue()"
330
+ [kjMeta]="editorMetaFor(c)"
331
+ (commit)="onEditorCommit(c, $event)"
332
+ (editCancel)="onEditorCancel()"
333
+ ></span>
334
+ } @else {
335
+ {{ c.getValue() }}
336
+ }
337
+ </td>
338
+ }
339
+ </tr>
340
+ }
341
+ </tbody>
342
+ }
343
+
344
+ @if (shouldVirtualize()) {
345
+ <tbody
346
+ kjTableVirtual
347
+ [kjCount]="centerRows().length"
348
+ [kjEstimateSize]="kjEstimatedRowSize()"
349
+ #v="kjTableVirtual"
350
+ >
351
+ @if (v.paddingTop() > 0) {
352
+ <tr aria-hidden="true">
353
+ <td [attr.colspan]="aria.colCount()" [style.height.px]="v.paddingTop()"></td>
354
+ </tr>
355
+ }
356
+ @for (vr of v.virtualRows(); track vr.key) {
357
+ @if (centerRows()[vr.index]; as r) {
358
+ <tr kjTableRow [kjRow]="r"
359
+ (click)="onRowClick(r, $event)"
360
+ (dblclick)="onRowDblClick(r, $event)">
361
+ @if (showSelectionColumn()) {
362
+ <td class="kj-table-select-cell"
363
+ (mousedown)="rememberClickModifiers($event)"
364
+ (click)="$event.stopPropagation()">
365
+ <kj-checkbox
366
+ [checked]="r.getIsSelected()"
367
+ (checkedChange)="onRowCheckboxToggle(r)"
368
+ kjAriaLabel="Select row"
369
+ />
370
+ </td>
371
+ }
372
+ @for (c of r.getVisibleCells(); track c.id) {
373
+ <td kjTableCell [kjCell]="c" tabindex="-1"
374
+ [class.kj-table-cell--editing]="isEditing(c)"
375
+ [style.width.px]="kjEnableResize() ? c.column.getSize() : null"
376
+ (click)="onCellClick(c, $event)"
377
+ (dblclick)="onCellDblClick(c, $event)"
378
+ (keydown)="onCellKeydown(c, $event)">
379
+ @if (isEditing(c)) {
380
+ <span class="kj-table-cell-ghost" aria-hidden="true">{{ c.getValue() }}</span>
381
+ <span
382
+ kjCellEditorOutlet
383
+ class="kj-table-editor-anchor"
384
+ [kjEditor]="editorTypeFor(c)"
385
+ [kjValue]="c.getValue()"
386
+ [kjMeta]="editorMetaFor(c)"
387
+ (commit)="onEditorCommit(c, $event)"
388
+ (editCancel)="onEditorCancel()"
389
+ ></span>
390
+ } @else {
391
+ {{ c.getValue() }}
392
+ }
393
+ </td>
394
+ }
395
+ </tr>
396
+ @if (kjRowExpansionTpl() && r.getIsExpanded?.()) {
397
+ <tr class="kj-table-expansion-row">
398
+ <td [attr.colspan]="aria.colCount()">
399
+ <ng-container
400
+ [ngTemplateOutlet]="kjRowExpansionTpl()!"
401
+ [ngTemplateOutletContext]="{ $implicit: r.original, row: r.original }"
402
+ />
403
+ </td>
404
+ </tr>
405
+ }
406
+ }
407
+ }
408
+ @if (v.paddingBottom() > 0) {
409
+ <tr aria-hidden="true">
410
+ <td [attr.colspan]="aria.colCount()" [style.height.px]="v.paddingBottom()"></td>
411
+ </tr>
412
+ }
413
+ </tbody>
414
+ } @else {
415
+ <tbody>
416
+ @for (r of centerRows(); track r.id) {
417
+ <tr kjTableRow [kjRow]="r"
418
+ [attr.data-row-grouped]="r.getIsGrouped?.() ? '' : null"
419
+ (click)="onRowClick(r, $event)"
420
+ (dblclick)="onRowDblClick(r, $event)">
421
+ @if (showSelectionColumn()) {
422
+ <td class="kj-table-select-cell"
423
+ (mousedown)="rememberClickModifiers($event)"
424
+ (click)="$event.stopPropagation()">
425
+ <kj-checkbox
426
+ [checked]="r.getIsSelected()"
427
+ (checkedChange)="onRowCheckboxToggle(r)"
428
+ kjAriaLabel="Select row"
429
+ />
430
+ </td>
431
+ }
432
+ @for (c of r.getVisibleCells(); track c.id) {
433
+ <td kjTableCell [kjCell]="c" tabindex="-1"
434
+ [class.kj-table-cell--editing]="isEditing(c)"
435
+ [style.width.px]="kjEnableResize() ? c.column.getSize() : null"
436
+ (click)="onCellClick(c, $event)"
437
+ (dblclick)="onCellDblClick(c, $event)"
438
+ (keydown)="onCellKeydown(c, $event)">
439
+ @if (isEditing(c)) {
440
+ <span class="kj-table-cell-ghost" aria-hidden="true">{{ c.getValue() }}</span>
441
+ <span
442
+ kjCellEditorOutlet
443
+ class="kj-table-editor-anchor"
444
+ [kjEditor]="editorTypeFor(c)"
445
+ [kjValue]="c.getValue()"
446
+ [kjMeta]="editorMetaFor(c)"
447
+ (commit)="onEditorCommit(c, $event)"
448
+ (editCancel)="onEditorCancel()"
449
+ ></span>
450
+ } @else if (c.getIsGrouped?.()) {
451
+ <button type="button"
452
+ class="kj-table-group-toggle"
453
+ [attr.aria-expanded]="r.getIsExpanded?.() ? 'true' : 'false'"
454
+ (click)="onGroupToggle(r, $event)">
455
+ <span class="kj-table-group-toggle__chevron" aria-hidden="true">›</span>
456
+ {{ c.getValue() }}
457
+ <span class="kj-table-group-toggle__count">({{ r.subRows?.length ?? 0 }})</span>
458
+ </button>
459
+ } @else if (c.getIsAggregated?.()) {
460
+ {{ c.renderValue() }}
461
+ } @else if (c.getIsPlaceholder?.()) {
462
+ } @else {
463
+ {{ c.getValue() }}
464
+ }
465
+ </td>
466
+ }
467
+ </tr>
468
+ @if (kjRowExpansionTpl() && r.getIsExpanded?.() && !r.getIsGrouped?.()) {
469
+ <tr class="kj-table-expansion-row">
470
+ <td [attr.colspan]="aria.colCount()">
471
+ <ng-container
472
+ [ngTemplateOutlet]="kjRowExpansionTpl()!"
473
+ [ngTemplateOutletContext]="{ $implicit: r.original, row: r.original }"
474
+ />
475
+ </td>
476
+ </tr>
477
+ }
478
+ }
479
+ </tbody>
480
+ }
481
+
482
+ @if (kjEnableRowPinning() && t.table().getBottomRows().length > 0) {
483
+ <tbody class="kj-table-tbody-pinned" data-pin="bottom">
484
+ @for (r of t.table().getBottomRows(); track r.id) {
485
+ <tr kjTableRow [kjRow]="r"
486
+ (click)="onRowClick(r, $event)"
487
+ (dblclick)="onRowDblClick(r, $event)">
488
+ @if (showSelectionColumn()) {
489
+ <td class="kj-table-select-cell"
490
+ (mousedown)="rememberClickModifiers($event)"
491
+ (click)="$event.stopPropagation()">
492
+ <kj-checkbox
493
+ [checked]="r.getIsSelected()"
494
+ (checkedChange)="onRowCheckboxToggle(r)"
495
+ kjAriaLabel="Select row"
496
+ />
497
+ </td>
498
+ }
499
+ @for (c of r.getVisibleCells(); track c.id) {
500
+ <td kjTableCell [kjCell]="c" tabindex="-1">{{ c.getValue() }}</td>
501
+ }
502
+ </tr>
503
+ }
504
+ </tbody>
505
+ }
506
+ </table>
507
+
508
+ <ng-content select="[kjSidePanel]" />
509
+ </div>
510
+
511
+ @if (showEmpty()) {
512
+ <div class="kj-table-empty" role="status">
513
+ <ng-content select="[kjEmpty]" />
514
+ </div>
515
+ }
516
+ @if (hasError()) {
517
+ <div class="kj-table-error" role="alert">
518
+ <ng-content select="[kjError]" />
519
+ </div>
520
+ }
521
+ @if (isLoading()) {
522
+ <div class="kj-table-loading"
523
+ aria-live="polite"
524
+ aria-busy="true"
525
+ [attr.data-has-rows]="effectiveData().length > 0 ? '' : null">
526
+ <ng-content select="[kjLoading]">
527
+ <span class="kj-table-loading-fallback">Loading…</span>
528
+ </ng-content>
529
+ </div>
530
+ }
531
+
532
+ <ng-content />
533
+ </div>
534
+ `,
535
+ styleUrl: './table.css',
536
+ encapsulation: ViewEncapsulation.Emulated,
537
+ })
538
+ export class KjTableComponent<TData extends RowData = unknown> {
539
+ // ── Data ────────────────────────────────────────────────────────────────
540
+ // `kjColumns`, `kjData`, `kjGetRowId` are exposed via `hostDirectives` input
541
+ // forwarding (see the `@Component` metadata) — bindings on `<kj-table>`
542
+ // flow straight into the hosted `KjTable` directive. We read them back via
543
+ // the injected directive instance (`this.t`) when the wrapper needs them.
544
+
545
+ /**
546
+ * Resource-backed data source. When set, rows come from
547
+ * `kjResource.value().rows`, `kjLoading` is derived from `isLoading()`, and
548
+ * the error slot renders when `error()` is non-null. The wrapper writes
549
+ * the resolved rows into the hosted `KjTable.kjTableData` model — the
550
+ * underlying TanStack instance always sees a single rows source.
551
+ */
552
+ readonly kjResource = input<ResourceRef<KjResourceResult<TData> | undefined> | null>(null);
553
+
554
+ // ── Theming ─────────────────────────────────────────────────────────────
555
+ readonly kjDensity = input<'compact' | 'standard' | 'comfortable'>('standard');
556
+ readonly kjVariant = input<'bordered' | 'striped' | 'clean'>('bordered');
557
+ /** External "I'm loading" flag, ORed with the resource's `isLoading()`. */
558
+ readonly kjLoading = input(false);
559
+
560
+ // ── Selection ───────────────────────────────────────────────────────────
561
+ readonly kjSelection = model<Set<string> | string | null>(null);
562
+ readonly kjSelectionMode = input<'single' | 'multi' | 'none'>('none');
563
+ /**
564
+ * Whether the wrapper auto-renders a leading checkbox column. Defaults to
565
+ * `true` whenever selection is enabled; set `false` to drive selection
566
+ * purely from row clicks / external state without the column.
567
+ */
568
+ readonly kjShowSelectionColumn = input<boolean>(true);
569
+
570
+ // ── Persistence ─────────────────────────────────────────────────────────
571
+ readonly kjStorageKey = input<string | null>(null);
572
+ readonly kjStorageAdapter = input<KjStorageAdapter | null>(null);
573
+
574
+ // ── Virtualization ──────────────────────────────────────────────────────
575
+ readonly kjVirtual = input<boolean | 'auto'>('auto');
576
+ readonly kjEstimatedRowSize = input<number>(36);
577
+
578
+ // ── Feature toggles ─────────────────────────────────────────────────────
579
+ readonly kjEnableFilters = input<boolean>(false);
580
+ readonly kjEnableResize = input<boolean>(false);
581
+ readonly kjEnableRowPinning = input<boolean>(false);
582
+ readonly kjEditOnDoubleClick = input<boolean>(true);
583
+
584
+ // ── Row expansion template ─────────────────────────────────────────────
585
+ /** Template for master-detail row expansion. Receives `$implicit = row`. */
586
+ readonly kjRowExpansionTpl = contentChild<TemplateRef<unknown>>('kjRowExpansion');
587
+
588
+ // ── Outputs ─────────────────────────────────────────────────────────────
589
+ readonly cellEdit = output<KjCellEditEvent<TData>>();
590
+ readonly stateChange = output<KjTableState>();
591
+ readonly rowClick = output<KjRowClickEvent<TData>>();
592
+ readonly rowDoubleClick = output<KjRowClickEvent<TData>>();
593
+
594
+ // ── Refs ────────────────────────────────────────────────────────────────
595
+ /**
596
+ * The hosted `KjTable` directive instance. Exposed under the legacy
597
+ * `tableRef()` API for examples that drive the table imperatively
598
+ * (`tableRef().setState(...)`, `tableRef().setRowPinning(...)`).
599
+ *
600
+ * `t` is the template-side alias for the same instance, used everywhere
601
+ * the template needs the TanStack table proxy (`t.table().getRowModel()`).
602
+ */
603
+ protected readonly t = inject(KjTable) as unknown as KjTable<TData>;
604
+ readonly tableRef = (): KjTable<TData> => this.t;
605
+
606
+ // ── Internal state ──────────────────────────────────────────────────────
607
+ private readonly tokenStorage = inject(KJ_TABLE_STORAGE, { optional: true });
608
+
609
+ /** Tracks the cell currently in edit mode by row+column id. */
610
+ protected readonly editingCell = signal<{ rowId: string; columnId: string } | null>(null);
611
+
612
+ // ── Computed ────────────────────────────────────────────────────────────
613
+ /**
614
+ * Effective rows driving TanStack:
615
+ * - `kjResource` set → unwrap `resource.value().rows`
616
+ * - otherwise → use the hosted directive's `kjTableData` model
617
+ * (fed by `[kjData]` on the host).
618
+ */
619
+ protected readonly effectiveData = computed<TData[]>(() => {
620
+ const res = this.kjResource();
621
+ if (res) {
622
+ // Skip `.value()` when the resource is in error / loading — both throw
623
+ // or return stale data. The error / loading panes render instead, and
624
+ // the table model holds whatever the write-through effect last set.
625
+ if (res.error() != null || res.isLoading()) return [];
626
+ const v = res.value();
627
+ const rows = v?.rows;
628
+ return rows ? Array.from(rows) : [];
629
+ }
630
+ return this.t.kjTableData();
631
+ });
632
+
633
+ /**
634
+ * All center (non-pinned) rows from TanStack.
635
+ *
636
+ * When virtualization is active we skip pagination — the virtualizer is the
637
+ * windowing mechanism, so feeding it a 25-row page (TanStack's default) makes
638
+ * a 10k dataset look like 25 rows that can't scroll. `getPrePaginationRowModel`
639
+ * keeps sort + filter applied but returns the full slice.
640
+ */
641
+ protected readonly centerRows = computed<Row<TData>[]>(() => {
642
+ const tbl = this.t.table();
643
+ if (this.kjEnableRowPinning()) return tbl.getCenterRows();
644
+ return this.shouldVirtualize()
645
+ ? tbl.getPrePaginationRowModel().rows
646
+ : tbl.getRowModel().rows;
647
+ });
648
+
649
+ /**
650
+ * Whether the leading checkbox column should render. Auto-enables when
651
+ * selection mode is non-`none` AND the user hasn't opted out.
652
+ */
653
+ protected readonly showSelectionColumn = computed<boolean>(
654
+ () => this.kjSelectionMode() !== 'none' && this.kjShowSelectionColumn(),
655
+ );
656
+
657
+ /**
658
+ * Captured at mousedown on a select-cell so the subsequent checkbox
659
+ * `checkedChange` can branch on shift / ctrl/cmd without losing the modifier
660
+ * state (the keyboard modifiers are only on the originating MouseEvent;
661
+ * the change event from kj-checkbox doesn't carry them).
662
+ */
663
+ private lastClickShift = false;
664
+ private lastAnchorRowId: string | null = null;
665
+
666
+ /** True when the active resource is loading OR `kjLoading` is set. */
667
+ protected readonly isLoading = computed<boolean>(() => {
668
+ if (this.kjLoading()) return true;
669
+ const res = this.kjResource();
670
+ return res ? res.isLoading() : false;
671
+ });
672
+
673
+ /** True when the active resource is in error state. */
674
+ protected readonly hasError = computed<boolean>(() => {
675
+ const res = this.kjResource();
676
+ return res ? res.error() != null : false;
677
+ });
678
+
679
+ /** True when there are no rows AND we are not loading or errored. */
680
+ protected readonly showEmpty = computed<boolean>(
681
+ () => this.effectiveData().length === 0 && !this.isLoading() && !this.hasError(),
682
+ );
683
+
684
+ /**
685
+ * Whether row virtualization should be enabled. Counts against the
686
+ * pre-pagination row model so `'auto'` flips on for large datasets that
687
+ * would otherwise be split across paginated pages.
688
+ */
689
+ protected readonly shouldVirtualize = computed<boolean>(() => {
690
+ const mode = this.kjVirtual();
691
+ if (mode === true) return true;
692
+ if (mode === false) return false;
693
+ return this.t.table().getPrePaginationRowModel().rows.length > VIRTUAL_AUTO_THRESHOLD;
694
+ });
695
+
696
+ protected readonly aria = {
697
+ rowCount: computed(() => this.effectiveData().length + 1),
698
+ colCount: computed(() => {
699
+ const cols = this.t.kjTable();
700
+ // Approximate: flatten one level of column groups for ARIA.
701
+ let n = 0;
702
+ for (const c of cols) {
703
+ const sub = (c as { columns?: unknown[] }).columns;
704
+ n += Array.isArray(sub) ? sub.length : 1;
705
+ }
706
+ return n;
707
+ }),
708
+ };
709
+
710
+ constructor() {
711
+ // Wrapper's `kjDensity` input → hosted directive's density state. Both
712
+ // the user's external binding AND the toolbar's density toggle write
713
+ // into `KjTable.density` via `setState`, so a single source of truth
714
+ // backs the host's `data-density` attribute and the row-padding CSS.
715
+ //
716
+ // The internal `t.density()` read is wrapped in `untracked` so the
717
+ // effect only fires on `kjDensity` input changes — without that, a
718
+ // toolbar click would update `t.density`, re-trigger this effect, and
719
+ // get clobbered back to the input value (feedback loop).
720
+ effect(() => {
721
+ const next = this.kjDensity();
722
+ untracked(() => {
723
+ if (this.t.state.density() !== next) this.t.setState({ density: next });
724
+ });
725
+ });
726
+
727
+ // Pipe resource rows into the hosted KjTable.kjTableData model so the
728
+ // single TanStack instance always sees one rows source. When kjResource
729
+ // is null the user's `[kjData]` binding flows through unchanged.
730
+ //
731
+ // `resource.value()` throws when the resource is in an error state
732
+ // (Angular's contract — read errors live on `.error()`). We guard on
733
+ // both `error()` and `isLoading()` so the error / loading panes own the
734
+ // UX while the table model keeps the last-known rows empty.
735
+ effect(() => {
736
+ const res = this.kjResource();
737
+ if (!res) {
738
+ // No resource → clear the manual-pagination total so the table
739
+ // falls back to client-side pagination on the user's `[kjData]`.
740
+ this.t.setRowCount(null);
741
+ return;
742
+ }
743
+ if (res.error() != null) {
744
+ this.t.kjTableData.set([]);
745
+ return;
746
+ }
747
+ if (res.isLoading()) return;
748
+ const value = res.value();
749
+ const rows = value?.rows;
750
+ this.t.kjTableData.set(rows ? Array.from(rows) as TData[] : []);
751
+ // Flip into manual-pagination mode and report the remote total
752
+ // so the pagination footer / status bar see the full dataset
753
+ // instead of just the current page slice.
754
+ this.t.setRowCount(value?.rowCount ?? null);
755
+ });
756
+
757
+ // Persistence: on init, read from adapter and seed table state.
758
+ effect(() => {
759
+ const key = this.kjStorageKey();
760
+ if (!key) return;
761
+ const adapter = this.kjStorageAdapter() ?? this.tokenStorage;
762
+ if (!adapter) return;
763
+ const tbl = untracked(() => this.t);
764
+ if (!tbl) return;
765
+ const persisted = adapter.read<Partial<KjTableState>>(key);
766
+ if (persisted) {
767
+ untracked(() => tbl.setState(persisted));
768
+ }
769
+ });
770
+
771
+ // Persistence: watch state and write through. Reading `state()` once
772
+ // is enough — the single signal invalidates on any slice change.
773
+ effect(() => {
774
+ const key = this.kjStorageKey();
775
+ if (!key) return;
776
+ const adapter = this.kjStorageAdapter() ?? this.tokenStorage;
777
+ if (!adapter) return;
778
+ adapter.write(key, this.t.state());
779
+ });
780
+
781
+ // State-change emission.
782
+ effect(() => {
783
+ this.stateChange.emit(this.t.state());
784
+ });
785
+ }
786
+
787
+ // ── Cell-edit handlers ──────────────────────────────────────────────────
788
+ protected isEditing(cell: Cell<TData, unknown>): boolean {
789
+ const e = this.editingCell();
790
+ return !!e && e.rowId === cell.row.id && e.columnId === cell.column.id;
791
+ }
792
+
793
+ protected onCellClick(cell: Cell<TData, unknown>, _event: MouseEvent): void {
794
+ if (this.kjEditOnDoubleClick()) return;
795
+ this.tryBeginEdit(cell);
796
+ }
797
+
798
+ protected onCellDblClick(cell: Cell<TData, unknown>, _event: MouseEvent): void {
799
+ if (!this.kjEditOnDoubleClick()) return;
800
+ this.tryBeginEdit(cell);
801
+ }
802
+
803
+ protected onCellKeydown(cell: Cell<TData, unknown>, event: KeyboardEvent): void {
804
+ if (event.key === 'F2') {
805
+ event.preventDefault();
806
+ this.tryBeginEdit(cell);
807
+ } else if (event.key === 'Escape' && this.isEditing(cell)) {
808
+ this.editingCell.set(null);
809
+ } else if (event.key === ' ' && !this.isEditing(cell)) {
810
+ // Space toggles row selection when selection is enabled (WCAG grid pattern).
811
+ const mode = this.kjSelectionMode();
812
+ if (mode === 'multi') {
813
+ event.preventDefault();
814
+ (cell.row as { toggleSelected?: () => void }).toggleSelected?.();
815
+ } else if (mode === 'single') {
816
+ event.preventDefault();
817
+ this.t.table().setRowSelection({ [cell.row.id]: true });
818
+ }
819
+ } else if ((event.ctrlKey || event.metaKey) && (event.key === 'a' || event.key === 'A')) {
820
+ // Cmd/Ctrl+A — select all (multi mode only).
821
+ if (this.kjSelectionMode() === 'multi') {
822
+ event.preventDefault();
823
+ this.t.table().toggleAllRowsSelected(true);
824
+ }
825
+ }
826
+ }
827
+
828
+ private tryBeginEdit(cell: Cell<TData, unknown>): void {
829
+ const meta = cellMeta(cell.column);
830
+ if (!meta?.editable) return;
831
+ this.editingCell.set({ rowId: cell.row.id, columnId: cell.column.id });
832
+ }
833
+
834
+ // ── Row-click handlers ──────────────────────────────────────────────────
835
+ protected onRowClick(row: Row<TData>, event: MouseEvent): void {
836
+ // A click that lands on an interactive control inside the row (group
837
+ // toggle button, inline editor, link, etc.) should not double-toggle
838
+ // row selection — only bare-row clicks count.
839
+ const target = event.target as HTMLElement | null;
840
+ if (target?.closest('button, a, input, select, textarea, .kj-table-editor-anchor')) {
841
+ this.rowClick.emit({ row: row.original, event });
842
+ return;
843
+ }
844
+ this.applySelectionFromClick(row, event);
845
+ this.rowClick.emit({ row: row.original, event });
846
+ }
847
+
848
+ protected onRowDblClick(row: Row<TData>, event: MouseEvent): void {
849
+ this.rowDoubleClick.emit({ row: row.original, event });
850
+ }
851
+
852
+ /**
853
+ * Toggle / replace row selection based on `kjSelectionMode`:
854
+ * - `'multi'` → plain click toggles this row and moves the anchor.
855
+ * Shift-click selects every row between the anchor and here (range).
856
+ * Ctrl/Cmd-click toggles this row only (anchor moves, others kept).
857
+ * - `'single'` → set this row as the sole selection.
858
+ * - `'none'` → no-op.
859
+ */
860
+ private applySelectionFromClick(row: Row<TData>, event: MouseEvent): void {
861
+ const mode = this.kjSelectionMode();
862
+ if (mode === 'none') return;
863
+ const tbl = this.t.table();
864
+ if (mode === 'single') {
865
+ tbl.setRowSelection({ [row.id]: true });
866
+ this.lastAnchorRowId = row.id;
867
+ return;
868
+ }
869
+ // multi
870
+ if (event.shiftKey && this.lastAnchorRowId !== null) {
871
+ this.selectRange(this.lastAnchorRowId, row.id, true);
872
+ return;
873
+ }
874
+ (row as { toggleSelected?: () => void }).toggleSelected?.();
875
+ this.lastAnchorRowId = row.id;
876
+ }
877
+
878
+ /**
879
+ * Capture the shift modifier from mousedown on a select-cell. The
880
+ * checkbox's `checkedChange` doesn't carry the originating mouse event,
881
+ * so we stash the modifier and consume it in `onRowCheckboxToggle`.
882
+ */
883
+ protected rememberClickModifiers(event: MouseEvent): void {
884
+ this.lastClickShift = event.shiftKey;
885
+ }
886
+
887
+ /** Click on a row's checkbox: shift extends from anchor, else plain toggle. */
888
+ protected onRowCheckboxToggle(row: Row<TData>): void {
889
+ const wasShift = this.lastClickShift;
890
+ this.lastClickShift = false;
891
+ if (wasShift && this.lastAnchorRowId !== null && this.kjSelectionMode() === 'multi') {
892
+ this.selectRange(this.lastAnchorRowId, row.id, true);
893
+ return;
894
+ }
895
+ (row as { toggleSelected?: () => void }).toggleSelected?.();
896
+ this.lastAnchorRowId = row.id;
897
+ }
898
+
899
+ /** Header "select all" checkbox change. */
900
+ protected onSelectAll(checked: boolean): void {
901
+ this.t.table().toggleAllPageRowsSelected(checked);
902
+ }
903
+
904
+ /**
905
+ * Set every row between `fromId` and `toId` (inclusive, order-agnostic) to
906
+ * `selected`. Existing selections OUTSIDE that window are preserved.
907
+ */
908
+ private selectRange(fromId: string, toId: string, selected: boolean): void {
909
+ const rows = this.centerRows();
910
+ const fromIdx = rows.findIndex((r) => r.id === fromId);
911
+ const toIdx = rows.findIndex((r) => r.id === toId);
912
+ if (fromIdx === -1 || toIdx === -1) return;
913
+ const [start, end] = fromIdx < toIdx ? [fromIdx, toIdx] : [toIdx, fromIdx];
914
+ const next: Record<string, boolean> = { ...this.t.state.rowSelection() };
915
+ for (let i = start; i <= end; i++) {
916
+ next[rows[i].id] = selected;
917
+ }
918
+ this.t.table().setRowSelection(next);
919
+ }
920
+
921
+ /**
922
+ * Toggle a grouped row's expanded state. Wired to the click handler on the
923
+ * group-cell's toggle button; `stopPropagation` prevents the parent row's
924
+ * `(click)` from firing a row-click event for what is really a UI control.
925
+ */
926
+ protected onGroupToggle(row: Row<TData>, event: MouseEvent): void {
927
+ event.stopPropagation();
928
+ (row as { toggleExpanded?: () => void }).toggleExpanded?.();
929
+ }
930
+
931
+ // ── Header helpers ──────────────────────────────────────────────────────
932
+ protected headerPin(h: Header<TData, unknown>): 'left' | 'right' | null {
933
+ const p = h.column.getIsPinned?.();
934
+ return p === 'left' || p === 'right' ? p : null;
935
+ }
936
+
937
+ /**
938
+ * Lucide icon name for a sortable header's indicator. We read the column's
939
+ * current sort state directly so the template re-evaluates whenever the
940
+ * parent sort signal changes (TanStack's table proxy is signal-backed).
941
+ */
942
+ protected sortIcon(h: Header<TData, unknown>): 'chevron-up' | 'chevron-down' | 'chevrons-up-down' {
943
+ const dir = h.column.getIsSorted?.();
944
+ if (dir === 'asc') return 'chevron-up';
945
+ if (dir === 'desc') return 'chevron-down';
946
+ return 'chevrons-up-down';
947
+ }
948
+
949
+ protected filterTypeFor(col: Column<TData, unknown>): string | null {
950
+ const meta = (col.columnDef.meta as { kj?: KjColumnMeta<TData> } | undefined)?.kj;
951
+ if (!meta) return null;
952
+ if (meta.filterable === false) return null;
953
+ const type = meta.type;
954
+ if (!type) return null;
955
+ return type in BUILTIN_FILTERS ? type : null;
956
+ }
957
+
958
+ // ── Template helpers for the editor / filter outlet directives ─────────
959
+ /** Resolves the editor component for a cell — column `meta.kj.editor`
960
+ * override, else the built-in editor that matches `meta.kj.type`. */
961
+ protected editorTypeFor(cell: Cell<TData, unknown>): Type<unknown> | null {
962
+ const meta = (cell.column.columnDef.meta as { kj?: KjColumnMeta<TData> } | undefined)?.kj;
963
+ const custom = meta?.editor as Type<unknown> | undefined;
964
+ if (custom) return custom;
965
+ const type = meta?.type;
966
+ if (!type) return BUILTIN_EDITORS['text']!;
967
+ return BUILTIN_EDITORS[type] ?? null;
968
+ }
969
+
970
+ /** Build the meta bag handed to the editor through `KJ_EDITOR_CONTRACT`.
971
+ * Select options, min/max, custom params travel through here so editors
972
+ * don't need imperative input binding from the outlet. */
973
+ protected editorMetaFor(cell: Cell<TData, unknown>): Record<string, unknown> | undefined {
974
+ const meta = (cell.column.columnDef.meta as { kj?: KjColumnMeta<TData> } | undefined)?.kj;
975
+ if (!meta) return undefined;
976
+ const out: Record<string, unknown> = {};
977
+ if (meta.selectOptions) out['options'] = meta.selectOptions;
978
+ return Object.keys(out).length > 0 ? out : undefined;
979
+ }
980
+
981
+ /** Resolves the filter component for a column — `meta.kj.filterUi` override
982
+ * else the built-in filter that matches `type`. */
983
+ protected filterRendererFor(col: Column<TData, unknown>, type: string): Type<unknown> | null {
984
+ const meta = (col.columnDef.meta as { kj?: KjColumnMeta<TData> } | undefined)?.kj;
985
+ const custom = meta?.filterUi as Type<unknown> | undefined;
986
+ return custom ?? BUILTIN_FILTERS[type] ?? null;
987
+ }
988
+
989
+ /** Editor `(commit)` from `KjCellEditorOutlet`: forward + close the editor. */
990
+ protected onEditorCommit(cell: Cell<TData, unknown>, next: unknown): void {
991
+ this.cellEdit.emit({
992
+ row: cell.row.original,
993
+ columnId: cell.column.id,
994
+ oldValue: cell.getValue(),
995
+ newValue: next,
996
+ });
997
+ this.editingCell.set(null);
998
+ }
999
+
1000
+ /** Editor `(cancel)` from `KjCellEditorOutlet`: just close the editor. */
1001
+ protected onEditorCancel(): void {
1002
+ this.editingCell.set(null);
1003
+ }
1004
+ }
1005
+
1006
+ // ── helpers ───────────────────────────────────────────────────────────────
1007
+ function cellMeta<TData>(col: Column<TData, unknown>): KjColumnMeta<TData> | undefined {
1008
+ return (col.columnDef.meta as { kj?: KjColumnMeta<TData> } | undefined)?.kj;
1009
+ }