@keenthemes/ktui 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/README.md +0 -27
  2. package/dist/ktui.js +6790 -14063
  3. package/dist/ktui.min.js +1 -1
  4. package/dist/ktui.min.js.map +1 -1
  5. package/dist/styles.css +1132 -2705
  6. package/lib/cjs/components/datatable/__tests__/pagination-reset.test.js +596 -0
  7. package/lib/cjs/components/datatable/__tests__/pagination-reset.test.js.map +1 -0
  8. package/lib/cjs/components/datatable/__tests__/race-conditions.test.js +548 -0
  9. package/lib/cjs/components/datatable/__tests__/race-conditions.test.js.map +1 -0
  10. package/lib/cjs/components/datatable/__tests__/setup.js +63 -0
  11. package/lib/cjs/components/datatable/__tests__/setup.js.map +1 -0
  12. package/lib/cjs/components/datatable/datatable.js +92 -30
  13. package/lib/cjs/components/datatable/datatable.js.map +1 -1
  14. package/lib/cjs/index.js +1 -10
  15. package/lib/cjs/index.js.map +1 -1
  16. package/lib/esm/components/datatable/__tests__/pagination-reset.test.js +594 -0
  17. package/lib/esm/components/datatable/__tests__/pagination-reset.test.js.map +1 -0
  18. package/lib/esm/components/datatable/__tests__/race-conditions.test.js +546 -0
  19. package/lib/esm/components/datatable/__tests__/race-conditions.test.js.map +1 -0
  20. package/lib/esm/components/datatable/__tests__/setup.js +58 -0
  21. package/lib/esm/components/datatable/__tests__/setup.js.map +1 -0
  22. package/lib/esm/components/datatable/datatable.js +92 -30
  23. package/lib/esm/components/datatable/datatable.js.map +1 -1
  24. package/lib/esm/index.js +0 -7
  25. package/lib/esm/index.js.map +1 -1
  26. package/package.json +7 -9
  27. package/src/components/alert/alert.css +188 -429
  28. package/src/components/datatable/__tests__/pagination-reset.test.ts +657 -0
  29. package/src/components/datatable/__tests__/race-conditions.test.ts +455 -0
  30. package/src/components/datatable/__tests__/setup.ts +67 -0
  31. package/src/components/datatable/datatable.ts +66 -11
  32. package/src/components/input/input.css +0 -1
  33. package/src/components/select/select.css +0 -1
  34. package/src/components/select/variants.css +4 -0
  35. package/src/components/textarea/textarea.css +0 -1
  36. package/src/index.ts +0 -10
  37. package/styles.css +0 -1
  38. package/lib/cjs/components/alert/alert.js +0 -1025
  39. package/lib/cjs/components/alert/alert.js.map +0 -1
  40. package/lib/cjs/components/alert/index.js +0 -20
  41. package/lib/cjs/components/alert/index.js.map +0 -1
  42. package/lib/cjs/components/alert/templates.js +0 -120
  43. package/lib/cjs/components/alert/templates.js.map +0 -1
  44. package/lib/cjs/components/alert/types.js +0 -7
  45. package/lib/cjs/components/alert/types.js.map +0 -1
  46. package/lib/cjs/components/datepicker/config/config.js +0 -42
  47. package/lib/cjs/components/datepicker/config/config.js.map +0 -1
  48. package/lib/cjs/components/datepicker/config/index.js +0 -24
  49. package/lib/cjs/components/datepicker/config/index.js.map +0 -1
  50. package/lib/cjs/components/datepicker/config/interfaces.js +0 -7
  51. package/lib/cjs/components/datepicker/config/interfaces.js.map +0 -1
  52. package/lib/cjs/components/datepicker/config/types.js +0 -7
  53. package/lib/cjs/components/datepicker/config/types.js.map +0 -1
  54. package/lib/cjs/components/datepicker/core/event-manager.js +0 -135
  55. package/lib/cjs/components/datepicker/core/event-manager.js.map +0 -1
  56. package/lib/cjs/components/datepicker/core/focus-manager.js +0 -167
  57. package/lib/cjs/components/datepicker/core/focus-manager.js.map +0 -1
  58. package/lib/cjs/components/datepicker/core/helpers.js +0 -219
  59. package/lib/cjs/components/datepicker/core/helpers.js.map +0 -1
  60. package/lib/cjs/components/datepicker/core/index.js +0 -25
  61. package/lib/cjs/components/datepicker/core/index.js.map +0 -1
  62. package/lib/cjs/components/datepicker/core/unified-state-manager.js +0 -394
  63. package/lib/cjs/components/datepicker/core/unified-state-manager.js.map +0 -1
  64. package/lib/cjs/components/datepicker/datepicker.js +0 -2252
  65. package/lib/cjs/components/datepicker/datepicker.js.map +0 -1
  66. package/lib/cjs/components/datepicker/index.js +0 -24
  67. package/lib/cjs/components/datepicker/index.js.map +0 -1
  68. package/lib/cjs/components/datepicker/ui/index.js +0 -23
  69. package/lib/cjs/components/datepicker/ui/index.js.map +0 -1
  70. package/lib/cjs/components/datepicker/ui/input/dropdown.js +0 -489
  71. package/lib/cjs/components/datepicker/ui/input/dropdown.js.map +0 -1
  72. package/lib/cjs/components/datepicker/ui/input/index.js +0 -23
  73. package/lib/cjs/components/datepicker/ui/input/index.js.map +0 -1
  74. package/lib/cjs/components/datepicker/ui/input/segmented-input.js +0 -640
  75. package/lib/cjs/components/datepicker/ui/input/segmented-input.js.map +0 -1
  76. package/lib/cjs/components/datepicker/ui/renderers/calendar.js +0 -446
  77. package/lib/cjs/components/datepicker/ui/renderers/calendar.js.map +0 -1
  78. package/lib/cjs/components/datepicker/ui/renderers/footer.js +0 -42
  79. package/lib/cjs/components/datepicker/ui/renderers/footer.js.map +0 -1
  80. package/lib/cjs/components/datepicker/ui/renderers/header.js +0 -32
  81. package/lib/cjs/components/datepicker/ui/renderers/header.js.map +0 -1
  82. package/lib/cjs/components/datepicker/ui/renderers/index.js +0 -25
  83. package/lib/cjs/components/datepicker/ui/renderers/index.js.map +0 -1
  84. package/lib/cjs/components/datepicker/ui/renderers/time-picker.js +0 -384
  85. package/lib/cjs/components/datepicker/ui/renderers/time-picker.js.map +0 -1
  86. package/lib/cjs/components/datepicker/ui/templates/index.js +0 -22
  87. package/lib/cjs/components/datepicker/ui/templates/index.js.map +0 -1
  88. package/lib/cjs/components/datepicker/ui/templates/templates.js +0 -253
  89. package/lib/cjs/components/datepicker/ui/templates/templates.js.map +0 -1
  90. package/lib/cjs/components/datepicker/utils/date-formatters.js +0 -88
  91. package/lib/cjs/components/datepicker/utils/date-formatters.js.map +0 -1
  92. package/lib/cjs/components/datepicker/utils/date-utils.js +0 -194
  93. package/lib/cjs/components/datepicker/utils/date-utils.js.map +0 -1
  94. package/lib/cjs/components/datepicker/utils/index.js +0 -24
  95. package/lib/cjs/components/datepicker/utils/index.js.map +0 -1
  96. package/lib/cjs/components/datepicker/utils/time-utils.js +0 -213
  97. package/lib/cjs/components/datepicker/utils/time-utils.js.map +0 -1
  98. package/lib/esm/components/alert/alert.js +0 -1022
  99. package/lib/esm/components/alert/alert.js.map +0 -1
  100. package/lib/esm/components/alert/index.js +0 -4
  101. package/lib/esm/components/alert/index.js.map +0 -1
  102. package/lib/esm/components/alert/templates.js +0 -112
  103. package/lib/esm/components/alert/templates.js.map +0 -1
  104. package/lib/esm/components/alert/types.js +0 -6
  105. package/lib/esm/components/alert/types.js.map +0 -1
  106. package/lib/esm/components/datepicker/config/config.js +0 -39
  107. package/lib/esm/components/datepicker/config/config.js.map +0 -1
  108. package/lib/esm/components/datepicker/config/index.js +0 -8
  109. package/lib/esm/components/datepicker/config/index.js.map +0 -1
  110. package/lib/esm/components/datepicker/config/interfaces.js +0 -6
  111. package/lib/esm/components/datepicker/config/interfaces.js.map +0 -1
  112. package/lib/esm/components/datepicker/config/types.js +0 -6
  113. package/lib/esm/components/datepicker/config/types.js.map +0 -1
  114. package/lib/esm/components/datepicker/core/event-manager.js +0 -133
  115. package/lib/esm/components/datepicker/core/event-manager.js.map +0 -1
  116. package/lib/esm/components/datepicker/core/focus-manager.js +0 -164
  117. package/lib/esm/components/datepicker/core/focus-manager.js.map +0 -1
  118. package/lib/esm/components/datepicker/core/helpers.js +0 -211
  119. package/lib/esm/components/datepicker/core/helpers.js.map +0 -1
  120. package/lib/esm/components/datepicker/core/index.js +0 -9
  121. package/lib/esm/components/datepicker/core/index.js.map +0 -1
  122. package/lib/esm/components/datepicker/core/unified-state-manager.js +0 -391
  123. package/lib/esm/components/datepicker/core/unified-state-manager.js.map +0 -1
  124. package/lib/esm/components/datepicker/datepicker.js +0 -2248
  125. package/lib/esm/components/datepicker/datepicker.js.map +0 -1
  126. package/lib/esm/components/datepicker/index.js +0 -7
  127. package/lib/esm/components/datepicker/index.js.map +0 -1
  128. package/lib/esm/components/datepicker/ui/index.js +0 -7
  129. package/lib/esm/components/datepicker/ui/index.js.map +0 -1
  130. package/lib/esm/components/datepicker/ui/input/dropdown.js +0 -486
  131. package/lib/esm/components/datepicker/ui/input/dropdown.js.map +0 -1
  132. package/lib/esm/components/datepicker/ui/input/index.js +0 -7
  133. package/lib/esm/components/datepicker/ui/input/index.js.map +0 -1
  134. package/lib/esm/components/datepicker/ui/input/segmented-input.js +0 -637
  135. package/lib/esm/components/datepicker/ui/input/segmented-input.js.map +0 -1
  136. package/lib/esm/components/datepicker/ui/renderers/calendar.js +0 -443
  137. package/lib/esm/components/datepicker/ui/renderers/calendar.js.map +0 -1
  138. package/lib/esm/components/datepicker/ui/renderers/footer.js +0 -39
  139. package/lib/esm/components/datepicker/ui/renderers/footer.js.map +0 -1
  140. package/lib/esm/components/datepicker/ui/renderers/header.js +0 -29
  141. package/lib/esm/components/datepicker/ui/renderers/header.js.map +0 -1
  142. package/lib/esm/components/datepicker/ui/renderers/index.js +0 -9
  143. package/lib/esm/components/datepicker/ui/renderers/index.js.map +0 -1
  144. package/lib/esm/components/datepicker/ui/renderers/time-picker.js +0 -381
  145. package/lib/esm/components/datepicker/ui/renderers/time-picker.js.map +0 -1
  146. package/lib/esm/components/datepicker/ui/templates/index.js +0 -6
  147. package/lib/esm/components/datepicker/ui/templates/index.js.map +0 -1
  148. package/lib/esm/components/datepicker/ui/templates/templates.js +0 -242
  149. package/lib/esm/components/datepicker/ui/templates/templates.js.map +0 -1
  150. package/lib/esm/components/datepicker/utils/date-formatters.js +0 -83
  151. package/lib/esm/components/datepicker/utils/date-formatters.js.map +0 -1
  152. package/lib/esm/components/datepicker/utils/date-utils.js +0 -184
  153. package/lib/esm/components/datepicker/utils/date-utils.js.map +0 -1
  154. package/lib/esm/components/datepicker/utils/index.js +0 -8
  155. package/lib/esm/components/datepicker/utils/index.js.map +0 -1
  156. package/lib/esm/components/datepicker/utils/time-utils.js +0 -201
  157. package/lib/esm/components/datepicker/utils/time-utils.js.map +0 -1
  158. package/src/components/alert/alert.ts +0 -990
  159. package/src/components/alert/index.ts +0 -4
  160. package/src/components/alert/templates.ts +0 -110
  161. package/src/components/alert/tests/accessibility/aria-roles.test.ts +0 -19
  162. package/src/components/alert/tests/accessibility/focus-management.test.ts +0 -19
  163. package/src/components/alert/tests/accessibility/keyboard-nav.test.ts +0 -22
  164. package/src/components/alert/tests/actions/confirm-cancel.test.ts +0 -122
  165. package/src/components/alert/tests/actions/input-field.test.ts +0 -180
  166. package/src/components/alert/tests/alert.basic.test.ts +0 -126
  167. package/src/components/alert/tests/alert.config.test.ts +0 -75
  168. package/src/components/alert/tests/alert.templates.test.ts +0 -17
  169. package/src/components/alert/tests/config/attribute-config.test.ts +0 -94
  170. package/src/components/alert/tests/config/json-config.test.ts +0 -119
  171. package/src/components/alert/tests/config/merging.test.ts +0 -89
  172. package/src/components/alert/tests/dismissal/auto-dismiss.test.ts +0 -96
  173. package/src/components/alert/tests/dismissal/escape-key-dismiss.test.ts +0 -105
  174. package/src/components/alert/tests/dismissal/manual-dismiss.test.ts +0 -90
  175. package/src/components/alert/tests/dismissal/outside-click-dismiss.test.ts +0 -91
  176. package/src/components/alert/tests/edge-cases/invalid-config.test.ts +0 -19
  177. package/src/components/alert/tests/edge-cases/multiple-alerts.test.ts +0 -19
  178. package/src/components/alert/tests/rendering/custom-content.test.ts +0 -81
  179. package/src/components/alert/tests/rendering/info-alert.test.ts +0 -84
  180. package/src/components/alert/tests/rendering/success-alert.test.ts +0 -100
  181. package/src/components/alert/tests/templates/default-templates.test.ts +0 -16
  182. package/src/components/alert/tests/templates/user-templates.test.ts +0 -16
  183. package/src/components/alert/types.ts +0 -145
  184. package/src/components/datepicker/__tests__/datepicker-events.test.ts +0 -356
  185. package/src/components/datepicker/__tests__/datepicker-init.test.ts +0 -343
  186. package/src/components/datepicker/__tests__/datepicker-integration.test.ts +0 -435
  187. package/src/components/datepicker/__tests__/datepicker-timezone.test.ts +0 -220
  188. package/src/components/datepicker/__tests__/segmented-input-focus.test.ts +0 -380
  189. package/src/components/datepicker/__tests__/selective-state-updates.test.ts +0 -400
  190. package/src/components/datepicker/__tests__/state-manager.test.ts +0 -421
  191. package/src/components/datepicker/__tests__/time-preservation.test.ts +0 -387
  192. package/src/components/datepicker/config/config.ts +0 -40
  193. package/src/components/datepicker/config/index.ts +0 -8
  194. package/src/components/datepicker/config/interfaces.ts +0 -82
  195. package/src/components/datepicker/config/types.ts +0 -188
  196. package/src/components/datepicker/core/event-manager.ts +0 -159
  197. package/src/components/datepicker/core/focus-manager.ts +0 -201
  198. package/src/components/datepicker/core/helpers.ts +0 -231
  199. package/src/components/datepicker/core/index.ts +0 -9
  200. package/src/components/datepicker/core/unified-state-manager.ts +0 -459
  201. package/src/components/datepicker/datepicker.css +0 -435
  202. package/src/components/datepicker/datepicker.ts +0 -2548
  203. package/src/components/datepicker/index.ts +0 -8
  204. package/src/components/datepicker/ui/index.ts +0 -7
  205. package/src/components/datepicker/ui/input/dropdown.ts +0 -552
  206. package/src/components/datepicker/ui/input/index.ts +0 -7
  207. package/src/components/datepicker/ui/input/segmented-input.ts +0 -638
  208. package/src/components/datepicker/ui/renderers/__tests__/calendar-optimizations.test.ts +0 -611
  209. package/src/components/datepicker/ui/renderers/calendar.ts +0 -530
  210. package/src/components/datepicker/ui/renderers/footer.ts +0 -43
  211. package/src/components/datepicker/ui/renderers/header.ts +0 -33
  212. package/src/components/datepicker/ui/renderers/index.ts +0 -9
  213. package/src/components/datepicker/ui/renderers/time-picker.ts +0 -438
  214. package/src/components/datepicker/ui/templates/index.ts +0 -6
  215. package/src/components/datepicker/ui/templates/templates.ts +0 -306
  216. package/src/components/datepicker/utils/__tests__/date-formatters.test.ts +0 -160
  217. package/src/components/datepicker/utils/__tests__/date-utils-keys.test.ts +0 -86
  218. package/src/components/datepicker/utils/__tests__/date-utils-timezone.test.ts +0 -215
  219. package/src/components/datepicker/utils/date-formatters.ts +0 -85
  220. package/src/components/datepicker/utils/date-utils.ts +0 -172
  221. package/src/components/datepicker/utils/index.ts +0 -8
  222. package/src/components/datepicker/utils/time-utils.ts +0 -221
@@ -1,306 +0,0 @@
1
- /*
2
- * templates.ts - Unified template system for KTDatepicker
3
- * Consolidates all template functionality including default templates, merging logic,
4
- * rendering utilities, and template management into a single, unified system.
5
- */
6
-
7
- import { KTDatepickerConfig, KTDatepickerTemplateStrings } from '../../config/types';
8
-
9
- // Default template strings for all UI fragments
10
- export const defaultTemplates: KTDatepickerTemplateStrings = {
11
- // Add role="dialog" and aria-modal to the dropdown container
12
- container: `<div data-kt-datepicker-container {{class}}></div>`,
13
- header: `<div data-kt-datepicker-header {{class}}">{{prevButton}}<span data-kt-datepicker-month-year>{{month}} {{year}}</span>{{nextButton}}</div>`,
14
- footer: `<div data-kt-datepicker-footer {{class}}">{{todayButton}} {{clearButton}} {{applyButton}}</div>`,
15
- // Add role="grid" and aria-label to the calendar grid
16
- calendarGrid: `<table data-kt-datepicker-calendar-grid role="grid" aria-label="Calendar" aria-readonly="true" {{class}}>{{calendar}}</table>`,
17
- // Add role="gridcell" to dayCell, aria-selected, and tabindex for keyboard nav
18
- dayCell: `<td data-kt-datepicker-day role="gridcell" {{attributes}} {{class}}><button type="button" data-day="{{day}}" aria-label="Select {{day}}" tabindex="-1">{{day}}</button></td>`,
19
- // Month/year selectors (add aria-live for dynamic updates)
20
- monthYearSelect: `<div data-kt-datepicker-monthyear-select aria-live="polite" {{class}}>{{monthSelect}} {{yearSelect}}</div>`,
21
- monthSelection: `<div data-kt-datepicker-month-selection {{class}}>{{months}}</div>`,
22
- yearSelection: `<div data-kt-datepicker-year-selection {{class}}>{{years}}</div>`,
23
- inputWrapper: `<div data-kt-datepicker-input-wrapper class="flex items-center {{class}}">{{input}} {{icon}}</div>`,
24
- segmentedDateInput: `<div data-kt-datepicker-segmented-input class="flex items-center {{class}}">{{segments}}</div>`,
25
- segmentedDateRangeInput: `<div data-kt-datepicker-segmented-range-input class="flex items-center {{class}}">{{start}}{{separator}}{{end}}</div>`,
26
- /**
27
- * Template for a single date segment (e.g., day, month, year)
28
- * Placeholders: segmentType, segmentValue, ariaLabel, ariaValueNow, ariaValueText, ariaValueMin, ariaValueMax, tabindex, contenteditable
29
- */
30
- dateSegment: `<span data-segment="{{segmentType}}" role="spinbutton" aria-label="{{ariaLabel}}" aria-valuenow="{{ariaValueNow}}" aria-valuetext="{{ariaValueText}}" aria-valuemin="{{ariaValueMin}}" aria-valuemax="{{ariaValueMax}}" tabindex="{{tabindex}}" contenteditable="{{contenteditable}}" {{class}}>{{segmentValue}}</span>`,
31
- /**
32
- * Template for a segment separator (e.g., / or space)
33
- * Placeholders: separator
34
- */
35
- segmentSeparator: `<span data-segment-separator {{class}}>{{separator}}</span>`,
36
- placeholder: `<span data-kt-datepicker-placeholder {{class}}>{{placeholder}}</span>`,
37
- displayWrapper: `<div data-kt-datepicker-display-wrapper {{class}}>{{value}}</div>`,
38
- displayElement: `<span data-kt-datepicker-display-element {{class}}>{{value}}</span>`,
39
- timePanel: `<div data-kt-datepicker-time-panel {{class}}>{{hours}}:{{minutes}}:{{seconds}} {{amPm}}</div>`,
40
- multiDateTag: `<span data-kt-datepicker-multidate-tag {{class}}>{{date}} <button>{{removeButton}}</button></span>`,
41
- emptyState: `<div data-kt-datepicker-empty {{class}}>{{message}}</div>`,
42
- // Add aria-haspopup and aria-expanded to calendar button
43
- calendarButton: `<button type="button" data-kt-datepicker-calendar-btn aria-label="Open calendar" aria-haspopup="dialog" aria-expanded="false" {{class}}>
44
- <svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true">
45
- <rect x="3" y="4" width="18" height="18" rx="2"/>
46
- <path d="M16 2v4M8 2v4M3 10h18"/>
47
- </svg>
48
- </button>`,
49
- // Add role="dialog" and aria-modal to dropdown
50
- dropdown: `<div data-kt-datepicker-dropdown role="dialog" aria-modal="true" aria-label="Date picker" class="hidden {{class}}"></div>`,
51
- prevButton: `<button type="button" data-kt-datepicker-prev aria-label="Previous month" {{class}}>
52
- <svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24" aria-hidden="true">
53
- <path d="m15 18-6-6 6-6"/>
54
- </svg>
55
- </button>`,
56
- nextButton: `<button type="button" data-kt-datepicker-next aria-label="Next month" {{class}}>
57
- <svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24" aria-hidden="true">
58
- <path d="m9 18 6-6-6-6"/>
59
- </svg>
60
- </button>`,
61
- // Add role="row" to calendar table rows
62
- calendarTable: `<table data-kt-datepicker-calendar-table role="grid" aria-label="Calendar" aria-readonly="true" {{class}}><thead><tr role="row">
63
- <th class="py-1 px-1 text-xs font-semibold text-gray-500 dark:text-gray-400">{{sunday}}</th>
64
- <th class="py-1 px-1 text-xs font-semibold text-gray-500 dark:text-gray-400">{{monday}}</th>
65
- <th class="py-1 px-1 text-xs font-semibold text-gray-500 dark:text-gray-400">{{tuesday}}</th>
66
- <th class="py-1 px-1 text-xs font-semibold text-gray-500 dark:text-gray-400">{{wednesday}}</th>
67
- <th class="py-1 px-1 text-xs font-semibold text-gray-500 dark:text-gray-400">{{thursday}}</th>
68
- <th class="py-1 px-1 text-xs font-semibold text-gray-500 dark:text-gray-400">{{friday}}</th>
69
- <th class="py-1 px-1 text-xs font-semibold text-gray-500 dark:text-gray-400">{{saturday}}</th>
70
- </tr></thead>{{body}}</table>`,
71
- calendarBody: `<tbody data-kt-datepicker-calendar-body {{class}}>{{rows}}</tbody>`,
72
- calendarRow: `<tr data-kt-datepicker-calendar-row role="row" {{class}}>{{cells}}</tr>`,
73
- todayButton: `<button type="button" data-kt-datepicker-today {{class}}>Today</button>`,
74
- clearButton: `<button type="button" data-kt-datepicker-clear {{class}}>Clear</button>`,
75
- applyButton: `<button type="button" data-kt-datepicker-apply {{class}}>Apply</button>`,
76
- /**
77
- * Container for multiple calendar months (horizontal multi-month view)
78
- */
79
- multiMonthContainer: `<div data-kt-datepicker-multimonth-container class="flex flex-col md:flex-row gap-4 {{class}}">{{calendars}}</div>`,
80
-
81
- // Time picker templates
82
- timePickerWrapper: `<div data-kt-datepicker-time-picker {{class}}>{{timeDisplay}} {{timeControls}}</div>`,
83
- timeDisplay: `<div data-kt-datepicker-time-display {{class}}>{{timeValue}}</div>`,
84
- timeControls: `<div data-kt-datepicker-time-controls {{class}}>{{timeUnits}} {{ampmControl}}</div>`,
85
- timeUnit: `<div data-kt-datepicker-time-unit data-kt-datepicker-time-unit="{{unitType}}" {{class}}>{{upButton}} {{valueDisplay}} {{downButton}}</div>`,
86
- timeUpButton: `<button type="button" data-kt-datepicker-time-up aria-label="Increment {{unitType}}" {{class}} {{disabled}}>▲</button>`,
87
- timeDownButton: `<button type="button" data-kt-datepicker-time-down aria-label="Decrement {{unitType}}" {{class}} {{disabled}}>▼</button>`,
88
- timeValue: `<span data-kt-datepicker-time-value {{class}}>{{value}}</span>`,
89
- timeSeparator: `<span data-kt-datepicker-time-separator {{class}}>{{separator}}</span>`,
90
- ampmControl: `<div data-kt-datepicker-ampm-control {{class}}>{{ampmButton}}</div>`,
91
- ampmButton: `<button type="button" data-kt-datepicker-ampm-button aria-label="Toggle AM/PM" {{class}} {{disabled}}>{{ampmValue}}</button>`,
92
- /**
93
- * Panel wrapper for header + calendar
94
- */
95
- panel: `<div data-kt-datepicker-panel {{class}}>{{header}}{{calendar}}</div>`,
96
- /**
97
- * Live region for accessibility announcements
98
- */
99
- liveRegion: `<div data-kt-datepicker-live aria-live="polite" {{class}}></div>`,
100
- /**
101
- * Container for range input start date segment
102
- */
103
- rangeStartContainer: `<div data-kt-datepicker-segmented-start {{class}}></div>`,
104
- /**
105
- * Container for range input end date segment
106
- */
107
- rangeEndContainer: `<div data-kt-datepicker-segmented-end {{class}}></div>`,
108
- };
109
-
110
- /**
111
- * Template rendering options
112
- */
113
- export interface TemplateRenderOptions {
114
- templateKey: keyof KTDatepickerTemplateStrings;
115
- data: Record<string, any>;
116
- configClasses?: Record<string, string>;
117
- fallbackTemplate?: string | ((data: any) => string);
118
- }
119
-
120
- /**
121
- * Merges default templates with user overrides.
122
- * User overrides take precedence.
123
- */
124
- export function mergeTemplates(
125
- defaults: KTDatepickerTemplateStrings,
126
- overrides?: KTDatepickerTemplateStrings
127
- ): KTDatepickerTemplateStrings {
128
- return { ...defaults, ...(overrides || {}) };
129
- }
130
-
131
- /**
132
- * Merges default, config, and user templates (string or function)
133
- * Precedence: default < config < user
134
- */
135
- export function getMergedTemplates(
136
- configTemplates?: Record<string, string | ((data: any) => string)>,
137
- userTemplates?: Record<string, string | ((data: any) => string)>
138
- ): Record<string, string | ((data: any) => string)> {
139
- return {
140
- ...(defaultTemplates as Record<string, string | ((data: any) => string)>),
141
- ...(configTemplates || {}),
142
- ...(userTemplates || {}),
143
- };
144
- }
145
-
146
- /**
147
- * Renders a template string with data using {{key}} placeholders.
148
- * Enhanced to handle class placeholders specifically.
149
- */
150
- export function renderTemplateString(
151
- template: string,
152
- data: Record<string, any>
153
- ): string {
154
- return template.replace(/{{(\w+)}}/g, (_, key) => {
155
- const value = data[key];
156
- if (value !== undefined) {
157
- return String(value);
158
- }
159
- return '';
160
- });
161
- }
162
-
163
- /**
164
- * Merges class data with template data for rendering.
165
- * Extracts class for specific template key from config classes object.
166
- */
167
- export function mergeClassData(
168
- templateKey: string,
169
- templateData: Record<string, any>,
170
- configClasses?: Record<string, string>
171
- ): Record<string, any> {
172
- const classValue = configClasses?.[templateKey] || '';
173
- return {
174
- ...templateData,
175
- class: classValue
176
- };
177
- }
178
-
179
- /**
180
- * Checks if a template is a function.
181
- */
182
- export function isTemplateFunction(tpl: unknown): tpl is (data: any) => string {
183
- return typeof tpl === 'function';
184
- }
185
-
186
- /**
187
- * Renders a template string with data and returns a DocumentFragment.
188
- * Usage: const frag = renderTemplateToDOM(template, data)
189
- */
190
- export function renderTemplateToDOM(template: string, data: Record<string, any> = {}): DocumentFragment {
191
- const html = renderTemplateString(template, data);
192
- const frag = document.createDocumentFragment();
193
- const temp = document.createElement('div');
194
- temp.innerHTML = html;
195
- while (temp.firstChild) {
196
- frag.appendChild(temp.firstChild);
197
- }
198
- return frag;
199
- }
200
-
201
- /**
202
- * Unified template renderer for all datepicker UI components
203
- * Ensures consistent template usage and eliminates scattered rendering logic
204
- */
205
- export class TemplateRenderer {
206
- private _templates: KTDatepickerTemplateStrings;
207
-
208
- constructor(templates: KTDatepickerTemplateStrings) {
209
- this._templates = templates;
210
- }
211
-
212
- /**
213
- * Render a template with data and return HTML string
214
- */
215
- renderTemplateString(options: TemplateRenderOptions): string {
216
- const { templateKey, data, configClasses, fallbackTemplate } = options;
217
-
218
- // Get template from template set
219
- let template = this._templates[templateKey];
220
-
221
- // Use fallback if template not found
222
- if (!template && fallbackTemplate) {
223
- template = fallbackTemplate;
224
- }
225
-
226
- // Validate template exists
227
- if (!template) {
228
- throw new Error(`Template not found for key: ${templateKey}`);
229
- }
230
-
231
- // Merge class data
232
- const mergedData = mergeClassData(templateKey, data, configClasses);
233
-
234
- // Render template
235
- if (isTemplateFunction(template)) {
236
- return template(mergedData);
237
- } else {
238
- return renderTemplateString(template as string, mergedData);
239
- }
240
- }
241
-
242
- /**
243
- * Render a template with data and return HTMLElement
244
- */
245
- renderTemplateToElement(options: TemplateRenderOptions): HTMLElement {
246
- const html = this.renderTemplateString(options);
247
- const fragment = renderTemplateToDOM(html);
248
- const element = fragment.firstElementChild as HTMLElement;
249
-
250
- if (!element) {
251
- throw new Error(`Failed to render template to element for key: ${options.templateKey}`);
252
- }
253
-
254
- return element;
255
- }
256
-
257
- /**
258
- * Render a template with data and return DocumentFragment
259
- */
260
- renderTemplateToFragment(options: TemplateRenderOptions): DocumentFragment {
261
- const html = this.renderTemplateString(options);
262
- return renderTemplateToDOM(html);
263
- }
264
-
265
- /**
266
- * Check if a template exists
267
- */
268
- hasTemplate(templateKey: keyof KTDatepickerTemplateStrings): boolean {
269
- return !!this._templates[templateKey];
270
- }
271
-
272
- /**
273
- * Get template by key
274
- */
275
- getTemplate(templateKey: keyof KTDatepickerTemplateStrings): string | ((data: any) => string) | undefined {
276
- return this._templates[templateKey];
277
- }
278
-
279
- /**
280
- * Update templates
281
- */
282
- updateTemplates(templates: KTDatepickerTemplateStrings): void {
283
- this._templates = templates;
284
- }
285
-
286
- /**
287
- * Get all templates
288
- */
289
- getTemplates(): KTDatepickerTemplateStrings {
290
- return { ...this._templates };
291
- }
292
- }
293
-
294
- /**
295
- * Factory function to create a template renderer
296
- */
297
- export function createTemplateRenderer(templates: KTDatepickerTemplateStrings): TemplateRenderer {
298
- return new TemplateRenderer(templates);
299
- }
300
-
301
- /**
302
- * Returns the merged template set for a given config.
303
- */
304
- export function getTemplateStrings(config?: KTDatepickerConfig): KTDatepickerTemplateStrings {
305
- return mergeTemplates(defaultTemplates, config?.templates);
306
- }
@@ -1,160 +0,0 @@
1
- /*
2
- * date-formatters.test.ts - Unit tests for date formatting utilities
3
- */
4
-
5
- import { describe, it, expect } from 'vitest';
6
- import { formatDate, isSameDay, normalizeDateToMidnight } from '../date-formatters';
7
-
8
- describe('formatDate', () => {
9
- it('should format date with yyyy-MM-dd format', () => {
10
- const date = new Date(2024, 0, 15); // January 15, 2024
11
- expect(formatDate(date, 'yyyy-MM-dd')).toBe('2024-01-15');
12
- });
13
-
14
- it('should format date with dd/MM/yyyy format', () => {
15
- const date = new Date(2024, 0, 15);
16
- expect(formatDate(date, 'dd/MM/yyyy')).toBe('15/01/2024');
17
- });
18
-
19
- it('should format date with time components', () => {
20
- const date = new Date(2024, 0, 15, 14, 30, 45);
21
- expect(formatDate(date, 'HH:mm:ss')).toBe('14:30:45');
22
- });
23
-
24
- it('should format date with AM/PM indicator', () => {
25
- const date = new Date(2024, 0, 15, 14, 30); // 2:30 PM
26
- expect(formatDate(date, 'HH:mm a')).toBe('14:30 PM');
27
- const morningDate = new Date(2024, 0, 15, 9, 30); // 9:30 AM
28
- expect(formatDate(morningDate, 'HH:mm a')).toBe('09:30 AM');
29
- const midnightDate = new Date(2024, 0, 15, 0, 0); // Midnight
30
- expect(formatDate(midnightDate, 'HH:mm a')).toBe('00:00 AM');
31
- });
32
-
33
- it('should handle single digit months and days', () => {
34
- const date = new Date(2024, 0, 5); // January 5, 2024
35
- expect(formatDate(date, 'M/d/yyyy')).toBe('1/5/2024');
36
- expect(formatDate(date, 'MM/dd/yyyy')).toBe('01/05/2024');
37
- });
38
-
39
- it('should handle 2-digit year format', () => {
40
- const date = new Date(2024, 0, 15);
41
- expect(formatDate(date, 'yy-MM-dd')).toBe('24-01-15');
42
- });
43
-
44
- it('should return empty string for invalid date', () => {
45
- const invalidDate = new Date('invalid');
46
- expect(formatDate(invalidDate, 'yyyy-MM-dd')).toBe('');
47
- });
48
-
49
- it('should return empty string for non-Date object', () => {
50
- expect(formatDate(null as any, 'yyyy-MM-dd')).toBe('');
51
- expect(formatDate(undefined as any, 'yyyy-MM-dd')).toBe('');
52
- });
53
-
54
- it('should handle complex format strings', () => {
55
- const date = new Date(2024, 0, 15, 14, 30, 45);
56
- expect(formatDate(date, 'yyyy-MM-dd HH:mm:ss')).toBe('2024-01-15 14:30:45');
57
- });
58
- });
59
-
60
- describe('isSameDay', () => {
61
- it('should return true for same day with different times', () => {
62
- const date1 = new Date(2024, 0, 15, 10, 30);
63
- const date2 = new Date(2024, 0, 15, 14, 45);
64
- expect(isSameDay(date1, date2)).toBe(true);
65
- });
66
-
67
- it('should return false for different days', () => {
68
- const date1 = new Date(2024, 0, 15);
69
- const date2 = new Date(2024, 0, 16);
70
- expect(isSameDay(date1, date2)).toBe(false);
71
- });
72
-
73
- it('should return false for different months', () => {
74
- const date1 = new Date(2024, 0, 15);
75
- const date2 = new Date(2024, 1, 15);
76
- expect(isSameDay(date1, date2)).toBe(false);
77
- });
78
-
79
- it('should return false for different years', () => {
80
- const date1 = new Date(2024, 0, 15);
81
- const date2 = new Date(2025, 0, 15);
82
- expect(isSameDay(date1, date2)).toBe(false);
83
- });
84
-
85
- it('should return true for same date at midnight', () => {
86
- const date1 = new Date(2024, 0, 15, 0, 0, 0);
87
- const date2 = new Date(2024, 0, 15, 0, 0, 0);
88
- expect(isSameDay(date1, date2)).toBe(true);
89
- });
90
-
91
- it('should handle edge case: last day of month', () => {
92
- const date1 = new Date(2024, 0, 31, 10, 0);
93
- const date2 = new Date(2024, 0, 31, 20, 0);
94
- expect(isSameDay(date1, date2)).toBe(true);
95
- });
96
-
97
- it('should handle edge case: first day of month', () => {
98
- const date1 = new Date(2024, 0, 1, 0, 0);
99
- const date2 = new Date(2024, 0, 1, 23, 59);
100
- expect(isSameDay(date1, date2)).toBe(true);
101
- });
102
- });
103
-
104
- describe('normalizeDateToMidnight', () => {
105
- it('should set time to 00:00:00', () => {
106
- const date = new Date(2024, 0, 15, 14, 30, 45);
107
- const normalized = normalizeDateToMidnight(date);
108
- expect(normalized.getHours()).toBe(0);
109
- expect(normalized.getMinutes()).toBe(0);
110
- expect(normalized.getSeconds()).toBe(0);
111
- expect(normalized.getMilliseconds()).toBe(0);
112
- });
113
-
114
- it('should preserve date components', () => {
115
- const date = new Date(2024, 0, 15, 14, 30, 45);
116
- const normalized = normalizeDateToMidnight(date);
117
- expect(normalized.getFullYear()).toBe(2024);
118
- expect(normalized.getMonth()).toBe(0);
119
- expect(normalized.getDate()).toBe(15);
120
- });
121
-
122
- it('should return a new Date object', () => {
123
- const date = new Date(2024, 0, 15, 14, 30, 45);
124
- const normalized = normalizeDateToMidnight(date);
125
- expect(normalized).not.toBe(date);
126
- expect(date.getHours()).toBe(14); // Original date unchanged
127
- });
128
-
129
- it('should handle date already at midnight', () => {
130
- const date = new Date(2024, 0, 15, 0, 0, 0);
131
- const normalized = normalizeDateToMidnight(date);
132
- expect(normalized.getHours()).toBe(0);
133
- expect(normalized.getMinutes()).toBe(0);
134
- expect(normalized.getSeconds()).toBe(0);
135
- });
136
-
137
- it('should handle date at end of day', () => {
138
- const date = new Date(2024, 0, 15, 23, 59, 59);
139
- const normalized = normalizeDateToMidnight(date);
140
- expect(normalized.getHours()).toBe(0);
141
- expect(normalized.getDate()).toBe(15); // Same day
142
- });
143
-
144
- it('should work with dates at different times', () => {
145
- const times = [
146
- new Date(2024, 0, 15, 0, 0, 0),
147
- new Date(2024, 0, 15, 12, 0, 0),
148
- new Date(2024, 0, 15, 23, 59, 59)
149
- ];
150
-
151
- times.forEach(date => {
152
- const normalized = normalizeDateToMidnight(date);
153
- expect(normalized.getHours()).toBe(0);
154
- expect(normalized.getMinutes()).toBe(0);
155
- expect(normalized.getSeconds()).toBe(0);
156
- expect(normalized.getDate()).toBe(15);
157
- });
158
- });
159
- });
160
-
@@ -1,86 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { getDateKey, isSameDayByKey } from '../date-utils';
3
-
4
- describe('Date Utils - Date Key Functions', () => {
5
- describe('getDateKey', () => {
6
- it('should generate correct date key for a given date', () => {
7
- const date = new Date(2024, 0, 15); // Jan 15, 2024
8
- const key = getDateKey(date);
9
- expect(key).toBe(20240115); // year * 10000 + month * 100 + day
10
- });
11
-
12
- it('should handle single-digit months and days', () => {
13
- const date = new Date(2024, 0, 5); // Jan 5, 2024
14
- const key = getDateKey(date);
15
- expect(key).toBe(20240105);
16
- });
17
-
18
- it('should handle year boundaries correctly', () => {
19
- const date1 = new Date(2023, 11, 31); // Dec 31, 2023
20
- const date2 = new Date(2024, 0, 1); // Jan 1, 2024
21
- expect(getDateKey(date1)).toBe(20231231);
22
- expect(getDateKey(date2)).toBe(20240101);
23
- });
24
-
25
- it('should handle leap years correctly', () => {
26
- const date = new Date(2024, 1, 29); // Feb 29, 2024 (leap year)
27
- const key = getDateKey(date);
28
- expect(key).toBe(20240229);
29
- });
30
-
31
- it('should ignore time components', () => {
32
- const date1 = new Date(2024, 0, 15, 0, 0, 0); // Jan 15, 2024 00:00:00
33
- const date2 = new Date(2024, 0, 15, 23, 59, 59); // Jan 15, 2024 23:59:59
34
- expect(getDateKey(date1)).toBe(getDateKey(date2));
35
- });
36
-
37
- it('should generate unique keys for different dates', () => {
38
- const date1 = new Date(2024, 0, 15);
39
- const date2 = new Date(2024, 0, 16);
40
- const date3 = new Date(2024, 1, 15);
41
- const date4 = new Date(2025, 0, 15);
42
-
43
- const key1 = getDateKey(date1);
44
- const key2 = getDateKey(date2);
45
- const key3 = getDateKey(date3);
46
- const key4 = getDateKey(date4);
47
-
48
- expect(key1).not.toBe(key2);
49
- expect(key1).not.toBe(key3);
50
- expect(key1).not.toBe(key4);
51
- });
52
- });
53
-
54
- describe('isSameDayByKey', () => {
55
- it('should return true for same calendar day', () => {
56
- const date1 = new Date(2024, 0, 15, 10, 30, 0);
57
- const date2 = new Date(2024, 0, 15, 20, 45, 0);
58
- expect(isSameDayByKey(date1, date2)).toBe(true);
59
- });
60
-
61
- it('should return false for different days', () => {
62
- const date1 = new Date(2024, 0, 15);
63
- const date2 = new Date(2024, 0, 16);
64
- expect(isSameDayByKey(date1, date2)).toBe(false);
65
- });
66
-
67
- it('should return false for different months', () => {
68
- const date1 = new Date(2024, 0, 15);
69
- const date2 = new Date(2024, 1, 15);
70
- expect(isSameDayByKey(date1, date2)).toBe(false);
71
- });
72
-
73
- it('should return false for different years', () => {
74
- const date1 = new Date(2024, 0, 15);
75
- const date2 = new Date(2025, 0, 15);
76
- expect(isSameDayByKey(date1, date2)).toBe(false);
77
- });
78
-
79
- it('should handle year boundaries correctly', () => {
80
- const date1 = new Date(2023, 11, 31);
81
- const date2 = new Date(2024, 0, 1);
82
- expect(isSameDayByKey(date1, date2)).toBe(false);
83
- });
84
- });
85
- });
86
-