@keenthemes/ktui 1.0.28 → 1.1.0
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 +27 -0
- package/dist/ktui.js +8780 -6199
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +2744 -1367
- package/lib/cjs/components/alert/alert.js +1025 -0
- package/lib/cjs/components/alert/alert.js.map +1 -0
- package/lib/cjs/components/alert/index.js +20 -0
- package/lib/cjs/components/alert/index.js.map +1 -0
- package/lib/cjs/components/alert/templates.js +120 -0
- package/lib/cjs/components/alert/templates.js.map +1 -0
- package/lib/cjs/components/alert/types.js +7 -0
- package/lib/cjs/components/alert/types.js.map +1 -0
- package/lib/cjs/components/datepicker/config/config.js +42 -0
- package/lib/cjs/components/datepicker/config/config.js.map +1 -0
- package/lib/cjs/components/datepicker/config/index.js +24 -0
- package/lib/cjs/components/datepicker/config/index.js.map +1 -0
- package/lib/cjs/components/datepicker/config/interfaces.js +7 -0
- package/lib/cjs/components/datepicker/config/interfaces.js.map +1 -0
- package/lib/cjs/components/datepicker/config/types.js +7 -0
- package/lib/cjs/components/datepicker/config/types.js.map +1 -0
- package/lib/cjs/components/datepicker/core/event-manager.js +135 -0
- package/lib/cjs/components/datepicker/core/event-manager.js.map +1 -0
- package/lib/cjs/components/datepicker/core/focus-manager.js +167 -0
- package/lib/cjs/components/datepicker/core/focus-manager.js.map +1 -0
- package/lib/cjs/components/datepicker/core/helpers.js +219 -0
- package/lib/cjs/components/datepicker/core/helpers.js.map +1 -0
- package/lib/cjs/components/datepicker/core/index.js +25 -0
- package/lib/cjs/components/datepicker/core/index.js.map +1 -0
- package/lib/cjs/components/datepicker/core/unified-state-manager.js +394 -0
- package/lib/cjs/components/datepicker/core/unified-state-manager.js.map +1 -0
- package/lib/cjs/components/datepicker/datepicker.js +2066 -763
- package/lib/cjs/components/datepicker/datepicker.js.map +1 -1
- package/lib/cjs/components/datepicker/index.js +19 -8
- package/lib/cjs/components/datepicker/index.js.map +1 -1
- package/lib/cjs/components/datepicker/ui/index.js +23 -0
- package/lib/cjs/components/datepicker/ui/index.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/input/dropdown.js +489 -0
- package/lib/cjs/components/datepicker/ui/input/dropdown.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/input/index.js +23 -0
- package/lib/cjs/components/datepicker/ui/input/index.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/input/segmented-input.js +640 -0
- package/lib/cjs/components/datepicker/ui/input/segmented-input.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/renderers/calendar.js +446 -0
- package/lib/cjs/components/datepicker/ui/renderers/calendar.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/renderers/footer.js +42 -0
- package/lib/cjs/components/datepicker/ui/renderers/footer.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/renderers/header.js +32 -0
- package/lib/cjs/components/datepicker/ui/renderers/header.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/renderers/index.js +25 -0
- package/lib/cjs/components/datepicker/ui/renderers/index.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/renderers/time-picker.js +384 -0
- package/lib/cjs/components/datepicker/ui/renderers/time-picker.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/templates/index.js +22 -0
- package/lib/cjs/components/datepicker/ui/templates/index.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/templates/templates.js +253 -0
- package/lib/cjs/components/datepicker/ui/templates/templates.js.map +1 -0
- package/lib/cjs/components/datepicker/utils/date-formatters.js +88 -0
- package/lib/cjs/components/datepicker/utils/date-formatters.js.map +1 -0
- package/lib/cjs/components/datepicker/utils/date-utils.js +194 -0
- package/lib/cjs/components/datepicker/utils/date-utils.js.map +1 -0
- package/lib/cjs/components/datepicker/utils/index.js +24 -0
- package/lib/cjs/components/datepicker/utils/index.js.map +1 -0
- package/lib/cjs/components/datepicker/utils/time-utils.js +213 -0
- package/lib/cjs/components/datepicker/utils/time-utils.js.map +1 -0
- package/lib/cjs/index.js +6 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/esm/components/alert/alert.js +1022 -0
- package/lib/esm/components/alert/alert.js.map +1 -0
- package/lib/esm/components/alert/index.js +4 -0
- package/lib/esm/components/alert/index.js.map +1 -0
- package/lib/esm/components/alert/templates.js +112 -0
- package/lib/esm/components/alert/templates.js.map +1 -0
- package/lib/esm/components/alert/types.js +6 -0
- package/lib/esm/components/alert/types.js.map +1 -0
- package/lib/esm/components/datepicker/config/config.js +39 -0
- package/lib/esm/components/datepicker/config/config.js.map +1 -0
- package/lib/esm/components/datepicker/config/index.js +8 -0
- package/lib/esm/components/datepicker/config/index.js.map +1 -0
- package/lib/esm/components/datepicker/config/interfaces.js +6 -0
- package/lib/esm/components/datepicker/config/interfaces.js.map +1 -0
- package/lib/esm/components/datepicker/config/types.js +6 -0
- package/lib/esm/components/datepicker/config/types.js.map +1 -0
- package/lib/esm/components/datepicker/core/event-manager.js +133 -0
- package/lib/esm/components/datepicker/core/event-manager.js.map +1 -0
- package/lib/esm/components/datepicker/core/focus-manager.js +164 -0
- package/lib/esm/components/datepicker/core/focus-manager.js.map +1 -0
- package/lib/esm/components/datepicker/core/helpers.js +211 -0
- package/lib/esm/components/datepicker/core/helpers.js.map +1 -0
- package/lib/esm/components/datepicker/core/index.js +9 -0
- package/lib/esm/components/datepicker/core/index.js.map +1 -0
- package/lib/esm/components/datepicker/core/unified-state-manager.js +391 -0
- package/lib/esm/components/datepicker/core/unified-state-manager.js.map +1 -0
- package/lib/esm/components/datepicker/datepicker.js +2065 -763
- package/lib/esm/components/datepicker/datepicker.js.map +1 -1
- package/lib/esm/components/datepicker/index.js +6 -8
- package/lib/esm/components/datepicker/index.js.map +1 -1
- package/lib/esm/components/datepicker/ui/index.js +7 -0
- package/lib/esm/components/datepicker/ui/index.js.map +1 -0
- package/lib/esm/components/datepicker/ui/input/dropdown.js +486 -0
- package/lib/esm/components/datepicker/ui/input/dropdown.js.map +1 -0
- package/lib/esm/components/datepicker/ui/input/index.js +7 -0
- package/lib/esm/components/datepicker/ui/input/index.js.map +1 -0
- package/lib/esm/components/datepicker/ui/input/segmented-input.js +637 -0
- package/lib/esm/components/datepicker/ui/input/segmented-input.js.map +1 -0
- package/lib/esm/components/datepicker/ui/renderers/calendar.js +443 -0
- package/lib/esm/components/datepicker/ui/renderers/calendar.js.map +1 -0
- package/lib/esm/components/datepicker/ui/renderers/footer.js +39 -0
- package/lib/esm/components/datepicker/ui/renderers/footer.js.map +1 -0
- package/lib/esm/components/datepicker/ui/renderers/header.js +29 -0
- package/lib/esm/components/datepicker/ui/renderers/header.js.map +1 -0
- package/lib/esm/components/datepicker/ui/renderers/index.js +9 -0
- package/lib/esm/components/datepicker/ui/renderers/index.js.map +1 -0
- package/lib/esm/components/datepicker/ui/renderers/time-picker.js +381 -0
- package/lib/esm/components/datepicker/ui/renderers/time-picker.js.map +1 -0
- package/lib/esm/components/datepicker/ui/templates/index.js +6 -0
- package/lib/esm/components/datepicker/ui/templates/index.js.map +1 -0
- package/lib/esm/components/datepicker/ui/templates/templates.js +242 -0
- package/lib/esm/components/datepicker/ui/templates/templates.js.map +1 -0
- package/lib/esm/components/datepicker/utils/date-formatters.js +83 -0
- package/lib/esm/components/datepicker/utils/date-formatters.js.map +1 -0
- package/lib/esm/components/datepicker/utils/date-utils.js +184 -0
- package/lib/esm/components/datepicker/utils/date-utils.js.map +1 -0
- package/lib/esm/components/datepicker/utils/index.js +8 -0
- package/lib/esm/components/datepicker/utils/index.js.map +1 -0
- package/lib/esm/components/datepicker/utils/time-utils.js +201 -0
- package/lib/esm/components/datepicker/utils/time-utils.js.map +1 -0
- package/lib/esm/index.js +4 -0
- package/lib/esm/index.js.map +1 -1
- package/package.json +22 -3
- package/src/components/alert/alert.css +429 -188
- package/src/components/alert/alert.ts +990 -0
- package/src/components/alert/index.ts +4 -0
- package/src/components/alert/templates.ts +110 -0
- package/src/components/alert/tests/accessibility/aria-roles.test.ts +19 -0
- package/src/components/alert/tests/accessibility/focus-management.test.ts +19 -0
- package/src/components/alert/tests/accessibility/keyboard-nav.test.ts +22 -0
- package/src/components/alert/tests/actions/confirm-cancel.test.ts +122 -0
- package/src/components/alert/tests/actions/input-field.test.ts +180 -0
- package/src/components/alert/tests/alert.basic.test.ts +126 -0
- package/src/components/alert/tests/alert.config.test.ts +75 -0
- package/src/components/alert/tests/alert.templates.test.ts +17 -0
- package/src/components/alert/tests/config/attribute-config.test.ts +94 -0
- package/src/components/alert/tests/config/json-config.test.ts +119 -0
- package/src/components/alert/tests/config/merging.test.ts +89 -0
- package/src/components/alert/tests/dismissal/auto-dismiss.test.ts +96 -0
- package/src/components/alert/tests/dismissal/escape-key-dismiss.test.ts +105 -0
- package/src/components/alert/tests/dismissal/manual-dismiss.test.ts +90 -0
- package/src/components/alert/tests/dismissal/outside-click-dismiss.test.ts +91 -0
- package/src/components/alert/tests/edge-cases/invalid-config.test.ts +19 -0
- package/src/components/alert/tests/edge-cases/multiple-alerts.test.ts +19 -0
- package/src/components/alert/tests/rendering/custom-content.test.ts +81 -0
- package/src/components/alert/tests/rendering/info-alert.test.ts +84 -0
- package/src/components/alert/tests/rendering/success-alert.test.ts +100 -0
- package/src/components/alert/tests/templates/default-templates.test.ts +16 -0
- package/src/components/alert/tests/templates/user-templates.test.ts +16 -0
- package/src/components/alert/types.ts +145 -0
- package/src/components/datepicker/__tests__/datepicker-events.test.ts +356 -0
- package/src/components/datepicker/__tests__/datepicker-init.test.ts +343 -0
- package/src/components/datepicker/__tests__/datepicker-integration.test.ts +435 -0
- package/src/components/datepicker/__tests__/datepicker-timezone.test.ts +220 -0
- package/src/components/datepicker/__tests__/segmented-input-focus.test.ts +380 -0
- package/src/components/datepicker/__tests__/selective-state-updates.test.ts +400 -0
- package/src/components/datepicker/__tests__/state-manager.test.ts +421 -0
- package/src/components/datepicker/__tests__/time-preservation.test.ts +387 -0
- package/src/components/datepicker/config/config.ts +40 -0
- package/src/components/datepicker/config/index.ts +8 -0
- package/src/components/datepicker/config/interfaces.ts +82 -0
- package/src/components/datepicker/config/types.ts +188 -0
- package/src/components/datepicker/core/event-manager.ts +159 -0
- package/src/components/datepicker/core/focus-manager.ts +201 -0
- package/src/components/datepicker/core/helpers.ts +231 -0
- package/src/components/datepicker/core/index.ts +9 -0
- package/src/components/datepicker/core/unified-state-manager.ts +459 -0
- package/src/components/datepicker/datepicker.css +429 -1
- package/src/components/datepicker/datepicker.ts +2538 -1277
- package/src/components/datepicker/index.ts +6 -8
- package/src/components/datepicker/ui/index.ts +7 -0
- package/src/components/datepicker/ui/input/dropdown.ts +552 -0
- package/src/components/datepicker/ui/input/index.ts +7 -0
- package/src/components/datepicker/ui/input/segmented-input.ts +638 -0
- package/src/components/datepicker/ui/renderers/__tests__/calendar-optimizations.test.ts +611 -0
- package/src/components/datepicker/ui/renderers/calendar.ts +530 -0
- package/src/components/datepicker/ui/renderers/footer.ts +43 -0
- package/src/components/datepicker/ui/renderers/header.ts +33 -0
- package/src/components/datepicker/ui/renderers/index.ts +9 -0
- package/src/components/datepicker/ui/renderers/time-picker.ts +438 -0
- package/src/components/datepicker/ui/templates/index.ts +6 -0
- package/src/components/datepicker/ui/templates/templates.ts +306 -0
- package/src/components/datepicker/utils/__tests__/date-formatters.test.ts +160 -0
- package/src/components/datepicker/utils/__tests__/date-utils-keys.test.ts +86 -0
- package/src/components/datepicker/utils/__tests__/date-utils-timezone.test.ts +215 -0
- package/src/components/datepicker/utils/date-formatters.ts +85 -0
- package/src/components/datepicker/utils/date-utils.ts +172 -0
- package/src/components/datepicker/utils/index.ts +8 -0
- package/src/components/datepicker/utils/time-utils.ts +221 -0
- package/src/index.ts +7 -1
- package/CONTRIBUTING.md +0 -101
- package/examples/datatable/checkbox-events-test.html +0 -400
- package/examples/datatable/credentials-test.html +0 -423
- package/examples/datatable/remote-checkbox-test.html +0 -365
- package/examples/datatable/sorting-test.html +0 -258
- package/examples/image-input/file-upload-example.html +0 -189
- package/examples/modal/persistent.html +0 -205
- package/examples/modal/remote-select-dropdown.html +0 -166
- package/examples/modal/select-dropdown-container.html +0 -129
- package/examples/select/avatar.html +0 -47
- package/examples/select/basic-usage.html +0 -39
- package/examples/select/country.html +0 -43
- package/examples/select/dark-mode.html +0 -93
- package/examples/select/description.html +0 -53
- package/examples/select/disable-option.html +0 -37
- package/examples/select/disable-select.html +0 -35
- package/examples/select/dropdowncontainer.html +0 -111
- package/examples/select/dynamic-methods.html +0 -273
- package/examples/select/formdata-remote.html +0 -161
- package/examples/select/global-config.html +0 -81
- package/examples/select/icon-multiple.html +0 -50
- package/examples/select/icon.html +0 -48
- package/examples/select/max-selection.html +0 -38
- package/examples/select/modal-container.html +0 -128
- package/examples/select/modal-positioning-test.html +0 -338
- package/examples/select/modal.html +0 -80
- package/examples/select/multiple.html +0 -40
- package/examples/select/native-selected.html +0 -64
- package/examples/select/placeholder.html +0 -40
- package/examples/select/remote-data-preselected.html +0 -283
- package/examples/select/remote-data.html +0 -38
- package/examples/select/search.html +0 -57
- package/examples/select/sizes.html +0 -94
- package/examples/select/tags-enhanced.html +0 -86
- package/examples/select/tags-icons.html +0 -57
- package/examples/select/template-customization.html +0 -61
- package/examples/sticky/README.md +0 -158
- package/examples/sticky/debug-sticky.html +0 -144
- package/examples/sticky/test-runner.html +0 -175
- package/examples/sticky/test-sticky-logic.js +0 -369
- package/examples/sticky/test-sticky-positioning.html +0 -386
- package/examples/toast/example.html +0 -479
- package/lib/cjs/components/datepicker/calendar.js +0 -1061
- package/lib/cjs/components/datepicker/calendar.js.map +0 -1
- package/lib/cjs/components/datepicker/config.js +0 -332
- package/lib/cjs/components/datepicker/config.js.map +0 -1
- package/lib/cjs/components/datepicker/dropdown.js +0 -635
- package/lib/cjs/components/datepicker/dropdown.js.map +0 -1
- package/lib/cjs/components/datepicker/events.js +0 -129
- package/lib/cjs/components/datepicker/events.js.map +0 -1
- package/lib/cjs/components/datepicker/keyboard.js +0 -536
- package/lib/cjs/components/datepicker/keyboard.js.map +0 -1
- package/lib/cjs/components/datepicker/locales.js +0 -78
- package/lib/cjs/components/datepicker/locales.js.map +0 -1
- package/lib/cjs/components/datepicker/templates.js +0 -403
- package/lib/cjs/components/datepicker/templates.js.map +0 -1
- package/lib/cjs/components/datepicker/types.js +0 -23
- package/lib/cjs/components/datepicker/types.js.map +0 -1
- package/lib/cjs/components/datepicker/utils.js +0 -524
- package/lib/cjs/components/datepicker/utils.js.map +0 -1
- package/lib/esm/components/datepicker/calendar.js +0 -1058
- package/lib/esm/components/datepicker/calendar.js.map +0 -1
- package/lib/esm/components/datepicker/config.js +0 -329
- package/lib/esm/components/datepicker/config.js.map +0 -1
- package/lib/esm/components/datepicker/dropdown.js +0 -632
- package/lib/esm/components/datepicker/dropdown.js.map +0 -1
- package/lib/esm/components/datepicker/events.js +0 -126
- package/lib/esm/components/datepicker/events.js.map +0 -1
- package/lib/esm/components/datepicker/keyboard.js +0 -533
- package/lib/esm/components/datepicker/keyboard.js.map +0 -1
- package/lib/esm/components/datepicker/locales.js +0 -74
- package/lib/esm/components/datepicker/locales.js.map +0 -1
- package/lib/esm/components/datepicker/templates.js +0 -390
- package/lib/esm/components/datepicker/templates.js.map +0 -1
- package/lib/esm/components/datepicker/types.js +0 -20
- package/lib/esm/components/datepicker/types.js.map +0 -1
- package/lib/esm/components/datepicker/utils.js +0 -508
- package/lib/esm/components/datepicker/utils.js.map +0 -1
- package/prettier.config.js +0 -9
- package/src/components/datepicker/calendar.ts +0 -1397
- package/src/components/datepicker/config.ts +0 -368
- package/src/components/datepicker/dropdown.ts +0 -757
- package/src/components/datepicker/events.ts +0 -149
- package/src/components/datepicker/keyboard.ts +0 -646
- package/src/components/datepicker/locales.ts +0 -80
- package/src/components/datepicker/templates.ts +0 -792
- package/src/components/datepicker/types.ts +0 -154
- package/src/components/datepicker/utils.ts +0 -631
- package/src/components/select/variants.css +0 -4
- package/tsconfig.json +0 -17
- package/webpack.config.js +0 -118
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* time-preservation.test.ts - Tests for time preservation on calendar date clicks
|
|
3
|
+
* Ensures time is preserved across single, range, and multi-date selection modes
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import { KTDatepicker } from '../datepicker';
|
|
8
|
+
import { dateToTimeState, applyTimeToDate } from '../utils/time-utils';
|
|
9
|
+
|
|
10
|
+
describe('KTDatepicker Time Preservation', () => {
|
|
11
|
+
let container: HTMLElement;
|
|
12
|
+
let datepicker: KTDatepicker;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
// Create a fresh container for each test
|
|
16
|
+
container = document.createElement('div');
|
|
17
|
+
container.innerHTML = `
|
|
18
|
+
<div class="kt-datepicker" data-kt-datepicker>
|
|
19
|
+
<input type="text" data-kt-datepicker-input placeholder="Select date">
|
|
20
|
+
</div>
|
|
21
|
+
`;
|
|
22
|
+
document.body.innerHTML = '';
|
|
23
|
+
document.body.appendChild(container);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
if (datepicker) {
|
|
28
|
+
datepicker.destroy();
|
|
29
|
+
}
|
|
30
|
+
document.body.innerHTML = '';
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('Single Date Mode', () => {
|
|
34
|
+
it('should preserve time when selectedTime exists', () => {
|
|
35
|
+
const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
|
|
36
|
+
const initialDate = new Date(2024, 0, 15, 14, 30, 0); // Jan 15, 2024, 2:30 PM
|
|
37
|
+
|
|
38
|
+
datepicker = new KTDatepicker(element, {
|
|
39
|
+
enableTime: true,
|
|
40
|
+
value: initialDate,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Verify initial date has time set
|
|
44
|
+
const initialState = datepicker.getState();
|
|
45
|
+
expect(initialState.selectedDate).toBeDefined();
|
|
46
|
+
expect(initialState.selectedDate?.getHours()).toBe(14);
|
|
47
|
+
expect(initialState.selectedDate?.getMinutes()).toBe(30);
|
|
48
|
+
|
|
49
|
+
// Select a new date
|
|
50
|
+
const newDate = new Date(2024, 0, 20, 0, 0, 0); // Jan 20, 2024, midnight
|
|
51
|
+
datepicker.setDate(newDate);
|
|
52
|
+
|
|
53
|
+
// Verify time is preserved
|
|
54
|
+
const newState = datepicker.getState();
|
|
55
|
+
expect(newState.selectedDate).toBeDefined();
|
|
56
|
+
expect(newState.selectedDate?.getDate()).toBe(20);
|
|
57
|
+
expect(newState.selectedDate?.getHours()).toBe(14);
|
|
58
|
+
expect(newState.selectedDate?.getMinutes()).toBe(30);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should extract time from selectedDate when selectedTime is missing', () => {
|
|
62
|
+
const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
|
|
63
|
+
const initialDate = new Date(2024, 0, 15, 16, 45, 0); // Jan 15, 2024, 4:45 PM
|
|
64
|
+
|
|
65
|
+
datepicker = new KTDatepicker(element, {
|
|
66
|
+
enableTime: true,
|
|
67
|
+
value: initialDate,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Clear selectedTime state (simulate missing state)
|
|
71
|
+
const state = datepicker.getState();
|
|
72
|
+
(datepicker as any)._unifiedStateManager.updateState(
|
|
73
|
+
{ selectedTime: null },
|
|
74
|
+
'test-clear'
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Select a new date
|
|
78
|
+
const newDate = new Date(2024, 0, 25, 0, 0, 0);
|
|
79
|
+
datepicker.setDate(newDate);
|
|
80
|
+
|
|
81
|
+
// Verify time is extracted from selectedDate
|
|
82
|
+
const newState = datepicker.getState();
|
|
83
|
+
expect(newState.selectedDate?.getDate()).toBe(25);
|
|
84
|
+
expect(newState.selectedDate?.getHours()).toBe(16);
|
|
85
|
+
expect(newState.selectedDate?.getMinutes()).toBe(45);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('should default to current time when no time exists', () => {
|
|
89
|
+
const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
|
|
90
|
+
const now = new Date();
|
|
91
|
+
|
|
92
|
+
datepicker = new KTDatepicker(element, {
|
|
93
|
+
enableTime: true,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Select a date
|
|
97
|
+
const newDate = new Date(2024, 0, 15, 0, 0, 0);
|
|
98
|
+
datepicker.setDate(newDate);
|
|
99
|
+
|
|
100
|
+
// Verify time defaults to current time
|
|
101
|
+
const state = datepicker.getState();
|
|
102
|
+
expect(state.selectedDate).toBeDefined();
|
|
103
|
+
expect(state.selectedDate?.getDate()).toBe(15);
|
|
104
|
+
// Allow 1-minute tolerance for test execution time
|
|
105
|
+
const timeDiff = Math.abs(state.selectedDate!.getHours() - now.getHours());
|
|
106
|
+
expect(timeDiff).toBeLessThanOrEqual(1);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('should not reset time to midnight', () => {
|
|
110
|
+
const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
|
|
111
|
+
const initialDate = new Date(2024, 0, 15, 10, 15, 30); // Jan 15, 2024, 10:15:30 AM
|
|
112
|
+
|
|
113
|
+
datepicker = new KTDatepicker(element, {
|
|
114
|
+
enableTime: true,
|
|
115
|
+
timeGranularity: 'second',
|
|
116
|
+
value: initialDate,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Select a new date
|
|
120
|
+
const newDate = new Date(2024, 0, 20, 0, 0, 0);
|
|
121
|
+
datepicker.setDate(newDate);
|
|
122
|
+
|
|
123
|
+
// Verify time is NOT midnight
|
|
124
|
+
const state = datepicker.getState();
|
|
125
|
+
expect(state.selectedDate?.getHours()).not.toBe(0);
|
|
126
|
+
expect(state.selectedDate?.getMinutes()).not.toBe(0);
|
|
127
|
+
expect(state.selectedDate?.getSeconds()).not.toBe(0);
|
|
128
|
+
expect(state.selectedDate?.getHours()).toBe(10);
|
|
129
|
+
expect(state.selectedDate?.getMinutes()).toBe(15);
|
|
130
|
+
expect(state.selectedDate?.getSeconds()).toBe(30);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe('Range Selection Mode', () => {
|
|
135
|
+
it('should preserve time for both start and end dates', () => {
|
|
136
|
+
const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
|
|
137
|
+
const initialDate = new Date(2024, 0, 15, 14, 30, 0); // Jan 15, 2024, 2:30 PM
|
|
138
|
+
|
|
139
|
+
datepicker = new KTDatepicker(element, {
|
|
140
|
+
range: true,
|
|
141
|
+
enableTime: true,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Manually set selectedTime to simulate time picker selection
|
|
145
|
+
// Use immediate update (third parameter = true)
|
|
146
|
+
(datepicker as any)._unifiedStateManager.updateState(
|
|
147
|
+
{ selectedTime: { hour: 14, minute: 30, second: 0 } },
|
|
148
|
+
'test-init',
|
|
149
|
+
true
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
// Select start date (first click creates start)
|
|
153
|
+
const startDate = new Date(2024, 0, 10, 0, 0, 0);
|
|
154
|
+
(datepicker as any)._selectRangeDate(startDate);
|
|
155
|
+
|
|
156
|
+
// Verify start has time preserved
|
|
157
|
+
const afterStartState = datepicker.getState();
|
|
158
|
+
expect(afterStartState.selectedRange?.start?.getDate()).toBe(10);
|
|
159
|
+
expect(afterStartState.selectedRange?.start?.getHours()).toBe(14);
|
|
160
|
+
expect(afterStartState.selectedRange?.start?.getMinutes()).toBe(30);
|
|
161
|
+
|
|
162
|
+
// Select end date (second click creates end)
|
|
163
|
+
const endDate = new Date(2024, 0, 20, 0, 0, 0);
|
|
164
|
+
(datepicker as any)._selectRangeDate(endDate);
|
|
165
|
+
|
|
166
|
+
// Verify both dates preserve time
|
|
167
|
+
const newState = datepicker.getState();
|
|
168
|
+
expect(newState.selectedRange).toBeDefined();
|
|
169
|
+
expect(newState.selectedRange?.start).toBeDefined();
|
|
170
|
+
expect(newState.selectedRange?.end).toBeDefined();
|
|
171
|
+
|
|
172
|
+
expect(newState.selectedRange?.start?.getDate()).toBe(10);
|
|
173
|
+
expect(newState.selectedRange?.start?.getHours()).toBe(14);
|
|
174
|
+
expect(newState.selectedRange?.start?.getMinutes()).toBe(30);
|
|
175
|
+
|
|
176
|
+
expect(newState.selectedRange?.end?.getDate()).toBe(20);
|
|
177
|
+
expect(newState.selectedRange?.end?.getHours()).toBe(14);
|
|
178
|
+
expect(newState.selectedRange?.end?.getMinutes()).toBe(30);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should not reset range dates to midnight', () => {
|
|
182
|
+
const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
|
|
183
|
+
const initialDate = new Date(2024, 0, 15, 16, 45, 0); // Jan 15, 2024, 4:45 PM
|
|
184
|
+
|
|
185
|
+
datepicker = new KTDatepicker(element, {
|
|
186
|
+
range: true,
|
|
187
|
+
enableTime: true,
|
|
188
|
+
value: initialDate,
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Select start and end dates
|
|
192
|
+
const startDate = new Date(2024, 0, 10, 0, 0, 0);
|
|
193
|
+
(datepicker as any)._selectRangeDate(startDate);
|
|
194
|
+
|
|
195
|
+
const endDate = new Date(2024, 0, 25, 0, 0, 0);
|
|
196
|
+
(datepicker as any)._selectRangeDate(endDate);
|
|
197
|
+
|
|
198
|
+
// Verify time is NOT midnight for either date
|
|
199
|
+
const state = datepicker.getState();
|
|
200
|
+
expect(state.selectedRange?.start?.getHours()).not.toBe(0);
|
|
201
|
+
expect(state.selectedRange?.start?.getMinutes()).not.toBe(0);
|
|
202
|
+
expect(state.selectedRange?.end?.getHours()).not.toBe(0);
|
|
203
|
+
expect(state.selectedRange?.end?.getMinutes()).not.toBe(0);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('should extract time from range start when selectedTime is missing', () => {
|
|
207
|
+
const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
|
|
208
|
+
|
|
209
|
+
datepicker = new KTDatepicker(element, {
|
|
210
|
+
range: true,
|
|
211
|
+
enableTime: true,
|
|
212
|
+
valueRange: {
|
|
213
|
+
start: new Date(2024, 0, 10, 13, 20, 0), // Jan 10, 2024, 1:20 PM
|
|
214
|
+
end: new Date(2024, 0, 15, 13, 20, 0), // Jan 15, 2024, 1:20 PM
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
// Clear selectedTime
|
|
219
|
+
(datepicker as any)._unifiedStateManager.updateState(
|
|
220
|
+
{ selectedTime: null },
|
|
221
|
+
'test-clear'
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
// Reset range to only have start
|
|
225
|
+
(datepicker as any)._unifiedStateManager.setSelectedRange(
|
|
226
|
+
{
|
|
227
|
+
start: new Date(2024, 0, 10, 13, 20, 0),
|
|
228
|
+
end: null,
|
|
229
|
+
},
|
|
230
|
+
'test-reset'
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
// Select a new end date
|
|
234
|
+
const newEndDate = new Date(2024, 0, 25, 0, 0, 0);
|
|
235
|
+
(datepicker as any)._selectRangeDate(newEndDate);
|
|
236
|
+
|
|
237
|
+
// Verify time is extracted from range start
|
|
238
|
+
const state = datepicker.getState();
|
|
239
|
+
expect(state.selectedRange?.end?.getDate()).toBe(25);
|
|
240
|
+
expect(state.selectedRange?.end?.getHours()).toBe(13);
|
|
241
|
+
expect(state.selectedRange?.end?.getMinutes()).toBe(20);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
describe('Multi-Date Selection Mode', () => {
|
|
246
|
+
it('should preserve time for all selected dates', () => {
|
|
247
|
+
const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
|
|
248
|
+
const initialDate = new Date(2024, 0, 15, 11, 30, 0); // Jan 15, 2024, 11:30 AM
|
|
249
|
+
|
|
250
|
+
datepicker = new KTDatepicker(element, {
|
|
251
|
+
multiDate: true,
|
|
252
|
+
enableTime: true,
|
|
253
|
+
values: [initialDate],
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// Verify initial date has time set
|
|
257
|
+
const initialState = datepicker.getState();
|
|
258
|
+
expect(initialState.selectedDates).toBeDefined();
|
|
259
|
+
expect(initialState.selectedDates.length).toBe(1);
|
|
260
|
+
expect(initialState.selectedDates[0].getHours()).toBe(11);
|
|
261
|
+
expect(initialState.selectedDates[0].getMinutes()).toBe(30);
|
|
262
|
+
|
|
263
|
+
// Select multiple dates
|
|
264
|
+
const date1 = new Date(2024, 0, 10, 0, 0, 0);
|
|
265
|
+
(datepicker as any)._selectMultiDate(date1);
|
|
266
|
+
|
|
267
|
+
const date2 = new Date(2024, 0, 20, 0, 0, 0);
|
|
268
|
+
(datepicker as any)._selectMultiDate(date2);
|
|
269
|
+
|
|
270
|
+
const date3 = new Date(2024, 0, 25, 0, 0, 0);
|
|
271
|
+
(datepicker as any)._selectMultiDate(date3);
|
|
272
|
+
|
|
273
|
+
// Verify all dates preserve time
|
|
274
|
+
const newState = datepicker.getState();
|
|
275
|
+
expect(newState.selectedDates).toBeDefined();
|
|
276
|
+
expect(newState.selectedDates.length).toBeGreaterThan(1);
|
|
277
|
+
|
|
278
|
+
newState.selectedDates.forEach((date) => {
|
|
279
|
+
expect(date.getHours()).toBe(11);
|
|
280
|
+
expect(date.getMinutes()).toBe(30);
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it('should not reset multi-dates to midnight', () => {
|
|
285
|
+
const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
|
|
286
|
+
const initialDate = new Date(2024, 0, 15, 9, 15, 0); // Jan 15, 2024, 9:15 AM
|
|
287
|
+
|
|
288
|
+
datepicker = new KTDatepicker(element, {
|
|
289
|
+
multiDate: true,
|
|
290
|
+
enableTime: true,
|
|
291
|
+
value: initialDate,
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Select dates
|
|
295
|
+
const date1 = new Date(2024, 0, 10, 0, 0, 0);
|
|
296
|
+
(datepicker as any)._selectMultiDate(date1);
|
|
297
|
+
|
|
298
|
+
const date2 = new Date(2024, 0, 20, 0, 0, 0);
|
|
299
|
+
(datepicker as any)._selectMultiDate(date2);
|
|
300
|
+
|
|
301
|
+
// Verify time is NOT midnight for any date
|
|
302
|
+
const state = datepicker.getState();
|
|
303
|
+
state.selectedDates.forEach((date) => {
|
|
304
|
+
expect(date.getHours()).not.toBe(0);
|
|
305
|
+
expect(date.getMinutes()).not.toBe(0);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('should extract time from existing selected dates when selectedTime is missing', () => {
|
|
310
|
+
const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
|
|
311
|
+
|
|
312
|
+
datepicker = new KTDatepicker(element, {
|
|
313
|
+
multiDate: true,
|
|
314
|
+
enableTime: true,
|
|
315
|
+
values: [
|
|
316
|
+
new Date(2024, 0, 10, 15, 45, 0), // Jan 10, 2024, 3:45 PM
|
|
317
|
+
new Date(2024, 0, 15, 15, 45, 0), // Jan 15, 2024, 3:45 PM
|
|
318
|
+
],
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Clear selectedTime
|
|
322
|
+
(datepicker as any)._unifiedStateManager.updateState(
|
|
323
|
+
{ selectedTime: null },
|
|
324
|
+
'test-clear'
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
// Select a new date
|
|
328
|
+
const newDate = new Date(2024, 0, 25, 0, 0, 0);
|
|
329
|
+
(datepicker as any)._selectMultiDate(newDate);
|
|
330
|
+
|
|
331
|
+
// Verify time is extracted from existing dates
|
|
332
|
+
const state = datepicker.getState();
|
|
333
|
+
const addedDate = state.selectedDates.find((d) => d.getDate() === 25);
|
|
334
|
+
expect(addedDate).toBeDefined();
|
|
335
|
+
expect(addedDate?.getHours()).toBe(15);
|
|
336
|
+
expect(addedDate?.getMinutes()).toBe(45);
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
describe('Date-Only Mode (No Time)', () => {
|
|
341
|
+
it('should not apply time when enableTime is false', () => {
|
|
342
|
+
const element = container.querySelector('[data-kt-datepicker]') as HTMLElement;
|
|
343
|
+
|
|
344
|
+
datepicker = new KTDatepicker(element, {
|
|
345
|
+
enableTime: false,
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Select a date
|
|
349
|
+
const date = new Date(2024, 0, 15, 0, 0, 0);
|
|
350
|
+
datepicker.setDate(date);
|
|
351
|
+
|
|
352
|
+
// Verify time remains at midnight (default for date-only)
|
|
353
|
+
const state = datepicker.getState();
|
|
354
|
+
expect(state.selectedDate?.getDate()).toBe(15);
|
|
355
|
+
// Time should be normalized to midnight for date-only mode
|
|
356
|
+
expect(state.selectedDate?.getHours()).toBe(0);
|
|
357
|
+
expect(state.selectedDate?.getMinutes()).toBe(0);
|
|
358
|
+
expect(state.selectedDate?.getSeconds()).toBe(0);
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
describe('Time Utility Functions', () => {
|
|
363
|
+
it('dateToTimeState should extract time correctly', () => {
|
|
364
|
+
const date = new Date(2024, 0, 15, 14, 30, 45);
|
|
365
|
+
const timeState = dateToTimeState(date);
|
|
366
|
+
|
|
367
|
+
expect(timeState.hour).toBe(14);
|
|
368
|
+
expect(timeState.minute).toBe(30);
|
|
369
|
+
expect(timeState.second).toBe(45);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it('applyTimeToDate should preserve date and apply time', () => {
|
|
373
|
+
const date = new Date(2024, 0, 15, 0, 0, 0);
|
|
374
|
+
const timeState = { hour: 16, minute: 45, second: 30 };
|
|
375
|
+
|
|
376
|
+
const result = applyTimeToDate(date, timeState);
|
|
377
|
+
|
|
378
|
+
expect(result.getFullYear()).toBe(2024);
|
|
379
|
+
expect(result.getMonth()).toBe(0);
|
|
380
|
+
expect(result.getDate()).toBe(15);
|
|
381
|
+
expect(result.getHours()).toBe(16);
|
|
382
|
+
expect(result.getMinutes()).toBe(45);
|
|
383
|
+
expect(result.getSeconds()).toBe(30);
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { KTDatepickerConfig } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default configuration for KTDatepicker
|
|
5
|
+
*/
|
|
6
|
+
export const defaultDatepickerConfig: KTDatepickerConfig = {
|
|
7
|
+
templates: {},
|
|
8
|
+
format: 'yyyy-MM-dd',
|
|
9
|
+
range: false,
|
|
10
|
+
multiDate: false,
|
|
11
|
+
minDate: undefined,
|
|
12
|
+
maxDate: undefined,
|
|
13
|
+
disabled: false,
|
|
14
|
+
locale: 'en-US',
|
|
15
|
+
placeholder: '',
|
|
16
|
+
value: undefined,
|
|
17
|
+
valueRange: undefined,
|
|
18
|
+
values: undefined,
|
|
19
|
+
showOnFocus: true,
|
|
20
|
+
closeOnSelect: false, // Default: don't close dropdown by default
|
|
21
|
+
closeOnOutsideClick: true, // Default: close dropdown when clicking outside
|
|
22
|
+
// Number of calendar months to display side-by-side (horizontal). Default: 1.
|
|
23
|
+
visibleMonths: 1,
|
|
24
|
+
// Time-related defaults
|
|
25
|
+
enableTime: false,
|
|
26
|
+
timeGranularity: 'minute',
|
|
27
|
+
timeFormat: '24h',
|
|
28
|
+
minTime: undefined,
|
|
29
|
+
maxTime: undefined,
|
|
30
|
+
timeStep: 1,
|
|
31
|
+
// Dropdown defaults
|
|
32
|
+
dropdownPlacement: 'bottom-end', // Position relative to calendar button (right side)
|
|
33
|
+
dropdownOffset: '0, 5',
|
|
34
|
+
dropdownBoundary: 'clippingParents',
|
|
35
|
+
dropdownWidth: 'auto', // 'auto' for fixed CSS width (20rem), 'toggle' to match input width, or custom string value
|
|
36
|
+
dropdownZindex: undefined,
|
|
37
|
+
dropdownContainer: undefined,
|
|
38
|
+
// Custom classes for template elements
|
|
39
|
+
classes: {},
|
|
40
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* interfaces.ts - Interfaces for KTDatepicker components
|
|
3
|
+
* Defines contracts between components to reduce coupling and improve testability.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { KTDatepickerConfig, KTDatepickerState, KTDatepickerTemplateStrings } from './types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Interface for UI rendering operations
|
|
10
|
+
*/
|
|
11
|
+
export interface IUIRenderer {
|
|
12
|
+
renderContainer(): HTMLElement;
|
|
13
|
+
renderInputWrapper(calendarButtonHtml: string): HTMLElement;
|
|
14
|
+
renderDropdown(): HTMLElement;
|
|
15
|
+
renderDropdownContent(dropdownEl: HTMLElement): void;
|
|
16
|
+
renderCalendarButton(): string;
|
|
17
|
+
updateState(newState: KTDatepickerState): void;
|
|
18
|
+
updateConfig(newConfig: KTDatepickerConfig): void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Interface for state management operations
|
|
23
|
+
*/
|
|
24
|
+
export interface IStateManager {
|
|
25
|
+
isOpen(): boolean;
|
|
26
|
+
isTransitioning(): boolean;
|
|
27
|
+
isDisabled(): boolean;
|
|
28
|
+
open(source?: string): boolean;
|
|
29
|
+
close(source?: string): boolean;
|
|
30
|
+
toggle(source?: string): boolean;
|
|
31
|
+
enable(source?: string): boolean;
|
|
32
|
+
disable(source?: string): boolean;
|
|
33
|
+
setFocus(focused: boolean, source?: string): boolean;
|
|
34
|
+
getState(): any;
|
|
35
|
+
subscribe(observer: (event: any) => void): () => void;
|
|
36
|
+
dispose(): void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Interface for event management operations
|
|
41
|
+
*/
|
|
42
|
+
export interface IEventManager {
|
|
43
|
+
addListener(element: HTMLElement, event: string, handler: (e: Event) => void): void;
|
|
44
|
+
removeListener(element: HTMLElement, event: string, handler: (e: Event) => void): void;
|
|
45
|
+
removeAllListeners(element: HTMLElement): void;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Interface for dropdown positioning operations
|
|
50
|
+
*/
|
|
51
|
+
export interface IDropdownManager {
|
|
52
|
+
open(): void;
|
|
53
|
+
close(): void;
|
|
54
|
+
isOpen(): boolean;
|
|
55
|
+
updatePosition(): void;
|
|
56
|
+
dispose(): void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Interface for date selection operations
|
|
61
|
+
*/
|
|
62
|
+
export interface IDateSelector {
|
|
63
|
+
selectDate(date: Date): void;
|
|
64
|
+
selectRange(start: Date, end: Date): void;
|
|
65
|
+
selectMultipleDates(dates: Date[]): void;
|
|
66
|
+
clearSelection(): void;
|
|
67
|
+
getSelectedDate(): Date | null;
|
|
68
|
+
getSelectedRange(): { start: Date | null; end: Date | null } | null;
|
|
69
|
+
getSelectedDates(): Date[];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Interface for input management operations
|
|
74
|
+
*/
|
|
75
|
+
export interface IInputManager {
|
|
76
|
+
setValue(value: string): void;
|
|
77
|
+
getValue(): string;
|
|
78
|
+
setPlaceholder(placeholder: string): void;
|
|
79
|
+
setDisabled(disabled: boolean): void;
|
|
80
|
+
focus(): void;
|
|
81
|
+
blur(): void;
|
|
82
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* types.ts - Type definitions for KTDatepicker (revamp)
|
|
3
|
+
* Defines config, template, and state interfaces for modular, extensible template customization.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Template keys for all customizable UI fragments
|
|
7
|
+
export type KTDatepickerTemplateKey =
|
|
8
|
+
| 'container'
|
|
9
|
+
| 'header'
|
|
10
|
+
| 'footer'
|
|
11
|
+
| 'calendarGrid'
|
|
12
|
+
| 'dayCell'
|
|
13
|
+
| 'monthYearSelect'
|
|
14
|
+
| 'monthSelection'
|
|
15
|
+
| 'yearSelection'
|
|
16
|
+
| 'inputWrapper'
|
|
17
|
+
| 'segmentedDateInput'
|
|
18
|
+
| 'segmentedDateRangeInput'
|
|
19
|
+
| 'placeholder'
|
|
20
|
+
| 'displayWrapper'
|
|
21
|
+
| 'displayElement'
|
|
22
|
+
| 'timePanel'
|
|
23
|
+
| 'multiDateTag'
|
|
24
|
+
| 'emptyState'
|
|
25
|
+
| 'calendarButton'
|
|
26
|
+
| 'dropdown'
|
|
27
|
+
| 'prevButton'
|
|
28
|
+
| 'nextButton'
|
|
29
|
+
| 'calendarTable'
|
|
30
|
+
| 'calendarRow'
|
|
31
|
+
| 'calendarBody'
|
|
32
|
+
| 'todayButton'
|
|
33
|
+
| 'clearButton'
|
|
34
|
+
| 'applyButton'
|
|
35
|
+
| 'multiMonthContainer'
|
|
36
|
+
| 'dateSegment'
|
|
37
|
+
| 'segmentSeparator'
|
|
38
|
+
| 'timePickerWrapper'
|
|
39
|
+
| 'timeDisplay'
|
|
40
|
+
| 'timeControls'
|
|
41
|
+
| 'timeUnit'
|
|
42
|
+
| 'timeUpButton'
|
|
43
|
+
| 'timeDownButton'
|
|
44
|
+
| 'timeValue'
|
|
45
|
+
| 'timeSeparator'
|
|
46
|
+
| 'ampmControl'
|
|
47
|
+
| 'ampmButton'
|
|
48
|
+
| 'panel'
|
|
49
|
+
| 'liveRegion'
|
|
50
|
+
| 'rangeStartContainer'
|
|
51
|
+
| 'rangeEndContainer';
|
|
52
|
+
|
|
53
|
+
// Template string map
|
|
54
|
+
export type KTDatepickerTemplateStrings = {
|
|
55
|
+
[K in KTDatepickerTemplateKey]?: string | ((data: any) => string);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Configuration options for KTDatepicker
|
|
60
|
+
*/
|
|
61
|
+
export interface KTDatepickerConfig {
|
|
62
|
+
/** Custom templates for UI fragments */
|
|
63
|
+
templates?: KTDatepickerTemplateStrings;
|
|
64
|
+
/** Date format string (e.g. 'yyyy-mm-dd', 'dd/mm/yyyy') */
|
|
65
|
+
format?: string;
|
|
66
|
+
/** Enable date range selection */
|
|
67
|
+
range?: boolean;
|
|
68
|
+
/** Enable multi-date selection */
|
|
69
|
+
multiDate?: boolean;
|
|
70
|
+
/** Minimum selectable date */
|
|
71
|
+
minDate?: Date | string;
|
|
72
|
+
/** Maximum selectable date */
|
|
73
|
+
maxDate?: Date | string;
|
|
74
|
+
/** Disable the datepicker */
|
|
75
|
+
disabled?: boolean;
|
|
76
|
+
/** Locale for date formatting (e.g. 'en-US') */
|
|
77
|
+
locale?: string;
|
|
78
|
+
/** Placeholder text for the input */
|
|
79
|
+
placeholder?: string;
|
|
80
|
+
/** Initial selected date */
|
|
81
|
+
value?: Date | string;
|
|
82
|
+
/** Initial selected date range */
|
|
83
|
+
valueRange?: { start: Date | string; end: Date | string };
|
|
84
|
+
/** Initial selected dates (multi-date) */
|
|
85
|
+
values?: (Date | string)[];
|
|
86
|
+
/** Custom class for the root element */
|
|
87
|
+
className?: string;
|
|
88
|
+
/** Whether to show the calendar on input focus (default: true) */
|
|
89
|
+
showOnFocus?: boolean;
|
|
90
|
+
/** Whether to close the calendar on date selection (default: true) */
|
|
91
|
+
closeOnSelect?: boolean;
|
|
92
|
+
/** Whether to close the calendar when clicking outside (default: true) */
|
|
93
|
+
closeOnOutsideClick?: boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Number of calendar months to display side-by-side (horizontal). Default: 1.
|
|
96
|
+
*/
|
|
97
|
+
visibleMonths?: number;
|
|
98
|
+
/** Enable time selection (default: false) */
|
|
99
|
+
enableTime?: boolean;
|
|
100
|
+
/** Time granularity - smallest unit to display (default: 'minute') */
|
|
101
|
+
timeGranularity?: 'second' | 'minute' | 'hour';
|
|
102
|
+
/** Time format - 12 or 24 hour (default: '24h') */
|
|
103
|
+
timeFormat?: '12h' | '24h';
|
|
104
|
+
/** Minimum time constraint (format: 'HH:MM' or 'HH:MM:SS') */
|
|
105
|
+
minTime?: string;
|
|
106
|
+
/** Maximum time constraint (format: 'HH:MM' or 'HH:MM:SS') */
|
|
107
|
+
maxTime?: string;
|
|
108
|
+
/** Time step increment in minutes (default: 1) */
|
|
109
|
+
timeStep?: number;
|
|
110
|
+
/** Dropdown positioning and behavior options */
|
|
111
|
+
dropdownPlacement?: string;
|
|
112
|
+
dropdownOffset?: string;
|
|
113
|
+
dropdownBoundary?: string;
|
|
114
|
+
dropdownWidth?: 'auto' | 'toggle' | string;
|
|
115
|
+
dropdownZindex?: number;
|
|
116
|
+
dropdownContainer?: string;
|
|
117
|
+
/** Custom classes for template elements */
|
|
118
|
+
classes?: {
|
|
119
|
+
container?: string;
|
|
120
|
+
header?: string;
|
|
121
|
+
footer?: string;
|
|
122
|
+
calendarGrid?: string;
|
|
123
|
+
dayCell?: string;
|
|
124
|
+
monthYearSelect?: string;
|
|
125
|
+
monthSelection?: string;
|
|
126
|
+
yearSelection?: string;
|
|
127
|
+
inputWrapper?: string;
|
|
128
|
+
segmentedDateInput?: string;
|
|
129
|
+
segmentedDateRangeInput?: string;
|
|
130
|
+
dateSegment?: string;
|
|
131
|
+
segmentSeparator?: string;
|
|
132
|
+
placeholder?: string;
|
|
133
|
+
displayWrapper?: string;
|
|
134
|
+
displayElement?: string;
|
|
135
|
+
timePanel?: string;
|
|
136
|
+
multiDateTag?: string;
|
|
137
|
+
emptyState?: string;
|
|
138
|
+
calendarButton?: string;
|
|
139
|
+
dropdown?: string;
|
|
140
|
+
prevButton?: string;
|
|
141
|
+
nextButton?: string;
|
|
142
|
+
calendarTable?: string;
|
|
143
|
+
calendarRow?: string;
|
|
144
|
+
calendarBody?: string;
|
|
145
|
+
todayButton?: string;
|
|
146
|
+
clearButton?: string;
|
|
147
|
+
applyButton?: string;
|
|
148
|
+
multiMonthContainer?: string;
|
|
149
|
+
};
|
|
150
|
+
/** Any additional custom config options */
|
|
151
|
+
[key: string]: any;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Time state interface
|
|
155
|
+
export interface TimeState {
|
|
156
|
+
hour: number;
|
|
157
|
+
minute: number;
|
|
158
|
+
second: number;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// State interface for KTDatepicker
|
|
162
|
+
/**
|
|
163
|
+
* Dropdown state interface
|
|
164
|
+
*/
|
|
165
|
+
export interface DropdownState {
|
|
166
|
+
isOpen: boolean;
|
|
167
|
+
isTransitioning: boolean;
|
|
168
|
+
isDisabled: boolean;
|
|
169
|
+
isFocused: boolean;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export interface KTDatepickerState {
|
|
173
|
+
currentDate: Date;
|
|
174
|
+
selectedDate: Date | null;
|
|
175
|
+
selectedRange: { start: Date | null; end: Date | null } | null;
|
|
176
|
+
selectedDates: Date[];
|
|
177
|
+
selectedTime: TimeState | null;
|
|
178
|
+
timeGranularity: 'second' | 'minute' | 'hour';
|
|
179
|
+
viewMode: 'days' | 'months' | 'years';
|
|
180
|
+
isOpen: boolean;
|
|
181
|
+
isFocused: boolean;
|
|
182
|
+
isTransitioning: boolean;
|
|
183
|
+
isDisabled: boolean;
|
|
184
|
+
validationErrors: string[];
|
|
185
|
+
isValid: boolean;
|
|
186
|
+
// Dropdown state (consolidated from legacy state manager)
|
|
187
|
+
dropdownState: DropdownState;
|
|
188
|
+
}
|