@keenthemes/ktui 1.0.28 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/dist/ktui.js +8780 -6199
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +2744 -1367
- package/lib/cjs/components/alert/alert.js +1025 -0
- package/lib/cjs/components/alert/alert.js.map +1 -0
- package/lib/cjs/components/alert/index.js +20 -0
- package/lib/cjs/components/alert/index.js.map +1 -0
- package/lib/cjs/components/alert/templates.js +120 -0
- package/lib/cjs/components/alert/templates.js.map +1 -0
- package/lib/cjs/components/alert/types.js +7 -0
- package/lib/cjs/components/alert/types.js.map +1 -0
- package/lib/cjs/components/datepicker/config/config.js +42 -0
- package/lib/cjs/components/datepicker/config/config.js.map +1 -0
- package/lib/cjs/components/datepicker/config/index.js +24 -0
- package/lib/cjs/components/datepicker/config/index.js.map +1 -0
- package/lib/cjs/components/datepicker/config/interfaces.js +7 -0
- package/lib/cjs/components/datepicker/config/interfaces.js.map +1 -0
- package/lib/cjs/components/datepicker/config/types.js +7 -0
- package/lib/cjs/components/datepicker/config/types.js.map +1 -0
- package/lib/cjs/components/datepicker/core/event-manager.js +135 -0
- package/lib/cjs/components/datepicker/core/event-manager.js.map +1 -0
- package/lib/cjs/components/datepicker/core/focus-manager.js +167 -0
- package/lib/cjs/components/datepicker/core/focus-manager.js.map +1 -0
- package/lib/cjs/components/datepicker/core/helpers.js +219 -0
- package/lib/cjs/components/datepicker/core/helpers.js.map +1 -0
- package/lib/cjs/components/datepicker/core/index.js +25 -0
- package/lib/cjs/components/datepicker/core/index.js.map +1 -0
- package/lib/cjs/components/datepicker/core/unified-state-manager.js +394 -0
- package/lib/cjs/components/datepicker/core/unified-state-manager.js.map +1 -0
- package/lib/cjs/components/datepicker/datepicker.js +2066 -763
- package/lib/cjs/components/datepicker/datepicker.js.map +1 -1
- package/lib/cjs/components/datepicker/index.js +19 -8
- package/lib/cjs/components/datepicker/index.js.map +1 -1
- package/lib/cjs/components/datepicker/ui/index.js +23 -0
- package/lib/cjs/components/datepicker/ui/index.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/input/dropdown.js +489 -0
- package/lib/cjs/components/datepicker/ui/input/dropdown.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/input/index.js +23 -0
- package/lib/cjs/components/datepicker/ui/input/index.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/input/segmented-input.js +640 -0
- package/lib/cjs/components/datepicker/ui/input/segmented-input.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/renderers/calendar.js +446 -0
- package/lib/cjs/components/datepicker/ui/renderers/calendar.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/renderers/footer.js +42 -0
- package/lib/cjs/components/datepicker/ui/renderers/footer.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/renderers/header.js +32 -0
- package/lib/cjs/components/datepicker/ui/renderers/header.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/renderers/index.js +25 -0
- package/lib/cjs/components/datepicker/ui/renderers/index.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/renderers/time-picker.js +384 -0
- package/lib/cjs/components/datepicker/ui/renderers/time-picker.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/templates/index.js +22 -0
- package/lib/cjs/components/datepicker/ui/templates/index.js.map +1 -0
- package/lib/cjs/components/datepicker/ui/templates/templates.js +253 -0
- package/lib/cjs/components/datepicker/ui/templates/templates.js.map +1 -0
- package/lib/cjs/components/datepicker/utils/date-formatters.js +88 -0
- package/lib/cjs/components/datepicker/utils/date-formatters.js.map +1 -0
- package/lib/cjs/components/datepicker/utils/date-utils.js +194 -0
- package/lib/cjs/components/datepicker/utils/date-utils.js.map +1 -0
- package/lib/cjs/components/datepicker/utils/index.js +24 -0
- package/lib/cjs/components/datepicker/utils/index.js.map +1 -0
- package/lib/cjs/components/datepicker/utils/time-utils.js +213 -0
- package/lib/cjs/components/datepicker/utils/time-utils.js.map +1 -0
- package/lib/cjs/index.js +6 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/esm/components/alert/alert.js +1022 -0
- package/lib/esm/components/alert/alert.js.map +1 -0
- package/lib/esm/components/alert/index.js +4 -0
- package/lib/esm/components/alert/index.js.map +1 -0
- package/lib/esm/components/alert/templates.js +112 -0
- package/lib/esm/components/alert/templates.js.map +1 -0
- package/lib/esm/components/alert/types.js +6 -0
- package/lib/esm/components/alert/types.js.map +1 -0
- package/lib/esm/components/datepicker/config/config.js +39 -0
- package/lib/esm/components/datepicker/config/config.js.map +1 -0
- package/lib/esm/components/datepicker/config/index.js +8 -0
- package/lib/esm/components/datepicker/config/index.js.map +1 -0
- package/lib/esm/components/datepicker/config/interfaces.js +6 -0
- package/lib/esm/components/datepicker/config/interfaces.js.map +1 -0
- package/lib/esm/components/datepicker/config/types.js +6 -0
- package/lib/esm/components/datepicker/config/types.js.map +1 -0
- package/lib/esm/components/datepicker/core/event-manager.js +133 -0
- package/lib/esm/components/datepicker/core/event-manager.js.map +1 -0
- package/lib/esm/components/datepicker/core/focus-manager.js +164 -0
- package/lib/esm/components/datepicker/core/focus-manager.js.map +1 -0
- package/lib/esm/components/datepicker/core/helpers.js +211 -0
- package/lib/esm/components/datepicker/core/helpers.js.map +1 -0
- package/lib/esm/components/datepicker/core/index.js +9 -0
- package/lib/esm/components/datepicker/core/index.js.map +1 -0
- package/lib/esm/components/datepicker/core/unified-state-manager.js +391 -0
- package/lib/esm/components/datepicker/core/unified-state-manager.js.map +1 -0
- package/lib/esm/components/datepicker/datepicker.js +2065 -763
- package/lib/esm/components/datepicker/datepicker.js.map +1 -1
- package/lib/esm/components/datepicker/index.js +6 -8
- package/lib/esm/components/datepicker/index.js.map +1 -1
- package/lib/esm/components/datepicker/ui/index.js +7 -0
- package/lib/esm/components/datepicker/ui/index.js.map +1 -0
- package/lib/esm/components/datepicker/ui/input/dropdown.js +486 -0
- package/lib/esm/components/datepicker/ui/input/dropdown.js.map +1 -0
- package/lib/esm/components/datepicker/ui/input/index.js +7 -0
- package/lib/esm/components/datepicker/ui/input/index.js.map +1 -0
- package/lib/esm/components/datepicker/ui/input/segmented-input.js +637 -0
- package/lib/esm/components/datepicker/ui/input/segmented-input.js.map +1 -0
- package/lib/esm/components/datepicker/ui/renderers/calendar.js +443 -0
- package/lib/esm/components/datepicker/ui/renderers/calendar.js.map +1 -0
- package/lib/esm/components/datepicker/ui/renderers/footer.js +39 -0
- package/lib/esm/components/datepicker/ui/renderers/footer.js.map +1 -0
- package/lib/esm/components/datepicker/ui/renderers/header.js +29 -0
- package/lib/esm/components/datepicker/ui/renderers/header.js.map +1 -0
- package/lib/esm/components/datepicker/ui/renderers/index.js +9 -0
- package/lib/esm/components/datepicker/ui/renderers/index.js.map +1 -0
- package/lib/esm/components/datepicker/ui/renderers/time-picker.js +381 -0
- package/lib/esm/components/datepicker/ui/renderers/time-picker.js.map +1 -0
- package/lib/esm/components/datepicker/ui/templates/index.js +6 -0
- package/lib/esm/components/datepicker/ui/templates/index.js.map +1 -0
- package/lib/esm/components/datepicker/ui/templates/templates.js +242 -0
- package/lib/esm/components/datepicker/ui/templates/templates.js.map +1 -0
- package/lib/esm/components/datepicker/utils/date-formatters.js +83 -0
- package/lib/esm/components/datepicker/utils/date-formatters.js.map +1 -0
- package/lib/esm/components/datepicker/utils/date-utils.js +184 -0
- package/lib/esm/components/datepicker/utils/date-utils.js.map +1 -0
- package/lib/esm/components/datepicker/utils/index.js +8 -0
- package/lib/esm/components/datepicker/utils/index.js.map +1 -0
- package/lib/esm/components/datepicker/utils/time-utils.js +201 -0
- package/lib/esm/components/datepicker/utils/time-utils.js.map +1 -0
- package/lib/esm/index.js +4 -0
- package/lib/esm/index.js.map +1 -1
- package/package.json +22 -3
- package/src/components/alert/alert.css +429 -188
- package/src/components/alert/alert.ts +990 -0
- package/src/components/alert/index.ts +4 -0
- package/src/components/alert/templates.ts +110 -0
- package/src/components/alert/tests/accessibility/aria-roles.test.ts +19 -0
- package/src/components/alert/tests/accessibility/focus-management.test.ts +19 -0
- package/src/components/alert/tests/accessibility/keyboard-nav.test.ts +22 -0
- package/src/components/alert/tests/actions/confirm-cancel.test.ts +122 -0
- package/src/components/alert/tests/actions/input-field.test.ts +180 -0
- package/src/components/alert/tests/alert.basic.test.ts +126 -0
- package/src/components/alert/tests/alert.config.test.ts +75 -0
- package/src/components/alert/tests/alert.templates.test.ts +17 -0
- package/src/components/alert/tests/config/attribute-config.test.ts +94 -0
- package/src/components/alert/tests/config/json-config.test.ts +119 -0
- package/src/components/alert/tests/config/merging.test.ts +89 -0
- package/src/components/alert/tests/dismissal/auto-dismiss.test.ts +96 -0
- package/src/components/alert/tests/dismissal/escape-key-dismiss.test.ts +105 -0
- package/src/components/alert/tests/dismissal/manual-dismiss.test.ts +90 -0
- package/src/components/alert/tests/dismissal/outside-click-dismiss.test.ts +91 -0
- package/src/components/alert/tests/edge-cases/invalid-config.test.ts +19 -0
- package/src/components/alert/tests/edge-cases/multiple-alerts.test.ts +19 -0
- package/src/components/alert/tests/rendering/custom-content.test.ts +81 -0
- package/src/components/alert/tests/rendering/info-alert.test.ts +84 -0
- package/src/components/alert/tests/rendering/success-alert.test.ts +100 -0
- package/src/components/alert/tests/templates/default-templates.test.ts +16 -0
- package/src/components/alert/tests/templates/user-templates.test.ts +16 -0
- package/src/components/alert/types.ts +145 -0
- package/src/components/datepicker/__tests__/datepicker-events.test.ts +356 -0
- package/src/components/datepicker/__tests__/datepicker-init.test.ts +343 -0
- package/src/components/datepicker/__tests__/datepicker-integration.test.ts +435 -0
- package/src/components/datepicker/__tests__/datepicker-timezone.test.ts +220 -0
- package/src/components/datepicker/__tests__/segmented-input-focus.test.ts +380 -0
- package/src/components/datepicker/__tests__/selective-state-updates.test.ts +400 -0
- package/src/components/datepicker/__tests__/state-manager.test.ts +421 -0
- package/src/components/datepicker/__tests__/time-preservation.test.ts +387 -0
- package/src/components/datepicker/config/config.ts +40 -0
- package/src/components/datepicker/config/index.ts +8 -0
- package/src/components/datepicker/config/interfaces.ts +82 -0
- package/src/components/datepicker/config/types.ts +188 -0
- package/src/components/datepicker/core/event-manager.ts +159 -0
- package/src/components/datepicker/core/focus-manager.ts +201 -0
- package/src/components/datepicker/core/helpers.ts +231 -0
- package/src/components/datepicker/core/index.ts +9 -0
- package/src/components/datepicker/core/unified-state-manager.ts +459 -0
- package/src/components/datepicker/datepicker.css +429 -1
- package/src/components/datepicker/datepicker.ts +2538 -1277
- package/src/components/datepicker/index.ts +6 -8
- package/src/components/datepicker/ui/index.ts +7 -0
- package/src/components/datepicker/ui/input/dropdown.ts +552 -0
- package/src/components/datepicker/ui/input/index.ts +7 -0
- package/src/components/datepicker/ui/input/segmented-input.ts +638 -0
- package/src/components/datepicker/ui/renderers/__tests__/calendar-optimizations.test.ts +611 -0
- package/src/components/datepicker/ui/renderers/calendar.ts +530 -0
- package/src/components/datepicker/ui/renderers/footer.ts +43 -0
- package/src/components/datepicker/ui/renderers/header.ts +33 -0
- package/src/components/datepicker/ui/renderers/index.ts +9 -0
- package/src/components/datepicker/ui/renderers/time-picker.ts +438 -0
- package/src/components/datepicker/ui/templates/index.ts +6 -0
- package/src/components/datepicker/ui/templates/templates.ts +306 -0
- package/src/components/datepicker/utils/__tests__/date-formatters.test.ts +160 -0
- package/src/components/datepicker/utils/__tests__/date-utils-keys.test.ts +86 -0
- package/src/components/datepicker/utils/__tests__/date-utils-timezone.test.ts +215 -0
- package/src/components/datepicker/utils/date-formatters.ts +85 -0
- package/src/components/datepicker/utils/date-utils.ts +172 -0
- package/src/components/datepicker/utils/index.ts +8 -0
- package/src/components/datepicker/utils/time-utils.ts +221 -0
- package/src/index.ts +7 -1
- package/CONTRIBUTING.md +0 -101
- package/examples/datatable/checkbox-events-test.html +0 -400
- package/examples/datatable/credentials-test.html +0 -423
- package/examples/datatable/remote-checkbox-test.html +0 -365
- package/examples/datatable/sorting-test.html +0 -258
- package/examples/image-input/file-upload-example.html +0 -189
- package/examples/modal/persistent.html +0 -205
- package/examples/modal/remote-select-dropdown.html +0 -166
- package/examples/modal/select-dropdown-container.html +0 -129
- package/examples/select/avatar.html +0 -47
- package/examples/select/basic-usage.html +0 -39
- package/examples/select/country.html +0 -43
- package/examples/select/dark-mode.html +0 -93
- package/examples/select/description.html +0 -53
- package/examples/select/disable-option.html +0 -37
- package/examples/select/disable-select.html +0 -35
- package/examples/select/dropdowncontainer.html +0 -111
- package/examples/select/dynamic-methods.html +0 -273
- package/examples/select/formdata-remote.html +0 -161
- package/examples/select/global-config.html +0 -81
- package/examples/select/icon-multiple.html +0 -50
- package/examples/select/icon.html +0 -48
- package/examples/select/max-selection.html +0 -38
- package/examples/select/modal-container.html +0 -128
- package/examples/select/modal-positioning-test.html +0 -338
- package/examples/select/modal.html +0 -80
- package/examples/select/multiple.html +0 -40
- package/examples/select/native-selected.html +0 -64
- package/examples/select/placeholder.html +0 -40
- package/examples/select/remote-data-preselected.html +0 -283
- package/examples/select/remote-data.html +0 -38
- package/examples/select/search.html +0 -57
- package/examples/select/sizes.html +0 -94
- package/examples/select/tags-enhanced.html +0 -86
- package/examples/select/tags-icons.html +0 -57
- package/examples/select/template-customization.html +0 -61
- package/examples/sticky/README.md +0 -158
- package/examples/sticky/debug-sticky.html +0 -144
- package/examples/sticky/test-runner.html +0 -175
- package/examples/sticky/test-sticky-logic.js +0 -369
- package/examples/sticky/test-sticky-positioning.html +0 -386
- package/examples/toast/example.html +0 -479
- package/lib/cjs/components/datepicker/calendar.js +0 -1061
- package/lib/cjs/components/datepicker/calendar.js.map +0 -1
- package/lib/cjs/components/datepicker/config.js +0 -332
- package/lib/cjs/components/datepicker/config.js.map +0 -1
- package/lib/cjs/components/datepicker/dropdown.js +0 -635
- package/lib/cjs/components/datepicker/dropdown.js.map +0 -1
- package/lib/cjs/components/datepicker/events.js +0 -129
- package/lib/cjs/components/datepicker/events.js.map +0 -1
- package/lib/cjs/components/datepicker/keyboard.js +0 -536
- package/lib/cjs/components/datepicker/keyboard.js.map +0 -1
- package/lib/cjs/components/datepicker/locales.js +0 -78
- package/lib/cjs/components/datepicker/locales.js.map +0 -1
- package/lib/cjs/components/datepicker/templates.js +0 -403
- package/lib/cjs/components/datepicker/templates.js.map +0 -1
- package/lib/cjs/components/datepicker/types.js +0 -23
- package/lib/cjs/components/datepicker/types.js.map +0 -1
- package/lib/cjs/components/datepicker/utils.js +0 -524
- package/lib/cjs/components/datepicker/utils.js.map +0 -1
- package/lib/esm/components/datepicker/calendar.js +0 -1058
- package/lib/esm/components/datepicker/calendar.js.map +0 -1
- package/lib/esm/components/datepicker/config.js +0 -329
- package/lib/esm/components/datepicker/config.js.map +0 -1
- package/lib/esm/components/datepicker/dropdown.js +0 -632
- package/lib/esm/components/datepicker/dropdown.js.map +0 -1
- package/lib/esm/components/datepicker/events.js +0 -126
- package/lib/esm/components/datepicker/events.js.map +0 -1
- package/lib/esm/components/datepicker/keyboard.js +0 -533
- package/lib/esm/components/datepicker/keyboard.js.map +0 -1
- package/lib/esm/components/datepicker/locales.js +0 -74
- package/lib/esm/components/datepicker/locales.js.map +0 -1
- package/lib/esm/components/datepicker/templates.js +0 -390
- package/lib/esm/components/datepicker/templates.js.map +0 -1
- package/lib/esm/components/datepicker/types.js +0 -20
- package/lib/esm/components/datepicker/types.js.map +0 -1
- package/lib/esm/components/datepicker/utils.js +0 -508
- package/lib/esm/components/datepicker/utils.js.map +0 -1
- package/prettier.config.js +0 -9
- package/src/components/datepicker/calendar.ts +0 -1397
- package/src/components/datepicker/config.ts +0 -368
- package/src/components/datepicker/dropdown.ts +0 -757
- package/src/components/datepicker/events.ts +0 -149
- package/src/components/datepicker/keyboard.ts +0 -646
- package/src/components/datepicker/locales.ts +0 -80
- package/src/components/datepicker/templates.ts +0 -792
- package/src/components/datepicker/types.ts +0 -154
- package/src/components/datepicker/utils.ts +0 -631
- package/src/components/select/variants.css +0 -4
- package/tsconfig.json +0 -17
- package/webpack.config.js +0 -118
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* templates.ts - Default templates and merging logic for KTAlert (modular alert/dialog component)
|
|
3
|
+
* Defines all default template strings and provides merged template set.
|
|
4
|
+
*
|
|
5
|
+
* Accessibility: All templates include ARIA roles and attributes for screen reader and keyboard support.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { KTAlertConfig, KTAlertTemplateStrings } from './types';
|
|
9
|
+
|
|
10
|
+
// Core template strings for all UI fragments
|
|
11
|
+
export const coreTemplateStrings: KTAlertTemplateStrings = {
|
|
12
|
+
// Overlay: wraps the modal for modal alerts
|
|
13
|
+
overlay: `<div data-kt-alert-overlay aria-hidden="false" class="kt-alert-overlay {{class}}">{{modal}}</div>`,
|
|
14
|
+
// Modal container: role=alertdialog for modal, role=alert for non-modal
|
|
15
|
+
modal: `<div data-kt-alert data-kt-alert-type="{{type}}" data-kt-alert-variant="{{variant}}" aria-modal="{{ariaModal}}" role="{{role}}" aria-label="Alert Dialog" class="kt-alert-modal {{class}}" data-kt-alert-position="{{position}}">{{content}}</div>`,
|
|
16
|
+
// Fallback container (non-modal, or if no template provided)
|
|
17
|
+
container: `<div class="kt-alert-container {{class}}">{{content}}</div>`,
|
|
18
|
+
icon: `<span data-kt-alert-icon aria-hidden="true" class="kt-alert-icon {{class}}">{{icon}}</span>`,
|
|
19
|
+
title: `<h2 data-kt-alert-title id="kt-alert-title" class="kt-alert-title {{class}}">{{title}}</h2>`,
|
|
20
|
+
message: `<div data-kt-alert-message id="kt-alert-message" class="kt-alert-message {{class}}">{{message}}</div>`,
|
|
21
|
+
actions: `<div data-kt-alert-actions class="kt-alert-actions {{class}}">{{confirmButton}} {{cancelButton}}</div>`,
|
|
22
|
+
// Confirm/cancel buttons (default, can be overridden with custom class)
|
|
23
|
+
confirmButton: `<button type="button" data-kt-alert-confirm aria-label="Confirm" tabindex="0" class="kt-alert-confirm-button {{class}}">{{confirmText}}</button>`,
|
|
24
|
+
cancelButton: `<button type="button" data-kt-alert-cancel aria-label="Cancel" tabindex="0" class="kt-alert-cancel-button {{class}}">{{cancelText}}</button>`,
|
|
25
|
+
// Confirm/cancel buttons with custom class (for per-type theming)
|
|
26
|
+
confirmButtonCustomClass: `<button type="button" data-kt-alert-confirm aria-label="Confirm" tabindex="0" class="{{confirmButtonClass}}">{{confirmText}}</button>`,
|
|
27
|
+
cancelButtonCustomClass: `<button type="button" data-kt-alert-cancel aria-label="Cancel" tabindex="0" class="{{cancelButtonClass}}">{{cancelText}}</button>`,
|
|
28
|
+
// Input templates for each type
|
|
29
|
+
inputText: `<label data-kt-alert-input-label class="kt-alert-input-label {{inputLabelClass}}">{{inputLabel}}<input data-kt-alert-input type="{{inputType}}" placeholder="{{inputPlaceholder}}" value="{{inputValue}}" {{attrs}} aria-label="Prompt input" tabindex="0" class="kt-alert-input {{inputClass}}" /></label>`,
|
|
30
|
+
inputTextarea: `<label data-kt-alert-input-label class="kt-alert-input-label {{inputLabelClass}}">{{inputLabel}}<textarea data-kt-alert-input placeholder="{{inputPlaceholder}}" {{attrs}} aria-label="Prompt input" tabindex="0" class="kt-alert-input {{inputClass}}">{{inputValue}}</textarea></label>`,
|
|
31
|
+
inputSelect: `<label data-kt-alert-input-label class="kt-alert-input-label {{inputLabelClass}}">{{inputLabel}}<select data-kt-alert-input {{attrs}} aria-label="Prompt input" tabindex="0" class="kt-alert-input {{inputClass}}">{{optionsHtml}}</select></label>`,
|
|
32
|
+
inputRadio: `<fieldset data-kt-alert-input-label class="kt-alert-input-label {{inputLabelClass}}"><legend>{{inputLabel}}</legend>{{optionsHtml}}</fieldset>`,
|
|
33
|
+
inputCheckbox: `<fieldset data-kt-alert-input-label class="kt-alert-input-label {{inputLabelClass}}"><legend>{{inputLabel}}</legend>{{optionsHtml}}</fieldset>`,
|
|
34
|
+
inputError: `<div data-kt-alert-input-error class="kt-alert-input-error {{class}}" role="alert" aria-live="polite">{{errorMessage}}</div>`,
|
|
35
|
+
closeButton: `<button type="button" data-kt-alert-close aria-label="Close alert" tabindex="0" class="kt-alert-close-button {{class}}">×</button>`,
|
|
36
|
+
customContent: `<div data-kt-alert-custom-content class="kt-alert-custom-content {{class}}">{{customContent}}</div>`,
|
|
37
|
+
loaderHtml: `<span data-kt-alert-loader class="kt-alert-loader {{class}}">{{loaderHtml}}</span>`,
|
|
38
|
+
// Input option templates
|
|
39
|
+
option: `<option value="{{value}}"{{selected}} {{disabled}}>{{label}}</option>`,
|
|
40
|
+
radioOption: `<label><input type="radio" name="kt-alert-radio" data-kt-alert-input value="{{value}}"{{checked}} {{disabled}} {{attrs}} aria-label="{{label}}" tabindex="0" />{{label}}</label>`,
|
|
41
|
+
checkboxOption: `<label><input type="checkbox" name="kt-alert-checkbox" data-kt-alert-input value="{{value}}"{{checked}} {{disabled}} {{attrs}} aria-label="{{label}}" tabindex="0" />{{label}}</label>`,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the complete template set, merging defaults, user overrides, and config templates.
|
|
46
|
+
* @param config Optional config object with a "templates" property.
|
|
47
|
+
*/
|
|
48
|
+
export function getTemplateStrings(config?: KTAlertConfig): KTAlertTemplateStrings {
|
|
49
|
+
const templates = config?.templates;
|
|
50
|
+
if (templates) {
|
|
51
|
+
return { ...coreTemplateStrings, ...userTemplateStrings, ...templates };
|
|
52
|
+
}
|
|
53
|
+
return { ...coreTemplateStrings, ...userTemplateStrings };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Renders a template string with data using {{key}} placeholders.
|
|
58
|
+
*/
|
|
59
|
+
export function renderTemplateString(template: string, data: Record<string, any>): string {
|
|
60
|
+
return template.replace(/{{(\w+)}}/g, (_, key) =>
|
|
61
|
+
data[key] !== undefined ? String(data[key]) : ''
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Checks if a template is a function.
|
|
67
|
+
*/
|
|
68
|
+
export function isTemplateFunction(tpl: unknown): tpl is (data: any) => string {
|
|
69
|
+
return typeof tpl === 'function';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* User-supplied template overrides. Use setTemplateStrings() to add or update.
|
|
74
|
+
*/
|
|
75
|
+
let userTemplateStrings: Partial<typeof coreTemplateStrings> = {};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Register or update user template overrides.
|
|
79
|
+
* @param templates Partial template object to merge with defaults.
|
|
80
|
+
*/
|
|
81
|
+
export function setTemplateStrings(templates: Partial<typeof coreTemplateStrings>): void {
|
|
82
|
+
userTemplateStrings = { ...userTemplateStrings, ...templates };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Renders an array of options using a template.
|
|
87
|
+
*/
|
|
88
|
+
export function renderOptions(options: Array<any>, templateKey: string, templateSet: KTAlertTemplateStrings): string {
|
|
89
|
+
const template = templateSet[templateKey as keyof KTAlertTemplateStrings];
|
|
90
|
+
if (!template) return '';
|
|
91
|
+
|
|
92
|
+
return options.map(option => {
|
|
93
|
+
const data = {
|
|
94
|
+
value: option.value,
|
|
95
|
+
label: option.label,
|
|
96
|
+
selected: option.value === option.inputValue ? ' selected' : '',
|
|
97
|
+
checked: option.checked || false ? ' checked' : '',
|
|
98
|
+
disabled: option.disabled || false ? ' disabled' : '',
|
|
99
|
+
attrs: option.attrs || ''
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
if (isTemplateFunction(template)) {
|
|
103
|
+
return template(data);
|
|
104
|
+
} else if (typeof template === 'string') {
|
|
105
|
+
return renderTemplateString(template, data);
|
|
106
|
+
}
|
|
107
|
+
return '';
|
|
108
|
+
}).join('');
|
|
109
|
+
}
|
|
110
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TEST SUITE: ARIA Roles & Attributes
|
|
3
|
+
* PURPOSE: Test ARIA roles/attributes for modal and non-modal alerts
|
|
4
|
+
* SCOPE: KTAlert ARIA roles and attributes
|
|
5
|
+
* DEPENDENCIES: vitest, jsdom
|
|
6
|
+
* LAST UPDATED: 2024-06-08
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect } from 'vitest';
|
|
10
|
+
import { KTAlert } from '../../alert';
|
|
11
|
+
|
|
12
|
+
describe('KTAlert ARIA roles and attributes', () => {
|
|
13
|
+
it('should set correct ARIA roles and attributes for modal alert', () => {
|
|
14
|
+
// TODO: Implement test
|
|
15
|
+
});
|
|
16
|
+
it('should set correct ARIA roles and attributes for non-modal alert', () => {
|
|
17
|
+
// TODO: Implement test
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TEST SUITE: Focus Management
|
|
3
|
+
* PURPOSE: Test initial focus and focus trap in modal alerts
|
|
4
|
+
* SCOPE: KTAlert focus management
|
|
5
|
+
* DEPENDENCIES: vitest, jsdom
|
|
6
|
+
* LAST UPDATED: 2024-06-08
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect } from 'vitest';
|
|
10
|
+
import { KTAlert } from '../../alert';
|
|
11
|
+
|
|
12
|
+
describe('KTAlert focus management', () => {
|
|
13
|
+
it('should focus first interactive element on open', () => {
|
|
14
|
+
// TODO: Implement test
|
|
15
|
+
});
|
|
16
|
+
it('should trap focus within modal when open', () => {
|
|
17
|
+
// TODO: Implement test
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TEST SUITE: Keyboard Navigation
|
|
3
|
+
* PURPOSE: Test Tab/Shift+Tab navigation, Enter/Space activation, Escape to close
|
|
4
|
+
* SCOPE: KTAlert keyboard navigation
|
|
5
|
+
* DEPENDENCIES: vitest, jsdom
|
|
6
|
+
* LAST UPDATED: 2024-06-08
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect } from 'vitest';
|
|
10
|
+
import { KTAlert } from '../../alert';
|
|
11
|
+
|
|
12
|
+
describe('KTAlert keyboard navigation', () => {
|
|
13
|
+
it('should allow Tab and Shift+Tab navigation between interactive elements', () => {
|
|
14
|
+
// TODO: Implement test
|
|
15
|
+
});
|
|
16
|
+
it('should activate confirm on Enter/Space', () => {
|
|
17
|
+
// TODO: Implement test
|
|
18
|
+
});
|
|
19
|
+
it('should close alert on Escape if allowed', () => {
|
|
20
|
+
// TODO: Implement test
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TEST SUITE: Confirm/Cancel Actions
|
|
3
|
+
* PURPOSE: Test confirm and cancel button flows, event firing, and result values
|
|
4
|
+
* SCOPE: KTAlert confirm/cancel actions
|
|
5
|
+
* DEPENDENCIES: vitest, jsdom
|
|
6
|
+
* LAST UPDATED: 2024-06-08
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
10
|
+
import { KTAlert } from '../../alert';
|
|
11
|
+
|
|
12
|
+
describe('KTAlert confirm/cancel actions', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
document.body.innerHTML = '';
|
|
15
|
+
});
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
document.body.innerHTML = '';
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should fire confirm event and resolve with correct value', () => {
|
|
21
|
+
// ARRANGE
|
|
22
|
+
const element = document.createElement('div');
|
|
23
|
+
document.body.appendChild(element);
|
|
24
|
+
const alert = new KTAlert(element, { showConfirmButton: true });
|
|
25
|
+
const fireEventSpy = vi.spyOn(alert as any, '_fireEvent');
|
|
26
|
+
// ACT
|
|
27
|
+
const confirmButton = element.querySelector('[data-kt-alert-confirm]') as HTMLElement;
|
|
28
|
+
confirmButton?.click();
|
|
29
|
+
// ASSERT
|
|
30
|
+
expect(fireEventSpy).toHaveBeenCalledWith('confirm', { inputValue: undefined });
|
|
31
|
+
expect((alert as any)._state.isDismissed).toBe(true);
|
|
32
|
+
expect(element.innerHTML).toBe('');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should fire cancel event and resolve with correct value', () => {
|
|
36
|
+
// ARRANGE
|
|
37
|
+
const element = document.createElement('div');
|
|
38
|
+
document.body.appendChild(element);
|
|
39
|
+
const alert = new KTAlert(element, { showCancelButton: true });
|
|
40
|
+
const fireEventSpy = vi.spyOn(alert as any, '_fireEvent');
|
|
41
|
+
// ACT
|
|
42
|
+
const cancelButton = element.querySelector('[data-kt-alert-cancel]') as HTMLElement;
|
|
43
|
+
cancelButton?.click();
|
|
44
|
+
// ASSERT
|
|
45
|
+
expect(fireEventSpy).toHaveBeenCalledWith('cancel', {});
|
|
46
|
+
expect((alert as any)._state.isDismissed).toBe(true);
|
|
47
|
+
expect(element.innerHTML).toBe('');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should use custom button text if provided', () => {
|
|
51
|
+
// ARRANGE
|
|
52
|
+
const element = document.createElement('div');
|
|
53
|
+
document.body.appendChild(element);
|
|
54
|
+
const alert = new KTAlert(element, {
|
|
55
|
+
showConfirmButton: true,
|
|
56
|
+
showCancelButton: true,
|
|
57
|
+
confirmText: 'Yes, do it!',
|
|
58
|
+
cancelText: 'No, cancel'
|
|
59
|
+
});
|
|
60
|
+
// ACT
|
|
61
|
+
const confirmButton = element.querySelector('[data-kt-alert-confirm]') as HTMLElement;
|
|
62
|
+
const cancelButton = element.querySelector('[data-kt-alert-cancel]') as HTMLElement;
|
|
63
|
+
// ASSERT
|
|
64
|
+
expect(confirmButton?.textContent).toBe('Yes, do it!');
|
|
65
|
+
expect(cancelButton?.textContent).toBe('No, cancel');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should not render buttons if showConfirmButton and showCancelButton are false', () => {
|
|
69
|
+
// ARRANGE
|
|
70
|
+
const element = document.createElement('div');
|
|
71
|
+
document.body.appendChild(element);
|
|
72
|
+
const alert = new KTAlert(element, {
|
|
73
|
+
showConfirmButton: false,
|
|
74
|
+
showCancelButton: false
|
|
75
|
+
});
|
|
76
|
+
// ACT
|
|
77
|
+
const confirmButton = element.querySelector('[data-kt-alert-confirm]');
|
|
78
|
+
const cancelButton = element.querySelector('[data-kt-alert-cancel]');
|
|
79
|
+
// ASSERT
|
|
80
|
+
expect(confirmButton).toBeNull();
|
|
81
|
+
expect(cancelButton).toBeNull();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should clear timer when confirm button is clicked', () => {
|
|
85
|
+
// ARRANGE
|
|
86
|
+
const element = document.createElement('div');
|
|
87
|
+
document.body.appendChild(element);
|
|
88
|
+
const alert = new KTAlert(element, { showConfirmButton: true, timer: 5000 });
|
|
89
|
+
const clearTimerSpy = vi.spyOn(alert as any, '_clearTimer');
|
|
90
|
+
// ACT
|
|
91
|
+
const confirmButton = element.querySelector('[data-kt-alert-confirm]') as HTMLElement;
|
|
92
|
+
confirmButton?.click();
|
|
93
|
+
// ASSERT
|
|
94
|
+
expect(clearTimerSpy).toHaveBeenCalled();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should clear timer when cancel button is clicked', () => {
|
|
98
|
+
// ARRANGE
|
|
99
|
+
const element = document.createElement('div');
|
|
100
|
+
document.body.appendChild(element);
|
|
101
|
+
const alert = new KTAlert(element, { showCancelButton: true, timer: 5000 });
|
|
102
|
+
const clearTimerSpy = vi.spyOn(alert as any, '_clearTimer');
|
|
103
|
+
// ACT
|
|
104
|
+
const cancelButton = element.querySelector('[data-kt-alert-cancel]') as HTMLElement;
|
|
105
|
+
cancelButton?.click();
|
|
106
|
+
// ASSERT
|
|
107
|
+
expect(clearTimerSpy).toHaveBeenCalled();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should handle Enter key to trigger confirm button', () => {
|
|
111
|
+
// ARRANGE
|
|
112
|
+
const config = { showConfirmButton: true, title: 'Test' };
|
|
113
|
+
// ACT
|
|
114
|
+
KTAlert.fire(config);
|
|
115
|
+
const alert = document.querySelector('[data-kt-alert]');
|
|
116
|
+
const enterEvent = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true });
|
|
117
|
+
alert?.dispatchEvent(enterEvent);
|
|
118
|
+
// ASSERT
|
|
119
|
+
// The alert should be dismissed (confirm button clicked)
|
|
120
|
+
expect(document.querySelector('[data-kt-alert-overlay]')).toBeNull();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TEST SUITE: Input Field Actions
|
|
3
|
+
* PURPOSE: Test alerts with input fields (text, textarea, select, radio, checkbox), value propagation
|
|
4
|
+
* SCOPE: KTAlert input field handling
|
|
5
|
+
* DEPENDENCIES: vitest, jsdom
|
|
6
|
+
* LAST UPDATED: 2024-06-08
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
10
|
+
import { KTAlert } from '../../alert';
|
|
11
|
+
|
|
12
|
+
describe('KTAlert input field actions', () => {
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
document.body.innerHTML = '';
|
|
15
|
+
});
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
document.body.innerHTML = '';
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should propagate value from text input', () => {
|
|
21
|
+
// ARRANGE
|
|
22
|
+
const config = {
|
|
23
|
+
input: true,
|
|
24
|
+
inputType: 'text',
|
|
25
|
+
inputPlaceholder: 'Enter text',
|
|
26
|
+
showConfirmButton: true,
|
|
27
|
+
title: 'Test'
|
|
28
|
+
};
|
|
29
|
+
// ACT
|
|
30
|
+
KTAlert.fire(config);
|
|
31
|
+
const input = document.querySelector('input[type="text"]') as HTMLInputElement;
|
|
32
|
+
input.value = 'test value';
|
|
33
|
+
const confirmButton = document.querySelector('[data-kt-alert-confirm]') as HTMLElement;
|
|
34
|
+
confirmButton?.click();
|
|
35
|
+
// ASSERT
|
|
36
|
+
// The alert should be dismissed with the input value
|
|
37
|
+
expect(document.querySelector('[data-kt-alert-overlay]')).toBeNull();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should propagate value from textarea input', () => {
|
|
41
|
+
// ARRANGE
|
|
42
|
+
const config = {
|
|
43
|
+
input: true,
|
|
44
|
+
inputType: 'textarea',
|
|
45
|
+
inputPlaceholder: 'Enter text',
|
|
46
|
+
showConfirmButton: true,
|
|
47
|
+
title: 'Test'
|
|
48
|
+
};
|
|
49
|
+
// ACT
|
|
50
|
+
KTAlert.fire(config);
|
|
51
|
+
const textarea = document.querySelector('textarea') as HTMLTextAreaElement;
|
|
52
|
+
textarea.value = 'multiline\ntext';
|
|
53
|
+
const confirmButton = document.querySelector('[data-kt-alert-confirm]') as HTMLElement;
|
|
54
|
+
confirmButton?.click();
|
|
55
|
+
// ASSERT
|
|
56
|
+
// The alert should be dismissed with the input value
|
|
57
|
+
expect(document.querySelector('[data-kt-alert-overlay]')).toBeNull();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should propagate value from select input', () => {
|
|
61
|
+
// ARRANGE
|
|
62
|
+
const config = {
|
|
63
|
+
input: true,
|
|
64
|
+
inputType: 'select',
|
|
65
|
+
inputOptions: [
|
|
66
|
+
{ value: 'option1', label: 'Option 1' },
|
|
67
|
+
{ value: 'option2', label: 'Option 2' }
|
|
68
|
+
],
|
|
69
|
+
showConfirmButton: true,
|
|
70
|
+
title: 'Test'
|
|
71
|
+
};
|
|
72
|
+
// ACT
|
|
73
|
+
KTAlert.fire(config);
|
|
74
|
+
const select = document.querySelector('select') as HTMLSelectElement;
|
|
75
|
+
select.value = 'option2';
|
|
76
|
+
const confirmButton = document.querySelector('[data-kt-alert-confirm]') as HTMLElement;
|
|
77
|
+
confirmButton?.click();
|
|
78
|
+
// ASSERT
|
|
79
|
+
// The alert should be dismissed with the input value
|
|
80
|
+
expect(document.querySelector('[data-kt-alert-overlay]')).toBeNull();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should propagate value from radio input', () => {
|
|
84
|
+
// ARRANGE
|
|
85
|
+
const config = {
|
|
86
|
+
input: true,
|
|
87
|
+
inputType: 'radio',
|
|
88
|
+
inputOptions: [
|
|
89
|
+
{ value: 'radio1', label: 'Radio 1' },
|
|
90
|
+
{ value: 'radio2', label: 'Radio 2', checked: true }
|
|
91
|
+
],
|
|
92
|
+
showConfirmButton: true,
|
|
93
|
+
title: 'Test'
|
|
94
|
+
};
|
|
95
|
+
// ACT
|
|
96
|
+
KTAlert.fire(config);
|
|
97
|
+
const confirmButton = document.querySelector('[data-kt-alert-confirm]') as HTMLElement;
|
|
98
|
+
confirmButton?.click();
|
|
99
|
+
// ASSERT
|
|
100
|
+
// The alert should be dismissed with the input value
|
|
101
|
+
expect(document.querySelector('[data-kt-alert-overlay]')).toBeNull();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should propagate value from checkbox input', () => {
|
|
105
|
+
// ARRANGE
|
|
106
|
+
const config = {
|
|
107
|
+
input: true,
|
|
108
|
+
inputType: 'checkbox',
|
|
109
|
+
inputOptions: [
|
|
110
|
+
{ value: 'check1', label: 'Check 1' },
|
|
111
|
+
{ value: 'check2', label: 'Check 2' }
|
|
112
|
+
],
|
|
113
|
+
showConfirmButton: true,
|
|
114
|
+
title: 'Test'
|
|
115
|
+
};
|
|
116
|
+
// ACT
|
|
117
|
+
KTAlert.fire(config);
|
|
118
|
+
const checkboxes = document.querySelectorAll('input[type="checkbox"]') as NodeListOf<HTMLInputElement>;
|
|
119
|
+
checkboxes[0].checked = true;
|
|
120
|
+
checkboxes[1].checked = true;
|
|
121
|
+
const confirmButton = document.querySelector('[data-kt-alert-confirm]') as HTMLElement;
|
|
122
|
+
confirmButton?.click();
|
|
123
|
+
// ASSERT
|
|
124
|
+
// The alert should be dismissed with the input value
|
|
125
|
+
expect(document.querySelector('[data-kt-alert-overlay]')).toBeNull();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('should handle input change events', () => {
|
|
129
|
+
// ARRANGE
|
|
130
|
+
const config = {
|
|
131
|
+
input: true,
|
|
132
|
+
inputType: 'text',
|
|
133
|
+
showConfirmButton: true,
|
|
134
|
+
title: 'Test'
|
|
135
|
+
};
|
|
136
|
+
// ACT
|
|
137
|
+
KTAlert.fire(config);
|
|
138
|
+
const input = document.querySelector('input[type="text"]') as HTMLInputElement;
|
|
139
|
+
input.value = 'new value';
|
|
140
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
141
|
+
// ASSERT
|
|
142
|
+
// The input value should be updated
|
|
143
|
+
expect(input.value).toBe('new value');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('should not render input if input is false', () => {
|
|
147
|
+
// ARRANGE
|
|
148
|
+
const config = {
|
|
149
|
+
input: false,
|
|
150
|
+
showConfirmButton: true,
|
|
151
|
+
title: 'Test'
|
|
152
|
+
};
|
|
153
|
+
// ACT
|
|
154
|
+
KTAlert.fire(config);
|
|
155
|
+
const input = document.querySelector('input, textarea, select');
|
|
156
|
+
// ASSERT
|
|
157
|
+
expect(input).toBeNull();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it('should apply input attributes correctly', () => {
|
|
161
|
+
// ARRANGE
|
|
162
|
+
const config = {
|
|
163
|
+
input: true,
|
|
164
|
+
inputType: 'text',
|
|
165
|
+
inputAttributes: {
|
|
166
|
+
maxlength: '10',
|
|
167
|
+
required: 'true',
|
|
168
|
+
pattern: '[A-Za-z]+'
|
|
169
|
+
},
|
|
170
|
+
title: 'Test'
|
|
171
|
+
};
|
|
172
|
+
// ACT
|
|
173
|
+
KTAlert.fire(config);
|
|
174
|
+
const input = document.querySelector('input[type="text"]') as HTMLInputElement;
|
|
175
|
+
// ASSERT
|
|
176
|
+
expect(input?.getAttribute('maxlength')).toBe('10');
|
|
177
|
+
expect(input?.getAttribute('required')).toBe('true');
|
|
178
|
+
expect(input?.getAttribute('pattern')).toBe('[A-Za-z]+');
|
|
179
|
+
});
|
|
180
|
+
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// alert.basic.test.ts - Basic instantiation and type safety tests for KTAlert
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { KTAlert } from '../alert';
|
|
4
|
+
import { vi } from 'vitest';
|
|
5
|
+
|
|
6
|
+
describe('KTAlert', () => {
|
|
7
|
+
it('should instantiate without errors', () => {
|
|
8
|
+
// Create a dummy element
|
|
9
|
+
const el = document.createElement('div');
|
|
10
|
+
// Instantiate KTAlert
|
|
11
|
+
const alert = new KTAlert(document.createElement("div"));
|
|
12
|
+
// Should be defined
|
|
13
|
+
expect(alert).toBeDefined();
|
|
14
|
+
// Should have correct name
|
|
15
|
+
expect((alert as any)._name).toBe('alert');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should auto-dismiss after timer expires', async () => {
|
|
19
|
+
vi.useFakeTimers();
|
|
20
|
+
const el = document.createElement('div');
|
|
21
|
+
document.body.appendChild(el);
|
|
22
|
+
const alert = new KTAlert(el, { timer: 1000, dismissible: true });
|
|
23
|
+
// Spy on _fireEvent
|
|
24
|
+
const fireEventSpy = vi.spyOn(alert as any, '_fireEvent');
|
|
25
|
+
// Fast-forward time
|
|
26
|
+
vi.advanceTimersByTime(1000);
|
|
27
|
+
// Wait for microtasks
|
|
28
|
+
await vi.runAllTicks();
|
|
29
|
+
expect(fireEventSpy).toHaveBeenCalledWith('dismiss', { reason: 'timer' });
|
|
30
|
+
expect(el.innerHTML).toBe('');
|
|
31
|
+
vi.useRealTimers();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should not auto-dismiss if manually dismissed first', async () => {
|
|
35
|
+
vi.useFakeTimers();
|
|
36
|
+
const el = document.createElement('div');
|
|
37
|
+
document.body.appendChild(el);
|
|
38
|
+
const alert = new KTAlert(el, { timer: 1000, dismissible: true });
|
|
39
|
+
// Spy on _fireEvent
|
|
40
|
+
const fireEventSpy = vi.spyOn(alert as any, '_fireEvent');
|
|
41
|
+
// Simulate manual dismiss
|
|
42
|
+
(alert as any)._clearTimer();
|
|
43
|
+
(alert as any)._state.isDismissed = true;
|
|
44
|
+
(alert as any)._element.innerHTML = '';
|
|
45
|
+
// Fast-forward time
|
|
46
|
+
vi.advanceTimersByTime(1000);
|
|
47
|
+
// Wait for microtasks
|
|
48
|
+
await vi.runAllTicks();
|
|
49
|
+
// Should not call _fireEvent again for timer
|
|
50
|
+
expect(fireEventSpy).not.toHaveBeenCalledWith('dismiss', { reason: 'timer' });
|
|
51
|
+
vi.useRealTimers();
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe('KTAlert input types', () => {
|
|
56
|
+
it('should render and capture text input', () => {
|
|
57
|
+
const el = document.createElement('div');
|
|
58
|
+
document.body.appendChild(el);
|
|
59
|
+
const alert = new KTAlert(el, { input: true, inputType: 'text', inputValue: 'foo' });
|
|
60
|
+
const input = el.querySelector('input[data-kt-alert-input]') as HTMLInputElement;
|
|
61
|
+
expect(input).toBeDefined();
|
|
62
|
+
expect(input.value).toBe('foo');
|
|
63
|
+
input.value = 'bar';
|
|
64
|
+
input.dispatchEvent(new Event('input'));
|
|
65
|
+
expect((alert as any)._state.inputValue).toBe('bar');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should render and capture textarea input', () => {
|
|
69
|
+
const el = document.createElement('div');
|
|
70
|
+
document.body.appendChild(el);
|
|
71
|
+
const alert = new KTAlert(el, { input: true, inputType: 'textarea', inputValue: 'foo' });
|
|
72
|
+
const textarea = el.querySelector('textarea[data-kt-alert-input]') as HTMLTextAreaElement;
|
|
73
|
+
expect(textarea).toBeDefined();
|
|
74
|
+
expect(textarea.value).toBe('foo');
|
|
75
|
+
textarea.value = 'bar';
|
|
76
|
+
textarea.dispatchEvent(new Event('input'));
|
|
77
|
+
expect((alert as any)._state.inputValue).toBe('bar');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should render and capture select input', () => {
|
|
81
|
+
const el = document.createElement('div');
|
|
82
|
+
document.body.appendChild(el);
|
|
83
|
+
const alert = new KTAlert(el, { input: true, inputType: 'select', inputValue: 'b', inputOptions: [
|
|
84
|
+
{ value: 'a', label: 'A' },
|
|
85
|
+
{ value: 'b', label: 'B' },
|
|
86
|
+
{ value: 'c', label: 'C' },
|
|
87
|
+
] });
|
|
88
|
+
const select = el.querySelector('select[data-kt-alert-input]') as HTMLSelectElement;
|
|
89
|
+
expect(select).toBeDefined();
|
|
90
|
+
expect(select.value).toBe('b');
|
|
91
|
+
select.value = 'c';
|
|
92
|
+
select.dispatchEvent(new Event('change'));
|
|
93
|
+
expect((alert as any)._state.inputValue).toBe('c');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should render and capture radio input', () => {
|
|
97
|
+
const el = document.createElement('div');
|
|
98
|
+
document.body.appendChild(el);
|
|
99
|
+
const alert = new KTAlert(el, { input: true, inputType: 'radio', inputValue: 'b', inputOptions: [
|
|
100
|
+
{ value: 'a', label: 'A' },
|
|
101
|
+
{ value: 'b', label: 'B' },
|
|
102
|
+
{ value: 'c', label: 'C' },
|
|
103
|
+
] });
|
|
104
|
+
const radios = el.querySelectorAll('input[type="radio"][data-kt-alert-input]') as NodeListOf<HTMLInputElement>;
|
|
105
|
+
expect(radios.length).toBe(3);
|
|
106
|
+
radios[2].checked = true;
|
|
107
|
+
radios[2].dispatchEvent(new Event('change'));
|
|
108
|
+
expect((alert as any)._state.inputValue).toBe('c');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('should render and capture checkbox input', () => {
|
|
112
|
+
const el = document.createElement('div');
|
|
113
|
+
document.body.appendChild(el);
|
|
114
|
+
const alert = new KTAlert(el, { input: true, inputType: 'checkbox', inputOptions: [
|
|
115
|
+
{ value: 'a', label: 'A', checked: true },
|
|
116
|
+
{ value: 'b', label: 'B' },
|
|
117
|
+
{ value: 'c', label: 'C', checked: true },
|
|
118
|
+
] });
|
|
119
|
+
const checkboxes = el.querySelectorAll('input[type="checkbox"][data-kt-alert-input]') as NodeListOf<HTMLInputElement>;
|
|
120
|
+
expect(checkboxes.length).toBe(3);
|
|
121
|
+
checkboxes[1].checked = true;
|
|
122
|
+
checkboxes[1].dispatchEvent(new Event('change'));
|
|
123
|
+
// Should be comma-separated string of checked values
|
|
124
|
+
expect((alert as any)._state.inputValue.split(',').sort()).toEqual(['a','b','c'].sort());
|
|
125
|
+
});
|
|
126
|
+
});
|