@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.
- package/README.md +0 -27
- package/dist/ktui.js +6790 -14063
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +1132 -2705
- package/lib/cjs/components/datatable/__tests__/pagination-reset.test.js +596 -0
- package/lib/cjs/components/datatable/__tests__/pagination-reset.test.js.map +1 -0
- package/lib/cjs/components/datatable/__tests__/race-conditions.test.js +548 -0
- package/lib/cjs/components/datatable/__tests__/race-conditions.test.js.map +1 -0
- package/lib/cjs/components/datatable/__tests__/setup.js +63 -0
- package/lib/cjs/components/datatable/__tests__/setup.js.map +1 -0
- package/lib/cjs/components/datatable/datatable.js +92 -30
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/index.js +1 -10
- package/lib/cjs/index.js.map +1 -1
- package/lib/esm/components/datatable/__tests__/pagination-reset.test.js +594 -0
- package/lib/esm/components/datatable/__tests__/pagination-reset.test.js.map +1 -0
- package/lib/esm/components/datatable/__tests__/race-conditions.test.js +546 -0
- package/lib/esm/components/datatable/__tests__/race-conditions.test.js.map +1 -0
- package/lib/esm/components/datatable/__tests__/setup.js +58 -0
- package/lib/esm/components/datatable/__tests__/setup.js.map +1 -0
- package/lib/esm/components/datatable/datatable.js +92 -30
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/index.js +0 -7
- package/lib/esm/index.js.map +1 -1
- package/package.json +7 -9
- package/src/components/alert/alert.css +188 -429
- package/src/components/datatable/__tests__/pagination-reset.test.ts +657 -0
- package/src/components/datatable/__tests__/race-conditions.test.ts +455 -0
- package/src/components/datatable/__tests__/setup.ts +67 -0
- package/src/components/datatable/datatable.ts +66 -11
- package/src/components/input/input.css +0 -1
- package/src/components/select/select.css +0 -1
- package/src/components/select/variants.css +4 -0
- package/src/components/textarea/textarea.css +0 -1
- package/src/index.ts +0 -10
- package/styles.css +0 -1
- package/lib/cjs/components/alert/alert.js +0 -1025
- package/lib/cjs/components/alert/alert.js.map +0 -1
- package/lib/cjs/components/alert/index.js +0 -20
- package/lib/cjs/components/alert/index.js.map +0 -1
- package/lib/cjs/components/alert/templates.js +0 -120
- package/lib/cjs/components/alert/templates.js.map +0 -1
- package/lib/cjs/components/alert/types.js +0 -7
- package/lib/cjs/components/alert/types.js.map +0 -1
- package/lib/cjs/components/datepicker/config/config.js +0 -42
- package/lib/cjs/components/datepicker/config/config.js.map +0 -1
- package/lib/cjs/components/datepicker/config/index.js +0 -24
- package/lib/cjs/components/datepicker/config/index.js.map +0 -1
- package/lib/cjs/components/datepicker/config/interfaces.js +0 -7
- package/lib/cjs/components/datepicker/config/interfaces.js.map +0 -1
- package/lib/cjs/components/datepicker/config/types.js +0 -7
- package/lib/cjs/components/datepicker/config/types.js.map +0 -1
- package/lib/cjs/components/datepicker/core/event-manager.js +0 -135
- package/lib/cjs/components/datepicker/core/event-manager.js.map +0 -1
- package/lib/cjs/components/datepicker/core/focus-manager.js +0 -167
- package/lib/cjs/components/datepicker/core/focus-manager.js.map +0 -1
- package/lib/cjs/components/datepicker/core/helpers.js +0 -219
- package/lib/cjs/components/datepicker/core/helpers.js.map +0 -1
- package/lib/cjs/components/datepicker/core/index.js +0 -25
- package/lib/cjs/components/datepicker/core/index.js.map +0 -1
- package/lib/cjs/components/datepicker/core/unified-state-manager.js +0 -394
- package/lib/cjs/components/datepicker/core/unified-state-manager.js.map +0 -1
- package/lib/cjs/components/datepicker/datepicker.js +0 -2252
- package/lib/cjs/components/datepicker/datepicker.js.map +0 -1
- package/lib/cjs/components/datepicker/index.js +0 -24
- package/lib/cjs/components/datepicker/index.js.map +0 -1
- package/lib/cjs/components/datepicker/ui/index.js +0 -23
- package/lib/cjs/components/datepicker/ui/index.js.map +0 -1
- package/lib/cjs/components/datepicker/ui/input/dropdown.js +0 -489
- package/lib/cjs/components/datepicker/ui/input/dropdown.js.map +0 -1
- package/lib/cjs/components/datepicker/ui/input/index.js +0 -23
- package/lib/cjs/components/datepicker/ui/input/index.js.map +0 -1
- package/lib/cjs/components/datepicker/ui/input/segmented-input.js +0 -640
- package/lib/cjs/components/datepicker/ui/input/segmented-input.js.map +0 -1
- package/lib/cjs/components/datepicker/ui/renderers/calendar.js +0 -446
- package/lib/cjs/components/datepicker/ui/renderers/calendar.js.map +0 -1
- package/lib/cjs/components/datepicker/ui/renderers/footer.js +0 -42
- package/lib/cjs/components/datepicker/ui/renderers/footer.js.map +0 -1
- package/lib/cjs/components/datepicker/ui/renderers/header.js +0 -32
- package/lib/cjs/components/datepicker/ui/renderers/header.js.map +0 -1
- package/lib/cjs/components/datepicker/ui/renderers/index.js +0 -25
- package/lib/cjs/components/datepicker/ui/renderers/index.js.map +0 -1
- package/lib/cjs/components/datepicker/ui/renderers/time-picker.js +0 -384
- package/lib/cjs/components/datepicker/ui/renderers/time-picker.js.map +0 -1
- package/lib/cjs/components/datepicker/ui/templates/index.js +0 -22
- package/lib/cjs/components/datepicker/ui/templates/index.js.map +0 -1
- package/lib/cjs/components/datepicker/ui/templates/templates.js +0 -253
- package/lib/cjs/components/datepicker/ui/templates/templates.js.map +0 -1
- package/lib/cjs/components/datepicker/utils/date-formatters.js +0 -88
- package/lib/cjs/components/datepicker/utils/date-formatters.js.map +0 -1
- package/lib/cjs/components/datepicker/utils/date-utils.js +0 -194
- package/lib/cjs/components/datepicker/utils/date-utils.js.map +0 -1
- package/lib/cjs/components/datepicker/utils/index.js +0 -24
- package/lib/cjs/components/datepicker/utils/index.js.map +0 -1
- package/lib/cjs/components/datepicker/utils/time-utils.js +0 -213
- package/lib/cjs/components/datepicker/utils/time-utils.js.map +0 -1
- package/lib/esm/components/alert/alert.js +0 -1022
- package/lib/esm/components/alert/alert.js.map +0 -1
- package/lib/esm/components/alert/index.js +0 -4
- package/lib/esm/components/alert/index.js.map +0 -1
- package/lib/esm/components/alert/templates.js +0 -112
- package/lib/esm/components/alert/templates.js.map +0 -1
- package/lib/esm/components/alert/types.js +0 -6
- package/lib/esm/components/alert/types.js.map +0 -1
- package/lib/esm/components/datepicker/config/config.js +0 -39
- package/lib/esm/components/datepicker/config/config.js.map +0 -1
- package/lib/esm/components/datepicker/config/index.js +0 -8
- package/lib/esm/components/datepicker/config/index.js.map +0 -1
- package/lib/esm/components/datepicker/config/interfaces.js +0 -6
- package/lib/esm/components/datepicker/config/interfaces.js.map +0 -1
- package/lib/esm/components/datepicker/config/types.js +0 -6
- package/lib/esm/components/datepicker/config/types.js.map +0 -1
- package/lib/esm/components/datepicker/core/event-manager.js +0 -133
- package/lib/esm/components/datepicker/core/event-manager.js.map +0 -1
- package/lib/esm/components/datepicker/core/focus-manager.js +0 -164
- package/lib/esm/components/datepicker/core/focus-manager.js.map +0 -1
- package/lib/esm/components/datepicker/core/helpers.js +0 -211
- package/lib/esm/components/datepicker/core/helpers.js.map +0 -1
- package/lib/esm/components/datepicker/core/index.js +0 -9
- package/lib/esm/components/datepicker/core/index.js.map +0 -1
- package/lib/esm/components/datepicker/core/unified-state-manager.js +0 -391
- package/lib/esm/components/datepicker/core/unified-state-manager.js.map +0 -1
- package/lib/esm/components/datepicker/datepicker.js +0 -2248
- package/lib/esm/components/datepicker/datepicker.js.map +0 -1
- package/lib/esm/components/datepicker/index.js +0 -7
- package/lib/esm/components/datepicker/index.js.map +0 -1
- package/lib/esm/components/datepicker/ui/index.js +0 -7
- package/lib/esm/components/datepicker/ui/index.js.map +0 -1
- package/lib/esm/components/datepicker/ui/input/dropdown.js +0 -486
- package/lib/esm/components/datepicker/ui/input/dropdown.js.map +0 -1
- package/lib/esm/components/datepicker/ui/input/index.js +0 -7
- package/lib/esm/components/datepicker/ui/input/index.js.map +0 -1
- package/lib/esm/components/datepicker/ui/input/segmented-input.js +0 -637
- package/lib/esm/components/datepicker/ui/input/segmented-input.js.map +0 -1
- package/lib/esm/components/datepicker/ui/renderers/calendar.js +0 -443
- package/lib/esm/components/datepicker/ui/renderers/calendar.js.map +0 -1
- package/lib/esm/components/datepicker/ui/renderers/footer.js +0 -39
- package/lib/esm/components/datepicker/ui/renderers/footer.js.map +0 -1
- package/lib/esm/components/datepicker/ui/renderers/header.js +0 -29
- package/lib/esm/components/datepicker/ui/renderers/header.js.map +0 -1
- package/lib/esm/components/datepicker/ui/renderers/index.js +0 -9
- package/lib/esm/components/datepicker/ui/renderers/index.js.map +0 -1
- package/lib/esm/components/datepicker/ui/renderers/time-picker.js +0 -381
- package/lib/esm/components/datepicker/ui/renderers/time-picker.js.map +0 -1
- package/lib/esm/components/datepicker/ui/templates/index.js +0 -6
- package/lib/esm/components/datepicker/ui/templates/index.js.map +0 -1
- package/lib/esm/components/datepicker/ui/templates/templates.js +0 -242
- package/lib/esm/components/datepicker/ui/templates/templates.js.map +0 -1
- package/lib/esm/components/datepicker/utils/date-formatters.js +0 -83
- package/lib/esm/components/datepicker/utils/date-formatters.js.map +0 -1
- package/lib/esm/components/datepicker/utils/date-utils.js +0 -184
- package/lib/esm/components/datepicker/utils/date-utils.js.map +0 -1
- package/lib/esm/components/datepicker/utils/index.js +0 -8
- package/lib/esm/components/datepicker/utils/index.js.map +0 -1
- package/lib/esm/components/datepicker/utils/time-utils.js +0 -201
- package/lib/esm/components/datepicker/utils/time-utils.js.map +0 -1
- package/src/components/alert/alert.ts +0 -990
- package/src/components/alert/index.ts +0 -4
- package/src/components/alert/templates.ts +0 -110
- package/src/components/alert/tests/accessibility/aria-roles.test.ts +0 -19
- package/src/components/alert/tests/accessibility/focus-management.test.ts +0 -19
- package/src/components/alert/tests/accessibility/keyboard-nav.test.ts +0 -22
- package/src/components/alert/tests/actions/confirm-cancel.test.ts +0 -122
- package/src/components/alert/tests/actions/input-field.test.ts +0 -180
- package/src/components/alert/tests/alert.basic.test.ts +0 -126
- package/src/components/alert/tests/alert.config.test.ts +0 -75
- package/src/components/alert/tests/alert.templates.test.ts +0 -17
- package/src/components/alert/tests/config/attribute-config.test.ts +0 -94
- package/src/components/alert/tests/config/json-config.test.ts +0 -119
- package/src/components/alert/tests/config/merging.test.ts +0 -89
- package/src/components/alert/tests/dismissal/auto-dismiss.test.ts +0 -96
- package/src/components/alert/tests/dismissal/escape-key-dismiss.test.ts +0 -105
- package/src/components/alert/tests/dismissal/manual-dismiss.test.ts +0 -90
- package/src/components/alert/tests/dismissal/outside-click-dismiss.test.ts +0 -91
- package/src/components/alert/tests/edge-cases/invalid-config.test.ts +0 -19
- package/src/components/alert/tests/edge-cases/multiple-alerts.test.ts +0 -19
- package/src/components/alert/tests/rendering/custom-content.test.ts +0 -81
- package/src/components/alert/tests/rendering/info-alert.test.ts +0 -84
- package/src/components/alert/tests/rendering/success-alert.test.ts +0 -100
- package/src/components/alert/tests/templates/default-templates.test.ts +0 -16
- package/src/components/alert/tests/templates/user-templates.test.ts +0 -16
- package/src/components/alert/types.ts +0 -145
- package/src/components/datepicker/__tests__/datepicker-events.test.ts +0 -356
- package/src/components/datepicker/__tests__/datepicker-init.test.ts +0 -343
- package/src/components/datepicker/__tests__/datepicker-integration.test.ts +0 -435
- package/src/components/datepicker/__tests__/datepicker-timezone.test.ts +0 -220
- package/src/components/datepicker/__tests__/segmented-input-focus.test.ts +0 -380
- package/src/components/datepicker/__tests__/selective-state-updates.test.ts +0 -400
- package/src/components/datepicker/__tests__/state-manager.test.ts +0 -421
- package/src/components/datepicker/__tests__/time-preservation.test.ts +0 -387
- package/src/components/datepicker/config/config.ts +0 -40
- package/src/components/datepicker/config/index.ts +0 -8
- package/src/components/datepicker/config/interfaces.ts +0 -82
- package/src/components/datepicker/config/types.ts +0 -188
- package/src/components/datepicker/core/event-manager.ts +0 -159
- package/src/components/datepicker/core/focus-manager.ts +0 -201
- package/src/components/datepicker/core/helpers.ts +0 -231
- package/src/components/datepicker/core/index.ts +0 -9
- package/src/components/datepicker/core/unified-state-manager.ts +0 -459
- package/src/components/datepicker/datepicker.css +0 -435
- package/src/components/datepicker/datepicker.ts +0 -2548
- package/src/components/datepicker/index.ts +0 -8
- package/src/components/datepicker/ui/index.ts +0 -7
- package/src/components/datepicker/ui/input/dropdown.ts +0 -552
- package/src/components/datepicker/ui/input/index.ts +0 -7
- package/src/components/datepicker/ui/input/segmented-input.ts +0 -638
- package/src/components/datepicker/ui/renderers/__tests__/calendar-optimizations.test.ts +0 -611
- package/src/components/datepicker/ui/renderers/calendar.ts +0 -530
- package/src/components/datepicker/ui/renderers/footer.ts +0 -43
- package/src/components/datepicker/ui/renderers/header.ts +0 -33
- package/src/components/datepicker/ui/renderers/index.ts +0 -9
- package/src/components/datepicker/ui/renderers/time-picker.ts +0 -438
- package/src/components/datepicker/ui/templates/index.ts +0 -6
- package/src/components/datepicker/ui/templates/templates.ts +0 -306
- package/src/components/datepicker/utils/__tests__/date-formatters.test.ts +0 -160
- package/src/components/datepicker/utils/__tests__/date-utils-keys.test.ts +0 -86
- package/src/components/datepicker/utils/__tests__/date-utils-timezone.test.ts +0 -215
- package/src/components/datepicker/utils/date-formatters.ts +0 -85
- package/src/components/datepicker/utils/date-utils.ts +0 -172
- package/src/components/datepicker/utils/index.ts +0 -8
- package/src/components/datepicker/utils/time-utils.ts +0 -221
|
@@ -1,611 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* calendar-optimizations.test.ts - Tests for calendar rendering optimizations
|
|
3
|
-
* Tests day name caching, event delegation, cell reference caching, and date key optimizations
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
7
|
-
import { renderCalendar } from '../calendar';
|
|
8
|
-
import { getDateKey } from '../../../utils/date-utils';
|
|
9
|
-
import { defaultTemplates } from '../../templates/templates';
|
|
10
|
-
|
|
11
|
-
describe('Calendar Rendering Optimizations', () => {
|
|
12
|
-
let container: HTMLElement;
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
container = document.createElement('div');
|
|
16
|
-
document.body.appendChild(container);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
afterEach(() => {
|
|
20
|
-
if (container.parentNode) {
|
|
21
|
-
document.body.removeChild(container);
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
// Helper to generate calendar days for a month
|
|
26
|
-
function getCalendarDays(year: number, month: number): Date[] {
|
|
27
|
-
const firstDay = new Date(year, month, 1);
|
|
28
|
-
const lastDay = new Date(year, month + 1, 0);
|
|
29
|
-
const days: Date[] = [];
|
|
30
|
-
let start = new Date(firstDay);
|
|
31
|
-
start.setDate(firstDay.getDate() - firstDay.getDay());
|
|
32
|
-
let end = new Date(lastDay);
|
|
33
|
-
end.setDate(lastDay.getDate() + (6 - lastDay.getDay()));
|
|
34
|
-
for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
|
|
35
|
-
days.push(new Date(d));
|
|
36
|
-
}
|
|
37
|
-
return days;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
describe('Day Name Caching', () => {
|
|
41
|
-
it('should cache day names per locale', () => {
|
|
42
|
-
const days = getCalendarDays(2024, 0);
|
|
43
|
-
const onDayClick = vi.fn();
|
|
44
|
-
const currentDate = new Date(2024, 0, 15);
|
|
45
|
-
|
|
46
|
-
// First render with en-US
|
|
47
|
-
const calendar1 = renderCalendar(
|
|
48
|
-
defaultTemplates.dayCell as string,
|
|
49
|
-
days,
|
|
50
|
-
currentDate,
|
|
51
|
-
null,
|
|
52
|
-
onDayClick,
|
|
53
|
-
'en-US'
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
// Second render with same locale - should use cache
|
|
57
|
-
const calendar2 = renderCalendar(
|
|
58
|
-
defaultTemplates.dayCell as string,
|
|
59
|
-
days,
|
|
60
|
-
currentDate,
|
|
61
|
-
null,
|
|
62
|
-
onDayClick,
|
|
63
|
-
'en-US'
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
// Both should have same day names in thead
|
|
67
|
-
const dayNames1 = Array.from(calendar1.querySelectorAll('thead th')).map(th => th.textContent?.trim()).filter(Boolean);
|
|
68
|
-
const dayNames2 = Array.from(calendar2.querySelectorAll('thead th')).map(th => th.textContent?.trim()).filter(Boolean);
|
|
69
|
-
expect(dayNames1.length).toBeGreaterThan(0);
|
|
70
|
-
expect(dayNames1).toEqual(dayNames2);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('should cache different locales separately', () => {
|
|
74
|
-
const days = getCalendarDays(2024, 0);
|
|
75
|
-
const onDayClick = vi.fn();
|
|
76
|
-
const currentDate = new Date(2024, 0, 15);
|
|
77
|
-
|
|
78
|
-
const calendarEN = renderCalendar(
|
|
79
|
-
defaultTemplates.dayCell as string,
|
|
80
|
-
days,
|
|
81
|
-
currentDate,
|
|
82
|
-
null,
|
|
83
|
-
onDayClick,
|
|
84
|
-
'en-US'
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
const calendarDE = renderCalendar(
|
|
88
|
-
defaultTemplates.dayCell as string,
|
|
89
|
-
days,
|
|
90
|
-
currentDate,
|
|
91
|
-
null,
|
|
92
|
-
onDayClick,
|
|
93
|
-
'de-DE'
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
// Day names should be different for different locales
|
|
97
|
-
const dayNamesEN = Array.from(calendarEN.querySelectorAll('thead th')).map(th => th.textContent?.trim()).filter(Boolean);
|
|
98
|
-
const dayNamesDE = Array.from(calendarDE.querySelectorAll('thead th')).map(th => th.textContent?.trim()).filter(Boolean);
|
|
99
|
-
expect(dayNamesEN.length).toBeGreaterThan(0);
|
|
100
|
-
expect(dayNamesDE.length).toBeGreaterThan(0);
|
|
101
|
-
// Note: In some test environments, locale formatting might be the same
|
|
102
|
-
// So we just verify both have day names
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('should work with multiple locales (en-US, de-DE, fr-FR)', () => {
|
|
106
|
-
const days = getCalendarDays(2024, 0);
|
|
107
|
-
const onDayClick = vi.fn();
|
|
108
|
-
const currentDate = new Date(2024, 0, 15);
|
|
109
|
-
|
|
110
|
-
// Render calendars for all three locales
|
|
111
|
-
const calendarEN = renderCalendar(
|
|
112
|
-
defaultTemplates.dayCell as string,
|
|
113
|
-
days,
|
|
114
|
-
currentDate,
|
|
115
|
-
null,
|
|
116
|
-
onDayClick,
|
|
117
|
-
'en-US'
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
const calendarDE = renderCalendar(
|
|
121
|
-
defaultTemplates.dayCell as string,
|
|
122
|
-
days,
|
|
123
|
-
currentDate,
|
|
124
|
-
null,
|
|
125
|
-
onDayClick,
|
|
126
|
-
'de-DE'
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
const calendarFR = renderCalendar(
|
|
130
|
-
defaultTemplates.dayCell as string,
|
|
131
|
-
days,
|
|
132
|
-
currentDate,
|
|
133
|
-
null,
|
|
134
|
-
onDayClick,
|
|
135
|
-
'fr-FR'
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
// All should have day names
|
|
139
|
-
const dayNamesEN = Array.from(calendarEN.querySelectorAll('thead th')).map(th => th.textContent?.trim()).filter(Boolean);
|
|
140
|
-
const dayNamesDE = Array.from(calendarDE.querySelectorAll('thead th')).map(th => th.textContent?.trim()).filter(Boolean);
|
|
141
|
-
const dayNamesFR = Array.from(calendarFR.querySelectorAll('thead th')).map(th => th.textContent?.trim()).filter(Boolean);
|
|
142
|
-
|
|
143
|
-
expect(dayNamesEN.length).toBe(7);
|
|
144
|
-
expect(dayNamesDE.length).toBe(7);
|
|
145
|
-
expect(dayNamesFR.length).toBe(7);
|
|
146
|
-
|
|
147
|
-
// Verify cache persists across multiple renders of same locale
|
|
148
|
-
const calendarEN2 = renderCalendar(
|
|
149
|
-
defaultTemplates.dayCell as string,
|
|
150
|
-
days,
|
|
151
|
-
currentDate,
|
|
152
|
-
null,
|
|
153
|
-
onDayClick,
|
|
154
|
-
'en-US'
|
|
155
|
-
);
|
|
156
|
-
const dayNamesEN2 = Array.from(calendarEN2.querySelectorAll('thead th')).map(th => th.textContent?.trim()).filter(Boolean);
|
|
157
|
-
expect(dayNamesEN).toEqual(dayNamesEN2); // Should be cached
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it('should work correctly across multiple datepicker instances', () => {
|
|
161
|
-
const days = getCalendarDays(2024, 0);
|
|
162
|
-
const onDayClick = vi.fn();
|
|
163
|
-
const currentDate = new Date(2024, 0, 15);
|
|
164
|
-
|
|
165
|
-
// Simulate multiple instances using same locale
|
|
166
|
-
const instance1_calendar1 = renderCalendar(
|
|
167
|
-
defaultTemplates.dayCell as string,
|
|
168
|
-
days,
|
|
169
|
-
currentDate,
|
|
170
|
-
null,
|
|
171
|
-
onDayClick,
|
|
172
|
-
'en-US'
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
const instance2_calendar1 = renderCalendar(
|
|
176
|
-
defaultTemplates.dayCell as string,
|
|
177
|
-
days,
|
|
178
|
-
currentDate,
|
|
179
|
-
null,
|
|
180
|
-
onDayClick,
|
|
181
|
-
'en-US'
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
// Both instances should use the same cached day names
|
|
185
|
-
const dayNames1 = Array.from(instance1_calendar1.querySelectorAll('thead th')).map(th => th.textContent?.trim()).filter(Boolean);
|
|
186
|
-
const dayNames2 = Array.from(instance2_calendar1.querySelectorAll('thead th')).map(th => th.textContent?.trim()).filter(Boolean);
|
|
187
|
-
|
|
188
|
-
expect(dayNames1.length).toBe(7);
|
|
189
|
-
expect(dayNames2.length).toBe(7);
|
|
190
|
-
expect(dayNames1).toEqual(dayNames2); // Cache should be shared across instances
|
|
191
|
-
|
|
192
|
-
// Render again with different months - cache should still work
|
|
193
|
-
const days2 = getCalendarDays(2024, 1);
|
|
194
|
-
const instance1_calendar2 = renderCalendar(
|
|
195
|
-
defaultTemplates.dayCell as string,
|
|
196
|
-
days2,
|
|
197
|
-
new Date(2024, 1, 15),
|
|
198
|
-
null,
|
|
199
|
-
onDayClick,
|
|
200
|
-
'en-US'
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
const dayNames1_month2 = Array.from(instance1_calendar2.querySelectorAll('thead th')).map(th => th.textContent?.trim()).filter(Boolean);
|
|
204
|
-
expect(dayNames1_month2).toEqual(dayNames1); // Same locale = same cached day names
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
describe('Event Delegation', () => {
|
|
209
|
-
it('should use event delegation for click events', () => {
|
|
210
|
-
const days = getCalendarDays(2024, 0);
|
|
211
|
-
const onDayClick = vi.fn();
|
|
212
|
-
const currentDate = new Date(2024, 0, 15);
|
|
213
|
-
|
|
214
|
-
const calendar = renderCalendar(
|
|
215
|
-
defaultTemplates.dayCell as string,
|
|
216
|
-
days,
|
|
217
|
-
currentDate,
|
|
218
|
-
null,
|
|
219
|
-
onDayClick
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
// Count event listeners - should be minimal (delegated)
|
|
223
|
-
const buttons = calendar.querySelectorAll('button[data-day]');
|
|
224
|
-
expect(buttons.length).toBeGreaterThan(0);
|
|
225
|
-
|
|
226
|
-
// Click a button - should trigger delegated handler
|
|
227
|
-
const firstButton = buttons[0] as HTMLButtonElement;
|
|
228
|
-
firstButton.click();
|
|
229
|
-
|
|
230
|
-
// Should have called onDayClick if date is in current month
|
|
231
|
-
// Note: onDayClick only fires for dates in current month
|
|
232
|
-
const firstCell = firstButton.closest('td[data-kt-datepicker-day]') as HTMLElement;
|
|
233
|
-
const dateAttr = firstCell?.getAttribute('data-date');
|
|
234
|
-
if (dateAttr) {
|
|
235
|
-
const [year, month] = dateAttr.split('-').map(Number);
|
|
236
|
-
if (month - 1 === currentDate.getMonth()) {
|
|
237
|
-
expect(onDayClick).toHaveBeenCalled();
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it('should handle hover events via delegation', () => {
|
|
243
|
-
const days = getCalendarDays(2024, 0);
|
|
244
|
-
const onDayClick = vi.fn();
|
|
245
|
-
const currentDate = new Date(2024, 0, 15);
|
|
246
|
-
|
|
247
|
-
const calendar = renderCalendar(
|
|
248
|
-
defaultTemplates.dayCell as string,
|
|
249
|
-
days,
|
|
250
|
-
currentDate,
|
|
251
|
-
null,
|
|
252
|
-
onDayClick
|
|
253
|
-
);
|
|
254
|
-
|
|
255
|
-
const firstCell = calendar.querySelector('td[data-kt-datepicker-day]') as HTMLElement;
|
|
256
|
-
const firstButton = firstCell?.querySelector('button[data-day]') as HTMLButtonElement;
|
|
257
|
-
|
|
258
|
-
if (firstButton) {
|
|
259
|
-
// Simulate mouseover - should trigger delegated handler
|
|
260
|
-
const mouseoverEvent = new MouseEvent('mouseover', { bubbles: true });
|
|
261
|
-
firstButton.dispatchEvent(mouseoverEvent);
|
|
262
|
-
|
|
263
|
-
// Cell should have hover attribute set by delegated handler
|
|
264
|
-
expect(firstCell.hasAttribute('data-kt-hover')).toBe(true);
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
it('should only attach listeners to calendar table, not individual cells', () => {
|
|
269
|
-
const days = getCalendarDays(2024, 0);
|
|
270
|
-
const onDayClick = vi.fn();
|
|
271
|
-
const currentDate = new Date(2024, 0, 15);
|
|
272
|
-
|
|
273
|
-
const calendar = renderCalendar(
|
|
274
|
-
defaultTemplates.dayCell as string,
|
|
275
|
-
days,
|
|
276
|
-
currentDate,
|
|
277
|
-
null,
|
|
278
|
-
onDayClick
|
|
279
|
-
);
|
|
280
|
-
|
|
281
|
-
// Verify calendar has event listeners (delegated)
|
|
282
|
-
// We can't directly count listeners, but we can verify behavior
|
|
283
|
-
const buttons = calendar.querySelectorAll('button[data-day]');
|
|
284
|
-
expect(buttons.length).toBeGreaterThan(0);
|
|
285
|
-
|
|
286
|
-
// All buttons should be clickable via delegation
|
|
287
|
-
// Click a button in current month
|
|
288
|
-
const currentMonthButtons = Array.from(buttons).filter(btn => {
|
|
289
|
-
const cell = btn.closest('td[data-kt-datepicker-day]') as HTMLElement;
|
|
290
|
-
const dateAttr = cell?.getAttribute('data-date');
|
|
291
|
-
if (dateAttr) {
|
|
292
|
-
const [year, month] = dateAttr.split('-').map(Number);
|
|
293
|
-
return month - 1 === currentDate.getMonth();
|
|
294
|
-
}
|
|
295
|
-
return false;
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
if (currentMonthButtons.length > 0) {
|
|
299
|
-
(currentMonthButtons[0] as HTMLButtonElement).click();
|
|
300
|
-
expect(onDayClick).toHaveBeenCalled();
|
|
301
|
-
}
|
|
302
|
-
});
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
describe('Date Key Optimization', () => {
|
|
306
|
-
it('should use date keys for selected date highlighting', () => {
|
|
307
|
-
const days = getCalendarDays(2024, 0);
|
|
308
|
-
const onDayClick = vi.fn();
|
|
309
|
-
const currentDate = new Date(2024, 0, 15);
|
|
310
|
-
const selectedDate = new Date(2024, 0, 15);
|
|
311
|
-
|
|
312
|
-
const calendar = renderCalendar(
|
|
313
|
-
defaultTemplates.dayCell as string,
|
|
314
|
-
days,
|
|
315
|
-
currentDate,
|
|
316
|
-
selectedDate,
|
|
317
|
-
onDayClick
|
|
318
|
-
);
|
|
319
|
-
|
|
320
|
-
// Find the selected cell
|
|
321
|
-
const selectedCell = calendar.querySelector('[data-kt-selected="true"]') as HTMLElement;
|
|
322
|
-
expect(selectedCell).toBeTruthy();
|
|
323
|
-
|
|
324
|
-
// Verify it has the correct date
|
|
325
|
-
const dateAttr = selectedCell.getAttribute('data-date');
|
|
326
|
-
expect(dateAttr).toBe('2024-01-15');
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
it('should use date keys for multi-date selection', () => {
|
|
330
|
-
const days = getCalendarDays(2024, 0);
|
|
331
|
-
const onDayClick = vi.fn();
|
|
332
|
-
const currentDate = new Date(2024, 0, 15);
|
|
333
|
-
const selectedDates = [
|
|
334
|
-
new Date(2024, 0, 10),
|
|
335
|
-
new Date(2024, 0, 15),
|
|
336
|
-
new Date(2024, 0, 20)
|
|
337
|
-
];
|
|
338
|
-
|
|
339
|
-
const calendar = renderCalendar(
|
|
340
|
-
defaultTemplates.dayCell as string,
|
|
341
|
-
days,
|
|
342
|
-
currentDate,
|
|
343
|
-
null,
|
|
344
|
-
onDayClick,
|
|
345
|
-
'en-US',
|
|
346
|
-
undefined,
|
|
347
|
-
selectedDates
|
|
348
|
-
);
|
|
349
|
-
|
|
350
|
-
// All selected dates should be highlighted
|
|
351
|
-
const selectedCells = calendar.querySelectorAll('[data-kt-selected="true"]');
|
|
352
|
-
expect(selectedCells.length).toBe(3);
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
it('should use date keys for range selection', () => {
|
|
356
|
-
const days = getCalendarDays(2024, 0);
|
|
357
|
-
const onDayClick = vi.fn();
|
|
358
|
-
const currentDate = new Date(2024, 0, 15);
|
|
359
|
-
const selectedRange = {
|
|
360
|
-
start: new Date(2024, 0, 10),
|
|
361
|
-
end: new Date(2024, 0, 20)
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
const calendar = renderCalendar(
|
|
365
|
-
defaultTemplates.dayCell as string,
|
|
366
|
-
days,
|
|
367
|
-
currentDate,
|
|
368
|
-
null,
|
|
369
|
-
onDayClick,
|
|
370
|
-
'en-US',
|
|
371
|
-
selectedRange
|
|
372
|
-
);
|
|
373
|
-
|
|
374
|
-
// Start and end dates should be highlighted
|
|
375
|
-
const selectedCells = calendar.querySelectorAll('[data-kt-selected="true"]');
|
|
376
|
-
expect(selectedCells.length).toBeGreaterThanOrEqual(2);
|
|
377
|
-
|
|
378
|
-
// Range dates should have data-kt-hover-range attribute (consolidated from data-in-range)
|
|
379
|
-
const inRangeCells = calendar.querySelectorAll('[data-kt-hover-range]');
|
|
380
|
-
expect(inRangeCells.length).toBeGreaterThan(0);
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
it('should optimize tabbable index calculation using date keys', () => {
|
|
384
|
-
const days = getCalendarDays(2024, 0);
|
|
385
|
-
const onDayClick = vi.fn();
|
|
386
|
-
const currentDate = new Date(2024, 0, 15);
|
|
387
|
-
const selectedDate = new Date(2024, 0, 15);
|
|
388
|
-
|
|
389
|
-
const calendar = renderCalendar(
|
|
390
|
-
defaultTemplates.dayCell as string,
|
|
391
|
-
days,
|
|
392
|
-
currentDate,
|
|
393
|
-
selectedDate,
|
|
394
|
-
onDayClick
|
|
395
|
-
);
|
|
396
|
-
|
|
397
|
-
// Selected date should be tabbable (tabindex="0")
|
|
398
|
-
const selectedCell = calendar.querySelector('[data-kt-selected="true"]') as HTMLElement;
|
|
399
|
-
expect(selectedCell).toBeTruthy();
|
|
400
|
-
const selectedButton = selectedCell?.querySelector('button[data-day]') as HTMLButtonElement;
|
|
401
|
-
expect(selectedButton).toBeTruthy();
|
|
402
|
-
|
|
403
|
-
// tabindex is set in the attributes string on the td, not directly on button
|
|
404
|
-
// The button has tabindex="-1" by default in template, but the cell has tabindex="0" for selected
|
|
405
|
-
// Check that the cell has the correct tabindex attribute
|
|
406
|
-
const cellTabindex = selectedCell.getAttribute('tabindex');
|
|
407
|
-
// The tabindex should be 0 for the selected date (set in attributes)
|
|
408
|
-
// Since attributes are in the td, we check the cell
|
|
409
|
-
expect(cellTabindex === '0' || selectedCell.tabIndex === 0).toBe(true);
|
|
410
|
-
});
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
describe('Cell Reference Caching', () => {
|
|
414
|
-
it('should cache cell references for hover range updates', () => {
|
|
415
|
-
const days = getCalendarDays(2024, 0);
|
|
416
|
-
const onDayClick = vi.fn();
|
|
417
|
-
const currentDate = new Date(2024, 0, 15);
|
|
418
|
-
const selectedRange = {
|
|
419
|
-
start: new Date(2024, 0, 10),
|
|
420
|
-
end: null
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
const calendar = renderCalendar(
|
|
424
|
-
defaultTemplates.dayCell as string,
|
|
425
|
-
days,
|
|
426
|
-
currentDate,
|
|
427
|
-
null,
|
|
428
|
-
onDayClick,
|
|
429
|
-
'en-US',
|
|
430
|
-
selectedRange
|
|
431
|
-
);
|
|
432
|
-
|
|
433
|
-
// All cells should have data-date attributes for caching
|
|
434
|
-
const cells = calendar.querySelectorAll('td[data-kt-datepicker-day]');
|
|
435
|
-
expect(cells.length).toBeGreaterThan(0);
|
|
436
|
-
cells.forEach(cell => {
|
|
437
|
-
expect(cell.hasAttribute('data-date')).toBe(true);
|
|
438
|
-
});
|
|
439
|
-
});
|
|
440
|
-
|
|
441
|
-
it('should use cached cell references for hover range', () => {
|
|
442
|
-
const days = getCalendarDays(2024, 0);
|
|
443
|
-
const onDayClick = vi.fn();
|
|
444
|
-
const currentDate = new Date(2024, 0, 15);
|
|
445
|
-
const selectedRange = {
|
|
446
|
-
start: new Date(2024, 0, 10),
|
|
447
|
-
end: null
|
|
448
|
-
};
|
|
449
|
-
|
|
450
|
-
const calendar = renderCalendar(
|
|
451
|
-
defaultTemplates.dayCell as string,
|
|
452
|
-
days,
|
|
453
|
-
currentDate,
|
|
454
|
-
null,
|
|
455
|
-
onDayClick,
|
|
456
|
-
'en-US',
|
|
457
|
-
selectedRange
|
|
458
|
-
);
|
|
459
|
-
|
|
460
|
-
// Simulate hover on a date in range preview mode
|
|
461
|
-
const hoverCell = calendar.querySelector(`[data-date="2024-01-15"]`) as HTMLElement;
|
|
462
|
-
const hoverButton = hoverCell?.querySelector('button[data-day]') as HTMLButtonElement;
|
|
463
|
-
|
|
464
|
-
if (hoverButton) {
|
|
465
|
-
const mouseoverEvent = new MouseEvent('mouseover', { bubbles: true });
|
|
466
|
-
hoverButton.dispatchEvent(mouseoverEvent);
|
|
467
|
-
|
|
468
|
-
// Should have hover range attributes set (if in range preview mode)
|
|
469
|
-
// Note: This depends on the range state being set correctly
|
|
470
|
-
const hoverRangeCells = calendar.querySelectorAll('[data-kt-hover-range]');
|
|
471
|
-
// May be 0 if range preview mode conditions aren't met, but cell should exist
|
|
472
|
-
expect(hoverCell).toBeTruthy();
|
|
473
|
-
}
|
|
474
|
-
});
|
|
475
|
-
});
|
|
476
|
-
|
|
477
|
-
describe('Date Object Reuse', () => {
|
|
478
|
-
it('should cache today date object', () => {
|
|
479
|
-
const days = getCalendarDays(2024, 0);
|
|
480
|
-
const onDayClick = vi.fn();
|
|
481
|
-
const currentDate = new Date(2024, 0, 15);
|
|
482
|
-
|
|
483
|
-
const calendar = renderCalendar(
|
|
484
|
-
defaultTemplates.dayCell as string,
|
|
485
|
-
days,
|
|
486
|
-
currentDate,
|
|
487
|
-
null,
|
|
488
|
-
onDayClick
|
|
489
|
-
);
|
|
490
|
-
|
|
491
|
-
// Today's date should be marked if it's in the visible month
|
|
492
|
-
const today = new Date();
|
|
493
|
-
if (today.getMonth() === currentDate.getMonth() && today.getFullYear() === currentDate.getFullYear()) {
|
|
494
|
-
const todayKey = getDateKey(today);
|
|
495
|
-
const todayDateStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`;
|
|
496
|
-
const todayCell = calendar.querySelector(`[data-date="${todayDateStr}"]`) as HTMLElement;
|
|
497
|
-
if (todayCell) {
|
|
498
|
-
expect(todayCell.hasAttribute('data-today')).toBe(true);
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
});
|
|
502
|
-
|
|
503
|
-
it('should use date keys for range normalization instead of creating Date objects', () => {
|
|
504
|
-
const days = getCalendarDays(2024, 0);
|
|
505
|
-
const onDayClick = vi.fn();
|
|
506
|
-
const currentDate = new Date(2024, 0, 15);
|
|
507
|
-
const selectedRange = {
|
|
508
|
-
start: new Date(2024, 0, 10),
|
|
509
|
-
end: new Date(2024, 0, 20)
|
|
510
|
-
};
|
|
511
|
-
|
|
512
|
-
const calendar = renderCalendar(
|
|
513
|
-
defaultTemplates.dayCell as string,
|
|
514
|
-
days,
|
|
515
|
-
currentDate,
|
|
516
|
-
null,
|
|
517
|
-
onDayClick,
|
|
518
|
-
'en-US',
|
|
519
|
-
selectedRange
|
|
520
|
-
);
|
|
521
|
-
|
|
522
|
-
// Range dates should be marked without creating Date objects in loop
|
|
523
|
-
// Note: Uses data-kt-hover-range (consolidated from data-in-range)
|
|
524
|
-
const inRangeCells = calendar.querySelectorAll('[data-kt-hover-range]');
|
|
525
|
-
expect(inRangeCells.length).toBeGreaterThan(0);
|
|
526
|
-
|
|
527
|
-
// Verify range calculation is correct using date keys
|
|
528
|
-
const startKey = getDateKey(selectedRange.start);
|
|
529
|
-
const endKey = getDateKey(selectedRange.end);
|
|
530
|
-
inRangeCells.forEach(cell => {
|
|
531
|
-
const dateAttr = cell.getAttribute('data-date');
|
|
532
|
-
if (dateAttr) {
|
|
533
|
-
const [year, month, day] = dateAttr.split('-').map(Number);
|
|
534
|
-
const cellKey = getDateKey(new Date(year, month - 1, day));
|
|
535
|
-
expect(cellKey).toBeGreaterThanOrEqual(startKey);
|
|
536
|
-
expect(cellKey).toBeLessThanOrEqual(endKey);
|
|
537
|
-
}
|
|
538
|
-
});
|
|
539
|
-
});
|
|
540
|
-
});
|
|
541
|
-
|
|
542
|
-
describe('Performance Optimizations Integration', () => {
|
|
543
|
-
it('should render calendar efficiently with all optimizations', () => {
|
|
544
|
-
const days = getCalendarDays(2024, 0);
|
|
545
|
-
const onDayClick = vi.fn();
|
|
546
|
-
const currentDate = new Date(2024, 0, 15);
|
|
547
|
-
const selectedDate = new Date(2024, 0, 15);
|
|
548
|
-
const selectedDates = [
|
|
549
|
-
new Date(2024, 0, 10),
|
|
550
|
-
new Date(2024, 0, 20)
|
|
551
|
-
];
|
|
552
|
-
const selectedRange = {
|
|
553
|
-
start: new Date(2024, 0, 5),
|
|
554
|
-
end: new Date(2024, 0, 25)
|
|
555
|
-
};
|
|
556
|
-
|
|
557
|
-
// Render with all selection modes to test optimizations
|
|
558
|
-
const calendar = renderCalendar(
|
|
559
|
-
defaultTemplates.dayCell as string,
|
|
560
|
-
days,
|
|
561
|
-
currentDate,
|
|
562
|
-
selectedDate,
|
|
563
|
-
onDayClick,
|
|
564
|
-
'en-US',
|
|
565
|
-
selectedRange,
|
|
566
|
-
selectedDates
|
|
567
|
-
);
|
|
568
|
-
|
|
569
|
-
// Verify calendar rendered correctly
|
|
570
|
-
expect(calendar).toBeTruthy();
|
|
571
|
-
const cells = calendar.querySelectorAll('td[data-kt-datepicker-day]');
|
|
572
|
-
expect(cells.length).toBeGreaterThan(0);
|
|
573
|
-
|
|
574
|
-
// Verify optimizations are working
|
|
575
|
-
// 1. Day names should be cached (no way to directly test, but rendering works)
|
|
576
|
-
// 2. Event delegation should work (tested separately)
|
|
577
|
-
// 3. Date keys should work (selected dates highlighted)
|
|
578
|
-
const selectedCells = calendar.querySelectorAll('[data-kt-selected="true"]');
|
|
579
|
-
expect(selectedCells.length).toBeGreaterThan(0);
|
|
580
|
-
});
|
|
581
|
-
|
|
582
|
-
it('should handle multiple renders efficiently', () => {
|
|
583
|
-
const days = getCalendarDays(2024, 0);
|
|
584
|
-
const onDayClick = vi.fn();
|
|
585
|
-
const currentDate = new Date(2024, 0, 15);
|
|
586
|
-
|
|
587
|
-
// Render multiple times - day name cache should speed up subsequent renders
|
|
588
|
-
const calendars: HTMLElement[] = [];
|
|
589
|
-
for (let i = 0; i < 5; i++) {
|
|
590
|
-
const calendar = renderCalendar(
|
|
591
|
-
defaultTemplates.dayCell as string,
|
|
592
|
-
days,
|
|
593
|
-
currentDate,
|
|
594
|
-
null,
|
|
595
|
-
onDayClick,
|
|
596
|
-
'en-US'
|
|
597
|
-
);
|
|
598
|
-
calendars.push(calendar);
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// All calendars should render correctly
|
|
602
|
-
expect(calendars.length).toBe(5);
|
|
603
|
-
calendars.forEach(cal => {
|
|
604
|
-
expect(cal).toBeTruthy();
|
|
605
|
-
const cells = cal.querySelectorAll('td[data-kt-datepicker-day]');
|
|
606
|
-
expect(cells.length).toBeGreaterThan(0);
|
|
607
|
-
});
|
|
608
|
-
});
|
|
609
|
-
});
|
|
610
|
-
});
|
|
611
|
-
|