@keenthemes/ktui 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (426) hide show
  1. package/CONTRIBUTING.md +88 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +124 -0
  4. package/dist/ktui.js +19201 -0
  5. package/dist/ktui.min.js +2 -0
  6. package/dist/ktui.min.js.map +1 -0
  7. package/lib/cjs/components/accordion/accordion.js +168 -0
  8. package/lib/cjs/components/accordion/accordion.js.map +1 -0
  9. package/lib/cjs/components/accordion/index.js +6 -0
  10. package/lib/cjs/components/accordion/index.js.map +1 -0
  11. package/lib/cjs/components/accordion/types.js +3 -0
  12. package/lib/cjs/components/accordion/types.js.map +1 -0
  13. package/lib/cjs/components/collapse/collapse.js +169 -0
  14. package/lib/cjs/components/collapse/collapse.js.map +1 -0
  15. package/lib/cjs/components/collapse/index.js +6 -0
  16. package/lib/cjs/components/collapse/index.js.map +1 -0
  17. package/lib/cjs/components/collapse/types.js +3 -0
  18. package/lib/cjs/components/collapse/types.js.map +1 -0
  19. package/lib/cjs/components/component.js +135 -0
  20. package/lib/cjs/components/component.js.map +1 -0
  21. package/lib/cjs/components/config.js +26 -0
  22. package/lib/cjs/components/config.js.map +1 -0
  23. package/lib/cjs/components/config.umd.js +23 -0
  24. package/lib/cjs/components/config.umd.js.map +1 -0
  25. package/lib/cjs/components/constants.js +15 -0
  26. package/lib/cjs/components/constants.js.map +1 -0
  27. package/lib/cjs/components/datatable/datatable.js +1464 -0
  28. package/lib/cjs/components/datatable/datatable.js.map +1 -0
  29. package/lib/cjs/components/datatable/index.js +6 -0
  30. package/lib/cjs/components/datatable/index.js.map +1 -0
  31. package/lib/cjs/components/datatable/types.js +3 -0
  32. package/lib/cjs/components/datatable/types.js.map +1 -0
  33. package/lib/cjs/components/dismiss/dismiss.js +131 -0
  34. package/lib/cjs/components/dismiss/dismiss.js.map +1 -0
  35. package/lib/cjs/components/dismiss/index.js +6 -0
  36. package/lib/cjs/components/dismiss/index.js.map +1 -0
  37. package/lib/cjs/components/dismiss/types.js +3 -0
  38. package/lib/cjs/components/dismiss/types.js.map +1 -0
  39. package/lib/cjs/components/drawer/drawer.js +347 -0
  40. package/lib/cjs/components/drawer/drawer.js.map +1 -0
  41. package/lib/cjs/components/drawer/index.js +6 -0
  42. package/lib/cjs/components/drawer/index.js.map +1 -0
  43. package/lib/cjs/components/drawer/types.js +3 -0
  44. package/lib/cjs/components/drawer/types.js.map +1 -0
  45. package/lib/cjs/components/dropdown/dropdown.js +403 -0
  46. package/lib/cjs/components/dropdown/dropdown.js.map +1 -0
  47. package/lib/cjs/components/dropdown/index.js +6 -0
  48. package/lib/cjs/components/dropdown/index.js.map +1 -0
  49. package/lib/cjs/components/dropdown/types.js +3 -0
  50. package/lib/cjs/components/dropdown/types.js.map +1 -0
  51. package/lib/cjs/components/image-input/image-input.js +191 -0
  52. package/lib/cjs/components/image-input/image-input.js.map +1 -0
  53. package/lib/cjs/components/image-input/index.js +6 -0
  54. package/lib/cjs/components/image-input/index.js.map +1 -0
  55. package/lib/cjs/components/image-input/types.js +3 -0
  56. package/lib/cjs/components/image-input/types.js.map +1 -0
  57. package/lib/cjs/components/menu/index.js +6 -0
  58. package/lib/cjs/components/menu/index.js.map +1 -0
  59. package/lib/cjs/components/menu/menu.js +1021 -0
  60. package/lib/cjs/components/menu/menu.js.map +1 -0
  61. package/lib/cjs/components/menu/types.js +3 -0
  62. package/lib/cjs/components/menu/types.js.map +1 -0
  63. package/lib/cjs/components/modal/index.js +6 -0
  64. package/lib/cjs/components/modal/index.js.map +1 -0
  65. package/lib/cjs/components/modal/modal.js +316 -0
  66. package/lib/cjs/components/modal/modal.js.map +1 -0
  67. package/lib/cjs/components/modal/types.js +3 -0
  68. package/lib/cjs/components/modal/types.js.map +1 -0
  69. package/lib/cjs/components/reparent/index.js +6 -0
  70. package/lib/cjs/components/reparent/index.js.map +1 -0
  71. package/lib/cjs/components/reparent/reparent.js +93 -0
  72. package/lib/cjs/components/reparent/reparent.js.map +1 -0
  73. package/lib/cjs/components/reparent/types.js +3 -0
  74. package/lib/cjs/components/reparent/types.js.map +1 -0
  75. package/lib/cjs/components/scrollable/index.js +6 -0
  76. package/lib/cjs/components/scrollable/index.js.map +1 -0
  77. package/lib/cjs/components/scrollable/scrollable.js +259 -0
  78. package/lib/cjs/components/scrollable/scrollable.js.map +1 -0
  79. package/lib/cjs/components/scrollable/types.js +3 -0
  80. package/lib/cjs/components/scrollable/types.js.map +1 -0
  81. package/lib/cjs/components/scrollspy/index.js +6 -0
  82. package/lib/cjs/components/scrollspy/index.js.map +1 -0
  83. package/lib/cjs/components/scrollspy/scrollspy.js +174 -0
  84. package/lib/cjs/components/scrollspy/scrollspy.js.map +1 -0
  85. package/lib/cjs/components/scrollspy/types.js +3 -0
  86. package/lib/cjs/components/scrollspy/types.js.map +1 -0
  87. package/lib/cjs/components/scrollto/index.js +6 -0
  88. package/lib/cjs/components/scrollto/index.js.map +1 -0
  89. package/lib/cjs/components/scrollto/scrollto.js +103 -0
  90. package/lib/cjs/components/scrollto/scrollto.js.map +1 -0
  91. package/lib/cjs/components/scrollto/types.js +3 -0
  92. package/lib/cjs/components/scrollto/types.js.map +1 -0
  93. package/lib/cjs/components/stepper/index.js +6 -0
  94. package/lib/cjs/components/stepper/index.js.map +1 -0
  95. package/lib/cjs/components/stepper/stepper.js +258 -0
  96. package/lib/cjs/components/stepper/stepper.js.map +1 -0
  97. package/lib/cjs/components/stepper/types.js +3 -0
  98. package/lib/cjs/components/stepper/types.js.map +1 -0
  99. package/lib/cjs/components/sticky/index.js +6 -0
  100. package/lib/cjs/components/sticky/index.js.map +1 -0
  101. package/lib/cjs/components/sticky/sticky.js +297 -0
  102. package/lib/cjs/components/sticky/sticky.js.map +1 -0
  103. package/lib/cjs/components/sticky/types.js +3 -0
  104. package/lib/cjs/components/sticky/types.js.map +1 -0
  105. package/lib/cjs/components/tabs/index.js +6 -0
  106. package/lib/cjs/components/tabs/index.js.map +1 -0
  107. package/lib/cjs/components/tabs/tabs.js +146 -0
  108. package/lib/cjs/components/tabs/tabs.js.map +1 -0
  109. package/lib/cjs/components/tabs/types.js +3 -0
  110. package/lib/cjs/components/tabs/types.js.map +1 -0
  111. package/lib/cjs/components/theme/index.js +6 -0
  112. package/lib/cjs/components/theme/index.js.map +1 -0
  113. package/lib/cjs/components/theme/theme.js +147 -0
  114. package/lib/cjs/components/theme/theme.js.map +1 -0
  115. package/lib/cjs/components/theme/types.js +3 -0
  116. package/lib/cjs/components/theme/types.js.map +1 -0
  117. package/lib/cjs/components/toggle/index.js +6 -0
  118. package/lib/cjs/components/toggle/index.js.map +1 -0
  119. package/lib/cjs/components/toggle/toggle.js +139 -0
  120. package/lib/cjs/components/toggle/toggle.js.map +1 -0
  121. package/lib/cjs/components/toggle/types.js +3 -0
  122. package/lib/cjs/components/toggle/types.js.map +1 -0
  123. package/lib/cjs/components/toggle-password/index.js +6 -0
  124. package/lib/cjs/components/toggle-password/index.js.map +1 -0
  125. package/lib/cjs/components/toggle-password/toggle-password.js +131 -0
  126. package/lib/cjs/components/toggle-password/toggle-password.js.map +1 -0
  127. package/lib/cjs/components/toggle-password/types.js +3 -0
  128. package/lib/cjs/components/toggle-password/types.js.map +1 -0
  129. package/lib/cjs/components/tooltip/index.js +6 -0
  130. package/lib/cjs/components/tooltip/index.js.map +1 -0
  131. package/lib/cjs/components/tooltip/tooltip.js +271 -0
  132. package/lib/cjs/components/tooltip/tooltip.js.map +1 -0
  133. package/lib/cjs/components/tooltip/types.js +3 -0
  134. package/lib/cjs/components/tooltip/types.js.map +1 -0
  135. package/lib/cjs/helpers/data.js +33 -0
  136. package/lib/cjs/helpers/data.js.map +1 -0
  137. package/lib/cjs/helpers/dom.js +297 -0
  138. package/lib/cjs/helpers/dom.js.map +1 -0
  139. package/lib/cjs/helpers/event-handler.js +36 -0
  140. package/lib/cjs/helpers/event-handler.js.map +1 -0
  141. package/lib/cjs/helpers/utils.js +94 -0
  142. package/lib/cjs/helpers/utils.js.map +1 -0
  143. package/lib/cjs/index.js +105 -0
  144. package/lib/cjs/index.js.map +1 -0
  145. package/lib/cjs/types.js +3 -0
  146. package/lib/cjs/types.js.map +1 -0
  147. package/lib/esm/components/accordion/accordion.js +165 -0
  148. package/lib/esm/components/accordion/accordion.js.map +1 -0
  149. package/lib/esm/components/accordion/index.js +2 -0
  150. package/lib/esm/components/accordion/index.js.map +1 -0
  151. package/lib/esm/components/accordion/types.js +2 -0
  152. package/lib/esm/components/accordion/types.js.map +1 -0
  153. package/lib/esm/components/collapse/collapse.js +166 -0
  154. package/lib/esm/components/collapse/collapse.js.map +1 -0
  155. package/lib/esm/components/collapse/index.js +2 -0
  156. package/lib/esm/components/collapse/index.js.map +1 -0
  157. package/lib/esm/components/collapse/types.js +2 -0
  158. package/lib/esm/components/collapse/types.js.map +1 -0
  159. package/lib/esm/components/component.js +133 -0
  160. package/lib/esm/components/component.js.map +1 -0
  161. package/lib/esm/components/config.js +24 -0
  162. package/lib/esm/components/config.js.map +1 -0
  163. package/lib/esm/components/config.umd.js +23 -0
  164. package/lib/esm/components/config.umd.js.map +1 -0
  165. package/lib/esm/components/constants.js +12 -0
  166. package/lib/esm/components/constants.js.map +1 -0
  167. package/lib/esm/components/datatable/datatable.js +1461 -0
  168. package/lib/esm/components/datatable/datatable.js.map +1 -0
  169. package/lib/esm/components/datatable/index.js +2 -0
  170. package/lib/esm/components/datatable/index.js.map +1 -0
  171. package/lib/esm/components/datatable/types.js +2 -0
  172. package/lib/esm/components/datatable/types.js.map +1 -0
  173. package/lib/esm/components/dismiss/dismiss.js +128 -0
  174. package/lib/esm/components/dismiss/dismiss.js.map +1 -0
  175. package/lib/esm/components/dismiss/index.js +2 -0
  176. package/lib/esm/components/dismiss/index.js.map +1 -0
  177. package/lib/esm/components/dismiss/types.js +2 -0
  178. package/lib/esm/components/dismiss/types.js.map +1 -0
  179. package/lib/esm/components/drawer/drawer.js +344 -0
  180. package/lib/esm/components/drawer/drawer.js.map +1 -0
  181. package/lib/esm/components/drawer/index.js +2 -0
  182. package/lib/esm/components/drawer/index.js.map +1 -0
  183. package/lib/esm/components/drawer/types.js +2 -0
  184. package/lib/esm/components/drawer/types.js.map +1 -0
  185. package/lib/esm/components/dropdown/dropdown.js +400 -0
  186. package/lib/esm/components/dropdown/dropdown.js.map +1 -0
  187. package/lib/esm/components/dropdown/index.js +2 -0
  188. package/lib/esm/components/dropdown/index.js.map +1 -0
  189. package/lib/esm/components/dropdown/types.js +2 -0
  190. package/lib/esm/components/dropdown/types.js.map +1 -0
  191. package/lib/esm/components/image-input/image-input.js +188 -0
  192. package/lib/esm/components/image-input/image-input.js.map +1 -0
  193. package/lib/esm/components/image-input/index.js +2 -0
  194. package/lib/esm/components/image-input/index.js.map +1 -0
  195. package/lib/esm/components/image-input/types.js +2 -0
  196. package/lib/esm/components/image-input/types.js.map +1 -0
  197. package/lib/esm/components/menu/index.js +2 -0
  198. package/lib/esm/components/menu/index.js.map +1 -0
  199. package/lib/esm/components/menu/menu.js +1018 -0
  200. package/lib/esm/components/menu/menu.js.map +1 -0
  201. package/lib/esm/components/menu/types.js +2 -0
  202. package/lib/esm/components/menu/types.js.map +1 -0
  203. package/lib/esm/components/modal/index.js +2 -0
  204. package/lib/esm/components/modal/index.js.map +1 -0
  205. package/lib/esm/components/modal/modal.js +313 -0
  206. package/lib/esm/components/modal/modal.js.map +1 -0
  207. package/lib/esm/components/modal/types.js +2 -0
  208. package/lib/esm/components/modal/types.js.map +1 -0
  209. package/lib/esm/components/reparent/index.js +2 -0
  210. package/lib/esm/components/reparent/index.js.map +1 -0
  211. package/lib/esm/components/reparent/reparent.js +90 -0
  212. package/lib/esm/components/reparent/reparent.js.map +1 -0
  213. package/lib/esm/components/reparent/types.js +2 -0
  214. package/lib/esm/components/reparent/types.js.map +1 -0
  215. package/lib/esm/components/scrollable/index.js +2 -0
  216. package/lib/esm/components/scrollable/index.js.map +1 -0
  217. package/lib/esm/components/scrollable/scrollable.js +256 -0
  218. package/lib/esm/components/scrollable/scrollable.js.map +1 -0
  219. package/lib/esm/components/scrollable/types.js +2 -0
  220. package/lib/esm/components/scrollable/types.js.map +1 -0
  221. package/lib/esm/components/scrollspy/index.js +2 -0
  222. package/lib/esm/components/scrollspy/index.js.map +1 -0
  223. package/lib/esm/components/scrollspy/scrollspy.js +171 -0
  224. package/lib/esm/components/scrollspy/scrollspy.js.map +1 -0
  225. package/lib/esm/components/scrollspy/types.js +2 -0
  226. package/lib/esm/components/scrollspy/types.js.map +1 -0
  227. package/lib/esm/components/scrollto/index.js +2 -0
  228. package/lib/esm/components/scrollto/index.js.map +1 -0
  229. package/lib/esm/components/scrollto/scrollto.js +100 -0
  230. package/lib/esm/components/scrollto/scrollto.js.map +1 -0
  231. package/lib/esm/components/scrollto/types.js +2 -0
  232. package/lib/esm/components/scrollto/types.js.map +1 -0
  233. package/lib/esm/components/stepper/index.js +2 -0
  234. package/lib/esm/components/stepper/index.js.map +1 -0
  235. package/lib/esm/components/stepper/stepper.js +255 -0
  236. package/lib/esm/components/stepper/stepper.js.map +1 -0
  237. package/lib/esm/components/stepper/types.js +2 -0
  238. package/lib/esm/components/stepper/types.js.map +1 -0
  239. package/lib/esm/components/sticky/index.js +2 -0
  240. package/lib/esm/components/sticky/index.js.map +1 -0
  241. package/lib/esm/components/sticky/sticky.js +294 -0
  242. package/lib/esm/components/sticky/sticky.js.map +1 -0
  243. package/lib/esm/components/sticky/types.js +2 -0
  244. package/lib/esm/components/sticky/types.js.map +1 -0
  245. package/lib/esm/components/tabs/index.js +2 -0
  246. package/lib/esm/components/tabs/index.js.map +1 -0
  247. package/lib/esm/components/tabs/tabs.js +143 -0
  248. package/lib/esm/components/tabs/tabs.js.map +1 -0
  249. package/lib/esm/components/tabs/types.js +2 -0
  250. package/lib/esm/components/tabs/types.js.map +1 -0
  251. package/lib/esm/components/theme/index.js +2 -0
  252. package/lib/esm/components/theme/index.js.map +1 -0
  253. package/lib/esm/components/theme/theme.js +144 -0
  254. package/lib/esm/components/theme/theme.js.map +1 -0
  255. package/lib/esm/components/theme/types.js +2 -0
  256. package/lib/esm/components/theme/types.js.map +1 -0
  257. package/lib/esm/components/toggle/index.js +2 -0
  258. package/lib/esm/components/toggle/index.js.map +1 -0
  259. package/lib/esm/components/toggle/toggle.js +136 -0
  260. package/lib/esm/components/toggle/toggle.js.map +1 -0
  261. package/lib/esm/components/toggle/types.js +2 -0
  262. package/lib/esm/components/toggle/types.js.map +1 -0
  263. package/lib/esm/components/toggle-password/index.js +2 -0
  264. package/lib/esm/components/toggle-password/index.js.map +1 -0
  265. package/lib/esm/components/toggle-password/toggle-password.js +128 -0
  266. package/lib/esm/components/toggle-password/toggle-password.js.map +1 -0
  267. package/lib/esm/components/toggle-password/types.js +2 -0
  268. package/lib/esm/components/toggle-password/types.js.map +1 -0
  269. package/lib/esm/components/tooltip/index.js +2 -0
  270. package/lib/esm/components/tooltip/index.js.map +1 -0
  271. package/lib/esm/components/tooltip/tooltip.js +268 -0
  272. package/lib/esm/components/tooltip/tooltip.js.map +1 -0
  273. package/lib/esm/components/tooltip/types.js +2 -0
  274. package/lib/esm/components/tooltip/types.js.map +1 -0
  275. package/lib/esm/helpers/data.js +31 -0
  276. package/lib/esm/helpers/data.js.map +1 -0
  277. package/lib/esm/helpers/dom.js +295 -0
  278. package/lib/esm/helpers/dom.js.map +1 -0
  279. package/lib/esm/helpers/event-handler.js +34 -0
  280. package/lib/esm/helpers/event-handler.js.map +1 -0
  281. package/lib/esm/helpers/utils.js +92 -0
  282. package/lib/esm/helpers/utils.js.map +1 -0
  283. package/lib/esm/index.js +79 -0
  284. package/lib/esm/index.js.map +1 -0
  285. package/lib/esm/types.js +2 -0
  286. package/lib/esm/types.js.map +1 -0
  287. package/package.json +85 -0
  288. package/prettier.config.js +9 -0
  289. package/src/components/accordion/accordion-menu.css +51 -0
  290. package/src/components/accordion/accordion.css +86 -0
  291. package/src/components/accordion/accordion.ts +221 -0
  292. package/src/components/accordion/index.ts +7 -0
  293. package/src/components/accordion/types.ts +16 -0
  294. package/src/components/alert/alert.css +282 -0
  295. package/src/components/avatar/avatar.css +46 -0
  296. package/src/components/badge/badge.css +176 -0
  297. package/src/components/breadcrumb/breadcrumb.css +38 -0
  298. package/src/components/btn/btn.css +227 -0
  299. package/src/components/card/card.css +158 -0
  300. package/src/components/checkbox/checkbox.css +74 -0
  301. package/src/components/collapse/collapse.css +14 -0
  302. package/src/components/collapse/collapse.ts +200 -0
  303. package/src/components/collapse/index.ts +7 -0
  304. package/src/components/collapse/types.ts +16 -0
  305. package/src/components/component.ts +132 -0
  306. package/src/components/constants.ts +16 -0
  307. package/src/components/datatable/datatable-checkbox.ts +236 -0
  308. package/src/components/datatable/datatable-sort.ts +154 -0
  309. package/src/components/datatable/datatable.css +110 -0
  310. package/src/components/datatable/datatable.ts +1657 -0
  311. package/src/components/datatable/index.ts +19 -0
  312. package/src/components/datatable/types.ts +203 -0
  313. package/src/components/datepicker/calendar.ts +1397 -0
  314. package/src/components/datepicker/config.ts +368 -0
  315. package/src/components/datepicker/datepicker.css +7 -0
  316. package/src/components/datepicker/datepicker.ts +1287 -0
  317. package/src/components/datepicker/dropdown.ts +757 -0
  318. package/src/components/datepicker/events.ts +149 -0
  319. package/src/components/datepicker/index.ts +10 -0
  320. package/src/components/datepicker/keyboard.ts +646 -0
  321. package/src/components/datepicker/locales.ts +80 -0
  322. package/src/components/datepicker/templates.ts +792 -0
  323. package/src/components/datepicker/types.ts +154 -0
  324. package/src/components/datepicker/utils.ts +631 -0
  325. package/src/components/dismiss/dismiss.css +10 -0
  326. package/src/components/dismiss/dismiss.ts +152 -0
  327. package/src/components/dismiss/index.ts +7 -0
  328. package/src/components/dismiss/types.ts +17 -0
  329. package/src/components/drawer/drawer.css +97 -0
  330. package/src/components/drawer/drawer.ts +437 -0
  331. package/src/components/drawer/index.ts +7 -0
  332. package/src/components/drawer/types.ts +25 -0
  333. package/src/components/dropdown/dropdown-menu.css +56 -0
  334. package/src/components/dropdown/dropdown.css +46 -0
  335. package/src/components/dropdown/dropdown.ts +549 -0
  336. package/src/components/dropdown/index.ts +7 -0
  337. package/src/components/dropdown/types.ts +28 -0
  338. package/src/components/form/form.css +54 -0
  339. package/src/components/image-input/image-input.css +56 -0
  340. package/src/components/image-input/image-input.ts +249 -0
  341. package/src/components/image-input/index.ts +10 -0
  342. package/src/components/image-input/types.ts +12 -0
  343. package/src/components/input/input-group.css +42 -0
  344. package/src/components/input/input.css +136 -0
  345. package/src/components/kbd/kbd.css +30 -0
  346. package/src/components/label/label.css +20 -0
  347. package/src/components/link/link.css +81 -0
  348. package/src/components/modal/index.ts +7 -0
  349. package/src/components/modal/modal.css +73 -0
  350. package/src/components/modal/modal.ts +382 -0
  351. package/src/components/modal/types.ts +21 -0
  352. package/src/components/pagination/pagination.css +26 -0
  353. package/src/components/popover/popover.css +22 -0
  354. package/src/components/progress/progress.css +51 -0
  355. package/src/components/radio/radio.css +51 -0
  356. package/src/components/reparent/index.ts +7 -0
  357. package/src/components/reparent/reparent.ts +109 -0
  358. package/src/components/reparent/types.ts +15 -0
  359. package/src/components/scrollable/index.ts +10 -0
  360. package/src/components/scrollable/scrollable.css +29 -0
  361. package/src/components/scrollable/scrollable.ts +297 -0
  362. package/src/components/scrollable/types.ts +16 -0
  363. package/src/components/scrollspy/index.ts +7 -0
  364. package/src/components/scrollspy/scrollspy.css +13 -0
  365. package/src/components/scrollspy/scrollspy.ts +224 -0
  366. package/src/components/scrollspy/types.ts +15 -0
  367. package/src/components/scrollto/index.ts +7 -0
  368. package/src/components/scrollto/scrollto.ts +127 -0
  369. package/src/components/scrollto/types.ts +15 -0
  370. package/src/components/select/combobox.ts +305 -0
  371. package/src/components/select/config.ts +324 -0
  372. package/src/components/select/dropdown.ts +510 -0
  373. package/src/components/select/index.ts +13 -0
  374. package/src/components/select/option.ts +43 -0
  375. package/src/components/select/remote.ts +477 -0
  376. package/src/components/select/search.ts +430 -0
  377. package/src/components/select/select.css +105 -0
  378. package/src/components/select/select.ts +1916 -0
  379. package/src/components/select/tags.ts +123 -0
  380. package/src/components/select/templates.ts +531 -0
  381. package/src/components/select/types.ts +36 -0
  382. package/src/components/select/utils.ts +747 -0
  383. package/src/components/select/variants.css +5 -0
  384. package/src/components/separator/separator.css +14 -0
  385. package/src/components/skeleton/skeleton.css +10 -0
  386. package/src/components/stepper/index.ts +7 -0
  387. package/src/components/stepper/stepper.css +49 -0
  388. package/src/components/stepper/stepper.ts +308 -0
  389. package/src/components/stepper/types.ts +13 -0
  390. package/src/components/sticky/index.ts +7 -0
  391. package/src/components/sticky/sticky.css +22 -0
  392. package/src/components/sticky/sticky.ts +381 -0
  393. package/src/components/sticky/types.ts +23 -0
  394. package/src/components/switch/switch.css +110 -0
  395. package/src/components/table/table.css +168 -0
  396. package/src/components/tabs/index.ts +7 -0
  397. package/src/components/tabs/tabs.css +40 -0
  398. package/src/components/tabs/tabs.ts +190 -0
  399. package/src/components/tabs/types.ts +13 -0
  400. package/src/components/textarea/textarea.css +35 -0
  401. package/src/components/theme-switch/index.ts +10 -0
  402. package/src/components/theme-switch/theme-switch.css +22 -0
  403. package/src/components/theme-switch/theme-switch.ts +176 -0
  404. package/src/components/theme-switch/types.ts +15 -0
  405. package/src/components/toggle/index.ts +7 -0
  406. package/src/components/toggle/toggle.css +13 -0
  407. package/src/components/toggle/toggle.ts +173 -0
  408. package/src/components/toggle/types.ts +18 -0
  409. package/src/components/toggle-group/toggle-group.css +55 -0
  410. package/src/components/toggle-password/index.ts +10 -0
  411. package/src/components/toggle-password/toggle-password.css +13 -0
  412. package/src/components/toggle-password/toggle-password.ts +159 -0
  413. package/src/components/toggle-password/types.ts +13 -0
  414. package/src/components/tooltip/index.ts +7 -0
  415. package/src/components/tooltip/tooltip.css +18 -0
  416. package/src/components/tooltip/tooltip.ts +361 -0
  417. package/src/components/tooltip/types.ts +28 -0
  418. package/src/helpers/data.ts +46 -0
  419. package/src/helpers/dom.ts +405 -0
  420. package/src/helpers/event-handler.ts +61 -0
  421. package/src/helpers/utils.ts +183 -0
  422. package/src/index.ts +113 -0
  423. package/src/types.ts +23 -0
  424. package/styles.css +48 -0
  425. package/tsconfig.json +17 -0
  426. package/webpack.config.js +113 -0
@@ -0,0 +1,792 @@
1
+ /**
2
+ * KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
3
+ * Copyright 2025 by Keenthemes Inc
4
+ * @version: 1.0.0
5
+ */
6
+ import { LocaleConfigInterface } from './types';
7
+
8
+ /**
9
+ * Main container template for the datepicker dropdown
10
+ */
11
+ export const datepickerContainerTemplate = `
12
+ <div class="bg-white rounded-lg shadow-lg border border-gray-200 overflow-hidden">
13
+ <div class="border-b border-gray-200 pb-3 mb-3">
14
+ <div class="flex items-center justify-between px-3 pt-3">
15
+ <button type="button" class="p-1 rounded hover:bg-gray-100 text-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500" aria-label="Previous Month">
16
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
17
+ <polyline points="15 18 9 12 15 6"></polyline>
18
+ </svg>
19
+ </button>
20
+ <div class="flex items-center justify-center">
21
+ <select class="bg-transparent border border-gray-200 rounded px-2 py-1 mr-1 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" aria-label="Select Month"></select>
22
+ <select class="bg-transparent border border-gray-200 rounded px-2 py-1 ml-1 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" aria-label="Select Year"></select>
23
+ <span class="font-medium px-2 py-1 rounded hover:bg-gray-100 cursor-pointer"></span>
24
+ </div>
25
+ <button type="button" class="p-1 rounded hover:bg-gray-100 text-gray-500 focus:outline-none focus:ring-2 focus:ring-blue-500" aria-label="Next Month">
26
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
27
+ <polyline points="9 18 15 12 9 6"></polyline>
28
+ </svg>
29
+ </button>
30
+ </div>
31
+ </div>
32
+ <div class="flex flex-wrap gap-4"></div>
33
+ <div class="py-3 border-t border-gray-200 mt-3 hidden">
34
+ <div class="text-sm font-medium text-gray-600 mb-2 text-center">Time</div>
35
+ <div class="flex items-center justify-center gap-2">
36
+ <div class="relative w-12">
37
+ <input type="text" class="w-full py-1.5 px-1.5 text-center border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" min="0" max="23" aria-label="Hour">
38
+ </div>
39
+ <span class="text-xl font-medium text-gray-500 leading-none">:</span>
40
+ <div class="relative w-12">
41
+ <input type="text" class="w-full py-1.5 px-1.5 text-center border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" min="0" max="59" aria-label="Minute">
42
+ </div>
43
+ <span class="text-xl font-medium text-gray-500 leading-none">:</span>
44
+ <div class="relative w-12">
45
+ <input type="text" class="w-full py-1.5 px-1.5 text-center border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" min="0" max="59" aria-label="Second">
46
+ </div>
47
+ <div class="flex flex-col gap-1">
48
+ <button type="button" class="px-2 py-1 text-xs border border-gray-300 rounded-t bg-gray-50 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 text-center" aria-label="AM"></button>
49
+ <button type="button" class="px-2 py-1 text-xs border border-gray-300 rounded-b bg-gray-50 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 text-center" aria-label="PM"></button>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ <div class="flex justify-between pt-3 border-t border-gray-200 mt-3 px-3 pb-3">
54
+ <button type="button" class="px-3 py-1.5 text-sm border border-gray-300 rounded bg-gray-50 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500">Today</button>
55
+ <button type="button" class="px-3 py-1.5 text-sm border border-gray-300 rounded bg-gray-50 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500">Clear</button>
56
+ <button type="button" class="px-3 py-1.5 text-sm border border-blue-500 rounded bg-blue-500 text-white hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500">Apply</button>
57
+ </div>
58
+ </div>
59
+ `;
60
+
61
+ /**
62
+ * Input wrapper template with calendar icon
63
+ */
64
+ export const inputWrapperTemplate = `
65
+ <div class="relative flex items-center">
66
+ <div class="flex-grow segmented-input-container"></div>
67
+ <button type="button" class="absolute right-2 p-1 text-gray-400 hover:text-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500 calendar-toggle-btn" aria-label="Toggle Calendar">
68
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
69
+ <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
70
+ <line x1="16" y1="2" x2="16" y2="6"></line>
71
+ <line x1="8" y1="2" x2="8" y2="6"></line>
72
+ <line x1="3" y1="10" x2="21" y2="10"></line>
73
+ </svg>
74
+ </button>
75
+ </div>
76
+ `;
77
+
78
+ /**
79
+ * Template for segmented date input
80
+ *
81
+ * @param format - Date format string (e.g., 'dd/MM/yyyy')
82
+ * @returns HTML for segmented input
83
+ */
84
+ export function segmentedDateInputTemplate(format: string): string {
85
+ // Parse the format to determine the order of segments and separators
86
+ const formatSegments = parseFormatString(format);
87
+ const segments = [];
88
+ const separators = [];
89
+
90
+ // Extract segments and separators
91
+ for (let i = 0; i < formatSegments.length; i++) {
92
+ const seg = formatSegments[i];
93
+ if (seg.type === 'separator') {
94
+ separators.push(seg.value);
95
+ } else {
96
+ segments.push(seg);
97
+ }
98
+ }
99
+
100
+ // Ensure we have exactly 3 segments (day, month, year) and 2 separators
101
+ if (segments.length !== 3 || separators.length !== 2) {
102
+ console.warn('Invalid date format for segmented input:', format);
103
+ // Fall back to default MM/dd/yyyy
104
+ return getDefaultSegmentedTemplate();
105
+ }
106
+
107
+ // Create the template based on the parsed format
108
+ return `
109
+ <div class="flex items-center bg-transparent text-sm">
110
+ <div
111
+ class="${getSegmentWidthClass(
112
+ segments[0].type,
113
+ )} bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
114
+ data-segment="${getSegmentName(segments[0].type)}"
115
+ tabindex="0"
116
+ role="button"
117
+ aria-label="${getSegmentLabel(segments[0].type)}">${
118
+ segments[0].placeholder
119
+ }</div>
120
+ <span class="text-gray-500 mx-0.5">${separators[0]}</span>
121
+ <div
122
+ class="${getSegmentWidthClass(
123
+ segments[1].type,
124
+ )} bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
125
+ data-segment="${getSegmentName(segments[1].type)}"
126
+ tabindex="0"
127
+ role="button"
128
+ aria-label="${getSegmentLabel(segments[1].type)}">${
129
+ segments[1].placeholder
130
+ }</div>
131
+ <span class="text-gray-500 mx-0.5">${separators[1]}</span>
132
+ <div
133
+ class="${getSegmentWidthClass(
134
+ segments[2].type,
135
+ )} bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
136
+ data-segment="${getSegmentName(segments[2].type)}"
137
+ tabindex="0"
138
+ role="button"
139
+ aria-label="${getSegmentLabel(segments[2].type)}">${
140
+ segments[2].placeholder
141
+ }</div>
142
+ </div>
143
+ `;
144
+ }
145
+
146
+ /**
147
+ * Template for segmented date range input
148
+ *
149
+ * @param format - Date format string (e.g., 'dd/MM/yyyy')
150
+ * @param rangeSeparator - Separator between start and end dates
151
+ * @returns HTML for segmented range input
152
+ */
153
+ export function segmentedDateRangeInputTemplate(
154
+ format: string,
155
+ rangeSeparator: string = ' - ',
156
+ ): string {
157
+ // Parse the format to determine the order of segments and separators
158
+ const formatSegments = parseFormatString(format);
159
+ const segments = [];
160
+ const separators = [];
161
+
162
+ // Extract segments and separators
163
+ for (let i = 0; i < formatSegments.length; i++) {
164
+ const seg = formatSegments[i];
165
+ if (seg.type === 'separator') {
166
+ separators.push(seg.value);
167
+ } else {
168
+ segments.push(seg);
169
+ }
170
+ }
171
+
172
+ // Ensure we have exactly 3 segments (day, month, year) and 2 separators
173
+ if (segments.length !== 3 || separators.length !== 2) {
174
+ console.warn('Invalid date format for segmented range input:', format);
175
+ // Fall back to default MM/dd/yyyy
176
+ return getDefaultSegmentedRangeTemplate(rangeSeparator);
177
+ }
178
+
179
+ // Create the template based on the parsed format
180
+ return `
181
+ <div class="flex items-center w-full">
182
+ <div class="flex items-center bg-transparent text-sm">
183
+ <div
184
+ class="${getSegmentWidthClass(
185
+ segments[0].type,
186
+ )} bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
187
+ data-segment="start-${getSegmentName(segments[0].type)}"
188
+ tabindex="0"
189
+ role="button"
190
+ aria-label="Start ${getSegmentLabel(segments[0].type)}">${
191
+ segments[0].placeholder
192
+ }</div>
193
+ <span class="text-gray-500 mx-0.5">${separators[0]}</span>
194
+ <div
195
+ class="${getSegmentWidthClass(
196
+ segments[1].type,
197
+ )} bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
198
+ data-segment="start-${getSegmentName(segments[1].type)}"
199
+ tabindex="0"
200
+ role="button"
201
+ aria-label="Start ${getSegmentLabel(segments[1].type)}">${
202
+ segments[1].placeholder
203
+ }</div>
204
+ <span class="text-gray-500 mx-0.5">${separators[1]}</span>
205
+ <div
206
+ class="${getSegmentWidthClass(
207
+ segments[2].type,
208
+ )} bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
209
+ data-segment="start-${getSegmentName(segments[2].type)}"
210
+ tabindex="0"
211
+ role="button"
212
+ aria-label="Start ${getSegmentLabel(segments[2].type)}">${
213
+ segments[2].placeholder
214
+ }</div>
215
+ </div>
216
+ <span class="mx-1 text-gray-500">${rangeSeparator}</span>
217
+ <div class="flex items-center bg-transparent text-sm">
218
+ <div
219
+ class="${getSegmentWidthClass(
220
+ segments[0].type,
221
+ )} bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
222
+ data-segment="end-${getSegmentName(segments[0].type)}"
223
+ tabindex="0"
224
+ role="button"
225
+ aria-label="End ${getSegmentLabel(segments[0].type)}">${
226
+ segments[0].placeholder
227
+ }</div>
228
+ <span class="text-gray-500 mx-0.5">${separators[0]}</span>
229
+ <div
230
+ class="${getSegmentWidthClass(
231
+ segments[1].type,
232
+ )} bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
233
+ data-segment="end-${getSegmentName(segments[1].type)}"
234
+ tabindex="0"
235
+ role="button"
236
+ aria-label="End ${getSegmentLabel(segments[1].type)}">${
237
+ segments[1].placeholder
238
+ }</div>
239
+ <span class="text-gray-500 mx-0.5">${separators[1]}</span>
240
+ <div
241
+ class="${getSegmentWidthClass(
242
+ segments[2].type,
243
+ )} bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
244
+ data-segment="end-${getSegmentName(segments[2].type)}"
245
+ tabindex="0"
246
+ role="button"
247
+ aria-label="End ${getSegmentLabel(segments[2].type)}">${
248
+ segments[2].placeholder
249
+ }</div>
250
+ </div>
251
+ </div>
252
+ `;
253
+ }
254
+
255
+ /**
256
+ * Parse a date format string into segments and separators
257
+ *
258
+ * @param format - Date format string (e.g., 'dd/MM/yyyy')
259
+ * @returns Array of parsed segments with type, placeholder and value
260
+ */
261
+ function parseFormatString(
262
+ format: string,
263
+ ): Array<{ type: string; value?: string; placeholder?: string }> {
264
+ const result: Array<{ type: string; value?: string; placeholder?: string }> =
265
+ [];
266
+ let currentType = '';
267
+ let currentValue = '';
268
+
269
+ // Helper to add a segment to the result
270
+ const addSegment = () => {
271
+ if (!currentValue) return;
272
+
273
+ if (/^d+$/.test(currentValue)) {
274
+ result.push({
275
+ type: 'day',
276
+ value: currentValue,
277
+ placeholder: currentValue.length === 1 ? 'd' : 'dd',
278
+ });
279
+ } else if (/^M+$/.test(currentValue)) {
280
+ result.push({
281
+ type: 'month',
282
+ value: currentValue,
283
+ placeholder: currentValue.length === 1 ? 'M' : 'MM',
284
+ });
285
+ } else if (/^y+$/.test(currentValue)) {
286
+ result.push({
287
+ type: 'year',
288
+ value: currentValue,
289
+ placeholder: currentValue.length <= 2 ? 'yy' : 'yyyy',
290
+ });
291
+ } else {
292
+ // This is a separator
293
+ result.push({
294
+ type: 'separator',
295
+ value: currentValue,
296
+ });
297
+ }
298
+
299
+ currentValue = '';
300
+ };
301
+
302
+ // Process each character in the format string
303
+ for (let i = 0; i < format.length; i++) {
304
+ const char = format[i];
305
+
306
+ if (/[dMy]/.test(char)) {
307
+ // Date part characters
308
+ if (currentType === char) {
309
+ // Continue the current segment
310
+ currentValue += char;
311
+ } else {
312
+ // Start a new segment
313
+ addSegment();
314
+ currentType = char;
315
+ currentValue = char;
316
+ }
317
+ } else {
318
+ // Separator character
319
+ if (currentValue) {
320
+ addSegment();
321
+ }
322
+ currentType = '';
323
+ currentValue = char;
324
+ addSegment();
325
+ }
326
+ }
327
+
328
+ // Add the last segment
329
+ addSegment();
330
+
331
+ return result;
332
+ }
333
+
334
+ /**
335
+ * Get a suitable CSS width class based on segment type
336
+ *
337
+ * @param type - Segment type (day, month, year)
338
+ * @returns CSS class for width
339
+ */
340
+ function getSegmentWidthClass(type: string): string {
341
+ switch (type) {
342
+ case 'day':
343
+ return 'w-7';
344
+ case 'month':
345
+ return 'w-7';
346
+ case 'year':
347
+ return 'w-12';
348
+ default:
349
+ return 'w-7';
350
+ }
351
+ }
352
+
353
+ /**
354
+ * Get the segment name to be used in data-segment attribute
355
+ *
356
+ * @param type - Segment type (day, month, year)
357
+ * @returns Segment name
358
+ */
359
+ function getSegmentName(type: string): string {
360
+ return type;
361
+ }
362
+
363
+ /**
364
+ * Get a human-readable label for the segment
365
+ *
366
+ * @param type - Segment type (day, month, year)
367
+ * @returns Human-readable label
368
+ */
369
+ function getSegmentLabel(type: string): string {
370
+ return type.charAt(0).toUpperCase() + type.slice(1);
371
+ }
372
+
373
+ /**
374
+ * Get the default segmented date input template (MM/dd/yyyy)
375
+ *
376
+ * @returns Default template HTML
377
+ */
378
+ function getDefaultSegmentedTemplate(): string {
379
+ return `
380
+ <div class="flex items-center bg-transparent text-sm">
381
+ <div
382
+ class="w-7 bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
383
+ data-segment="month"
384
+ tabindex="0"
385
+ role="button"
386
+ aria-label="Month">MM</div>
387
+ <span class="text-gray-500 mx-0.5">/</span>
388
+ <div
389
+ class="w-7 bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
390
+ data-segment="day"
391
+ tabindex="0"
392
+ role="button"
393
+ aria-label="Day">dd</div>
394
+ <span class="text-gray-500 mx-0.5">/</span>
395
+ <div
396
+ class="w-12 bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
397
+ data-segment="year"
398
+ tabindex="0"
399
+ role="button"
400
+ aria-label="Year">yyyy</div>
401
+ </div>
402
+ `;
403
+ }
404
+
405
+ /**
406
+ * Get the default segmented date range input template (MM/dd/yyyy)
407
+ *
408
+ * @param rangeSeparator - Separator between start and end dates
409
+ * @returns Default range template HTML
410
+ */
411
+ function getDefaultSegmentedRangeTemplate(
412
+ rangeSeparator: string = ' - ',
413
+ ): string {
414
+ return `
415
+ <div class="flex items-center w-full">
416
+ <div class="flex items-center bg-transparent text-sm">
417
+ <div
418
+ class="w-7 bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
419
+ data-segment="start-month"
420
+ tabindex="0"
421
+ role="button"
422
+ aria-label="Start Month">MM</div>
423
+ <span class="text-gray-500 mx-0.5">/</span>
424
+ <div
425
+ class="w-7 bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
426
+ data-segment="start-day"
427
+ tabindex="0"
428
+ role="button"
429
+ aria-label="Start Day">dd</div>
430
+ <span class="text-gray-500 mx-0.5">/</span>
431
+ <div
432
+ class="w-12 bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
433
+ data-segment="start-year"
434
+ tabindex="0"
435
+ role="button"
436
+ aria-label="Start Year">yyyy</div>
437
+ </div>
438
+ <span class="mx-1 text-gray-500">${rangeSeparator}</span>
439
+ <div class="flex items-center bg-transparent text-sm">
440
+ <div
441
+ class="w-7 bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
442
+ data-segment="end-month"
443
+ tabindex="0"
444
+ role="button"
445
+ aria-label="End Month">MM</div>
446
+ <span class="text-gray-500 mx-0.5">/</span>
447
+ <div
448
+ class="w-7 bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
449
+ data-segment="end-day"
450
+ tabindex="0"
451
+ role="button"
452
+ aria-label="End Day">dd</div>
453
+ <span class="text-gray-500 mx-0.5">/</span>
454
+ <div
455
+ class="w-12 bg-transparent text-center text-gray-900 cursor-pointer segment-part hover:bg-gray-100 rounded-sm px-1 py-0.5"
456
+ data-segment="end-year"
457
+ tabindex="0"
458
+ role="button"
459
+ aria-label="End Year">yyyy</div>
460
+ </div>
461
+ </div>
462
+ `;
463
+ }
464
+
465
+ /**
466
+ * Get an array of day names based on locale and format
467
+ *
468
+ * @param locale - Locale configuration
469
+ * @param format - Format for day names ('long', 'short', or 'min')
470
+ * @returns Array of day names
471
+ */
472
+ function getDayNames(
473
+ locale: LocaleConfigInterface,
474
+ format: 'long' | 'short' | 'min',
475
+ ): string[] {
476
+ if (format === 'long') {
477
+ return locale.dayNames;
478
+ } else if (format === 'short') {
479
+ return locale.dayNamesShort;
480
+ } else {
481
+ return locale.dayNamesMin;
482
+ }
483
+ }
484
+
485
+ /**
486
+ * Calendar grid template
487
+ *
488
+ * @param locale - Locale configuration for the datepicker
489
+ * @param weekDayFormat - Format for the week day names ('long', 'short', or 'min')
490
+ * @returns Calendar grid template HTML
491
+ */
492
+ export function calendarGridTemplate(
493
+ locale: LocaleConfigInterface,
494
+ weekDayFormat: 'long' | 'short' | 'min',
495
+ ): string {
496
+ // Get the day names based on the locale and format
497
+ const dayNames = getDayNames(locale, weekDayFormat);
498
+
499
+ // Start from the first day of the week based on locale
500
+ const firstDay = locale.firstDayOfWeek;
501
+ const orderedDayNames = [
502
+ ...dayNames.slice(firstDay),
503
+ ...dayNames.slice(0, firstDay),
504
+ ];
505
+
506
+ // Create the header with day names
507
+ const headerCells = orderedDayNames
508
+ .map(
509
+ (day) =>
510
+ `<th class="py-2 text-center text-xs font-medium text-gray-500 uppercase w-10">${day}</th>`,
511
+ )
512
+ .join('');
513
+
514
+ return `
515
+ <div class="calendar-month-container">
516
+ <table class="w-full border-collapse calendar-grid" role="grid" aria-labelledby="datepicker-month">
517
+ <thead>
518
+ <tr class="border-b border-gray-200">
519
+ ${headerCells}
520
+ </tr>
521
+ </thead>
522
+ <tbody class="border-none"></tbody>
523
+ </table>
524
+ </div>
525
+ `;
526
+ }
527
+
528
+ /**
529
+ * Calendar day cell template
530
+ *
531
+ * @param day - Day number
532
+ * @param month - Month number (0-11)
533
+ * @param year - Year (4 digits)
534
+ * @param isCurrentMonth - Whether the day is in the current month
535
+ * @param isToday - Whether the day is today
536
+ * @param isSelected - Whether the day is selected
537
+ * @param isDisabled - Whether the day is disabled
538
+ * @param isRangeStart - Whether the day is the start of a range
539
+ * @param isRangeEnd - Whether the day is the end of a range
540
+ * @param isInRange - Whether the day is within a selected range
541
+ * @param isWeekend - Whether the day is a weekend
542
+ * @returns Day cell HTML
543
+ */
544
+ export function dayTemplate(
545
+ day: number,
546
+ month: number = 0,
547
+ year: number = 0,
548
+ isCurrentMonth: boolean = true,
549
+ isToday: boolean = false,
550
+ isSelected: boolean = false,
551
+ isDisabled: boolean = false,
552
+ isRangeStart: boolean = false,
553
+ isRangeEnd: boolean = false,
554
+ isInRange: boolean = false,
555
+ isWeekend: boolean = false,
556
+ ): string {
557
+ // Base classes for day button
558
+ let classes =
559
+ 'w-full h-8 rounded-full flex items-center justify-center text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 ';
560
+
561
+ // Apply conditional classes
562
+ if (!isCurrentMonth) {
563
+ classes += 'current';
564
+ } else if (isDisabled) {
565
+ classes += 'text-gray-300 cursor-not-allowed ';
566
+ } else if (isSelected || isRangeStart || isRangeEnd) {
567
+ classes += 'bg-blue-600 text-white hover:bg-blue-700 ';
568
+ } else if (isInRange) {
569
+ classes += 'bg-blue-100 text-blue-800 hover:bg-blue-200 ';
570
+ } else if (isToday) {
571
+ classes += 'border border-blue-500 text-blue-600 hover:bg-blue-50 ';
572
+ } else {
573
+ classes +=
574
+ 'text-gray-700 hover:bg-gray-100 hover:bg-blue-50 hover:text-blue-600 ';
575
+ }
576
+
577
+ // Add weekend-specific styling
578
+ if (isWeekend && !isSelected && !isRangeStart && !isRangeEnd && !isInRange) {
579
+ classes += 'text-gray-500 ';
580
+ }
581
+
582
+ // Add attributes for hover states in range selection
583
+ const hoverAttributes =
584
+ isCurrentMonth && !isDisabled ? 'data-hover-date="true"' : '';
585
+
586
+ // Create a date ID if month and year are provided
587
+ let dateIdAttr = '';
588
+ if (year > 0) {
589
+ // Format: YYYY-MM-DD (ensures leading zeros for month and day)
590
+ const monthStr = String(month + 1).padStart(2, '0'); // Add 1 since month is 0-indexed
591
+ const dayStr = String(day).padStart(2, '0');
592
+ const dateId = `${year}-${monthStr}-${dayStr}`;
593
+ dateIdAttr = `data-date-id="${dateId}"`;
594
+ }
595
+
596
+ return `
597
+ <td class="p-0.5">
598
+ <button
599
+ type="button"
600
+ class="${classes.trim()}"
601
+ data-date="${day}"
602
+ ${dateIdAttr}
603
+ ${isDisabled ? 'disabled' : ''}
604
+ ${!isCurrentMonth ? 'tabindex="-1"' : ''}
605
+ ${hoverAttributes}
606
+ aria-selected="${isSelected}"
607
+ aria-current="${isToday ? 'date' : 'false'}"
608
+ >
609
+ ${day}
610
+ </button>
611
+ </td>
612
+ `;
613
+ }
614
+
615
+ /**
616
+ * Month and year header template with buttons for toggling month/year view
617
+ *
618
+ * @param locale - Locale configuration
619
+ * @param currentMonth - Current month (0-11)
620
+ * @param currentYear - Current year
621
+ * @returns Month and year header HTML
622
+ */
623
+ export function monthYearSelectTemplate(
624
+ locale: LocaleConfigInterface,
625
+ currentMonth: number,
626
+ currentYear: number,
627
+ ): string {
628
+ return `
629
+ <div class="flex items-center justify-center space-x-2">
630
+ <button type="button"
631
+ class="month-selector px-2 py-1 rounded hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 text-gray-800 font-medium"
632
+ aria-label="Select Month">
633
+ ${locale.monthNames[currentMonth]}
634
+ </button>
635
+ <button type="button"
636
+ class="year-selector px-2 py-1 rounded hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 text-gray-800 font-medium"
637
+ aria-label="Select Year">
638
+ ${currentYear}
639
+ </button>
640
+ </div>
641
+ `;
642
+ }
643
+
644
+ /**
645
+ * Template for month selection view
646
+ *
647
+ * @param locale - Locale configuration
648
+ * @param currentMonth - Current selected month (0-11)
649
+ * @returns Month selection HTML
650
+ */
651
+ export function monthSelectionTemplate(
652
+ locale: LocaleConfigInterface,
653
+ currentMonth: number,
654
+ ): string {
655
+ const months = locale.monthNamesShort.map((month, idx) => {
656
+ const isCurrentMonth = idx === currentMonth;
657
+ const buttonClass = isCurrentMonth
658
+ ? 'py-3 px-2 text-sm rounded-md bg-blue-500 text-white font-medium hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500'
659
+ : 'py-3 px-2 text-sm rounded-md bg-transparent hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 text-gray-800';
660
+
661
+ return `
662
+ <button
663
+ type="button"
664
+ class="${buttonClass}"
665
+ data-month="${idx}"
666
+ aria-selected="${isCurrentMonth}"
667
+ aria-label="${locale.monthNames[idx]}"
668
+ >
669
+ ${month}
670
+ </button>
671
+ `;
672
+ });
673
+
674
+ return `
675
+ <div class="month-grid grid grid-cols-3 gap-2 p-2">
676
+ ${months.join('')}
677
+ </div>
678
+ `;
679
+ }
680
+
681
+ /**
682
+ * Template for year selection view
683
+ *
684
+ * @param startYear - Start year
685
+ * @param endYear - End year
686
+ * @param currentYear - Current selected year
687
+ * @returns Year selection HTML
688
+ */
689
+ export function yearSelectionTemplate(
690
+ startYear: number,
691
+ endYear: number,
692
+ currentYear: number,
693
+ ): string {
694
+ const years = [];
695
+
696
+ for (let year = startYear; year <= endYear; year++) {
697
+ const isCurrentYear = year === currentYear;
698
+ const yearClass = isCurrentYear
699
+ ? 'py-3 px-2 text-center text-sm rounded-md bg-blue-500 text-white font-medium hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500'
700
+ : 'py-3 px-2 text-center text-sm rounded-md bg-transparent hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 text-gray-800';
701
+
702
+ years.push(`
703
+ <button
704
+ type="button"
705
+ class="${yearClass}"
706
+ data-year="${year}"
707
+ aria-selected="${isCurrentYear}"
708
+ >
709
+ ${year}
710
+ </button>
711
+ `);
712
+ }
713
+
714
+ // Navigation to previous/next year ranges
715
+ const prevYearsBtn = `
716
+ <button
717
+ type="button"
718
+ class="py-2 px-2 text-center text-sm rounded-md bg-gray-100 text-gray-600 hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500"
719
+ data-year-nav="prev"
720
+ aria-label="Previous years"
721
+ >
722
+ ${startYear - 1}...
723
+ </button>
724
+ `;
725
+
726
+ const nextYearsBtn = `
727
+ <button
728
+ type="button"
729
+ class="py-2 px-2 text-center text-sm rounded-md bg-gray-100 text-gray-600 hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500"
730
+ data-year-nav="next"
731
+ aria-label="Next years"
732
+ >
733
+ ...${endYear + 1}
734
+ </button>
735
+ `;
736
+
737
+ return `
738
+ <div class="year-selection">
739
+ <div class="year-navigation flex justify-between mb-2 px-2">
740
+ ${prevYearsBtn}
741
+ <span class="text-gray-700 font-medium">${startYear}-${endYear}</span>
742
+ ${nextYearsBtn}
743
+ </div>
744
+ <div class="year-grid grid grid-cols-4 gap-2 p-2">
745
+ ${years.join('')}
746
+ </div>
747
+ </div>
748
+ `;
749
+ }
750
+
751
+ /**
752
+ * Create placeholder template with placeholder text
753
+ *
754
+ * @param placeholder - Placeholder text to display
755
+ * @returns HTML string for the placeholder
756
+ */
757
+ export const placeholderTemplate = (placeholder: string): string => {
758
+ return `<span class="text-gray-500">${placeholder}</span>`;
759
+ };
760
+
761
+ /**
762
+ * Create a template for the display wrapper
763
+ */
764
+ export function displayWrapperTemplate(classes: string = ''): string {
765
+ return `
766
+ <div class="kt-datepicker-display-wrapper relative w-full ${classes}"
767
+ role="combobox"
768
+ aria-haspopup="dialog"
769
+ aria-expanded="false"
770
+ >
771
+ </div>
772
+ `;
773
+ }
774
+
775
+ /**
776
+ * Create a template for the display element
777
+ */
778
+ export function displayElementTemplate(
779
+ placeholder: string,
780
+ classes: string = '',
781
+ ): string {
782
+ return `
783
+ <div class="kt-datepicker-display-element py-2 px-3 border rounded cursor-pointer ${classes}"
784
+ tabindex="0"
785
+ role="textbox"
786
+ aria-label="${placeholder}"
787
+ data-placeholder="${placeholder}"
788
+ >
789
+ <span class="kt-datepicker-display-text"></span>
790
+ </div>
791
+ `;
792
+ }