@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,459 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* unified-state-manager.ts - Centralized state management for KTDatepicker
|
|
3
|
-
* Provides single source of truth for all datepicker state with observer pattern
|
|
4
|
-
* for automatic UI synchronization across all components.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { KTDatepickerState, TimeState, DropdownState } from '../config/types';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* State observer interface for UI components
|
|
11
|
-
*/
|
|
12
|
-
export interface StateObserver {
|
|
13
|
-
onStateChange(newState: KTDatepickerState, oldState: KTDatepickerState): void;
|
|
14
|
-
getUpdatePriority(): number; // For update ordering (lower = higher priority)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* State validation result
|
|
19
|
-
*/
|
|
20
|
-
export interface ValidationResult {
|
|
21
|
-
isValid: boolean;
|
|
22
|
-
errors: string[];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* State manager configuration
|
|
27
|
-
*/
|
|
28
|
-
export interface StateManagerConfig {
|
|
29
|
-
enableValidation: boolean;
|
|
30
|
-
enableDebugging: boolean;
|
|
31
|
-
enableUpdateBatching: boolean;
|
|
32
|
-
batchDelay: number; // milliseconds
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* State change event
|
|
37
|
-
*/
|
|
38
|
-
export interface StateChangeEvent {
|
|
39
|
-
oldState: KTDatepickerState;
|
|
40
|
-
newState: KTDatepickerState;
|
|
41
|
-
source: string;
|
|
42
|
-
timestamp: number;
|
|
43
|
-
changes: Partial<KTDatepickerState>;
|
|
44
|
-
changedProperties: Set<string>; // Set of property keys that actually changed
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* KTDatepickerUnifiedStateManager
|
|
49
|
-
*
|
|
50
|
-
* Centralized state management for datepicker with observer pattern.
|
|
51
|
-
* Ensures all UI components automatically sync to state changes.
|
|
52
|
-
*
|
|
53
|
-
* Immediate vs Batched Updates:
|
|
54
|
-
* - Immediate updates: Use for user interactions requiring synchronous event firing
|
|
55
|
-
* (date selection, dropdown open/close). These bypass batching delays.
|
|
56
|
-
* - Batched updates: Use for programmatic changes that don't require immediate
|
|
57
|
-
* user feedback (navigation, initialization). These are batched for performance.
|
|
58
|
-
*/
|
|
59
|
-
export class KTDatepickerUnifiedStateManager {
|
|
60
|
-
private _state: KTDatepickerState;
|
|
61
|
-
private _observers: Set<StateObserver> = new Set();
|
|
62
|
-
private _config: StateManagerConfig;
|
|
63
|
-
private _batchTimeout: number | null = null;
|
|
64
|
-
private _pendingUpdates: Partial<KTDatepickerState> = {};
|
|
65
|
-
private _isUpdating = false;
|
|
66
|
-
private _lastUpdateSource: string = 'unknown';
|
|
67
|
-
private _lastChangedProperties: Set<string> = new Set();
|
|
68
|
-
|
|
69
|
-
constructor(config?: Partial<StateManagerConfig>) {
|
|
70
|
-
this._config = {
|
|
71
|
-
enableValidation: true,
|
|
72
|
-
enableDebugging: false,
|
|
73
|
-
enableUpdateBatching: true,
|
|
74
|
-
batchDelay: 16, // ~60fps
|
|
75
|
-
...config
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
this._state = this._getInitialState();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Get initial state
|
|
83
|
-
*/
|
|
84
|
-
private _getInitialState(): KTDatepickerState {
|
|
85
|
-
return {
|
|
86
|
-
currentDate: new Date(),
|
|
87
|
-
selectedDate: null,
|
|
88
|
-
selectedRange: null,
|
|
89
|
-
selectedDates: [],
|
|
90
|
-
selectedTime: null,
|
|
91
|
-
timeGranularity: 'minute',
|
|
92
|
-
viewMode: 'days',
|
|
93
|
-
isOpen: false,
|
|
94
|
-
isFocused: false,
|
|
95
|
-
isTransitioning: false,
|
|
96
|
-
isDisabled: false,
|
|
97
|
-
validationErrors: [],
|
|
98
|
-
isValid: true,
|
|
99
|
-
dropdownState: {
|
|
100
|
-
isOpen: false,
|
|
101
|
-
isTransitioning: false,
|
|
102
|
-
isDisabled: false,
|
|
103
|
-
isFocused: false
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Get current state (immutable)
|
|
110
|
-
*/
|
|
111
|
-
public getState(): Readonly<KTDatepickerState> {
|
|
112
|
-
return { ...this._state };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Get the source of the last state update
|
|
117
|
-
* @returns The source identifier of the last state update
|
|
118
|
-
*/
|
|
119
|
-
public getLastUpdateSource(): string {
|
|
120
|
-
return this._lastUpdateSource;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Get the set of properties that changed in the last state update
|
|
125
|
-
* @returns Set of property keys that changed
|
|
126
|
-
*/
|
|
127
|
-
public getLastChangedProperties(): ReadonlySet<string> {
|
|
128
|
-
return new Set(this._lastChangedProperties);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Update state with validation and observer notification
|
|
133
|
-
* @param updates - Partial state updates to apply
|
|
134
|
-
* @param source - Source identifier for debugging
|
|
135
|
-
* @param immediate - If true, bypass batching and apply updates immediately
|
|
136
|
-
*/
|
|
137
|
-
public updateState(updates: Partial<KTDatepickerState>, source: string = 'unknown', immediate: boolean = false): boolean {
|
|
138
|
-
if (this._isUpdating) {
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// If immediate is requested, or batching is disabled, apply updates immediately
|
|
143
|
-
if (immediate || !this._config.enableUpdateBatching) {
|
|
144
|
-
return this._applyUpdates(source, updates);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Merge updates with pending updates for batched processing
|
|
148
|
-
this._pendingUpdates = { ...this._pendingUpdates, ...updates };
|
|
149
|
-
|
|
150
|
-
if (this._batchTimeout) {
|
|
151
|
-
clearTimeout(this._batchTimeout);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
this._batchTimeout = window.setTimeout(() => {
|
|
155
|
-
this._applyUpdates(source);
|
|
156
|
-
}, this._config.batchDelay);
|
|
157
|
-
|
|
158
|
-
return true;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Apply updates to state
|
|
163
|
-
*/
|
|
164
|
-
private _applyUpdates(source: string, updates?: Partial<KTDatepickerState>): boolean {
|
|
165
|
-
const changes = updates || this._pendingUpdates;
|
|
166
|
-
const oldState = { ...this._state };
|
|
167
|
-
|
|
168
|
-
// Create new state with updates
|
|
169
|
-
const newState = { ...this._state, ...changes };
|
|
170
|
-
|
|
171
|
-
// Validate state if enabled
|
|
172
|
-
if (this._config.enableValidation) {
|
|
173
|
-
const validation = this._validateState(newState);
|
|
174
|
-
if (!validation.isValid) {
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
newState.validationErrors = validation.errors;
|
|
178
|
-
newState.isValid = validation.isValid;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// Update state
|
|
182
|
-
this._state = newState;
|
|
183
|
-
this._pendingUpdates = {};
|
|
184
|
-
|
|
185
|
-
// Notify observers
|
|
186
|
-
this._notifyObservers(oldState, newState, source, changes);
|
|
187
|
-
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Validate state
|
|
193
|
-
*/
|
|
194
|
-
private _validateState(state: KTDatepickerState): ValidationResult {
|
|
195
|
-
const errors: string[] = [];
|
|
196
|
-
|
|
197
|
-
// Validate dates
|
|
198
|
-
if (state.selectedDate && isNaN(state.selectedDate.getTime())) {
|
|
199
|
-
errors.push('Invalid selectedDate');
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (state.currentDate && isNaN(state.currentDate.getTime())) {
|
|
203
|
-
errors.push('Invalid currentDate');
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Validate range
|
|
207
|
-
if (state.selectedRange) {
|
|
208
|
-
if (state.selectedRange.start && isNaN(state.selectedRange.start.getTime())) {
|
|
209
|
-
errors.push('Invalid range start date');
|
|
210
|
-
}
|
|
211
|
-
if (state.selectedRange.end && isNaN(state.selectedRange.end.getTime())) {
|
|
212
|
-
errors.push('Invalid range end date');
|
|
213
|
-
}
|
|
214
|
-
if (state.selectedRange.start && state.selectedRange.end &&
|
|
215
|
-
state.selectedRange.start > state.selectedRange.end) {
|
|
216
|
-
errors.push('Range start date cannot be after end date');
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Validate time
|
|
221
|
-
if (state.selectedTime) {
|
|
222
|
-
if (state.selectedTime.hour < 0 || state.selectedTime.hour > 23) {
|
|
223
|
-
errors.push('Invalid hour value');
|
|
224
|
-
}
|
|
225
|
-
if (state.selectedTime.minute < 0 || state.selectedTime.minute > 59) {
|
|
226
|
-
errors.push('Invalid minute value');
|
|
227
|
-
}
|
|
228
|
-
if (state.selectedTime.second < 0 || state.selectedTime.second > 59) {
|
|
229
|
-
errors.push('Invalid second value');
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
return {
|
|
234
|
-
isValid: errors.length === 0,
|
|
235
|
-
errors
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Subscribe to state changes
|
|
241
|
-
*/
|
|
242
|
-
public subscribe(observer: StateObserver): () => void {
|
|
243
|
-
this._observers.add(observer);
|
|
244
|
-
|
|
245
|
-
// Return unsubscribe function
|
|
246
|
-
return () => {
|
|
247
|
-
this._observers.delete(observer);
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Compute which properties actually changed between old and new state
|
|
253
|
-
*/
|
|
254
|
-
private _computeChangedProperties(oldState: KTDatepickerState, newState: KTDatepickerState, changes: Partial<KTDatepickerState>): Set<string> {
|
|
255
|
-
const changedProperties = new Set<string>();
|
|
256
|
-
|
|
257
|
-
// Check each property in the changes object
|
|
258
|
-
for (const key in changes) {
|
|
259
|
-
if (changes.hasOwnProperty(key)) {
|
|
260
|
-
const oldValue = (oldState as any)[key];
|
|
261
|
-
const newValue = (newState as any)[key];
|
|
262
|
-
|
|
263
|
-
// Handle Date objects - compare by time value
|
|
264
|
-
if (oldValue instanceof Date && newValue instanceof Date) {
|
|
265
|
-
if (oldValue.getTime() !== newValue.getTime()) {
|
|
266
|
-
changedProperties.add(key);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
// Handle arrays - compare by JSON string (for selectedDates)
|
|
270
|
-
else if (Array.isArray(oldValue) && Array.isArray(newValue)) {
|
|
271
|
-
if (JSON.stringify(oldValue.map(d => d instanceof Date ? d.getTime() : d)) !==
|
|
272
|
-
JSON.stringify(newValue.map(d => d instanceof Date ? d.getTime() : d))) {
|
|
273
|
-
changedProperties.add(key);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
// Handle objects (like selectedRange, dropdownState)
|
|
277
|
-
else if (typeof oldValue === 'object' && oldValue !== null &&
|
|
278
|
-
typeof newValue === 'object' && newValue !== null) {
|
|
279
|
-
if (JSON.stringify(oldValue) !== JSON.stringify(newValue)) {
|
|
280
|
-
changedProperties.add(key);
|
|
281
|
-
// Also add nested properties if it's a complex object
|
|
282
|
-
if (key === 'selectedRange') {
|
|
283
|
-
if (oldValue.start?.getTime() !== newValue.start?.getTime()) changedProperties.add('selectedRange.start');
|
|
284
|
-
if (oldValue.end?.getTime() !== newValue.end?.getTime()) changedProperties.add('selectedRange.end');
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
// Primitive values
|
|
289
|
-
else if (oldValue !== newValue) {
|
|
290
|
-
changedProperties.add(key);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
return changedProperties;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Notify all observers of state change
|
|
300
|
-
*/
|
|
301
|
-
private _notifyObservers(oldState: KTDatepickerState, newState: KTDatepickerState, source: string, changes: Partial<KTDatepickerState>): void {
|
|
302
|
-
if (this._observers.size === 0) return;
|
|
303
|
-
|
|
304
|
-
// Store the last update source for external queries
|
|
305
|
-
this._lastUpdateSource = source;
|
|
306
|
-
|
|
307
|
-
// Compute which properties actually changed
|
|
308
|
-
const changedProperties = this._computeChangedProperties(oldState, newState, changes);
|
|
309
|
-
this._lastChangedProperties = changedProperties; // Store for observers to access
|
|
310
|
-
|
|
311
|
-
// Sort observers by priority
|
|
312
|
-
const sortedObservers = Array.from(this._observers).sort((a, b) =>
|
|
313
|
-
a.getUpdatePriority() - b.getUpdatePriority()
|
|
314
|
-
);
|
|
315
|
-
|
|
316
|
-
const event: StateChangeEvent = {
|
|
317
|
-
oldState,
|
|
318
|
-
newState,
|
|
319
|
-
source,
|
|
320
|
-
timestamp: Date.now(),
|
|
321
|
-
changes,
|
|
322
|
-
changedProperties
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
// Notify observers in priority order
|
|
326
|
-
for (const observer of sortedObservers) {
|
|
327
|
-
try {
|
|
328
|
-
observer.onStateChange(newState, oldState);
|
|
329
|
-
} catch (error) {
|
|
330
|
-
// Observer error - continue with other observers
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Convenience methods for common state updates
|
|
337
|
-
*/
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Set selected date - uses immediate update for synchronous event firing
|
|
341
|
-
*/
|
|
342
|
-
public setSelectedDate(date: Date | null, source: string = 'manual'): boolean {
|
|
343
|
-
return this.updateState({ selectedDate: date }, source, true); // immediate
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
public setSelectedTime(time: TimeState | null, source: string = 'manual'): boolean {
|
|
347
|
-
return this.updateState({ selectedTime: time }, source);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
public setCurrentDate(date: Date, source: string = 'manual'): boolean {
|
|
351
|
-
return this.updateState({ currentDate: date }, source);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Set selected range - uses immediate update for synchronous event firing
|
|
356
|
-
*/
|
|
357
|
-
public setSelectedRange(range: { start: Date | null; end: Date | null } | null, source: string = 'manual'): boolean {
|
|
358
|
-
return this.updateState({ selectedRange: range }, source, true); // immediate
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Set selected dates (multi-date) - uses immediate update for synchronous event firing
|
|
363
|
-
*/
|
|
364
|
-
public setSelectedDates(dates: Date[], source: string = 'manual'): boolean {
|
|
365
|
-
return this.updateState({ selectedDates: dates }, source, true); // immediate
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
public setViewMode(mode: 'days' | 'months' | 'years', source: string = 'manual'): boolean {
|
|
369
|
-
return this.updateState({ viewMode: mode }, source);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Set overall open state - uses immediate update for synchronous event firing
|
|
374
|
-
*/
|
|
375
|
-
public setOpen(isOpen: boolean, source: string = 'manual'): boolean {
|
|
376
|
-
return this.updateState({ isOpen }, source, true); // immediate
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
public setFocused(isFocused: boolean, source: string = 'manual'): boolean {
|
|
380
|
-
return this.updateState({ isFocused }, source);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
public setDisabled(isDisabled: boolean, source: string = 'manual'): boolean {
|
|
384
|
-
return this.updateState({ isDisabled }, source);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
public setTransitioning(isTransitioning: boolean, source: string = 'manual'): boolean {
|
|
388
|
-
return this.updateState({ isTransitioning }, source);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// Dropdown state methods (consolidated from legacy state manager)
|
|
392
|
-
/**
|
|
393
|
-
* Set dropdown open state - uses immediate update for synchronous event firing
|
|
394
|
-
*/
|
|
395
|
-
public setDropdownOpen(isOpen: boolean, source: string = 'manual'): boolean {
|
|
396
|
-
return this.updateState({
|
|
397
|
-
dropdownState: { ...this._state.dropdownState, isOpen },
|
|
398
|
-
isOpen // Also update the legacy isOpen field for compatibility
|
|
399
|
-
}, source, true); // immediate
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
public setDropdownTransitioning(isTransitioning: boolean, source: string = 'manual'): boolean {
|
|
403
|
-
return this.updateState({
|
|
404
|
-
dropdownState: { ...this._state.dropdownState, isTransitioning }
|
|
405
|
-
}, source);
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
public setDropdownDisabled(isDisabled: boolean, source: string = 'manual'): boolean {
|
|
409
|
-
return this.updateState({
|
|
410
|
-
dropdownState: { ...this._state.dropdownState, isDisabled }
|
|
411
|
-
}, source);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
public setDropdownFocused(isFocused: boolean, source: string = 'manual'): boolean {
|
|
415
|
-
return this.updateState({
|
|
416
|
-
dropdownState: { ...this._state.dropdownState, isFocused }
|
|
417
|
-
}, source);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
public getDropdownState(): Readonly<DropdownState> {
|
|
421
|
-
return { ...this._state.dropdownState };
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
public isDropdownOpen(): boolean {
|
|
425
|
-
return this._state.dropdownState.isOpen;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
public isDropdownTransitioning(): boolean {
|
|
429
|
-
return this._state.dropdownState.isTransitioning;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
public isDropdownDisabled(): boolean {
|
|
433
|
-
return this._state.dropdownState.isDisabled;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
public isDropdownFocused(): boolean {
|
|
437
|
-
return this._state.dropdownState.isFocused;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
/**
|
|
441
|
-
* Reset state to initial values
|
|
442
|
-
*/
|
|
443
|
-
public reset(source: string = 'manual'): void {
|
|
444
|
-
const oldState = { ...this._state };
|
|
445
|
-
this._state = this._getInitialState();
|
|
446
|
-
this._notifyObservers(oldState, this._state, source, this._state);
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/**
|
|
450
|
-
* Dispose of state manager
|
|
451
|
-
*/
|
|
452
|
-
public dispose(): void {
|
|
453
|
-
this._observers.clear();
|
|
454
|
-
if (this._batchTimeout) {
|
|
455
|
-
clearTimeout(this._batchTimeout);
|
|
456
|
-
this._batchTimeout = null;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|