@keenthemes/ktui 1.1.0 → 1.1.2
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 +5269 -12550
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +1133 -2706
- 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/components/select/combobox.js +0 -2
- package/lib/cjs/components/select/combobox.js.map +1 -1
- package/lib/cjs/components/select/config.js +4 -1
- package/lib/cjs/components/select/config.js.map +1 -1
- package/lib/cjs/components/select/dropdown.js +0 -16
- package/lib/cjs/components/select/dropdown.js.map +1 -1
- package/lib/cjs/components/select/remote.js +0 -40
- package/lib/cjs/components/select/remote.js.map +1 -1
- package/lib/cjs/components/select/search.js +80 -19
- package/lib/cjs/components/select/search.js.map +1 -1
- package/lib/cjs/components/select/select.js +98 -110
- package/lib/cjs/components/select/select.js.map +1 -1
- package/lib/cjs/components/select/tags.js +0 -2
- package/lib/cjs/components/select/tags.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/components/select/combobox.js +0 -2
- package/lib/esm/components/select/combobox.js.map +1 -1
- package/lib/esm/components/select/config.js +4 -1
- package/lib/esm/components/select/config.js.map +1 -1
- package/lib/esm/components/select/dropdown.js +0 -16
- package/lib/esm/components/select/dropdown.js.map +1 -1
- package/lib/esm/components/select/remote.js +0 -40
- package/lib/esm/components/select/remote.js.map +1 -1
- package/lib/esm/components/select/search.js +80 -19
- package/lib/esm/components/select/search.js.map +1 -1
- package/lib/esm/components/select/select.js +98 -110
- package/lib/esm/components/select/select.js.map +1 -1
- package/lib/esm/components/select/tags.js +0 -2
- package/lib/esm/components/select/tags.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/__tests__/ux-behaviors.test.ts +619 -0
- package/src/components/select/combobox.ts +0 -1
- package/src/components/select/config.ts +7 -1
- package/src/components/select/dropdown.ts +0 -24
- package/src/components/select/remote.ts +0 -49
- package/src/components/select/search.ts +85 -21
- package/src/components/select/select.css +0 -1
- package/src/components/select/select.ts +118 -149
- package/src/components/select/tags.ts +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,159 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* event-manager.ts - Internal event management for KTDatepicker
|
|
3
|
-
* Replaces external dependency on select component's EventManager
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Event listener function type
|
|
8
|
-
*/
|
|
9
|
-
export type EventListener = (event: Event) => void;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Event manager configuration
|
|
13
|
-
*/
|
|
14
|
-
export interface EventManagerConfig {
|
|
15
|
-
enableEventBubbling: boolean;
|
|
16
|
-
enableCustomEvents: boolean;
|
|
17
|
-
enableValidation: boolean;
|
|
18
|
-
enableDebugging: boolean;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Event manager for handling DOM events
|
|
23
|
-
*/
|
|
24
|
-
export class EventManager {
|
|
25
|
-
// Alias for backward compatibility
|
|
26
|
-
static KTDropdownEventManager = EventManager;
|
|
27
|
-
private _listeners: Map<HTMLElement, Map<string, Set<EventListener>>> = new Map();
|
|
28
|
-
private _config: EventManagerConfig;
|
|
29
|
-
|
|
30
|
-
constructor(config?: Partial<EventManagerConfig>) {
|
|
31
|
-
this._config = {
|
|
32
|
-
enableEventBubbling: true,
|
|
33
|
-
enableCustomEvents: false,
|
|
34
|
-
enableValidation: true,
|
|
35
|
-
enableDebugging: false,
|
|
36
|
-
...config
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Add event listener to element
|
|
42
|
-
*/
|
|
43
|
-
public addListener(element: HTMLElement, eventType: string, listener: EventListener): void {
|
|
44
|
-
if (!this._listeners.has(element)) {
|
|
45
|
-
this._listeners.set(element, new Map());
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const elementListeners = this._listeners.get(element)!;
|
|
49
|
-
if (!elementListeners.has(eventType)) {
|
|
50
|
-
elementListeners.set(eventType, new Set());
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const listeners = elementListeners.get(eventType)!;
|
|
54
|
-
listeners.add(listener);
|
|
55
|
-
|
|
56
|
-
element.addEventListener(eventType, listener, !this._config.enableEventBubbling);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Remove event listener from element
|
|
61
|
-
*/
|
|
62
|
-
public removeListener(element: HTMLElement, eventType: string, listener: EventListener): void {
|
|
63
|
-
const elementListeners = this._listeners.get(element);
|
|
64
|
-
if (!elementListeners) return;
|
|
65
|
-
|
|
66
|
-
const listeners = elementListeners.get(eventType);
|
|
67
|
-
if (!listeners) return;
|
|
68
|
-
|
|
69
|
-
listeners.delete(listener);
|
|
70
|
-
element.removeEventListener(eventType, listener, !this._config.enableEventBubbling);
|
|
71
|
-
|
|
72
|
-
if (listeners.size === 0) {
|
|
73
|
-
elementListeners.delete(eventType);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (elementListeners.size === 0) {
|
|
77
|
-
this._listeners.delete(element);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Remove all listeners from element
|
|
83
|
-
*/
|
|
84
|
-
public removeAllListeners(element: HTMLElement): void {
|
|
85
|
-
const elementListeners = this._listeners.get(element);
|
|
86
|
-
if (!elementListeners) return;
|
|
87
|
-
|
|
88
|
-
elementListeners.forEach((listeners, eventType) => {
|
|
89
|
-
listeners.forEach(listener => {
|
|
90
|
-
element.removeEventListener(eventType, listener, !this._config.enableEventBubbling);
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
this._listeners.delete(element);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Remove all listeners from all elements
|
|
99
|
-
*/
|
|
100
|
-
public removeAllListenersFromAll(): void {
|
|
101
|
-
this._listeners.forEach((elementListeners, element) => {
|
|
102
|
-
elementListeners.forEach((listeners, eventType) => {
|
|
103
|
-
listeners.forEach(listener => {
|
|
104
|
-
element.removeEventListener(eventType, listener, !this._config.enableEventBubbling);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
this._listeners.clear();
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Dispatch custom event
|
|
114
|
-
*/
|
|
115
|
-
public dispatchEvent(element: HTMLElement, eventType: string, detail?: any): boolean {
|
|
116
|
-
if (!this._config.enableCustomEvents) {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const event = new CustomEvent(eventType, {
|
|
121
|
-
detail,
|
|
122
|
-
bubbles: this._config.enableEventBubbling,
|
|
123
|
-
cancelable: true
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
const result = element.dispatchEvent(event);
|
|
127
|
-
|
|
128
|
-
return result;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Get listener count for element and event type
|
|
133
|
-
*/
|
|
134
|
-
public getListenerCount(element: HTMLElement, eventType?: string): number {
|
|
135
|
-
const elementListeners = this._listeners.get(element);
|
|
136
|
-
if (!elementListeners) return 0;
|
|
137
|
-
|
|
138
|
-
if (eventType) {
|
|
139
|
-
return elementListeners.get(eventType)?.size || 0;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
let total = 0;
|
|
143
|
-
elementListeners.forEach(listeners => {
|
|
144
|
-
total += listeners.size;
|
|
145
|
-
});
|
|
146
|
-
return total;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Dispose of event manager
|
|
151
|
-
*/
|
|
152
|
-
public dispose(): void {
|
|
153
|
-
this.removeAllListenersFromAll();
|
|
154
|
-
this._listeners.clear();
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Export alias for backward compatibility
|
|
159
|
-
export { EventManager as KTDropdownEventManager };
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* focus-manager.ts - Internal focus management for KTDatepicker
|
|
3
|
-
* Replaces external dependency on select component's FocusManager
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Focus manager configuration
|
|
8
|
-
*/
|
|
9
|
-
export interface FocusManagerConfig {
|
|
10
|
-
enableFocusTrapping: boolean;
|
|
11
|
-
enableFocusRestoration: boolean;
|
|
12
|
-
enableKeyboardNavigation: boolean;
|
|
13
|
-
enableDebugging: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Focusable element interface
|
|
18
|
-
*/
|
|
19
|
-
export interface FocusableElement {
|
|
20
|
-
element: HTMLElement;
|
|
21
|
-
tabIndex: number;
|
|
22
|
-
isFocusable: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Focus manager for handling focus states and navigation
|
|
27
|
-
*/
|
|
28
|
-
export class FocusManager {
|
|
29
|
-
private _config: FocusManagerConfig;
|
|
30
|
-
private _focusedElement: HTMLElement | null = null;
|
|
31
|
-
private _previousFocusedElement: HTMLElement | null = null;
|
|
32
|
-
private _focusableElements: FocusableElement[] = [];
|
|
33
|
-
private _currentFocusIndex: number = -1;
|
|
34
|
-
|
|
35
|
-
constructor(config?: Partial<FocusManagerConfig>) {
|
|
36
|
-
this._config = {
|
|
37
|
-
enableFocusTrapping: true,
|
|
38
|
-
enableFocusRestoration: true,
|
|
39
|
-
enableKeyboardNavigation: true,
|
|
40
|
-
enableDebugging: false,
|
|
41
|
-
...config
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Set focus to element
|
|
47
|
-
*/
|
|
48
|
-
public focus(element: HTMLElement): boolean {
|
|
49
|
-
if (!element || !this._isElementFocusable(element)) {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
this._previousFocusedElement = this._focusedElement;
|
|
54
|
-
this._focusedElement = element;
|
|
55
|
-
|
|
56
|
-
try {
|
|
57
|
-
element.focus();
|
|
58
|
-
return true;
|
|
59
|
-
} catch (error) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Get currently focused element
|
|
66
|
-
*/
|
|
67
|
-
public getFocusedElement(): HTMLElement | null {
|
|
68
|
-
return this._focusedElement;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Get previously focused element
|
|
73
|
-
*/
|
|
74
|
-
public getPreviousFocusedElement(): HTMLElement | null {
|
|
75
|
-
return this._previousFocusedElement;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Restore focus to previous element
|
|
80
|
-
*/
|
|
81
|
-
public restoreFocus(): boolean {
|
|
82
|
-
if (!this._config.enableFocusRestoration || !this._previousFocusedElement) {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return this.focus(this._previousFocusedElement);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Set focusable elements for navigation
|
|
91
|
-
*/
|
|
92
|
-
public setFocusableElements(elements: HTMLElement[]): void {
|
|
93
|
-
this._focusableElements = elements
|
|
94
|
-
.filter(element => this._isElementFocusable(element))
|
|
95
|
-
.map(element => ({
|
|
96
|
-
element,
|
|
97
|
-
tabIndex: this._getTabIndex(element),
|
|
98
|
-
isFocusable: true
|
|
99
|
-
}))
|
|
100
|
-
.sort((a, b) => a.tabIndex - b.tabIndex);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Focus next element
|
|
105
|
-
*/
|
|
106
|
-
public focusNext(): boolean {
|
|
107
|
-
if (!this._config.enableKeyboardNavigation || this._focusableElements.length === 0) {
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
this._currentFocusIndex = (this._currentFocusIndex + 1) % this._focusableElements.length;
|
|
112
|
-
const nextElement = this._focusableElements[this._currentFocusIndex];
|
|
113
|
-
|
|
114
|
-
return this.focus(nextElement.element);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Focus previous element
|
|
119
|
-
*/
|
|
120
|
-
public focusPrevious(): boolean {
|
|
121
|
-
if (!this._config.enableKeyboardNavigation || this._focusableElements.length === 0) {
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
this._currentFocusIndex = this._currentFocusIndex <= 0
|
|
126
|
-
? this._focusableElements.length - 1
|
|
127
|
-
: this._currentFocusIndex - 1;
|
|
128
|
-
|
|
129
|
-
const prevElement = this._focusableElements[this._currentFocusIndex];
|
|
130
|
-
|
|
131
|
-
return this.focus(prevElement.element);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Focus first element
|
|
136
|
-
*/
|
|
137
|
-
public focusFirst(): boolean {
|
|
138
|
-
if (this._focusableElements.length === 0) {
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
this._currentFocusIndex = 0;
|
|
143
|
-
return this.focus(this._focusableElements[0].element);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Focus last element
|
|
148
|
-
*/
|
|
149
|
-
public focusLast(): boolean {
|
|
150
|
-
if (this._focusableElements.length === 0) {
|
|
151
|
-
return false;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
this._currentFocusIndex = this._focusableElements.length - 1;
|
|
155
|
-
return this.focus(this._focusableElements[this._currentFocusIndex].element);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Check if element is focusable
|
|
160
|
-
*/
|
|
161
|
-
private _isElementFocusable(element: HTMLElement): boolean {
|
|
162
|
-
if (!element || element.hidden || element.style.display === 'none') {
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const tabIndex = this._getTabIndex(element);
|
|
167
|
-
return tabIndex >= 0;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Get tab index of element
|
|
172
|
-
*/
|
|
173
|
-
private _getTabIndex(element: HTMLElement): number {
|
|
174
|
-
const tabIndex = element.getAttribute('tabindex');
|
|
175
|
-
if (tabIndex === null) {
|
|
176
|
-
// Check if element is naturally focusable
|
|
177
|
-
const tagName = element.tagName.toLowerCase();
|
|
178
|
-
const naturallyFocusable = ['input', 'button', 'select', 'textarea', 'a'].includes(tagName);
|
|
179
|
-
return naturallyFocusable ? 0 : -1;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
return parseInt(tabIndex, 10);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Clear focus
|
|
187
|
-
*/
|
|
188
|
-
public clearFocus(): void {
|
|
189
|
-
this._focusedElement = null;
|
|
190
|
-
this._currentFocusIndex = -1;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Dispose of focus manager
|
|
195
|
-
*/
|
|
196
|
-
public dispose(): void {
|
|
197
|
-
this.clearFocus();
|
|
198
|
-
this._focusableElements = [];
|
|
199
|
-
this._previousFocusedElement = null;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* datepicker-helpers.ts - Modular helpers for KTDatepicker input rendering and state
|
|
3
|
-
*/
|
|
4
|
-
import { KTDatepickerConfig, KTDatepickerState } from '../config/types';
|
|
5
|
-
import { renderTemplateToDOM, createTemplateRenderer, getTemplateStrings } from '../ui/templates/templates';
|
|
6
|
-
import { SegmentedInput } from '../ui/input/segmented-input';
|
|
7
|
-
import { getTimeSegments } from '../utils/time-utils';
|
|
8
|
-
import { getSegmentOrderFromFormat, normalizeDateToLocalMidnight } from '../utils/date-utils';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Get segments array based on configuration (date + optional time)
|
|
12
|
-
* @param config Datepicker configuration
|
|
13
|
-
* @returns Array of segment types
|
|
14
|
-
*/
|
|
15
|
-
export function getSegmentsForConfig(config: KTDatepickerConfig): Array<'day' | 'month' | 'year' | 'hour' | 'minute' | 'second' | 'ampm'> {
|
|
16
|
-
// Determine date segments based on format
|
|
17
|
-
let segments: Array<'day' | 'month' | 'year' | 'hour' | 'minute' | 'second' | 'ampm'>;
|
|
18
|
-
|
|
19
|
-
if (config.format && typeof config.format === 'string') {
|
|
20
|
-
// Use format-derived segment order for date parts
|
|
21
|
-
segments = getSegmentOrderFromFormat(config.format);
|
|
22
|
-
} else {
|
|
23
|
-
// Default fallback
|
|
24
|
-
segments = ['month', 'day', 'year'];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Add time segments if time is enabled
|
|
28
|
-
if (config.enableTime) {
|
|
29
|
-
const timeSegments = getTimeSegments(config.timeGranularity || 'minute');
|
|
30
|
-
segments = [...segments, ...timeSegments];
|
|
31
|
-
|
|
32
|
-
// Add AM/PM for 12-hour format
|
|
33
|
-
if (config.timeFormat === '12h') {
|
|
34
|
-
segments.push('ampm');
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return segments;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export {};
|
|
42
|
-
|
|
43
|
-
export function renderSingleSegmentedInputUI(
|
|
44
|
-
inputWrapperTpl: string | ((data: any) => string),
|
|
45
|
-
calendarButtonHtml: string,
|
|
46
|
-
config?: KTDatepickerConfig
|
|
47
|
-
): HTMLElement {
|
|
48
|
-
// Get template renderer with proper configuration
|
|
49
|
-
const templates = getTemplateStrings(config);
|
|
50
|
-
const templateRenderer = createTemplateRenderer(templates);
|
|
51
|
-
|
|
52
|
-
// Create the segmented input container using the template system
|
|
53
|
-
const segmentedInputEl = templateRenderer.renderTemplateToElement({
|
|
54
|
-
templateKey: 'segmentedDateInput',
|
|
55
|
-
data: { segments: '' }, // Empty segments initially, will be populated by SegmentedInput
|
|
56
|
-
configClasses: config?.classes // Pass config classes for proper styling
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
let inputWrapperHtml: string;
|
|
60
|
-
if (typeof inputWrapperTpl === 'function') {
|
|
61
|
-
inputWrapperHtml = inputWrapperTpl({ input: segmentedInputEl.outerHTML, icon: calendarButtonHtml, class: '' });
|
|
62
|
-
} else {
|
|
63
|
-
inputWrapperHtml = inputWrapperTpl
|
|
64
|
-
.replace(/{{icon}}/g, calendarButtonHtml)
|
|
65
|
-
.replace(/{{input}}/g, segmentedInputEl.outerHTML)
|
|
66
|
-
.replace(/{{class}}/g, ''); // Replace class placeholder with empty string if no class provided
|
|
67
|
-
}
|
|
68
|
-
const inputWrapperFrag = renderTemplateToDOM(inputWrapperHtml);
|
|
69
|
-
return inputWrapperFrag.firstElementChild as HTMLElement;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function renderRangeSegmentedInputUI(
|
|
73
|
-
inputWrapperTpl: string | ((data: any) => string),
|
|
74
|
-
rangeTpl: string | ((data: any) => string),
|
|
75
|
-
calendarButtonHtml: string,
|
|
76
|
-
config?: KTDatepickerConfig
|
|
77
|
-
): { inputWrapperEl: HTMLElement; startContainer: HTMLElement; endContainer: HTMLElement } {
|
|
78
|
-
// Get template renderer with proper configuration
|
|
79
|
-
const templates = getTemplateStrings(config);
|
|
80
|
-
const templateRenderer = createTemplateRenderer(templates);
|
|
81
|
-
|
|
82
|
-
let inputWrapperHtml: string;
|
|
83
|
-
if (typeof inputWrapperTpl === 'function') {
|
|
84
|
-
inputWrapperHtml = inputWrapperTpl({ input: '', icon: calendarButtonHtml, class: '' });
|
|
85
|
-
} else {
|
|
86
|
-
inputWrapperHtml = inputWrapperTpl
|
|
87
|
-
.replace(/{{icon}}/g, calendarButtonHtml)
|
|
88
|
-
.replace(/{{input}}/g, '')
|
|
89
|
-
.replace(/{{class}}/g, ''); // Replace class placeholder with empty string if no class provided
|
|
90
|
-
}
|
|
91
|
-
const inputWrapperFrag = renderTemplateToDOM(inputWrapperHtml);
|
|
92
|
-
const inputWrapperEl = inputWrapperFrag.firstElementChild as HTMLElement;
|
|
93
|
-
|
|
94
|
-
// Create containers for start and end segmented inputs using template system
|
|
95
|
-
const startContainer = templateRenderer.renderTemplateToElement({
|
|
96
|
-
templateKey: 'segmentedDateInput',
|
|
97
|
-
data: { segments: '' },
|
|
98
|
-
configClasses: { ...config?.classes, segmentedDateInput: 'kt-segmented-input-start' }
|
|
99
|
-
});
|
|
100
|
-
startContainer.setAttribute('aria-label', 'Start date');
|
|
101
|
-
startContainer.setAttribute('data-kt-datepicker-start-container', '');
|
|
102
|
-
|
|
103
|
-
const endContainer = templateRenderer.renderTemplateToElement({
|
|
104
|
-
templateKey: 'segmentedDateInput',
|
|
105
|
-
data: { segments: '' },
|
|
106
|
-
configClasses: { ...config?.classes, segmentedDateInput: 'kt-segmented-input-end' }
|
|
107
|
-
});
|
|
108
|
-
endContainer.setAttribute('aria-label', 'End date');
|
|
109
|
-
endContainer.setAttribute('data-kt-datepicker-end-container', '');
|
|
110
|
-
// Render template with placeholders using template system
|
|
111
|
-
const separator = '–';
|
|
112
|
-
|
|
113
|
-
// Render start and end containers using templates
|
|
114
|
-
const startContainerHtml = templateRenderer.renderTemplateString({
|
|
115
|
-
templateKey: 'rangeStartContainer',
|
|
116
|
-
data: {},
|
|
117
|
-
configClasses: config?.classes
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const endContainerHtml = templateRenderer.renderTemplateString({
|
|
121
|
-
templateKey: 'rangeEndContainer',
|
|
122
|
-
data: {},
|
|
123
|
-
configClasses: config?.classes
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
let rangeHtml: string;
|
|
127
|
-
if (typeof rangeTpl === 'function') {
|
|
128
|
-
rangeHtml = rangeTpl({
|
|
129
|
-
start: startContainerHtml,
|
|
130
|
-
separator,
|
|
131
|
-
end: endContainerHtml,
|
|
132
|
-
class: ''
|
|
133
|
-
});
|
|
134
|
-
} else {
|
|
135
|
-
rangeHtml = rangeTpl
|
|
136
|
-
.replace(/{{start}}/g, startContainerHtml)
|
|
137
|
-
.replace(/{{separator}}/g, separator)
|
|
138
|
-
.replace(/{{end}}/g, endContainerHtml)
|
|
139
|
-
.replace(/{{class}}/g, ''); // Replace class placeholder with empty string if no class provided
|
|
140
|
-
}
|
|
141
|
-
const rangeFrag = renderTemplateToDOM(rangeHtml);
|
|
142
|
-
// Find mount points
|
|
143
|
-
const startMount = rangeFrag.querySelector('[data-kt-datepicker-segmented-start]') as HTMLElement;
|
|
144
|
-
const endMount = rangeFrag.querySelector('[data-kt-datepicker-segmented-end]') as HTMLElement;
|
|
145
|
-
if (startMount) startMount.replaceWith(startContainer);
|
|
146
|
-
if (endMount) endMount.replaceWith(endContainer);
|
|
147
|
-
// Insert the range input UI at the start of the wrapper
|
|
148
|
-
inputWrapperEl.insertBefore(rangeFrag.firstElementChild!, inputWrapperEl.firstChild);
|
|
149
|
-
return { inputWrapperEl, startContainer, endContainer };
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export function instantiateSingleSegmentedInput(
|
|
153
|
-
container: HTMLElement,
|
|
154
|
-
state: KTDatepickerState,
|
|
155
|
-
config: KTDatepickerConfig,
|
|
156
|
-
onChange: (date: Date) => void
|
|
157
|
-
): void {
|
|
158
|
-
// Use shared utility to determine segments
|
|
159
|
-
const segments = getSegmentsForConfig(config);
|
|
160
|
-
|
|
161
|
-
SegmentedInput(container, {
|
|
162
|
-
value: state.selectedDate || state.currentDate || new Date(),
|
|
163
|
-
format: config.format,
|
|
164
|
-
segments,
|
|
165
|
-
disabled: !!config.disabled,
|
|
166
|
-
required: !!config.required,
|
|
167
|
-
readOnly: !!config.readOnly,
|
|
168
|
-
locale: config.locale,
|
|
169
|
-
timeFormat: config.timeFormat,
|
|
170
|
-
onChange,
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export function instantiateRangeSegmentedInputs(
|
|
175
|
-
startContainer: HTMLElement,
|
|
176
|
-
endContainer: HTMLElement,
|
|
177
|
-
state: KTDatepickerState,
|
|
178
|
-
config: KTDatepickerConfig,
|
|
179
|
-
onStartChange: (date: Date) => void,
|
|
180
|
-
onEndChange: (date: Date) => void
|
|
181
|
-
): void {
|
|
182
|
-
// Use shared utility to determine segments (includes time if enabled)
|
|
183
|
-
const segments = getSegmentsForConfig(config);
|
|
184
|
-
|
|
185
|
-
SegmentedInput(startContainer, {
|
|
186
|
-
value: state.selectedRange?.start || new Date(),
|
|
187
|
-
format: config.format,
|
|
188
|
-
segments,
|
|
189
|
-
disabled: !!config.disabled,
|
|
190
|
-
required: !!config.required,
|
|
191
|
-
readOnly: !!config.readOnly,
|
|
192
|
-
locale: config.locale,
|
|
193
|
-
timeFormat: config.timeFormat,
|
|
194
|
-
onChange: onStartChange,
|
|
195
|
-
});
|
|
196
|
-
SegmentedInput(endContainer, {
|
|
197
|
-
value: state.selectedRange?.end || new Date(),
|
|
198
|
-
format: config.format,
|
|
199
|
-
segments,
|
|
200
|
-
disabled: !!config.disabled,
|
|
201
|
-
required: !!config.required,
|
|
202
|
-
readOnly: !!config.readOnly,
|
|
203
|
-
locale: config.locale,
|
|
204
|
-
timeFormat: config.timeFormat,
|
|
205
|
-
onChange: onEndChange,
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export function updateRangeSelection(
|
|
210
|
-
selectedRange: { start: Date | null; end: Date | null } | null,
|
|
211
|
-
date: Date
|
|
212
|
-
): { start: Date | null; end: Date | null } {
|
|
213
|
-
// Normalize dates to local midnight for date-only comparisons
|
|
214
|
-
const normalizedDate = normalizeDateToLocalMidnight(date);
|
|
215
|
-
|
|
216
|
-
if (!selectedRange || (!selectedRange.start && !selectedRange.end)) {
|
|
217
|
-
return { start: normalizedDate, end: null };
|
|
218
|
-
} else if (selectedRange.start && !selectedRange.end) {
|
|
219
|
-
const normalizedStart = normalizeDateToLocalMidnight(selectedRange.start);
|
|
220
|
-
if (normalizedDate >= normalizedStart) {
|
|
221
|
-
// Forward selection: new date is after start, becomes end
|
|
222
|
-
return { start: selectedRange.start, end: normalizedDate };
|
|
223
|
-
} else {
|
|
224
|
-
// Backward selection: new date is before start, swap so start is always earlier
|
|
225
|
-
// The clicked date becomes the actual start, original start becomes end
|
|
226
|
-
return { start: normalizedDate, end: selectedRange.start };
|
|
227
|
-
}
|
|
228
|
-
} else {
|
|
229
|
-
return { start: normalizedDate, end: null };
|
|
230
|
-
}
|
|
231
|
-
}
|