@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,640 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*
|
|
3
|
-
* segmented-input.ts - Modular segmented input for KTDatepicker (2025+)
|
|
4
|
-
* Each date/time part is rendered as a focusable, editable segment.
|
|
5
|
-
*
|
|
6
|
-
* Features:
|
|
7
|
-
* - Segments: day, month, year, (optionally hour, minute, second, AM/PM)
|
|
8
|
-
* - Keyboard navigation: Tab, Shift+Tab, arrow keys, Enter
|
|
9
|
-
* - Direct typing/editing of segments with focus preservation
|
|
10
|
-
* - ARIA roles and accessibility for all segments
|
|
11
|
-
* - Emits change events on value update (debounced)
|
|
12
|
-
* - Integrates with KTDatepicker for value sync
|
|
13
|
-
*
|
|
14
|
-
* Keyboard Navigation:
|
|
15
|
-
* - Tab/Shift+Tab: Move between segments
|
|
16
|
-
* - Arrow Left/Right: Move between segments
|
|
17
|
-
* - Arrow Up/Down: Increment/decrement segment value
|
|
18
|
-
* - Enter: Move to next segment (wraps from last to first)
|
|
19
|
-
* - Number keys: Direct input with validation (optimized for performance)
|
|
20
|
-
*
|
|
21
|
-
* Performance Optimizations:
|
|
22
|
-
* - No DOM re-rendering during number typing
|
|
23
|
-
* - Focus preserved during rapid input
|
|
24
|
-
* - Debounced onChange events (150ms delay)
|
|
25
|
-
* - Caret position maintained during editing
|
|
26
|
-
*/
|
|
27
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
-
exports.SegmentedInput = SegmentedInput;
|
|
29
|
-
var templates_1 = require("../templates/templates");
|
|
30
|
-
/**
|
|
31
|
-
* SegmentedInput - renders a segmented date/time input.
|
|
32
|
-
* @param container - HTMLElement to render into
|
|
33
|
-
* @param options - SegmentedInputOptions
|
|
34
|
-
* @returns cleanup function
|
|
35
|
-
*/
|
|
36
|
-
function SegmentedInput(container, options) {
|
|
37
|
-
// --- Internal state ---
|
|
38
|
-
var currentValue = new Date(options.value);
|
|
39
|
-
var segments = options.segments || ['month', 'day', 'year'];
|
|
40
|
-
var locale = options.locale || 'default';
|
|
41
|
-
// Global flag to track arrow navigation across all segmented inputs
|
|
42
|
-
if (!window.__ktui_segmented_input_arrow_navigation) {
|
|
43
|
-
window.__ktui_segmented_input_arrow_navigation = false;
|
|
44
|
-
}
|
|
45
|
-
// --- Get templates ---
|
|
46
|
-
// Use a minimal config to get templates; in real usage, pass full config if available
|
|
47
|
-
var templates = (0, templates_1.getTemplateStrings)({});
|
|
48
|
-
var segmentTpl = templates.dateSegment;
|
|
49
|
-
var separatorTpl = templates.segmentSeparator;
|
|
50
|
-
// --- Utility: get separator between segments ---
|
|
51
|
-
function getSeparatorBetweenSegments(segment1, segment2, format) {
|
|
52
|
-
// Time segments use ":" as separator
|
|
53
|
-
var timeSegments = ['hour', 'minute', 'second'];
|
|
54
|
-
if (timeSegments.includes(segment1) && timeSegments.includes(segment2)) {
|
|
55
|
-
return ':';
|
|
56
|
-
}
|
|
57
|
-
// Space between date and time
|
|
58
|
-
var dateSegments = ['day', 'month', 'year'];
|
|
59
|
-
if (dateSegments.includes(segment1) && timeSegments.includes(segment2)) {
|
|
60
|
-
return ' ';
|
|
61
|
-
}
|
|
62
|
-
// AM/PM has space before it
|
|
63
|
-
if (segment2 === 'ampm') {
|
|
64
|
-
return ' ';
|
|
65
|
-
}
|
|
66
|
-
// Second to AM/PM has space
|
|
67
|
-
if (segment1 === 'second' && segment2 === 'ampm') {
|
|
68
|
-
return ' ';
|
|
69
|
-
}
|
|
70
|
-
// Date segments use separator from format
|
|
71
|
-
if (dateSegments.includes(segment1) && dateSegments.includes(segment2)) {
|
|
72
|
-
return getSeparatorFromFormat(format);
|
|
73
|
-
}
|
|
74
|
-
// Default fallback
|
|
75
|
-
return '';
|
|
76
|
-
}
|
|
77
|
-
// --- Utility: get separator from format ---
|
|
78
|
-
function getSeparatorFromFormat(format) {
|
|
79
|
-
if (!format)
|
|
80
|
-
return '/'; // Default fallback
|
|
81
|
-
// Find the first non-date token character to use as separator
|
|
82
|
-
var tokenRegex = /(yyyy|yy|MM|M|dd|d)/g;
|
|
83
|
-
var lastIndex = 0;
|
|
84
|
-
var match;
|
|
85
|
-
while ((match = tokenRegex.exec(format)) !== null) {
|
|
86
|
-
if (match.index > lastIndex) {
|
|
87
|
-
// Found a separator character
|
|
88
|
-
var separator = format.slice(lastIndex, match.index);
|
|
89
|
-
if (separator && separator.length > 0) {
|
|
90
|
-
return separator;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
lastIndex = match.index + match[0].length;
|
|
94
|
-
}
|
|
95
|
-
// Check for separator after the last token
|
|
96
|
-
if (lastIndex < format.length) {
|
|
97
|
-
var separator = format.slice(lastIndex);
|
|
98
|
-
if (separator && separator.length > 0) {
|
|
99
|
-
return separator;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return '/'; // Default fallback
|
|
103
|
-
}
|
|
104
|
-
// --- Utility: check if segment should be padded based on format ---
|
|
105
|
-
function shouldPadSegment(segment, format) {
|
|
106
|
-
if (!format)
|
|
107
|
-
return true; // Default to padded for backward compatibility
|
|
108
|
-
var tokenRegex = /(yyyy|yy|MM|M|dd|d|HH|H|mm|m|ss|s)/g;
|
|
109
|
-
var match;
|
|
110
|
-
while ((match = tokenRegex.exec(format)) !== null) {
|
|
111
|
-
switch (match[0]) {
|
|
112
|
-
case 'dd':
|
|
113
|
-
if (segment === 'day')
|
|
114
|
-
return true;
|
|
115
|
-
break;
|
|
116
|
-
case 'd':
|
|
117
|
-
if (segment === 'day')
|
|
118
|
-
return false;
|
|
119
|
-
break;
|
|
120
|
-
case 'MM':
|
|
121
|
-
if (segment === 'month')
|
|
122
|
-
return true;
|
|
123
|
-
break;
|
|
124
|
-
case 'M':
|
|
125
|
-
if (segment === 'month')
|
|
126
|
-
return false;
|
|
127
|
-
break;
|
|
128
|
-
case 'yyyy':
|
|
129
|
-
if (segment === 'year')
|
|
130
|
-
return true;
|
|
131
|
-
break; // 4-digit year
|
|
132
|
-
case 'yy':
|
|
133
|
-
if (segment === 'year')
|
|
134
|
-
return false;
|
|
135
|
-
break; // 2-digit year
|
|
136
|
-
case 'HH':
|
|
137
|
-
case 'H':
|
|
138
|
-
if (segment === 'hour')
|
|
139
|
-
return match[0] === 'HH';
|
|
140
|
-
break;
|
|
141
|
-
case 'mm':
|
|
142
|
-
case 'm':
|
|
143
|
-
if (segment === 'minute')
|
|
144
|
-
return match[0] === 'mm';
|
|
145
|
-
break;
|
|
146
|
-
case 'ss':
|
|
147
|
-
case 's':
|
|
148
|
-
if (segment === 'second')
|
|
149
|
-
return match[0] === 'ss';
|
|
150
|
-
break;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return true; // Default fallback
|
|
154
|
-
}
|
|
155
|
-
// --- Utility: get segment value as string ---
|
|
156
|
-
function getSegmentValue(segment, date) {
|
|
157
|
-
var shouldPad = shouldPadSegment(segment, options.format);
|
|
158
|
-
switch (segment) {
|
|
159
|
-
case 'day':
|
|
160
|
-
var day = date.getDate();
|
|
161
|
-
return shouldPad ? day.toString().padStart(2, '0') : day.toString();
|
|
162
|
-
case 'month':
|
|
163
|
-
var month = date.getMonth() + 1;
|
|
164
|
-
return shouldPad ? month.toString().padStart(2, '0') : month.toString();
|
|
165
|
-
case 'year':
|
|
166
|
-
var year = date.getFullYear();
|
|
167
|
-
return shouldPad ? year.toString() : year.toString().slice(-2); // yy format shows last 2 digits
|
|
168
|
-
case 'hour':
|
|
169
|
-
// For 12-hour format, convert to 1-12 range
|
|
170
|
-
var hourValue = void 0;
|
|
171
|
-
if (options.timeFormat === '12h') {
|
|
172
|
-
var hour24 = date.getHours();
|
|
173
|
-
hourValue = hour24 === 0 ? 12 : hour24 > 12 ? hour24 - 12 : hour24;
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
hourValue = date.getHours();
|
|
177
|
-
}
|
|
178
|
-
return shouldPad ? hourValue.toString().padStart(2, '0') : hourValue.toString();
|
|
179
|
-
case 'minute':
|
|
180
|
-
var minute = date.getMinutes();
|
|
181
|
-
return shouldPad ? minute.toString().padStart(2, '0') : minute.toString();
|
|
182
|
-
case 'second':
|
|
183
|
-
var second = date.getSeconds();
|
|
184
|
-
return shouldPad ? second.toString().padStart(2, '0') : second.toString();
|
|
185
|
-
case 'ampm': return date.getHours() < 12 ? 'AM' : 'PM';
|
|
186
|
-
default: return '';
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
// --- Utility: set segment value ---
|
|
190
|
-
function setSegmentValue(segment, value, date) {
|
|
191
|
-
var d = new Date(date);
|
|
192
|
-
switch (segment) {
|
|
193
|
-
case 'day':
|
|
194
|
-
d.setDate(Number(value));
|
|
195
|
-
break;
|
|
196
|
-
case 'month':
|
|
197
|
-
d.setMonth(Number(value) - 1);
|
|
198
|
-
break;
|
|
199
|
-
case 'year':
|
|
200
|
-
d.setFullYear(Number(value));
|
|
201
|
-
break;
|
|
202
|
-
case 'hour':
|
|
203
|
-
// Handle 12-hour vs 24-hour format
|
|
204
|
-
var hourValue = Number(value);
|
|
205
|
-
if (options.timeFormat === '12h') {
|
|
206
|
-
// In 12-hour mode, convert 12-hour input to 24-hour
|
|
207
|
-
var currentHour = d.getHours();
|
|
208
|
-
var isPM = currentHour >= 12;
|
|
209
|
-
if (hourValue === 12) {
|
|
210
|
-
hourValue = isPM ? 12 : 0; // 12 AM = 0, 12 PM = 12
|
|
211
|
-
}
|
|
212
|
-
else if (isPM) {
|
|
213
|
-
hourValue += 12; // PM hours: add 12
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
// Preserve existing minutes and seconds when setting hour
|
|
217
|
-
var currentMinutes = d.getMinutes();
|
|
218
|
-
var currentSecondsForHour = d.getSeconds();
|
|
219
|
-
d.setHours(hourValue, currentMinutes, currentSecondsForHour);
|
|
220
|
-
break;
|
|
221
|
-
case 'minute':
|
|
222
|
-
// Preserve existing seconds when setting minute
|
|
223
|
-
var currentSecondsForMinute = d.getSeconds();
|
|
224
|
-
d.setMinutes(Number(value), currentSecondsForMinute);
|
|
225
|
-
break;
|
|
226
|
-
case 'second':
|
|
227
|
-
d.setSeconds(Number(value));
|
|
228
|
-
break;
|
|
229
|
-
case 'ampm':
|
|
230
|
-
if (value === 'AM' && d.getHours() >= 12) {
|
|
231
|
-
d.setHours(d.getHours() - 12);
|
|
232
|
-
}
|
|
233
|
-
else if (value === 'PM' && d.getHours() < 12) {
|
|
234
|
-
d.setHours(d.getHours() + 12);
|
|
235
|
-
}
|
|
236
|
-
break;
|
|
237
|
-
}
|
|
238
|
-
return d;
|
|
239
|
-
}
|
|
240
|
-
// --- Utility: get min/max for a segment ---
|
|
241
|
-
function getSegmentMin(segment, date) {
|
|
242
|
-
switch (segment) {
|
|
243
|
-
case 'day':
|
|
244
|
-
// Use actual month/year for max days
|
|
245
|
-
return 1;
|
|
246
|
-
case 'month':
|
|
247
|
-
return 1;
|
|
248
|
-
case 'year':
|
|
249
|
-
return options.min ? options.min.getFullYear() : undefined;
|
|
250
|
-
case 'hour':
|
|
251
|
-
return 0;
|
|
252
|
-
case 'minute':
|
|
253
|
-
case 'second':
|
|
254
|
-
return 0;
|
|
255
|
-
case 'ampm':
|
|
256
|
-
return 0; // 0 = AM, 1 = PM
|
|
257
|
-
default:
|
|
258
|
-
return undefined;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
function getSegmentMax(segment, date) {
|
|
262
|
-
switch (segment) {
|
|
263
|
-
case 'day':
|
|
264
|
-
// Use actual month/year for max days
|
|
265
|
-
return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
266
|
-
case 'month':
|
|
267
|
-
return 12;
|
|
268
|
-
case 'year':
|
|
269
|
-
return options.max ? options.max.getFullYear() : undefined;
|
|
270
|
-
case 'hour':
|
|
271
|
-
return 23;
|
|
272
|
-
case 'minute':
|
|
273
|
-
case 'second':
|
|
274
|
-
return 59;
|
|
275
|
-
case 'ampm':
|
|
276
|
-
return 1; // 0 = AM, 1 = PM
|
|
277
|
-
default:
|
|
278
|
-
return undefined;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
// --- Track focused segment index ---
|
|
282
|
-
var focusedIdx = 0;
|
|
283
|
-
// --- Track caret position (offset) ---
|
|
284
|
-
var caretOffset = null;
|
|
285
|
-
// --- Track if this is the first render ---
|
|
286
|
-
var isInitialRender = true;
|
|
287
|
-
// --- Track if we're in the middle of Arrow Up/Down navigation ---
|
|
288
|
-
var isArrowNavigation = false;
|
|
289
|
-
// --- Focus a segment by index and restore caret position ---
|
|
290
|
-
/**
|
|
291
|
-
* Restores focus to the segment at the given index and restores caret position if available.
|
|
292
|
-
* @param idx - Index of the segment to focus
|
|
293
|
-
* @param caret - Caret offset to restore (null for end)
|
|
294
|
-
*/
|
|
295
|
-
function restoreFocus(idx, caret) {
|
|
296
|
-
var _a;
|
|
297
|
-
if (caret === void 0) { caret = null; }
|
|
298
|
-
try {
|
|
299
|
-
var segs = Array.from(container.querySelectorAll('[data-segment]'));
|
|
300
|
-
if (segs[idx] && segs[idx].offsetParent !== null) { // Check if element is in DOM
|
|
301
|
-
segs.forEach(function (el, i) { return el.setAttribute('tabindex', i === idx ? '0' : '-1'); });
|
|
302
|
-
segs[idx].focus();
|
|
303
|
-
// Restore caret position (at end if null)
|
|
304
|
-
if (segs[idx].isContentEditable) {
|
|
305
|
-
var range = document.createRange();
|
|
306
|
-
range.selectNodeContents(segs[idx]);
|
|
307
|
-
range.collapse(false); // place at end
|
|
308
|
-
if (caret !== null && segs[idx].firstChild) {
|
|
309
|
-
range.setStart(segs[idx].firstChild, Math.min(caret, ((_a = segs[idx].textContent) === null || _a === void 0 ? void 0 : _a.length) || 0));
|
|
310
|
-
range.collapse(true);
|
|
311
|
-
}
|
|
312
|
-
var sel = window.getSelection();
|
|
313
|
-
if (sel) {
|
|
314
|
-
sel.removeAllRanges();
|
|
315
|
-
sel.addRange(range);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
catch (error) {
|
|
321
|
-
// Fallback: focus first available segment
|
|
322
|
-
var segs = Array.from(container.querySelectorAll('[data-segment]'));
|
|
323
|
-
if (segs[0])
|
|
324
|
-
segs[0].focus();
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
// --- Render segments using templates ---
|
|
328
|
-
function render() {
|
|
329
|
-
// Capture caret position before DOM update
|
|
330
|
-
var prevSegs = Array.from(container.querySelectorAll('[data-segment]'));
|
|
331
|
-
if (prevSegs[focusedIdx] && document.activeElement === prevSegs[focusedIdx]) {
|
|
332
|
-
var sel = window.getSelection();
|
|
333
|
-
if (sel && sel.anchorNode === prevSegs[focusedIdx].firstChild) {
|
|
334
|
-
caretOffset = sel.anchorOffset;
|
|
335
|
-
}
|
|
336
|
-
else {
|
|
337
|
-
caretOffset = null;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
else {
|
|
341
|
-
caretOffset = null;
|
|
342
|
-
}
|
|
343
|
-
container.innerHTML = '';
|
|
344
|
-
container.setAttribute('role', 'group');
|
|
345
|
-
container.setAttribute('aria-label', 'Date input');
|
|
346
|
-
container.tabIndex = -1;
|
|
347
|
-
// Build segments HTML using templates
|
|
348
|
-
var segmentsHtml = '';
|
|
349
|
-
segments.forEach(function (segment, idx) {
|
|
350
|
-
var _a, _b, _c, _d;
|
|
351
|
-
var segmentValue = getSegmentValue(segment, currentValue);
|
|
352
|
-
var segmentData = {
|
|
353
|
-
segmentType: segment,
|
|
354
|
-
segmentValue: segmentValue,
|
|
355
|
-
ariaLabel: segment.charAt(0).toUpperCase() + segment.slice(1),
|
|
356
|
-
ariaValueNow: segmentValue,
|
|
357
|
-
ariaValueText: segmentValue,
|
|
358
|
-
ariaValueMin: (_b = (_a = getSegmentMin(segment, currentValue)) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '',
|
|
359
|
-
ariaValueMax: (_d = (_c = getSegmentMax(segment, currentValue)) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '',
|
|
360
|
-
tabindex: idx === focusedIdx ? '0' : '-1',
|
|
361
|
-
contenteditable: (!options.disabled && !options.readOnly).toString(),
|
|
362
|
-
};
|
|
363
|
-
var segmentHtml = '';
|
|
364
|
-
if (typeof segmentTpl === 'function') {
|
|
365
|
-
segmentHtml = segmentTpl(segmentData);
|
|
366
|
-
}
|
|
367
|
-
else if (typeof segmentTpl === 'string') {
|
|
368
|
-
segmentHtml = segmentTpl
|
|
369
|
-
.replace(/{{segmentType}}/g, segmentData.segmentType)
|
|
370
|
-
.replace(/{{segmentValue}}/g, segmentData.segmentValue)
|
|
371
|
-
.replace(/{{ariaLabel}}/g, segmentData.ariaLabel)
|
|
372
|
-
.replace(/{{ariaValueNow}}/g, segmentData.ariaValueNow)
|
|
373
|
-
.replace(/{{ariaValueText}}/g, segmentData.ariaValueText)
|
|
374
|
-
.replace(/{{ariaValueMin}}/g, segmentData.ariaValueMin)
|
|
375
|
-
.replace(/{{ariaValueMax}}/g, segmentData.ariaValueMax)
|
|
376
|
-
.replace(/{{tabindex}}/g, segmentData.tabindex)
|
|
377
|
-
.replace(/{{contenteditable}}/g, segmentData.contenteditable)
|
|
378
|
-
.replace(/{{class}}/g, ''); // Replace class placeholder with empty string
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
segmentHtml = '';
|
|
382
|
-
}
|
|
383
|
-
segmentsHtml += segmentHtml;
|
|
384
|
-
if (idx < segments.length - 1) {
|
|
385
|
-
// Get appropriate separator between these segments
|
|
386
|
-
var nextSegment = segments[idx + 1];
|
|
387
|
-
var separator = getSeparatorBetweenSegments(segment, nextSegment, options.format);
|
|
388
|
-
var sepHtml = '';
|
|
389
|
-
if (typeof separatorTpl === 'function') {
|
|
390
|
-
sepHtml = separatorTpl({ separator: separator });
|
|
391
|
-
}
|
|
392
|
-
else if (typeof separatorTpl === 'string') {
|
|
393
|
-
sepHtml = separatorTpl
|
|
394
|
-
.replace(/{{separator}}/g, separator)
|
|
395
|
-
.replace(/{{class}}/g, ''); // Replace class placeholder with empty string
|
|
396
|
-
}
|
|
397
|
-
else {
|
|
398
|
-
sepHtml = '';
|
|
399
|
-
}
|
|
400
|
-
segmentsHtml += sepHtml;
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
|
-
// Render segments directly into container (container already has the correct structure from template)
|
|
404
|
-
container.innerHTML = segmentsHtml;
|
|
405
|
-
// Verify template rendering was successful
|
|
406
|
-
var segs = Array.from(container.querySelectorAll('[data-segment]'));
|
|
407
|
-
if (segs.length === 0) {
|
|
408
|
-
throw new Error('Segmented input template rendering failed');
|
|
409
|
-
}
|
|
410
|
-
// Re-bind events to all segments
|
|
411
|
-
segs.forEach(function (span, idx) {
|
|
412
|
-
span.addEventListener('keydown', function (e) {
|
|
413
|
-
var _a, _b, _c, _d;
|
|
414
|
-
if (options.disabled || options.readOnly)
|
|
415
|
-
return;
|
|
416
|
-
// Wrapping navigation
|
|
417
|
-
if (e.key === 'ArrowRight' || (e.key === 'Tab' && !e.shiftKey)) {
|
|
418
|
-
e.preventDefault();
|
|
419
|
-
isArrowNavigation = true; // Set flag to prevent blur onChange
|
|
420
|
-
focusedIdx = (idx + 1) % segments.length;
|
|
421
|
-
caretOffset = null;
|
|
422
|
-
// Update tabindex directly instead of full re-render
|
|
423
|
-
var segs_1 = Array.from(container.querySelectorAll('[data-segment]'));
|
|
424
|
-
segs_1.forEach(function (el, i) { return el.setAttribute('tabindex', i === focusedIdx ? '0' : '-1'); });
|
|
425
|
-
restoreFocus(focusedIdx, caretOffset);
|
|
426
|
-
// Reset flag after a short delay to allow focus to be restored
|
|
427
|
-
setTimeout(function () {
|
|
428
|
-
isArrowNavigation = false;
|
|
429
|
-
}, 10);
|
|
430
|
-
}
|
|
431
|
-
else if (e.key === 'ArrowLeft' || (e.key === 'Tab' && e.shiftKey)) {
|
|
432
|
-
e.preventDefault();
|
|
433
|
-
isArrowNavigation = true; // Set flag to prevent blur onChange
|
|
434
|
-
focusedIdx = (idx - 1 + segments.length) % segments.length;
|
|
435
|
-
caretOffset = null;
|
|
436
|
-
// Update tabindex directly instead of full re-render
|
|
437
|
-
var segs_2 = Array.from(container.querySelectorAll('[data-segment]'));
|
|
438
|
-
segs_2.forEach(function (el, i) { return el.setAttribute('tabindex', i === focusedIdx ? '0' : '-1'); });
|
|
439
|
-
restoreFocus(focusedIdx, caretOffset);
|
|
440
|
-
// Reset flag after a short delay to allow focus to be restored
|
|
441
|
-
setTimeout(function () {
|
|
442
|
-
isArrowNavigation = false;
|
|
443
|
-
}, 10);
|
|
444
|
-
}
|
|
445
|
-
else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
|
|
446
|
-
// Increment/decrement value
|
|
447
|
-
e.preventDefault();
|
|
448
|
-
e.stopPropagation(); // Prevent bubbling to main datepicker
|
|
449
|
-
isArrowNavigation = true; // Set flag to prevent blur onChange
|
|
450
|
-
var newValue = void 0;
|
|
451
|
-
if (segments[idx] === 'ampm') {
|
|
452
|
-
// Handle AM/PM toggle
|
|
453
|
-
var currentAmPm = span.textContent || 'AM';
|
|
454
|
-
if (e.key === 'ArrowUp') {
|
|
455
|
-
newValue = currentAmPm === 'AM' ? 'PM' : 'AM';
|
|
456
|
-
}
|
|
457
|
-
else {
|
|
458
|
-
newValue = currentAmPm === 'AM' ? 'PM' : 'AM';
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
// Handle numeric segments
|
|
463
|
-
var min = (_a = getSegmentMin(segments[idx], currentValue)) !== null && _a !== void 0 ? _a : 0;
|
|
464
|
-
var max = (_b = getSegmentMax(segments[idx], currentValue)) !== null && _b !== void 0 ? _b : 9999;
|
|
465
|
-
var current = Number(getSegmentValue(segments[idx], currentValue)) || min;
|
|
466
|
-
if (e.key === 'ArrowUp') {
|
|
467
|
-
current = Math.min(max, current + 1);
|
|
468
|
-
}
|
|
469
|
-
else if (e.key === 'ArrowDown') {
|
|
470
|
-
current = Math.max(min, current - 1);
|
|
471
|
-
}
|
|
472
|
-
newValue = current.toString();
|
|
473
|
-
var shouldPad = shouldPadSegment(segments[idx], options.format);
|
|
474
|
-
if (segments[idx] === 'year') {
|
|
475
|
-
if (shouldPad) {
|
|
476
|
-
newValue = newValue.padStart(4, '0');
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
else if (shouldPad) {
|
|
480
|
-
newValue = newValue.padStart(2, '0');
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
span.textContent = newValue;
|
|
484
|
-
currentValue = setSegmentValue(segments[idx], newValue, currentValue);
|
|
485
|
-
// Set global flag to prevent unified observer from overriding UI
|
|
486
|
-
window.__ktui_segmented_input_arrow_navigation = true;
|
|
487
|
-
// Call onChange immediately for Arrow Up/Down to update the main datepicker
|
|
488
|
-
if (options.onChange) {
|
|
489
|
-
options.onChange(currentValue);
|
|
490
|
-
}
|
|
491
|
-
// Clear flag after onChange callback
|
|
492
|
-
setTimeout(function () {
|
|
493
|
-
window.__ktui_segmented_input_arrow_navigation = false;
|
|
494
|
-
}, 50);
|
|
495
|
-
// Preserve caret position at end of content
|
|
496
|
-
if (span.isContentEditable) {
|
|
497
|
-
var range = document.createRange();
|
|
498
|
-
range.selectNodeContents(span);
|
|
499
|
-
range.collapse(false); // place at end
|
|
500
|
-
var sel = window.getSelection();
|
|
501
|
-
if (sel) {
|
|
502
|
-
sel.removeAllRanges();
|
|
503
|
-
sel.addRange(range);
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
// Reset flag after a short delay to allow focus to be restored
|
|
507
|
-
setTimeout(function () {
|
|
508
|
-
isArrowNavigation = false;
|
|
509
|
-
}, 10);
|
|
510
|
-
}
|
|
511
|
-
else if (e.key === 'Enter') {
|
|
512
|
-
// Move to next segment on Enter
|
|
513
|
-
e.preventDefault();
|
|
514
|
-
e.stopPropagation(); // Prevent bubbling to main datepicker
|
|
515
|
-
isArrowNavigation = true; // Set flag to prevent blur onChange
|
|
516
|
-
focusedIdx = (idx + 1) % segments.length;
|
|
517
|
-
caretOffset = null;
|
|
518
|
-
// Update tabindex directly instead of full re-render
|
|
519
|
-
var segs_3 = Array.from(container.querySelectorAll('[data-segment]'));
|
|
520
|
-
segs_3.forEach(function (el, i) { return el.setAttribute('tabindex', i === focusedIdx ? '0' : '-1'); });
|
|
521
|
-
restoreFocus(focusedIdx, caretOffset);
|
|
522
|
-
// Reset flag after a short delay to allow focus to be restored
|
|
523
|
-
setTimeout(function () {
|
|
524
|
-
isArrowNavigation = false;
|
|
525
|
-
}, 10);
|
|
526
|
-
}
|
|
527
|
-
else if (/^[0-9]$/.test(e.key)) {
|
|
528
|
-
// Direct typing, enforce min/max - optimized to avoid focus loss
|
|
529
|
-
e.preventDefault();
|
|
530
|
-
var newValue = void 0;
|
|
531
|
-
var currentText = span.textContent || '';
|
|
532
|
-
if (segments[idx] === 'year') {
|
|
533
|
-
// For year: shift left and append new digit (e.g., "2024" + "6" = "0246", then becomes "2026" after validation)
|
|
534
|
-
// If already 4 digits, shift left by removing first digit and appending new one
|
|
535
|
-
if (currentText.length === 4) {
|
|
536
|
-
newValue = (currentText.slice(1) + e.key);
|
|
537
|
-
}
|
|
538
|
-
else {
|
|
539
|
-
newValue = (currentText + e.key).slice(-4);
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
else {
|
|
543
|
-
// For day/month: shift left and append new digit (e.g., "12" + "5" = "25")
|
|
544
|
-
// If already 2 digits, shift left by removing first digit and appending new one
|
|
545
|
-
if (currentText.length === 2) {
|
|
546
|
-
newValue = (currentText.slice(1) + e.key);
|
|
547
|
-
}
|
|
548
|
-
else {
|
|
549
|
-
newValue = (currentText + e.key).slice(-2);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
var min = (_c = getSegmentMin(segments[idx], currentValue)) !== null && _c !== void 0 ? _c : 0;
|
|
553
|
-
var max = (_d = getSegmentMax(segments[idx], currentValue)) !== null && _d !== void 0 ? _d : (segments[idx] === 'year' ? 9999 : 99);
|
|
554
|
-
var num = Math.max(min, Math.min(max, Number(newValue)));
|
|
555
|
-
if (isNaN(num))
|
|
556
|
-
num = min;
|
|
557
|
-
// Update content directly without re-rendering to preserve focus
|
|
558
|
-
var shouldPad = shouldPadSegment(segments[idx], options.format);
|
|
559
|
-
if (segments[idx] === 'year') {
|
|
560
|
-
span.textContent = shouldPad ? num.toString().padStart(4, '0') : num.toString();
|
|
561
|
-
}
|
|
562
|
-
else {
|
|
563
|
-
span.textContent = shouldPad ? num.toString().padStart(2, '0') : num.toString();
|
|
564
|
-
}
|
|
565
|
-
// Update internal value
|
|
566
|
-
currentValue = setSegmentValue(segments[idx], span.textContent || '', currentValue);
|
|
567
|
-
// Debounce onChange to avoid excessive updates during rapid typing
|
|
568
|
-
if (options.onChange) {
|
|
569
|
-
clearTimeout(span._onChangeTimeout);
|
|
570
|
-
span._onChangeTimeout = setTimeout(function () {
|
|
571
|
-
options.onChange(currentValue);
|
|
572
|
-
}, 150); // 150ms debounce
|
|
573
|
-
}
|
|
574
|
-
// Preserve caret position at end of content
|
|
575
|
-
if (span.isContentEditable) {
|
|
576
|
-
var range = document.createRange();
|
|
577
|
-
range.selectNodeContents(span);
|
|
578
|
-
range.collapse(false); // place at end
|
|
579
|
-
var sel = window.getSelection();
|
|
580
|
-
if (sel) {
|
|
581
|
-
sel.removeAllRanges();
|
|
582
|
-
sel.addRange(range);
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
});
|
|
587
|
-
// Focus/blur styling (no classes, just ARIA/tabindex)
|
|
588
|
-
span.addEventListener('focus', function () {
|
|
589
|
-
span.setAttribute('tabindex', '0');
|
|
590
|
-
focusedIdx = idx;
|
|
591
|
-
});
|
|
592
|
-
span.addEventListener('blur', function () {
|
|
593
|
-
span.setAttribute('tabindex', '-1');
|
|
594
|
-
// Clear any pending debounced onChange calls
|
|
595
|
-
if (span._onChangeTimeout) {
|
|
596
|
-
clearTimeout(span._onChangeTimeout);
|
|
597
|
-
span._onChangeTimeout = null;
|
|
598
|
-
}
|
|
599
|
-
// Call onChange when user finishes editing to update the main datepicker
|
|
600
|
-
// But not during Arrow Up/Down navigation and only if value actually changed
|
|
601
|
-
if (options.onChange && !isArrowNavigation) {
|
|
602
|
-
var updatedValue = setSegmentValue(segments[idx], span.textContent || '', currentValue);
|
|
603
|
-
// Only call onChange if the value has actually changed
|
|
604
|
-
if (updatedValue.getTime() !== currentValue.getTime()) {
|
|
605
|
-
options.onChange(updatedValue);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
});
|
|
609
|
-
// Mouse click focuses segment (optimized to avoid unnecessary re-rendering)
|
|
610
|
-
span.addEventListener('mousedown', function (e) {
|
|
611
|
-
e.preventDefault();
|
|
612
|
-
focusedIdx = idx;
|
|
613
|
-
caretOffset = null;
|
|
614
|
-
// Only update tabindex and focus, no full re-render
|
|
615
|
-
var segs = Array.from(container.querySelectorAll('[data-segment]'));
|
|
616
|
-
segs.forEach(function (el, i) { return el.setAttribute('tabindex', i === focusedIdx ? '0' : '-1'); });
|
|
617
|
-
restoreFocus(focusedIdx, caretOffset);
|
|
618
|
-
});
|
|
619
|
-
});
|
|
620
|
-
// After rendering, restore focus to the correct segment and caret (skip on initial render)
|
|
621
|
-
if (!isInitialRender) {
|
|
622
|
-
restoreFocus(focusedIdx, caretOffset);
|
|
623
|
-
}
|
|
624
|
-
isInitialRender = false;
|
|
625
|
-
}
|
|
626
|
-
// --- Initial render ---
|
|
627
|
-
render();
|
|
628
|
-
// --- Cleanup function ---
|
|
629
|
-
return function () {
|
|
630
|
-
// Clear any pending debounced onChange calls
|
|
631
|
-
var segs = Array.from(container.querySelectorAll('[data-segment]'));
|
|
632
|
-
segs.forEach(function (span) {
|
|
633
|
-
if (span._onChangeTimeout) {
|
|
634
|
-
clearTimeout(span._onChangeTimeout);
|
|
635
|
-
}
|
|
636
|
-
});
|
|
637
|
-
container.innerHTML = '';
|
|
638
|
-
};
|
|
639
|
-
}
|
|
640
|
-
//# sourceMappingURL=segmented-input.js.map
|