@keenthemes/ktui 1.1.6 → 1.2.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 (492) hide show
  1. package/README.md +24 -0
  2. package/dist/ktui.js +4321 -2055
  3. package/dist/ktui.min.js +1 -1
  4. package/dist/ktui.min.js.map +1 -1
  5. package/dist/styles.css +108 -6
  6. package/lib/cjs/components/accordion/accordion.d.ts +32 -0
  7. package/lib/cjs/components/accordion/accordion.d.ts.map +1 -0
  8. package/lib/cjs/components/accordion/index.d.ts +7 -0
  9. package/lib/cjs/components/accordion/index.d.ts.map +1 -0
  10. package/lib/cjs/components/accordion/types.d.ts +15 -0
  11. package/lib/cjs/components/accordion/types.d.ts.map +1 -0
  12. package/lib/cjs/components/clipboard/clipboard.d.ts +37 -0
  13. package/lib/cjs/components/clipboard/clipboard.d.ts.map +1 -0
  14. package/lib/cjs/components/clipboard/clipboard.js +402 -0
  15. package/lib/cjs/components/clipboard/clipboard.js.map +1 -0
  16. package/lib/cjs/components/clipboard/index.d.ts +3 -0
  17. package/lib/cjs/components/clipboard/index.d.ts.map +1 -0
  18. package/lib/cjs/components/clipboard/index.js +6 -0
  19. package/lib/cjs/components/clipboard/index.js.map +1 -0
  20. package/lib/cjs/components/clipboard/types.d.ts +44 -0
  21. package/lib/cjs/components/clipboard/types.d.ts.map +1 -0
  22. package/lib/cjs/components/clipboard/types.js +7 -0
  23. package/lib/cjs/components/clipboard/types.js.map +1 -0
  24. package/lib/cjs/components/collapse/collapse.d.ts +28 -0
  25. package/lib/cjs/components/collapse/collapse.d.ts.map +1 -0
  26. package/lib/cjs/components/collapse/index.d.ts +7 -0
  27. package/lib/cjs/components/collapse/index.d.ts.map +1 -0
  28. package/lib/cjs/components/collapse/types.d.ts +15 -0
  29. package/lib/cjs/components/collapse/types.d.ts.map +1 -0
  30. package/lib/cjs/components/component.d.ts +44 -0
  31. package/lib/cjs/components/component.d.ts.map +1 -0
  32. package/lib/cjs/components/constants.d.ts +6 -0
  33. package/lib/cjs/components/constants.d.ts.map +1 -0
  34. package/lib/cjs/components/datatable/datatable-checkbox.d.ts +16 -0
  35. package/lib/cjs/components/datatable/datatable-checkbox.d.ts.map +1 -0
  36. package/lib/cjs/components/datatable/datatable-sort.d.ts +16 -0
  37. package/lib/cjs/components/datatable/datatable-sort.d.ts.map +1 -0
  38. package/lib/cjs/components/datatable/datatable.d.ts +339 -0
  39. package/lib/cjs/components/datatable/datatable.d.ts.map +1 -0
  40. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  41. package/lib/cjs/components/datatable/index.d.ts +7 -0
  42. package/lib/cjs/components/datatable/index.d.ts.map +1 -0
  43. package/lib/cjs/components/datatable/types.d.ts +166 -0
  44. package/lib/cjs/components/datatable/types.d.ts.map +1 -0
  45. package/lib/cjs/components/dismiss/dismiss.d.ts +30 -0
  46. package/lib/cjs/components/dismiss/dismiss.d.ts.map +1 -0
  47. package/lib/cjs/components/dismiss/index.d.ts +7 -0
  48. package/lib/cjs/components/dismiss/index.d.ts.map +1 -0
  49. package/lib/cjs/components/dismiss/types.d.ts +15 -0
  50. package/lib/cjs/components/dismiss/types.d.ts.map +1 -0
  51. package/lib/cjs/components/drawer/drawer.d.ts +63 -0
  52. package/lib/cjs/components/drawer/drawer.d.ts.map +1 -0
  53. package/lib/cjs/components/drawer/index.d.ts +7 -0
  54. package/lib/cjs/components/drawer/index.d.ts.map +1 -0
  55. package/lib/cjs/components/drawer/types.d.ts +27 -0
  56. package/lib/cjs/components/drawer/types.d.ts.map +1 -0
  57. package/lib/cjs/components/dropdown/dropdown.d.ts +71 -0
  58. package/lib/cjs/components/dropdown/dropdown.d.ts.map +1 -0
  59. package/lib/cjs/components/dropdown/index.d.ts +7 -0
  60. package/lib/cjs/components/dropdown/index.d.ts.map +1 -0
  61. package/lib/cjs/components/dropdown/types.d.ts +27 -0
  62. package/lib/cjs/components/dropdown/types.d.ts.map +1 -0
  63. package/lib/cjs/components/image-input/image-input.d.ts +42 -0
  64. package/lib/cjs/components/image-input/image-input.d.ts.map +1 -0
  65. package/lib/cjs/components/image-input/index.d.ts +7 -0
  66. package/lib/cjs/components/image-input/index.d.ts.map +1 -0
  67. package/lib/cjs/components/image-input/types.d.ts +12 -0
  68. package/lib/cjs/components/image-input/types.d.ts.map +1 -0
  69. package/lib/cjs/components/modal/index.d.ts +7 -0
  70. package/lib/cjs/components/modal/index.d.ts.map +1 -0
  71. package/lib/cjs/components/modal/modal.d.ts +45 -0
  72. package/lib/cjs/components/modal/modal.d.ts.map +1 -0
  73. package/lib/cjs/components/modal/types.d.ts +21 -0
  74. package/lib/cjs/components/modal/types.d.ts.map +1 -0
  75. package/lib/cjs/components/range-slider/index.d.ts +7 -0
  76. package/lib/cjs/components/range-slider/index.d.ts.map +1 -0
  77. package/lib/cjs/components/range-slider/index.js +10 -0
  78. package/lib/cjs/components/range-slider/index.js.map +1 -0
  79. package/lib/cjs/components/range-slider/range-slider.d.ts +42 -0
  80. package/lib/cjs/components/range-slider/range-slider.d.ts.map +1 -0
  81. package/lib/cjs/components/range-slider/range-slider.js +254 -0
  82. package/lib/cjs/components/range-slider/range-slider.js.map +1 -0
  83. package/lib/cjs/components/range-slider/types.d.ts +33 -0
  84. package/lib/cjs/components/range-slider/types.d.ts.map +1 -0
  85. package/lib/cjs/components/range-slider/types.js +7 -0
  86. package/lib/cjs/components/range-slider/types.js.map +1 -0
  87. package/lib/cjs/components/rating/index.d.ts +7 -0
  88. package/lib/cjs/components/rating/index.d.ts.map +1 -0
  89. package/lib/cjs/components/rating/index.js +10 -0
  90. package/lib/cjs/components/rating/index.js.map +1 -0
  91. package/lib/cjs/components/rating/rating.d.ts +31 -0
  92. package/lib/cjs/components/rating/rating.d.ts.map +1 -0
  93. package/lib/cjs/components/rating/rating.js +244 -0
  94. package/lib/cjs/components/rating/rating.js.map +1 -0
  95. package/lib/cjs/components/rating/types.d.ts +25 -0
  96. package/lib/cjs/components/rating/types.d.ts.map +1 -0
  97. package/lib/cjs/components/rating/types.js +7 -0
  98. package/lib/cjs/components/rating/types.js.map +1 -0
  99. package/lib/cjs/components/reparent/index.d.ts +7 -0
  100. package/lib/cjs/components/reparent/index.d.ts.map +1 -0
  101. package/lib/cjs/components/reparent/reparent.d.ts +25 -0
  102. package/lib/cjs/components/reparent/reparent.d.ts.map +1 -0
  103. package/lib/cjs/components/reparent/types.d.ts +13 -0
  104. package/lib/cjs/components/reparent/types.d.ts.map +1 -0
  105. package/lib/cjs/components/repeater/index.d.ts +7 -0
  106. package/lib/cjs/components/repeater/index.d.ts.map +1 -0
  107. package/lib/cjs/components/repeater/index.js +10 -0
  108. package/lib/cjs/components/repeater/index.js.map +1 -0
  109. package/lib/cjs/components/repeater/repeater.d.ts +33 -0
  110. package/lib/cjs/components/repeater/repeater.d.ts.map +1 -0
  111. package/lib/cjs/components/repeater/repeater.js +174 -0
  112. package/lib/cjs/components/repeater/repeater.js.map +1 -0
  113. package/lib/cjs/components/repeater/types.d.ts +18 -0
  114. package/lib/cjs/components/repeater/types.d.ts.map +1 -0
  115. package/lib/cjs/components/repeater/types.js +7 -0
  116. package/lib/cjs/components/repeater/types.js.map +1 -0
  117. package/lib/cjs/components/scrollable/index.d.ts +7 -0
  118. package/lib/cjs/components/scrollable/index.d.ts.map +1 -0
  119. package/lib/cjs/components/scrollable/scrollable.d.ts +37 -0
  120. package/lib/cjs/components/scrollable/scrollable.d.ts.map +1 -0
  121. package/lib/cjs/components/scrollable/types.d.ts +15 -0
  122. package/lib/cjs/components/scrollable/types.d.ts.map +1 -0
  123. package/lib/cjs/components/scrollspy/index.d.ts +7 -0
  124. package/lib/cjs/components/scrollspy/index.d.ts.map +1 -0
  125. package/lib/cjs/components/scrollspy/scrollspy.d.ts +35 -0
  126. package/lib/cjs/components/scrollspy/scrollspy.d.ts.map +1 -0
  127. package/lib/cjs/components/scrollspy/types.d.ts +14 -0
  128. package/lib/cjs/components/scrollspy/types.d.ts.map +1 -0
  129. package/lib/cjs/components/scrollto/index.d.ts +7 -0
  130. package/lib/cjs/components/scrollto/index.d.ts.map +1 -0
  131. package/lib/cjs/components/scrollto/scrollto.d.ts +28 -0
  132. package/lib/cjs/components/scrollto/scrollto.d.ts.map +1 -0
  133. package/lib/cjs/components/scrollto/types.d.ts +14 -0
  134. package/lib/cjs/components/scrollto/types.d.ts.map +1 -0
  135. package/lib/cjs/components/select/combobox.d.ts +52 -0
  136. package/lib/cjs/components/select/combobox.d.ts.map +1 -0
  137. package/lib/cjs/components/select/config.d.ts +105 -0
  138. package/lib/cjs/components/select/config.d.ts.map +1 -0
  139. package/lib/cjs/components/select/dropdown.d.ts +101 -0
  140. package/lib/cjs/components/select/dropdown.d.ts.map +1 -0
  141. package/lib/cjs/components/select/index.d.ts +13 -0
  142. package/lib/cjs/components/select/index.d.ts.map +1 -0
  143. package/lib/cjs/components/select/option.d.ts +23 -0
  144. package/lib/cjs/components/select/option.d.ts.map +1 -0
  145. package/lib/cjs/components/select/remote.d.ts +91 -0
  146. package/lib/cjs/components/select/remote.d.ts.map +1 -0
  147. package/lib/cjs/components/select/search.d.ts +67 -0
  148. package/lib/cjs/components/select/search.d.ts.map +1 -0
  149. package/lib/cjs/components/select/select.d.ts +427 -0
  150. package/lib/cjs/components/select/select.d.ts.map +1 -0
  151. package/lib/cjs/components/select/select.js +3 -0
  152. package/lib/cjs/components/select/select.js.map +1 -1
  153. package/lib/cjs/components/select/tags.d.ts +32 -0
  154. package/lib/cjs/components/select/tags.d.ts.map +1 -0
  155. package/lib/cjs/components/select/templates.d.ts +79 -0
  156. package/lib/cjs/components/select/templates.d.ts.map +1 -0
  157. package/lib/cjs/components/select/types.d.ts +23 -0
  158. package/lib/cjs/components/select/types.d.ts.map +1 -0
  159. package/lib/cjs/components/select/utils.d.ts +130 -0
  160. package/lib/cjs/components/select/utils.d.ts.map +1 -0
  161. package/lib/cjs/components/select/utils.js +3 -1
  162. package/lib/cjs/components/select/utils.js.map +1 -1
  163. package/lib/cjs/components/stepper/index.d.ts +7 -0
  164. package/lib/cjs/components/stepper/index.d.ts.map +1 -0
  165. package/lib/cjs/components/stepper/stepper.d.ts +53 -0
  166. package/lib/cjs/components/stepper/stepper.d.ts.map +1 -0
  167. package/lib/cjs/components/stepper/types.d.ts +12 -0
  168. package/lib/cjs/components/stepper/types.d.ts.map +1 -0
  169. package/lib/cjs/components/sticky/index.d.ts +7 -0
  170. package/lib/cjs/components/sticky/index.d.ts.map +1 -0
  171. package/lib/cjs/components/sticky/sticky.d.ts +51 -0
  172. package/lib/cjs/components/sticky/sticky.d.ts.map +1 -0
  173. package/lib/cjs/components/sticky/sticky.js +3 -1
  174. package/lib/cjs/components/sticky/sticky.js.map +1 -1
  175. package/lib/cjs/components/sticky/types.d.ts +28 -0
  176. package/lib/cjs/components/sticky/types.d.ts.map +1 -0
  177. package/lib/cjs/components/tabs/index.d.ts +7 -0
  178. package/lib/cjs/components/tabs/index.d.ts.map +1 -0
  179. package/lib/cjs/components/tabs/tabs.d.ts +38 -0
  180. package/lib/cjs/components/tabs/tabs.d.ts.map +1 -0
  181. package/lib/cjs/components/tabs/types.d.ts +12 -0
  182. package/lib/cjs/components/tabs/types.d.ts.map +1 -0
  183. package/lib/cjs/components/theme-switch/index.d.ts +7 -0
  184. package/lib/cjs/components/theme-switch/index.d.ts.map +1 -0
  185. package/lib/cjs/components/theme-switch/theme-switch.d.ts +33 -0
  186. package/lib/cjs/components/theme-switch/theme-switch.d.ts.map +1 -0
  187. package/lib/cjs/components/theme-switch/types.d.ts +13 -0
  188. package/lib/cjs/components/theme-switch/types.d.ts.map +1 -0
  189. package/lib/cjs/components/toast/index.d.ts +7 -0
  190. package/lib/cjs/components/toast/index.d.ts.map +1 -0
  191. package/lib/cjs/components/toast/toast.d.ts +76 -0
  192. package/lib/cjs/components/toast/toast.d.ts.map +1 -0
  193. package/lib/cjs/components/toast/types.d.ts +146 -0
  194. package/lib/cjs/components/toast/types.d.ts.map +1 -0
  195. package/lib/cjs/components/toggle/index.d.ts +7 -0
  196. package/lib/cjs/components/toggle/index.d.ts.map +1 -0
  197. package/lib/cjs/components/toggle/toggle.d.ts +31 -0
  198. package/lib/cjs/components/toggle/toggle.d.ts.map +1 -0
  199. package/lib/cjs/components/toggle/types.d.ts +17 -0
  200. package/lib/cjs/components/toggle/types.d.ts.map +1 -0
  201. package/lib/cjs/components/toggle-password/index.d.ts +7 -0
  202. package/lib/cjs/components/toggle-password/index.d.ts.map +1 -0
  203. package/lib/cjs/components/toggle-password/toggle-password.d.ts +32 -0
  204. package/lib/cjs/components/toggle-password/toggle-password.d.ts.map +1 -0
  205. package/lib/cjs/components/toggle-password/types.d.ts +12 -0
  206. package/lib/cjs/components/toggle-password/types.d.ts.map +1 -0
  207. package/lib/cjs/components/tooltip/index.d.ts +7 -0
  208. package/lib/cjs/components/tooltip/index.d.ts.map +1 -0
  209. package/lib/cjs/components/tooltip/tooltip.d.ts +46 -0
  210. package/lib/cjs/components/tooltip/tooltip.d.ts.map +1 -0
  211. package/lib/cjs/components/tooltip/types.d.ts +26 -0
  212. package/lib/cjs/components/tooltip/types.d.ts.map +1 -0
  213. package/lib/cjs/helpers/data.d.ts +13 -0
  214. package/lib/cjs/helpers/data.d.ts.map +1 -0
  215. package/lib/cjs/helpers/dom.d.ts +42 -0
  216. package/lib/cjs/helpers/dom.d.ts.map +1 -0
  217. package/lib/cjs/helpers/event-handler.d.ts +14 -0
  218. package/lib/cjs/helpers/event-handler.d.ts.map +1 -0
  219. package/lib/cjs/helpers/utils.d.ts +25 -0
  220. package/lib/cjs/helpers/utils.d.ts.map +1 -0
  221. package/lib/cjs/index.d.ts +122 -0
  222. package/lib/cjs/index.d.ts.map +1 -0
  223. package/lib/cjs/index.js +17 -1
  224. package/lib/cjs/index.js.map +1 -1
  225. package/lib/cjs/types.d.ts +17 -0
  226. package/lib/cjs/types.d.ts.map +1 -0
  227. package/lib/esm/components/accordion/accordion.d.ts +32 -0
  228. package/lib/esm/components/accordion/accordion.d.ts.map +1 -0
  229. package/lib/esm/components/accordion/index.d.ts +7 -0
  230. package/lib/esm/components/accordion/index.d.ts.map +1 -0
  231. package/lib/esm/components/accordion/types.d.ts +15 -0
  232. package/lib/esm/components/accordion/types.d.ts.map +1 -0
  233. package/lib/esm/components/clipboard/clipboard.d.ts +37 -0
  234. package/lib/esm/components/clipboard/clipboard.d.ts.map +1 -0
  235. package/lib/esm/components/clipboard/clipboard.js +399 -0
  236. package/lib/esm/components/clipboard/clipboard.js.map +1 -0
  237. package/lib/esm/components/clipboard/index.d.ts +3 -0
  238. package/lib/esm/components/clipboard/index.d.ts.map +1 -0
  239. package/lib/esm/components/clipboard/index.js +2 -0
  240. package/lib/esm/components/clipboard/index.js.map +1 -0
  241. package/lib/esm/components/clipboard/types.d.ts +44 -0
  242. package/lib/esm/components/clipboard/types.d.ts.map +1 -0
  243. package/lib/esm/components/clipboard/types.js +6 -0
  244. package/lib/esm/components/clipboard/types.js.map +1 -0
  245. package/lib/esm/components/collapse/collapse.d.ts +28 -0
  246. package/lib/esm/components/collapse/collapse.d.ts.map +1 -0
  247. package/lib/esm/components/collapse/index.d.ts +7 -0
  248. package/lib/esm/components/collapse/index.d.ts.map +1 -0
  249. package/lib/esm/components/collapse/types.d.ts +15 -0
  250. package/lib/esm/components/collapse/types.d.ts.map +1 -0
  251. package/lib/esm/components/component.d.ts +44 -0
  252. package/lib/esm/components/component.d.ts.map +1 -0
  253. package/lib/esm/components/constants.d.ts +6 -0
  254. package/lib/esm/components/constants.d.ts.map +1 -0
  255. package/lib/esm/components/datatable/datatable-checkbox.d.ts +16 -0
  256. package/lib/esm/components/datatable/datatable-checkbox.d.ts.map +1 -0
  257. package/lib/esm/components/datatable/datatable-sort.d.ts +16 -0
  258. package/lib/esm/components/datatable/datatable-sort.d.ts.map +1 -0
  259. package/lib/esm/components/datatable/datatable.d.ts +339 -0
  260. package/lib/esm/components/datatable/datatable.d.ts.map +1 -0
  261. package/lib/esm/components/datatable/datatable.js.map +1 -1
  262. package/lib/esm/components/datatable/index.d.ts +7 -0
  263. package/lib/esm/components/datatable/index.d.ts.map +1 -0
  264. package/lib/esm/components/datatable/types.d.ts +166 -0
  265. package/lib/esm/components/datatable/types.d.ts.map +1 -0
  266. package/lib/esm/components/dismiss/dismiss.d.ts +30 -0
  267. package/lib/esm/components/dismiss/dismiss.d.ts.map +1 -0
  268. package/lib/esm/components/dismiss/index.d.ts +7 -0
  269. package/lib/esm/components/dismiss/index.d.ts.map +1 -0
  270. package/lib/esm/components/dismiss/types.d.ts +15 -0
  271. package/lib/esm/components/dismiss/types.d.ts.map +1 -0
  272. package/lib/esm/components/drawer/drawer.d.ts +63 -0
  273. package/lib/esm/components/drawer/drawer.d.ts.map +1 -0
  274. package/lib/esm/components/drawer/index.d.ts +7 -0
  275. package/lib/esm/components/drawer/index.d.ts.map +1 -0
  276. package/lib/esm/components/drawer/types.d.ts +27 -0
  277. package/lib/esm/components/drawer/types.d.ts.map +1 -0
  278. package/lib/esm/components/dropdown/dropdown.d.ts +71 -0
  279. package/lib/esm/components/dropdown/dropdown.d.ts.map +1 -0
  280. package/lib/esm/components/dropdown/index.d.ts +7 -0
  281. package/lib/esm/components/dropdown/index.d.ts.map +1 -0
  282. package/lib/esm/components/dropdown/types.d.ts +27 -0
  283. package/lib/esm/components/dropdown/types.d.ts.map +1 -0
  284. package/lib/esm/components/image-input/image-input.d.ts +42 -0
  285. package/lib/esm/components/image-input/image-input.d.ts.map +1 -0
  286. package/lib/esm/components/image-input/index.d.ts +7 -0
  287. package/lib/esm/components/image-input/index.d.ts.map +1 -0
  288. package/lib/esm/components/image-input/types.d.ts +12 -0
  289. package/lib/esm/components/image-input/types.d.ts.map +1 -0
  290. package/lib/esm/components/modal/index.d.ts +7 -0
  291. package/lib/esm/components/modal/index.d.ts.map +1 -0
  292. package/lib/esm/components/modal/modal.d.ts +45 -0
  293. package/lib/esm/components/modal/modal.d.ts.map +1 -0
  294. package/lib/esm/components/modal/types.d.ts +21 -0
  295. package/lib/esm/components/modal/types.d.ts.map +1 -0
  296. package/lib/esm/components/range-slider/index.d.ts +7 -0
  297. package/lib/esm/components/range-slider/index.d.ts.map +1 -0
  298. package/lib/esm/components/range-slider/index.js +6 -0
  299. package/lib/esm/components/range-slider/index.js.map +1 -0
  300. package/lib/esm/components/range-slider/range-slider.d.ts +42 -0
  301. package/lib/esm/components/range-slider/range-slider.d.ts.map +1 -0
  302. package/lib/esm/components/range-slider/range-slider.js +251 -0
  303. package/lib/esm/components/range-slider/range-slider.js.map +1 -0
  304. package/lib/esm/components/range-slider/types.d.ts +33 -0
  305. package/lib/esm/components/range-slider/types.d.ts.map +1 -0
  306. package/lib/esm/components/range-slider/types.js +6 -0
  307. package/lib/esm/components/range-slider/types.js.map +1 -0
  308. package/lib/esm/components/rating/index.d.ts +7 -0
  309. package/lib/esm/components/rating/index.d.ts.map +1 -0
  310. package/lib/esm/components/rating/index.js +6 -0
  311. package/lib/esm/components/rating/index.js.map +1 -0
  312. package/lib/esm/components/rating/rating.d.ts +31 -0
  313. package/lib/esm/components/rating/rating.d.ts.map +1 -0
  314. package/lib/esm/components/rating/rating.js +241 -0
  315. package/lib/esm/components/rating/rating.js.map +1 -0
  316. package/lib/esm/components/rating/types.d.ts +25 -0
  317. package/lib/esm/components/rating/types.d.ts.map +1 -0
  318. package/lib/esm/components/rating/types.js +6 -0
  319. package/lib/esm/components/rating/types.js.map +1 -0
  320. package/lib/esm/components/reparent/index.d.ts +7 -0
  321. package/lib/esm/components/reparent/index.d.ts.map +1 -0
  322. package/lib/esm/components/reparent/reparent.d.ts +25 -0
  323. package/lib/esm/components/reparent/reparent.d.ts.map +1 -0
  324. package/lib/esm/components/reparent/types.d.ts +13 -0
  325. package/lib/esm/components/reparent/types.d.ts.map +1 -0
  326. package/lib/esm/components/repeater/index.d.ts +7 -0
  327. package/lib/esm/components/repeater/index.d.ts.map +1 -0
  328. package/lib/esm/components/repeater/index.js +6 -0
  329. package/lib/esm/components/repeater/index.js.map +1 -0
  330. package/lib/esm/components/repeater/repeater.d.ts +33 -0
  331. package/lib/esm/components/repeater/repeater.d.ts.map +1 -0
  332. package/lib/esm/components/repeater/repeater.js +171 -0
  333. package/lib/esm/components/repeater/repeater.js.map +1 -0
  334. package/lib/esm/components/repeater/types.d.ts +18 -0
  335. package/lib/esm/components/repeater/types.d.ts.map +1 -0
  336. package/lib/esm/components/repeater/types.js +6 -0
  337. package/lib/esm/components/repeater/types.js.map +1 -0
  338. package/lib/esm/components/scrollable/index.d.ts +7 -0
  339. package/lib/esm/components/scrollable/index.d.ts.map +1 -0
  340. package/lib/esm/components/scrollable/scrollable.d.ts +37 -0
  341. package/lib/esm/components/scrollable/scrollable.d.ts.map +1 -0
  342. package/lib/esm/components/scrollable/types.d.ts +15 -0
  343. package/lib/esm/components/scrollable/types.d.ts.map +1 -0
  344. package/lib/esm/components/scrollspy/index.d.ts +7 -0
  345. package/lib/esm/components/scrollspy/index.d.ts.map +1 -0
  346. package/lib/esm/components/scrollspy/scrollspy.d.ts +35 -0
  347. package/lib/esm/components/scrollspy/scrollspy.d.ts.map +1 -0
  348. package/lib/esm/components/scrollspy/types.d.ts +14 -0
  349. package/lib/esm/components/scrollspy/types.d.ts.map +1 -0
  350. package/lib/esm/components/scrollto/index.d.ts +7 -0
  351. package/lib/esm/components/scrollto/index.d.ts.map +1 -0
  352. package/lib/esm/components/scrollto/scrollto.d.ts +28 -0
  353. package/lib/esm/components/scrollto/scrollto.d.ts.map +1 -0
  354. package/lib/esm/components/scrollto/types.d.ts +14 -0
  355. package/lib/esm/components/scrollto/types.d.ts.map +1 -0
  356. package/lib/esm/components/select/combobox.d.ts +52 -0
  357. package/lib/esm/components/select/combobox.d.ts.map +1 -0
  358. package/lib/esm/components/select/config.d.ts +105 -0
  359. package/lib/esm/components/select/config.d.ts.map +1 -0
  360. package/lib/esm/components/select/dropdown.d.ts +101 -0
  361. package/lib/esm/components/select/dropdown.d.ts.map +1 -0
  362. package/lib/esm/components/select/index.d.ts +13 -0
  363. package/lib/esm/components/select/index.d.ts.map +1 -0
  364. package/lib/esm/components/select/option.d.ts +23 -0
  365. package/lib/esm/components/select/option.d.ts.map +1 -0
  366. package/lib/esm/components/select/remote.d.ts +91 -0
  367. package/lib/esm/components/select/remote.d.ts.map +1 -0
  368. package/lib/esm/components/select/search.d.ts +67 -0
  369. package/lib/esm/components/select/search.d.ts.map +1 -0
  370. package/lib/esm/components/select/select.d.ts +427 -0
  371. package/lib/esm/components/select/select.d.ts.map +1 -0
  372. package/lib/esm/components/select/select.js +3 -0
  373. package/lib/esm/components/select/select.js.map +1 -1
  374. package/lib/esm/components/select/tags.d.ts +32 -0
  375. package/lib/esm/components/select/tags.d.ts.map +1 -0
  376. package/lib/esm/components/select/templates.d.ts +79 -0
  377. package/lib/esm/components/select/templates.d.ts.map +1 -0
  378. package/lib/esm/components/select/types.d.ts +23 -0
  379. package/lib/esm/components/select/types.d.ts.map +1 -0
  380. package/lib/esm/components/select/utils.d.ts +130 -0
  381. package/lib/esm/components/select/utils.d.ts.map +1 -0
  382. package/lib/esm/components/select/utils.js +3 -1
  383. package/lib/esm/components/select/utils.js.map +1 -1
  384. package/lib/esm/components/stepper/index.d.ts +7 -0
  385. package/lib/esm/components/stepper/index.d.ts.map +1 -0
  386. package/lib/esm/components/stepper/stepper.d.ts +53 -0
  387. package/lib/esm/components/stepper/stepper.d.ts.map +1 -0
  388. package/lib/esm/components/stepper/types.d.ts +12 -0
  389. package/lib/esm/components/stepper/types.d.ts.map +1 -0
  390. package/lib/esm/components/sticky/index.d.ts +7 -0
  391. package/lib/esm/components/sticky/index.d.ts.map +1 -0
  392. package/lib/esm/components/sticky/sticky.d.ts +51 -0
  393. package/lib/esm/components/sticky/sticky.d.ts.map +1 -0
  394. package/lib/esm/components/sticky/sticky.js +3 -1
  395. package/lib/esm/components/sticky/sticky.js.map +1 -1
  396. package/lib/esm/components/sticky/types.d.ts +28 -0
  397. package/lib/esm/components/sticky/types.d.ts.map +1 -0
  398. package/lib/esm/components/tabs/index.d.ts +7 -0
  399. package/lib/esm/components/tabs/index.d.ts.map +1 -0
  400. package/lib/esm/components/tabs/tabs.d.ts +38 -0
  401. package/lib/esm/components/tabs/tabs.d.ts.map +1 -0
  402. package/lib/esm/components/tabs/types.d.ts +12 -0
  403. package/lib/esm/components/tabs/types.d.ts.map +1 -0
  404. package/lib/esm/components/theme-switch/index.d.ts +7 -0
  405. package/lib/esm/components/theme-switch/index.d.ts.map +1 -0
  406. package/lib/esm/components/theme-switch/theme-switch.d.ts +33 -0
  407. package/lib/esm/components/theme-switch/theme-switch.d.ts.map +1 -0
  408. package/lib/esm/components/theme-switch/types.d.ts +13 -0
  409. package/lib/esm/components/theme-switch/types.d.ts.map +1 -0
  410. package/lib/esm/components/toast/index.d.ts +7 -0
  411. package/lib/esm/components/toast/index.d.ts.map +1 -0
  412. package/lib/esm/components/toast/toast.d.ts +76 -0
  413. package/lib/esm/components/toast/toast.d.ts.map +1 -0
  414. package/lib/esm/components/toast/types.d.ts +146 -0
  415. package/lib/esm/components/toast/types.d.ts.map +1 -0
  416. package/lib/esm/components/toggle/index.d.ts +7 -0
  417. package/lib/esm/components/toggle/index.d.ts.map +1 -0
  418. package/lib/esm/components/toggle/toggle.d.ts +31 -0
  419. package/lib/esm/components/toggle/toggle.d.ts.map +1 -0
  420. package/lib/esm/components/toggle/types.d.ts +17 -0
  421. package/lib/esm/components/toggle/types.d.ts.map +1 -0
  422. package/lib/esm/components/toggle-password/index.d.ts +7 -0
  423. package/lib/esm/components/toggle-password/index.d.ts.map +1 -0
  424. package/lib/esm/components/toggle-password/toggle-password.d.ts +32 -0
  425. package/lib/esm/components/toggle-password/toggle-password.d.ts.map +1 -0
  426. package/lib/esm/components/toggle-password/types.d.ts +12 -0
  427. package/lib/esm/components/toggle-password/types.d.ts.map +1 -0
  428. package/lib/esm/components/tooltip/index.d.ts +7 -0
  429. package/lib/esm/components/tooltip/index.d.ts.map +1 -0
  430. package/lib/esm/components/tooltip/tooltip.d.ts +46 -0
  431. package/lib/esm/components/tooltip/tooltip.d.ts.map +1 -0
  432. package/lib/esm/components/tooltip/types.d.ts +26 -0
  433. package/lib/esm/components/tooltip/types.d.ts.map +1 -0
  434. package/lib/esm/helpers/data.d.ts +13 -0
  435. package/lib/esm/helpers/data.d.ts.map +1 -0
  436. package/lib/esm/helpers/dom.d.ts +42 -0
  437. package/lib/esm/helpers/dom.d.ts.map +1 -0
  438. package/lib/esm/helpers/event-handler.d.ts +14 -0
  439. package/lib/esm/helpers/event-handler.d.ts.map +1 -0
  440. package/lib/esm/helpers/utils.d.ts +25 -0
  441. package/lib/esm/helpers/utils.d.ts.map +1 -0
  442. package/lib/esm/index.d.ts +122 -0
  443. package/lib/esm/index.d.ts.map +1 -0
  444. package/lib/esm/index.js +12 -0
  445. package/lib/esm/index.js.map +1 -1
  446. package/lib/esm/types.d.ts +17 -0
  447. package/lib/esm/types.d.ts.map +1 -0
  448. package/package.json +4 -4
  449. package/skills/ktui-components/SKILL.md +41 -0
  450. package/skills/ktui-theming/SKILL.md +50 -0
  451. package/src/components/clipboard/__tests__/clipboard.test.ts +438 -0
  452. package/src/components/clipboard/clipboard.ts +416 -0
  453. package/src/components/clipboard/index.ts +2 -0
  454. package/src/components/clipboard/types.ts +51 -0
  455. package/src/components/datatable/__tests__/currency-sort.test.ts +2 -10
  456. package/src/components/datatable/__tests__/multi-row-headers.test.ts +2 -2
  457. package/src/components/datatable/__tests__/race-conditions.test.ts +11 -14
  458. package/src/components/datatable/datatable.ts +3 -5
  459. package/src/components/input/input-group.css +15 -5
  460. package/src/components/range-slider/__tests__/range-slider.test.ts +659 -0
  461. package/src/components/range-slider/index.ts +11 -0
  462. package/src/components/range-slider/range-slider.ts +276 -0
  463. package/src/components/range-slider/types.ts +36 -0
  464. package/src/components/rating/__tests__/rating.test.ts +241 -0
  465. package/src/components/rating/index.ts +11 -0
  466. package/src/components/rating/rating.css +11 -0
  467. package/src/components/rating/rating.ts +245 -0
  468. package/src/components/rating/types.ts +27 -0
  469. package/src/components/repeater/__tests__/repeater.test.ts +321 -0
  470. package/src/components/repeater/index.ts +7 -0
  471. package/src/components/repeater/repeater.ts +181 -0
  472. package/src/components/repeater/types.ts +19 -0
  473. package/src/components/select/__tests__/ux-behaviors.test.ts +21 -3
  474. package/src/components/select/select.ts +4 -0
  475. package/src/components/select/utils.ts +5 -1
  476. package/src/components/sticky/__tests__/sticky.test.ts +10 -3
  477. package/src/components/sticky/sticky.ts +14 -24
  478. package/src/components/sticky/types.ts +3 -3
  479. package/src/index.ts +125 -0
  480. package/styles.css +1 -0
  481. package/lib/cjs/components/datatable/__tests__/pagination-reset.test.js +0 -596
  482. package/lib/cjs/components/datatable/__tests__/pagination-reset.test.js.map +0 -1
  483. package/lib/cjs/components/datatable/__tests__/race-conditions.test.js +0 -548
  484. package/lib/cjs/components/datatable/__tests__/race-conditions.test.js.map +0 -1
  485. package/lib/cjs/components/datatable/__tests__/setup.js +0 -63
  486. package/lib/cjs/components/datatable/__tests__/setup.js.map +0 -1
  487. package/lib/esm/components/datatable/__tests__/pagination-reset.test.js +0 -594
  488. package/lib/esm/components/datatable/__tests__/pagination-reset.test.js.map +0 -1
  489. package/lib/esm/components/datatable/__tests__/race-conditions.test.js +0 -546
  490. package/lib/esm/components/datatable/__tests__/race-conditions.test.js.map +0 -1
  491. package/lib/esm/components/datatable/__tests__/setup.js +0 -58
  492. package/lib/esm/components/datatable/__tests__/setup.js.map +0 -1
@@ -0,0 +1,245 @@
1
+ /**
2
+ * KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
3
+ * Copyright 2025 by Keenthemes Inc
4
+ */
5
+
6
+ import KTData from '../../helpers/data';
7
+ import KTDom from '../../helpers/dom';
8
+ import KTComponent from '../component';
9
+ import { KTRatingConfigInterface, KTRatingInterface } from './types';
10
+
11
+ declare global {
12
+ interface Window {
13
+ KTRating: typeof KTRating;
14
+ }
15
+ }
16
+
17
+ const STAR_SVG =
18
+ '<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.282.95l-3.522 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>';
19
+ const HEART_SVG =
20
+ '<path fill-rule="evenodd" d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314z"/>';
21
+
22
+ export class KTRating extends KTComponent implements KTRatingInterface {
23
+ protected override _name: string = 'rating';
24
+ protected override _defaultConfig: KTRatingConfigInterface = {
25
+ value: 0,
26
+ max: 5,
27
+ readonly: false,
28
+ name: 'rating',
29
+ symbol: 'star',
30
+ lazy: false,
31
+ };
32
+ protected override _config: KTRatingConfigInterface = this._defaultConfig;
33
+ protected _container: HTMLElement | null = null;
34
+ protected _changeListener: ((e: Event) => void) | null = null;
35
+
36
+ constructor(
37
+ element: HTMLElement,
38
+ config: KTRatingConfigInterface | null = null,
39
+ ) {
40
+ super();
41
+
42
+ if (KTData.has(element as HTMLElement, this._name)) return;
43
+
44
+ this._init(element);
45
+ this._buildConfig(config);
46
+
47
+ this._render();
48
+ if (!this._config.readonly) {
49
+ this._handlers();
50
+ }
51
+ }
52
+
53
+ protected _getMax(): number {
54
+ const max = Number(this._getOption('max'));
55
+ return Number.isFinite(max) && max >= 1 ? Math.floor(max) : 5;
56
+ }
57
+
58
+ protected _getValue(): number {
59
+ const v = Number(this._getOption('value'));
60
+ const max = this._getMax();
61
+ return Number.isFinite(v) && v >= 0 && v <= max ? Math.floor(v) : 0;
62
+ }
63
+
64
+ protected _render(): void {
65
+ if (!this._element) return;
66
+ const max = this._getMax();
67
+ const value = this._getValue();
68
+ const readonly = this._config.readonly === true;
69
+ const symbol = (this._config.symbol as string) || 'star';
70
+ const name = (this._config.name as string) || 'rating';
71
+
72
+ const isStar = symbol !== 'heart';
73
+ const filledClass = isStar
74
+ ? 'text-yellow-400 dark:text-yellow-600'
75
+ : 'text-red-500 dark:text-red-500';
76
+ const unfilledClass =
77
+ 'text-muted-foreground/50 dark:text-muted-foreground/50';
78
+ const path = isStar ? STAR_SVG : HEART_SVG;
79
+ const svg = `<svg class="shrink-0 size-5" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">${path}</svg>`;
80
+
81
+ const container = document.createElement('div');
82
+ container.className =
83
+ 'kt-rating flex flex-row-reverse justify-end items-center gap-0';
84
+ container.setAttribute('role', readonly ? 'img' : 'group');
85
+ container.setAttribute('aria-label', `Rating: ${value} of ${max}`);
86
+ if (readonly) {
87
+ container.setAttribute('aria-valuenow', String(value));
88
+ container.setAttribute('aria-valuemin', '0');
89
+ container.setAttribute('aria-valuemax', String(max));
90
+ }
91
+
92
+ if (readonly) {
93
+ for (let i = max; i >= 1; i--) {
94
+ const filled = i <= value;
95
+ const span = document.createElement('span');
96
+ span.className = filled ? filledClass : unfilledClass;
97
+ span.innerHTML = svg;
98
+ container.appendChild(span);
99
+ }
100
+ } else {
101
+ container.setAttribute('aria-valuenow', String(value));
102
+ container.setAttribute('aria-valuemin', '1');
103
+ container.setAttribute('aria-valuemax', String(max));
104
+ for (let i = max; i >= 1; i--) {
105
+ const id = `kt-rating-${this._uid}-${i}`;
106
+ const radio = document.createElement('input');
107
+ radio.type = 'radio';
108
+ radio.name = name;
109
+ radio.value = String(i);
110
+ radio.id = id;
111
+ radio.className =
112
+ 'peer -ms-5 size-5 bg-transparent border-0 text-transparent cursor-pointer appearance-none checked:bg-none focus:bg-none focus:ring-0 focus:ring-offset-0';
113
+ radio.setAttribute('aria-label', `Rate ${i} of ${max}`);
114
+ if (i === value) radio.checked = true;
115
+
116
+ const label = document.createElement('label');
117
+ label.htmlFor = id;
118
+ label.setAttribute('data-kt-rating-value', String(i));
119
+ label.className = `cursor-pointer kt-rating-label ${i <= value ? filledClass : unfilledClass}`;
120
+ label.innerHTML = svg;
121
+
122
+ container.appendChild(radio);
123
+ container.appendChild(label);
124
+ }
125
+ this._updateInteractiveDisplay();
126
+ }
127
+
128
+ this._element.innerHTML = '';
129
+ this._element.appendChild(container);
130
+ this._container = container;
131
+ }
132
+
133
+ protected _updateInteractiveDisplay(): void {
134
+ if (!this._container || this._config.readonly) return;
135
+ const val = this.getValue();
136
+ const max = this._getMax();
137
+ const isStar = (this._config.symbol as string) !== 'heart';
138
+ const filledClass = isStar
139
+ ? 'text-yellow-400 dark:text-yellow-600'
140
+ : 'text-red-500 dark:text-red-500';
141
+ const unfilledClass =
142
+ 'text-muted-foreground/50 dark:text-muted-foreground/50';
143
+ const filledTokens = filledClass.split(' ');
144
+ const unfilledTokens = unfilledClass.split(' ');
145
+ this._container
146
+ .querySelectorAll<HTMLElement>('.kt-rating-label')
147
+ .forEach((label) => {
148
+ const v = parseInt(
149
+ label.getAttribute('data-kt-rating-value') || '0',
150
+ 10,
151
+ );
152
+ const filled = v <= (val ?? 0);
153
+ label.classList.remove(...filledTokens, ...unfilledTokens);
154
+ label.classList.add(...(filled ? filledTokens : unfilledTokens));
155
+ });
156
+ this._container.setAttribute(
157
+ 'aria-valuenow',
158
+ val != null ? String(val) : '0',
159
+ );
160
+ this._container.setAttribute('aria-label', `Rating: ${val ?? 0} of ${max}`);
161
+ }
162
+
163
+ protected _handlers(): void {
164
+ if (!this._container) return;
165
+ this._changeListener = () => {
166
+ this._updateInteractiveDisplay();
167
+ const val = this.getValue();
168
+ this._fireEvent('change', { value: val });
169
+ this._dispatchEvent('kt.rating.change', { value: val });
170
+ };
171
+ this._container.addEventListener('change', this._changeListener);
172
+ }
173
+
174
+ public getValue(): number | null {
175
+ if (!this._element) return null;
176
+ if (this._config.readonly) {
177
+ const v = this._getValue();
178
+ return v > 0 ? v : null;
179
+ }
180
+ const radio = this._container?.querySelector<HTMLInputElement>(
181
+ 'input[type="radio"]:checked',
182
+ );
183
+ if (!radio) return null;
184
+ const n = parseInt(radio.value, 10);
185
+ return Number.isFinite(n) ? n : null;
186
+ }
187
+
188
+ public setValue(value: number | null): void {
189
+ if (!this._container) return;
190
+ const max = this._getMax();
191
+ if (this._config.readonly) return;
192
+ if (value !== null && value >= 1 && value <= max) {
193
+ const radio = this._container.querySelector<HTMLInputElement>(
194
+ `input[type="radio"][value="${value}"]`,
195
+ );
196
+ if (radio) {
197
+ radio.checked = true;
198
+ this._updateInteractiveDisplay();
199
+ }
200
+ } else {
201
+ this._container
202
+ .querySelectorAll<HTMLInputElement>('input[type="radio"]')
203
+ .forEach((r) => {
204
+ r.checked = false;
205
+ });
206
+ this._updateInteractiveDisplay();
207
+ }
208
+ }
209
+
210
+ public override dispose(): void {
211
+ if (this._container && this._changeListener) {
212
+ this._container.removeEventListener('change', this._changeListener);
213
+ this._changeListener = null;
214
+ }
215
+ this._container = null;
216
+ super.dispose();
217
+ }
218
+
219
+ public static getInstance(element: HTMLElement): KTRating | null {
220
+ if (!element) return null;
221
+ if (KTData.has(element, 'rating')) {
222
+ return KTData.get(element, 'rating') as KTRating;
223
+ }
224
+ if (element.getAttribute('data-kt-rating') !== null) {
225
+ return new KTRating(element);
226
+ }
227
+ return null;
228
+ }
229
+
230
+ public static createInstances(): void {
231
+ const elements = document.querySelectorAll<HTMLElement>('[data-kt-rating]');
232
+ elements.forEach((el) => {
233
+ if (el.getAttribute('data-kt-rating-lazy') === 'true') return;
234
+ new KTRating(el);
235
+ });
236
+ }
237
+
238
+ public static init(): void {
239
+ KTRating.createInstances();
240
+ }
241
+ }
242
+
243
+ if (typeof window !== 'undefined') {
244
+ window.KTRating = KTRating;
245
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
3
+ * Copyright 2025 by Keenthemes Inc
4
+ */
5
+
6
+ export type KTRatingSymbolType = 'star' | 'heart';
7
+
8
+ export interface KTRatingConfigInterface {
9
+ /** Current rating value (1 to max). Omit or 0 for no selection. */
10
+ value?: number;
11
+ /** Maximum rating (default 5). */
12
+ max?: number;
13
+ /** If true, only display the rating; no user input. */
14
+ readonly?: boolean;
15
+ /** Form field name for interactive mode (for form submission). */
16
+ name?: string;
17
+ /** Symbol to display: 'star' (default) or 'heart'. */
18
+ symbol?: KTRatingSymbolType;
19
+ /** If true, do not auto-initialize; init() must be called programmatically. */
20
+ lazy?: boolean;
21
+ }
22
+
23
+ export interface KTRatingInterface {
24
+ getValue(): number | null;
25
+ setValue(value: number | null): void;
26
+ dispose(): void;
27
+ }
@@ -0,0 +1,321 @@
1
+ /**
2
+ * Tests for KTRepeater component
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
+ import { KTRepeater } from '../repeater';
7
+
8
+ function createFixture(options?: {
9
+ withInitialChild?: boolean;
10
+ limit?: number;
11
+ hiddenTemplate?: boolean;
12
+ withDeleteInTarget?: boolean;
13
+ }) {
14
+ document.body.innerHTML = '';
15
+ const container = document.createElement('div');
16
+ container.id = 'repeater-test-container';
17
+
18
+ const wrapper = document.createElement('div');
19
+ wrapper.id = 'repeater-wrapper';
20
+ wrapper.className = 'space-y-3';
21
+ container.appendChild(wrapper);
22
+
23
+ const target = document.createElement('div');
24
+ target.id = 'repeater-target';
25
+ const input = document.createElement('input');
26
+ input.type = 'text';
27
+ input.placeholder = 'Enter Name';
28
+ target.appendChild(input);
29
+ if (options?.withDeleteInTarget) {
30
+ const removeBtn = document.createElement('span');
31
+ removeBtn.setAttribute('data-kt-repeater-delete', '');
32
+ removeBtn.className = 'remove-btn';
33
+ target.appendChild(removeBtn);
34
+ }
35
+
36
+ if (options?.hiddenTemplate) {
37
+ const hidden = document.createElement('div');
38
+ hidden.id = 'repeater-template-container';
39
+ hidden.className = 'hidden';
40
+ hidden.style.display = 'none';
41
+ hidden.appendChild(target);
42
+ container.appendChild(hidden);
43
+ } else if (options?.withInitialChild !== false) {
44
+ wrapper.appendChild(target);
45
+ }
46
+
47
+ const trigger = document.createElement('button');
48
+ trigger.type = 'button';
49
+ trigger.setAttribute('data-kt-repeater', '');
50
+ trigger.setAttribute('data-kt-repeater-target', '#repeater-target');
51
+ trigger.setAttribute('data-kt-repeater-wrapper', '#repeater-wrapper');
52
+ if (options?.limit != null) {
53
+ trigger.setAttribute('data-kt-repeater-limit', String(options.limit));
54
+ }
55
+ trigger.textContent = 'Add';
56
+ container.appendChild(trigger);
57
+
58
+ document.body.appendChild(container);
59
+ return { container, wrapper, target, trigger };
60
+ }
61
+
62
+ describe('KTRepeater', () => {
63
+ afterEach(() => {
64
+ document.body.innerHTML = '';
65
+ });
66
+
67
+ describe('initialization', () => {
68
+ it('initializes on trigger element with data-kt-repeater and valid target/wrapper', () => {
69
+ const { trigger } = createFixture();
70
+ const instance = new KTRepeater(trigger);
71
+ expect(instance).toBeInstanceOf(KTRepeater);
72
+ expect(instance.getElement()).toBe(trigger);
73
+ instance.dispose();
74
+ });
75
+
76
+ it('reads target, wrapper, limit from data attributes', () => {
77
+ const { trigger } = createFixture({ limit: 5 });
78
+ const instance = new KTRepeater(trigger);
79
+ expect(instance.getOption('target')).toBe('#repeater-target');
80
+ expect(instance.getOption('wrapper')).toBe('#repeater-wrapper');
81
+ expect(Number(instance.getOption('limit'))).toBe(5);
82
+ instance.dispose();
83
+ });
84
+
85
+ it('does not double-initialize when constructor called twice on same trigger', () => {
86
+ const { trigger, wrapper } = createFixture();
87
+ new KTRepeater(trigger);
88
+ new KTRepeater(trigger);
89
+ expect(KTRepeater.getInstance(trigger)).not.toBeNull();
90
+ KTRepeater.getInstance(trigger)!.add();
91
+ expect(wrapper.children.length).toBe(2);
92
+ KTRepeater.getInstance(trigger)!.dispose();
93
+ });
94
+
95
+ it('accepts config object when wrapper has no id (config overrides)', () => {
96
+ const { trigger, wrapper } = createFixture();
97
+ wrapper.id = 'custom-wrapper';
98
+ trigger.removeAttribute('data-kt-repeater-wrapper');
99
+ const instance = new KTRepeater(trigger, {
100
+ target: '#repeater-target',
101
+ wrapper: '#custom-wrapper',
102
+ limit: 0,
103
+ });
104
+ expect(instance).toBeInstanceOf(KTRepeater);
105
+ instance.add();
106
+ expect(wrapper.children.length).toBe(2);
107
+ instance.dispose();
108
+ });
109
+ });
110
+
111
+ describe('add behavior', () => {
112
+ it('clones target into wrapper when trigger is clicked', () => {
113
+ const { wrapper, trigger } = createFixture();
114
+ const instance = new KTRepeater(trigger);
115
+ expect(wrapper.children.length).toBe(1);
116
+ trigger.click();
117
+ expect(wrapper.children.length).toBe(2);
118
+ trigger.click();
119
+ expect(wrapper.children.length).toBe(3);
120
+ instance.dispose();
121
+ });
122
+
123
+ it('add() method has the same effect as clicking the trigger', () => {
124
+ const { wrapper, trigger } = createFixture();
125
+ const instance = new KTRepeater(trigger);
126
+ expect(wrapper.children.length).toBe(1);
127
+ instance.add();
128
+ expect(wrapper.children.length).toBe(2);
129
+ instance.add();
130
+ expect(wrapper.children.length).toBe(3);
131
+ instance.dispose();
132
+ });
133
+
134
+ it('fires add event with cloned element in payload', () => {
135
+ const { trigger } = createFixture();
136
+ const instance = new KTRepeater(trigger);
137
+ const addedElements: HTMLElement[] = [];
138
+ instance.on('add', (payload: { element: HTMLElement }) => {
139
+ addedElements.push(payload.element);
140
+ });
141
+ instance.add();
142
+ instance.add();
143
+ expect(addedElements.length).toBe(2);
144
+ expect(addedElements[0]).toBeInstanceOf(HTMLElement);
145
+ expect(addedElements[0].querySelector('input')).not.toBeNull();
146
+ instance.dispose();
147
+ });
148
+
149
+ it('dispatches DOM add event with detail.payload.element', () => {
150
+ const { trigger } = createFixture();
151
+ const instance = new KTRepeater(trigger);
152
+ const events: CustomEvent[] = [];
153
+ trigger.addEventListener('add', ((e: Event) =>
154
+ events.push(e as CustomEvent)) as EventListener);
155
+ instance.add();
156
+ expect(events.length).toBe(1);
157
+ expect(events[0].detail?.payload?.element).toBeInstanceOf(HTMLElement);
158
+ instance.dispose();
159
+ });
160
+ });
161
+
162
+ describe('limit', () => {
163
+ it('does not add more clones when at limit', () => {
164
+ const { wrapper, trigger } = createFixture({ limit: 2 });
165
+ const instance = new KTRepeater(trigger);
166
+ expect(wrapper.children.length).toBe(1);
167
+ instance.add();
168
+ expect(wrapper.children.length).toBe(2);
169
+ instance.add();
170
+ expect(wrapper.children.length).toBe(2);
171
+ trigger.click();
172
+ expect(wrapper.children.length).toBe(2);
173
+ instance.dispose();
174
+ });
175
+
176
+ it('disables trigger when at limit', () => {
177
+ const { wrapper, trigger } = createFixture({ limit: 2 });
178
+ const instance = new KTRepeater(trigger);
179
+ expect(trigger.hasAttribute('disabled')).toBe(false);
180
+ instance.add();
181
+ expect(trigger.hasAttribute('disabled')).toBe(true);
182
+ instance.dispose();
183
+ });
184
+
185
+ it('re-enables trigger when a clone is removed (delete) and count drops below limit', () => {
186
+ const { wrapper, trigger } = createFixture({
187
+ limit: 2,
188
+ withDeleteInTarget: true,
189
+ });
190
+ const instance = new KTRepeater(trigger);
191
+ instance.add();
192
+ expect(wrapper.children.length).toBe(2);
193
+ expect(trigger.hasAttribute('disabled')).toBe(true);
194
+ const secondClone = wrapper.children[1];
195
+ const deleteBtn = secondClone.querySelector('[data-kt-repeater-delete]');
196
+ expect(deleteBtn).not.toBeNull();
197
+ (deleteBtn as HTMLElement).click();
198
+ expect(wrapper.children.length).toBe(1);
199
+ expect(trigger.hasAttribute('disabled')).toBe(false);
200
+ instance.dispose();
201
+ });
202
+
203
+ it('allows unlimited clones when limit is 0 or omitted', () => {
204
+ const { wrapper, trigger } = createFixture();
205
+ trigger.removeAttribute('data-kt-repeater-limit');
206
+ const instance = new KTRepeater(trigger);
207
+ for (let i = 0; i < 5; i++) instance.add();
208
+ expect(wrapper.children.length).toBe(6);
209
+ instance.dispose();
210
+ });
211
+ });
212
+
213
+ describe('delete', () => {
214
+ it('removes clone when clicking element with data-kt-repeater-delete', () => {
215
+ const { wrapper, trigger } = createFixture({ withDeleteInTarget: true });
216
+ const instance = new KTRepeater(trigger);
217
+ instance.add();
218
+ expect(wrapper.children.length).toBe(2);
219
+ const firstClone = wrapper.children[1];
220
+ const deleteBtn = firstClone.querySelector(
221
+ '[data-kt-repeater-delete]',
222
+ ) as HTMLElement;
223
+ deleteBtn.click();
224
+ expect(wrapper.children.length).toBe(1);
225
+ instance.dispose();
226
+ });
227
+
228
+ it('does not remove the last row (keeps at least one for template)', () => {
229
+ const { wrapper, trigger } = createFixture({ withDeleteInTarget: true });
230
+ const instance = new KTRepeater(trigger);
231
+ expect(wrapper.children.length).toBe(1);
232
+ const onlyRow = wrapper.children[0];
233
+ const deleteBtn = onlyRow.querySelector(
234
+ '[data-kt-repeater-delete]',
235
+ ) as HTMLElement;
236
+ deleteBtn.click();
237
+ expect(wrapper.children.length).toBe(1);
238
+ instance.dispose();
239
+ });
240
+ });
241
+
242
+ describe('predefined (hidden) template', () => {
243
+ it('clones from hidden template and appends to wrapper', () => {
244
+ const { wrapper, trigger } = createFixture({
245
+ hiddenTemplate: true,
246
+ withInitialChild: false,
247
+ });
248
+ expect(wrapper.children.length).toBe(0);
249
+ const instance = new KTRepeater(trigger);
250
+ instance.add();
251
+ expect(wrapper.children.length).toBe(1);
252
+ expect(
253
+ wrapper.querySelector('input[placeholder="Enter Name"]'),
254
+ ).not.toBeNull();
255
+ instance.dispose();
256
+ });
257
+ });
258
+
259
+ describe('getInstance and static methods', () => {
260
+ it('getInstance returns null for element without data-kt-repeater', () => {
261
+ const { trigger } = createFixture();
262
+ trigger.removeAttribute('data-kt-repeater');
263
+ expect(KTRepeater.getInstance(trigger)).toBeNull();
264
+ });
265
+
266
+ it('getInstance returns instance for initialized trigger', () => {
267
+ const { trigger } = createFixture();
268
+ const instance = new KTRepeater(trigger);
269
+ expect(KTRepeater.getInstance(trigger)).toBe(instance);
270
+ instance.dispose();
271
+ });
272
+
273
+ it('getOrCreateInstance returns existing instance or creates new one', () => {
274
+ const { trigger } = createFixture();
275
+ const a = KTRepeater.getOrCreateInstance(trigger);
276
+ const b = KTRepeater.getOrCreateInstance(trigger);
277
+ expect(a).toBe(b);
278
+ a.dispose();
279
+ });
280
+
281
+ it('createInstances initializes all data-kt-repeater elements', () => {
282
+ const { container, wrapper, trigger } = createFixture();
283
+ const trigger2 = document.createElement('button');
284
+ trigger2.setAttribute('data-kt-repeater', '');
285
+ trigger2.setAttribute('data-kt-repeater-target', '#repeater-target');
286
+ trigger2.setAttribute('data-kt-repeater-wrapper', '#repeater-wrapper');
287
+ container.appendChild(trigger2);
288
+ KTRepeater.createInstances();
289
+ expect(KTRepeater.getInstance(trigger)).not.toBeNull();
290
+ expect(KTRepeater.getInstance(trigger2)).not.toBeNull();
291
+ KTRepeater.getInstance(trigger)!.dispose();
292
+ KTRepeater.getInstance(trigger2)!.dispose();
293
+ });
294
+
295
+ it('init calls createInstances', () => {
296
+ const { trigger } = createFixture();
297
+ KTRepeater.init();
298
+ expect(KTRepeater.getInstance(trigger)).not.toBeNull();
299
+ KTRepeater.getInstance(trigger)!.dispose();
300
+ });
301
+ });
302
+
303
+ describe('dispose', () => {
304
+ it('removes listeners and allows re-initialization', () => {
305
+ const { wrapper, trigger } = createFixture();
306
+ const instance = new KTRepeater(trigger);
307
+ instance.dispose();
308
+ const instance2 = new KTRepeater(trigger);
309
+ instance2.add();
310
+ expect(wrapper.children.length).toBe(2);
311
+ instance2.dispose();
312
+ });
313
+
314
+ it('dispose is idempotent', () => {
315
+ const { trigger } = createFixture();
316
+ const instance = new KTRepeater(trigger);
317
+ instance.dispose();
318
+ expect(() => instance.dispose()).not.toThrow();
319
+ });
320
+ });
321
+ });
@@ -0,0 +1,7 @@
1
+ /**
2
+ * KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
3
+ * Copyright 2025 by Keenthemes Inc
4
+ */
5
+
6
+ export { KTRepeater } from './repeater';
7
+ export type { KTRepeaterConfigInterface, KTRepeaterInterface } from './types';